1 // Copyright (C) 2007-2012 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
20 #include "InterpKernelGeo2DComposedEdge.hxx"
21 #include "InterpKernelGeo2DElementaryEdge.hxx"
22 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
23 #include "InterpKernelGeo2DEdgeInfLin.hxx"
24 #include "InterpKernelException.hxx"
31 using namespace INTERP_KERNEL;
33 ComposedEdge::ComposedEdge(const ComposedEdge& other)
35 for(std::list<ElementaryEdge *>::const_iterator iter=other._sub_edges.begin();iter!=other._sub_edges.end();iter++)
36 _sub_edges.push_back((*iter)->clone());
39 ComposedEdge::~ComposedEdge()
41 clearAll(_sub_edges.begin());
44 void ComposedEdge::setValueAt(int i, Edge *e, bool direction)
46 std::list<ElementaryEdge*>::iterator it=_sub_edges.begin();
50 *it=new ElementaryEdge(e,direction);
55 AbsEdgeCmp(ElementaryEdge *b):_b1(b) { }
56 bool operator()(ElementaryEdge *a) { return a->getPtr()==_b1->getPtr();}
61 double ComposedEdge::getCommonLengthWith(const ComposedEdge& other) const
64 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
66 if(find_if(other._sub_edges.begin(),other._sub_edges.end(),AbsEdgeCmp(*iter))!=other._sub_edges.end())
68 const ElementaryEdge *tmp=static_cast<const ElementaryEdge *>(*iter);
69 ret+=tmp->getCurveLength();
75 void ComposedEdge::clear()
77 clearAll(_sub_edges.begin());
81 void ComposedEdge::pushBack(Edge *edge, bool direction)
83 _sub_edges.push_back(new ElementaryEdge(edge,direction));
86 void ComposedEdge::pushBack(ElementaryEdge *elem)
88 _sub_edges.push_back(elem);
91 void ComposedEdge::pushBack(ComposedEdge *elem)
93 std::list<ElementaryEdge *> *elemsOfElem=elem->getListBehind();
94 _sub_edges.insert(_sub_edges.end(),elemsOfElem->begin(),elemsOfElem->end());
97 ElementaryEdge *ComposedEdge::operator[](int i) const
99 std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();
100 for(int ii=0;ii<i;ii++)
105 void ComposedEdge::reverse()
107 _sub_edges.reverse();
108 for(std::list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
112 bool ComposedEdge::presenceOfOn() const
115 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end() && !ret;iter++)
116 ret=((*iter)->getLoc()==FULL_ON_1);
120 bool ComposedEdge::presenceOfQuadraticEdge() const
123 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end() && !ret;iter++)
125 Edge *e=(*iter)->getPtr();
127 ret=dynamic_cast<EdgeArcCircle*>(e)!=0;
132 void ComposedEdge::initLocations() const
134 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
135 (*iter)->initLocations();
138 ComposedEdge *ComposedEdge::clone() const
140 return new ComposedEdge(*this);
143 bool ComposedEdge::isNodeIn(Node *n) const
146 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end() && !ret;iter++)
147 ret=(*iter)->isNodeIn(n);
152 * This method computes the area of 'this'.
155 * Area=\int_{Polygon} dS
157 * Thanks to Green's theorem we have.
159 * \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}}
161 * Where \f$ AreaOfZone_{i} \f$ is computed virtually by INTERP_KERNEL::Edge::getAreaOfZone with following formula :
163 * AreaOfZone_{i}=\int_{Edge_{i}} -ydx
166 double ComposedEdge::getArea() const
169 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
170 ret+=(*iter)->getAreaOfZone();
174 double ComposedEdge::getPerimeter() const
177 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
178 ret+=(*iter)->getCurveLength();
182 double ComposedEdge::getHydraulicDiameter() const
184 return 4*fabs(getArea())/getPerimeter();
188 * This method computes barycenter of 'this' by returning xG in bary[0] and yG in bary[1].
191 * Area \cdot x_{G}=\int_{Polygon} x \cdot dS
194 * Area \cdot y_{G}=\int_{Polygon} y \cdot dS
196 * Thanks to Green's theorem we have.
198 * \int_{Polygon} x \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}yxdx
201 * \int_{Polygon} y \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}\frac{y^{2}}{2}dx
203 * Area is computed using the same principle than described in INTERP_KERNEL::ComposedEdge::getArea method.
204 * \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.
206 void ComposedEdge::getBarycenter(double *bary) const
211 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
213 (*iter)->getBarycenterOfZone(bary);
214 area+=(*iter)->getAreaOfZone();
221 * Idem ComposedEdge::getBarycenter except that the special case where _sub_edges==1 is dealt here.
223 void ComposedEdge::getBarycenterGeneral(double *bary) const
225 if(_sub_edges.empty())
226 throw INTERP_KERNEL::Exception("ComposedEdge::getBarycenterGeneral called on an empty polygon !");
227 if(_sub_edges.size()>2)
228 return getBarycenter(bary);
230 _sub_edges.back()->getBarycenter(bary,w);
233 double ComposedEdge::normalize(ComposedEdge *other, double& xBary, double& yBary)
236 b.prepareForAggregation();
238 other->fillBounds(b);
239 double dimChar=b.getCaracteristicDim();
240 b.getBarycenter(xBary,yBary);
241 applyGlobalSimilarity(xBary,yBary,dimChar);
242 other->applyGlobalSimilarity(xBary,yBary,dimChar);
247 * This method operates the opposite operation than ComposedEdge::applyGlobalSimilarity.
249 void ComposedEdge::unApplyGlobalSimilarityExt(ComposedEdge& other, double xBary, double yBary, double fact)
251 std::set<Node *> allNodes;
252 getAllNodes(allNodes);
253 other.getAllNodes(allNodes);
254 for(std::set<Node *>::iterator iter=allNodes.begin();iter!=allNodes.end();iter++)
255 (*iter)->unApplySimilarity(xBary,yBary,fact);
256 for(std::list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
257 (*iter)->unApplySimilarity(xBary,yBary,fact);
260 double ComposedEdge::normalizeExt(ComposedEdge *other, double& xBary, double& yBary)
263 b.prepareForAggregation();
265 other->fillBounds(b);
266 double dimChar=b.getCaracteristicDim();
267 b.getBarycenter(xBary,yBary);
268 applyGlobalSimilarity2(other,xBary,yBary,dimChar);
272 void ComposedEdge::dumpInXfigFile(std::ostream& stream, int resolution, const Bounds& box) const
274 stream.precision(10);
275 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
276 (*iter)->dumpInXfigFile(stream,resolution,box);
279 Node *ComposedEdge::getEndNode() const
281 return _sub_edges.back()->getEndNode();
284 Node *ComposedEdge::getStartNode() const
286 return _sub_edges.front()->getStartNode();
289 bool ComposedEdge::changeEndNodeWith(Node *node) const
291 return _sub_edges.back()->changeEndNodeWith(node);
294 bool ComposedEdge::changeStartNodeWith(Node *node) const
296 return _sub_edges.front()->changeStartNodeWith(node);
299 void ComposedEdge::fillBounds(Bounds& output) const
301 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
302 (*iter)->fillBounds(output);
306 * \b WARNING : applies similarity \b ONLY on edges without any change on Nodes. To perform a global similarity call applyGlobalSimilarity.
308 void ComposedEdge::applySimilarity(double xBary, double yBary, double dimChar)
310 for(std::list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
311 (*iter)->applySimilarity(xBary,yBary,dimChar);
315 * Perform Similarity transformation on all elements of this Nodes and Edges.
317 void ComposedEdge::applyGlobalSimilarity(double xBary, double yBary, double dimChar)
319 std::set<Node *> allNodes;
320 getAllNodes(allNodes);
321 for(std::set<Node *>::iterator iter=allNodes.begin();iter!=allNodes.end();iter++)
322 (*iter)->applySimilarity(xBary,yBary,dimChar);
323 for(std::list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
324 (*iter)->applySimilarity(xBary,yBary,dimChar);
328 * Perform Similarity transformation on all elements of this Nodes and Edges on 'this' and 'other'.
329 * Nodes can be shared between 'this' and 'other'.
331 void ComposedEdge::applyGlobalSimilarity2(ComposedEdge *other, double xBary, double yBary, double dimChar)
333 std::set<Node *> allNodes;
334 getAllNodes(allNodes);
335 std::set<Node *> allNodes2;
336 other->getAllNodes(allNodes2);
337 for(std::set<Node *>::const_iterator it=allNodes2.begin();it!=allNodes2.end();it++)
338 if(allNodes.find(*it)!=allNodes.end())
340 allNodes.insert(allNodes2.begin(),allNodes2.end());
341 for(std::set<Node *>::iterator iter=allNodes.begin();iter!=allNodes.end();iter++)
342 (*iter)->applySimilarity(xBary,yBary,dimChar);
343 for(std::list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
344 (*iter)->applySimilarity(xBary,yBary,dimChar);
345 for(std::list<ElementaryEdge *>::iterator iter=other->_sub_edges.begin();iter!=other->_sub_edges.end();iter++)
346 (*iter)->applySimilarity(xBary,yBary,dimChar);
350 * This method append to param 'partConsidered' the part of length of subedges IN or ON.
351 * @param partConsidered INOUT param.
353 void ComposedEdge::dispatchPerimeter(double& partConsidered) const
355 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
357 TypeOfEdgeLocInPolygon loc=(*iter)->getLoc();
358 if(loc==FULL_IN_1 || loc==FULL_ON_1)
359 partConsidered+=(*iter)->getCurveLength();
364 * Idem dispatchPerimeterExcl except that when a subedge is declared as ON this subedge is counted in commonPart.
366 void ComposedEdge::dispatchPerimeterExcl(double& partConsidered, double& commonPart) const
368 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
370 TypeOfEdgeLocInPolygon loc=(*iter)->getLoc();
372 partConsidered+=(*iter)->getCurveLength();
374 commonPart+=(*iter)->getCurveLength();
378 void ComposedEdge::getAllNodes(std::set<Node *>& output) const
380 std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();
381 for(;iter!=_sub_edges.end();iter++)
382 (*iter)->getAllNodes(output);
385 void ComposedEdge::getBarycenter(double *bary, double& weigh) const
387 weigh=0.; bary[0]=0.; bary[1]=0.;
389 for(std::list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
391 (*iter)->getBarycenter(tmp2,tmp1);
393 bary[0]+=tmp1*tmp2[0];
394 bary[1]+=tmp1*tmp2[1];
400 bool ComposedEdge::isInOrOut(Node *nodeToTest) const
402 Bounds b; b.prepareForAggregation();
404 if(b.nearlyWhere((*nodeToTest)[0],(*nodeToTest)[1])==OUT)
407 std::set<Node *> nodes;
409 std::set<double> radialDistributionOfNodes;
410 std::set<Node *>::const_iterator iter;
411 for(iter=nodes.begin();iter!=nodes.end();iter++)
412 radialDistributionOfNodes.insert(nodeToTest->getSlope(*(*iter)));
413 std::vector<double> radialDistrib(radialDistributionOfNodes.begin(),radialDistributionOfNodes.end());
414 radialDistributionOfNodes.clear();
415 std::vector<double> radialDistrib2(radialDistrib.size());
416 copy(radialDistrib.begin()+1,radialDistrib.end(),radialDistrib2.begin());
417 radialDistrib2.back()=M_PI+radialDistrib.front();
418 std::vector<double> radialDistrib3(radialDistrib.size());
419 std::transform(radialDistrib2.begin(),radialDistrib2.end(),radialDistrib.begin(),radialDistrib3.begin(),std::minus<double>());
420 std::vector<double>::iterator iter3=max_element(radialDistrib3.begin(),radialDistrib3.end());
421 int i=iter3-radialDistrib3.begin();
422 // ok for e1 - Let's go.
423 EdgeInfLin *e1=new EdgeInfLin(nodeToTest,radialDistrib[i]+radialDistrib3[i]/2.);
424 double ref=e1->getCharactValue(*nodeToTest);
425 std::set< IntersectElement > inOutSwitch;
426 for(std::list<ElementaryEdge *>::const_iterator iter4=_sub_edges.begin();iter4!=_sub_edges.end();iter4++)
428 ElementaryEdge *val=(*iter4);
431 Edge *e=val->getPtr();
432 std::auto_ptr<EdgeIntersector> intersc(Edge::BuildIntersectorWith(e1,e));
433 bool obviousNoIntersection,areOverlapped;
434 intersc->areOverlappedOrOnlyColinears(0,obviousNoIntersection,areOverlapped);
435 if(obviousNoIntersection)
441 std::list< IntersectElement > listOfIntesc=intersc->getIntersectionsCharacteristicVal();
442 for(std::list< IntersectElement >::iterator iter2=listOfIntesc.begin();iter2!=listOfIntesc.end();iter2++)
443 if((*iter2).isIncludedByBoth())
444 inOutSwitch.insert(*iter2);
446 //if overlapped we can forget
449 throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
453 for(std::set< IntersectElement >::iterator iter4=inOutSwitch.begin();iter4!=inOutSwitch.end();iter4++)
455 if((*iter4).getVal1()<ref)
457 if((*iter4).getNodeOnly()->getLoc()==ON_1)
466 /*bool ComposedEdge::isInOrOut(Node *aNodeOn, Node *nodeToTest) const
469 EdgeInfLin *e1=new EdgeInfLin(aNodeOn,nodeToTest);
470 double ref=e1->getCharactValue(*nodeToTest);
471 set< IntersectElement > inOutSwitch;
472 for(vector<AbstractEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
474 ElementaryEdge *val=dynamic_cast<ElementaryEdge *>(*iter);
477 Edge *e=val->getPtr();
478 auto_ptr<Intersector> intersc(Edge::buildIntersectorWith(e1,e));
479 bool obviousNoIntersection,areOverlapped;
480 intersc->areOverlappedOrOnlyColinears(0,obviousNoIntersection,areOverlapped);
481 if(obviousNoIntersection)
487 list< IntersectElement > listOfIntesc=intersc->getIntersectionsCharacteristicVal();
488 for(list< IntersectElement >::iterator iter2=listOfIntesc.begin();iter2!=listOfIntesc.end();iter2++)
489 if((*iter2).isIncludedByBoth())
490 inOutSwitch.insert(*iter2);
492 //if overlapped we can forget
495 throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
499 for(set< IntersectElement >::iterator iter=inOutSwitch.begin();iter!=inOutSwitch.end();iter++)
501 if((*iter).getVal1()<ref)
503 if((*iter).getNodeOnly()->getLoc()==ON_1)
512 bool ComposedEdge::getDirection() const
514 throw Exception("ComposedEdge::getDirection : no sense");
517 bool ComposedEdge::intresincEqCoarse(const Edge *other) const
519 if(_sub_edges.size()!=1)
521 return _sub_edges.front()->intresincEqCoarse(other);
524 void ComposedEdge::clearAll(std::list<ElementaryEdge *>::iterator startToDel)
526 for(std::list<ElementaryEdge *>::iterator iter=startToDel;iter!=_sub_edges.end();iter++)