1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include "ComposedEdge.hxx"
20 #include "ElementaryEdge.hxx"
21 #include "EdgeInfLin.hxx"
22 #include "InterpKernelException.hxx"
29 using namespace INTERP_KERNEL;
31 ComposedEdge::ComposedEdge(const ComposedEdge& other)
33 for(list<ElementaryEdge *>::const_iterator iter=other._sub_edges.begin();iter!=other._sub_edges.end();iter++)
34 _sub_edges.push_back((*iter)->clone());
37 ComposedEdge::~ComposedEdge()
39 clearAll(_sub_edges.begin());
42 void ComposedEdge::setValueAt(int i, Edge *e, bool direction)
44 list<ElementaryEdge*>::iterator it=_sub_edges.begin();
48 *it=new ElementaryEdge(e,direction);
53 AbsEdgeCmp(ElementaryEdge *b):_b1(b) { }
54 bool operator()(ElementaryEdge *a) { return a->getPtr()==_b1->getPtr();}
59 double ComposedEdge::getCommonLengthWith(const ComposedEdge& other) const
62 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
64 if(find_if(other._sub_edges.begin(),other._sub_edges.end(),AbsEdgeCmp(*iter))!=other._sub_edges.end())
66 const ElementaryEdge *tmp=static_cast<const ElementaryEdge *>(*iter);
67 ret+=tmp->getCurveLength();
73 void ComposedEdge::clear()
75 clearAll(_sub_edges.begin());
79 void ComposedEdge::pushBack(Edge *edge, bool direction)
81 _sub_edges.push_back(new ElementaryEdge(edge,direction));
84 void ComposedEdge::pushBack(ElementaryEdge *elem)
86 _sub_edges.push_back(elem);
89 void ComposedEdge::pushBack(ComposedEdge *elem)
91 list<ElementaryEdge *> *elemsOfElem=elem->getListBehind();
92 _sub_edges.insert(_sub_edges.end(),elemsOfElem->begin(),elemsOfElem->end());
95 ElementaryEdge *ComposedEdge::operator[](int i) const
97 list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();
98 for(int ii=0;ii<i;ii++)
103 void ComposedEdge::reverse()
105 _sub_edges.reverse();
106 for(list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
110 void ComposedEdge::initLocations() const
112 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
113 (*iter)->initLocations();
116 ComposedEdge *ComposedEdge::clone() const
118 return new ComposedEdge(*this);
121 bool ComposedEdge::isNodeIn(Node *n) const
124 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end() && !ret;iter++)
125 ret=(*iter)->isNodeIn(n);
130 * This method computes the area of 'this'.
133 * Area=\int_{Polygon} dS
135 * Thanks to Green's theorem we have.
137 * \int_{Polygon} x \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}ydx=\sum_{0 \leq i < nb of edges} AreaOfZone_{Edge_{i}}
139 * Where \f$ AreaOfZone_{i} \f$ is computed virtually by INTERP_KERNEL::Edge::getAreaOfZone with following formula :
141 * AreaOfZone_{i}=\int_{Edge_{i}} -ydx
144 double ComposedEdge::getArea() const
147 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
148 ret+=(*iter)->getAreaOfZone();
152 double ComposedEdge::getPerimeter() const
155 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
156 ret+=(*iter)->getCurveLength();
160 double ComposedEdge::getHydraulicDiameter() const
162 return 4*fabs(getArea())/getPerimeter();
166 * This method computes barycenter of 'this' by returning xG in bary[0] and yG in bary[1].
169 * Area \cdot x_{G}=\int_{Polygon} x \cdot dS
172 * Area \cdot y_{G}=\int_{Polygon} y \cdot dS
174 * Thanks to Green's theorem we have.
176 * \int_{Polygon} x \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}yxdx
179 * \int_{Polygon} y \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}\frac{y^{2}}{2}dx
181 * Area is computed using the same principle than described in INTERP_KERNEL::ComposedEdge::getArea method.
182 * \f$ -\int_{Edge_{i}}yxdx \f$ and \f$ -\int_{Edge_{i}}\frac{y^{2}}{2}dx \f$ are computed virtually with INTERP_KERNEL::Edge::getBarycenterOfZone.
184 void ComposedEdge::getBarycenter(double *bary) const
189 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
191 (*iter)->getBarycenterOfZone(bary);
192 area+=(*iter)->getAreaOfZone();
198 double ComposedEdge::normalize(ComposedEdge *other)
201 b.prepareForAggregation();
203 other->fillBounds(b);
204 double dimChar=b.getCaracteristicDim();
206 b.getBarycenter(xBary,yBary);
207 applyGlobalSimilarity(xBary,yBary,dimChar);
208 other->applyGlobalSimilarity(xBary,yBary,dimChar);
212 void ComposedEdge::dumpInXfigFile(std::ostream& stream, int resolution, const Bounds& box) const
214 stream.precision(10);
215 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
216 (*iter)->dumpInXfigFile(stream,resolution,box);
219 Node *ComposedEdge::getEndNode() const
221 return _sub_edges.back()->getEndNode();
224 Node *ComposedEdge::getStartNode() const
226 return _sub_edges.front()->getStartNode();
229 bool ComposedEdge::changeEndNodeWith(Node *node) const
231 return _sub_edges.back()->changeEndNodeWith(node);
234 bool ComposedEdge::changeStartNodeWith(Node *node) const
236 return _sub_edges.front()->changeStartNodeWith(node);
239 void ComposedEdge::fillBounds(Bounds& output) const
241 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
242 (*iter)->fillBounds(output);
246 * \b WARNING : applies similarity \b ONLY on edges without any change on Nodes. To perform a global similarity call applyGlobalSimilarity.
248 void ComposedEdge::applySimilarity(double xBary, double yBary, double dimChar)
250 for(list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
251 (*iter)->applySimilarity(xBary,yBary,dimChar);
255 * Perform Similarity transformation on all elements of this Nodes and Edges.
257 void ComposedEdge::applyGlobalSimilarity(double xBary, double yBary, double dimChar)
259 set<Node *> allNodes;
260 getAllNodes(allNodes);
261 for(set<Node *>::iterator iter=allNodes.begin();iter!=allNodes.end();iter++)
262 (*iter)->applySimilarity(xBary,yBary,dimChar);
263 for(list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
264 (*iter)->applySimilarity(xBary,yBary,dimChar);
268 * This method append to param 'partConsidered' the part of length of subedges IN or ON.
269 * @param partConsidered INOUT param.
271 void ComposedEdge::dispatchPerimeter(double& partConsidered) const
273 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
275 TypeOfEdgeLocInPolygon loc=(*iter)->getLoc();
276 if(loc==FULL_IN_1 || loc==FULL_ON_1)
277 partConsidered+=(*iter)->getCurveLength();
282 * Idem dispatchPerimeterExcl except that when a subedge is declared as ON this subedge is counted in commonPart.
284 void ComposedEdge::dispatchPerimeterExcl(double& partConsidered, double& commonPart) const
286 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
288 TypeOfEdgeLocInPolygon loc=(*iter)->getLoc();
290 partConsidered+=(*iter)->getCurveLength();
292 commonPart+=(*iter)->getCurveLength();
296 void ComposedEdge::getAllNodes(std::set<Node *>& output) const
298 list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();
299 for(;iter!=_sub_edges.end();iter++)
300 (*iter)->getAllNodes(output);
303 void ComposedEdge::getBarycenter(double *bary, double& weigh) const
305 weigh=0.; bary[0]=0.; bary[1]=0.;
307 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
309 (*iter)->getBarycenter(tmp2,tmp1);
311 bary[0]+=tmp1*tmp2[0];
312 bary[1]+=tmp1*tmp2[1];
318 bool ComposedEdge::isInOrOut(Node *nodeToTest) const
320 Bounds b; b.prepareForAggregation();
322 if(b.nearlyWhere((*nodeToTest)[0],(*nodeToTest)[1])==OUT)
327 set<double> radialDistributionOfNodes;
328 set<Node *>::const_iterator iter;
329 for(iter=nodes.begin();iter!=nodes.end();iter++)
330 radialDistributionOfNodes.insert(nodeToTest->getSlope(*(*iter)));
331 vector<double> radialDistrib(radialDistributionOfNodes.begin(),radialDistributionOfNodes.end());
332 radialDistributionOfNodes.clear();
333 vector<double> radialDistrib2(radialDistrib.size());
334 copy(radialDistrib.begin()+1,radialDistrib.end(),radialDistrib2.begin());
335 radialDistrib2.back()=M_PI+radialDistrib.front();
336 vector<double> radialDistrib3(radialDistrib.size());
337 transform(radialDistrib2.begin(),radialDistrib2.end(),radialDistrib.begin(),radialDistrib3.begin(),minus<double>());
338 vector<double>::iterator iter3=max_element(radialDistrib3.begin(),radialDistrib3.end());
339 int i=iter3-radialDistrib3.begin();
340 // ok for e1 - Let's go.
341 EdgeInfLin *e1=new EdgeInfLin(nodeToTest,radialDistrib[i]+radialDistrib3[i]/2.);
342 double ref=e1->getCharactValue(*nodeToTest);
343 set< IntersectElement > inOutSwitch;
344 for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
346 ElementaryEdge *val=(*iter);
349 Edge *e=val->getPtr();
350 auto_ptr<EdgeIntersector> intersc(Edge::buildIntersectorWith(e1,e));
351 bool obviousNoIntersection,areOverlapped;
352 intersc->areOverlappedOrOnlyColinears(0,obviousNoIntersection,areOverlapped);
353 if(obviousNoIntersection)
359 list< IntersectElement > listOfIntesc=intersc->getIntersectionsCharacteristicVal();
360 for(list< IntersectElement >::iterator iter2=listOfIntesc.begin();iter2!=listOfIntesc.end();iter2++)
361 if((*iter2).isIncludedByBoth())
362 inOutSwitch.insert(*iter2);
364 //if overlapped we can forget
367 throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
371 for(set< IntersectElement >::iterator iter=inOutSwitch.begin();iter!=inOutSwitch.end();iter++)
373 if((*iter).getVal1()<ref)
375 if((*iter).getNodeOnly()->getLoc()==ON_1)
384 /*bool ComposedEdge::isInOrOut(Node *aNodeOn, Node *nodeToTest) const
387 EdgeInfLin *e1=new EdgeInfLin(aNodeOn,nodeToTest);
388 double ref=e1->getCharactValue(*nodeToTest);
389 set< IntersectElement > inOutSwitch;
390 for(vector<AbstractEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
392 ElementaryEdge *val=dynamic_cast<ElementaryEdge *>(*iter);
395 Edge *e=val->getPtr();
396 auto_ptr<Intersector> intersc(Edge::buildIntersectorWith(e1,e));
397 bool obviousNoIntersection,areOverlapped;
398 intersc->areOverlappedOrOnlyColinears(0,obviousNoIntersection,areOverlapped);
399 if(obviousNoIntersection)
405 list< IntersectElement > listOfIntesc=intersc->getIntersectionsCharacteristicVal();
406 for(list< IntersectElement >::iterator iter2=listOfIntesc.begin();iter2!=listOfIntesc.end();iter2++)
407 if((*iter2).isIncludedByBoth())
408 inOutSwitch.insert(*iter2);
410 //if overlapped we can forget
413 throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
417 for(set< IntersectElement >::iterator iter=inOutSwitch.begin();iter!=inOutSwitch.end();iter++)
419 if((*iter).getVal1()<ref)
421 if((*iter).getNodeOnly()->getLoc()==ON_1)
430 bool ComposedEdge::getDirection() const
432 throw Exception("ComposedEdge::getDirection : no sense");
435 bool ComposedEdge::intresincEqCoarse(const Edge *other) const
437 if(_sub_edges.size()!=1)
439 return _sub_edges.front()->intresincEqCoarse(other);
442 void ComposedEdge::clearAll(list<ElementaryEdge *>::iterator startToDel)
444 for(list<ElementaryEdge *>::iterator iter=startToDel;iter!=_sub_edges.end();iter++)