]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/INTERP_KERNEL/Geometric2D/ComposedEdge.cxx
Salome HOME
Merge from BR_V5_DEV 16Feb09
[tools/medcoupling.git] / src / INTERP_KERNEL / Geometric2D / ComposedEdge.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "ComposedEdge.hxx"
20 #include "ElementaryEdge.hxx"
21 #include "EdgeInfLin.hxx"
22 #include "InterpKernelException.hxx"
23
24 #include <algorithm>
25 #include <iterator>
26 #include <set>
27
28 using namespace std;
29 using namespace INTERP_KERNEL;
30
31 ComposedEdge::ComposedEdge(const ComposedEdge& other)
32 {
33   for(list<ElementaryEdge *>::const_iterator iter=other._sub_edges.begin();iter!=other._sub_edges.end();iter++)
34     _sub_edges.push_back((*iter)->clone());
35 }
36
37 ComposedEdge::~ComposedEdge()
38 {
39   clearAll(_sub_edges.begin());
40 }
41
42 void ComposedEdge::setValueAt(int i, Edge *e, bool direction)
43 {
44   list<ElementaryEdge*>::iterator it=_sub_edges.begin();
45   for(int j=0;j<i;j++)
46     it++;
47   delete *it;
48   *it=new ElementaryEdge(e,direction);
49 }
50
51 struct AbsEdgeCmp
52 {
53   AbsEdgeCmp(ElementaryEdge *b):_b1(b) { }
54   bool operator()(ElementaryEdge *a) { return a->getPtr()==_b1->getPtr();}
55
56   ElementaryEdge *_b1;
57 };
58
59 double ComposedEdge::getCommonLengthWith(const ComposedEdge& other) const
60 {
61   double ret=0.;
62   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
63     {
64       if(find_if(other._sub_edges.begin(),other._sub_edges.end(),AbsEdgeCmp(*iter))!=other._sub_edges.end())
65         {
66           const ElementaryEdge *tmp=static_cast<const ElementaryEdge *>(*iter);
67           ret+=tmp->getCurveLength();
68         }
69     }
70   return ret;
71 }
72
73 void ComposedEdge::clear()
74 {
75   clearAll(_sub_edges.begin());
76   _sub_edges.clear();
77 }
78
79 void ComposedEdge::pushBack(Edge *edge, bool direction)
80 {
81   _sub_edges.push_back(new ElementaryEdge(edge,direction));
82 }
83
84 void ComposedEdge::pushBack(ElementaryEdge *elem)
85 {
86   _sub_edges.push_back(elem);
87 }
88
89 void ComposedEdge::pushBack(ComposedEdge *elem)
90 {
91   list<ElementaryEdge *> *elemsOfElem=elem->getListBehind();
92   _sub_edges.insert(_sub_edges.end(),elemsOfElem->begin(),elemsOfElem->end());
93 }
94
95 ElementaryEdge *ComposedEdge::operator[](int i) const
96 {
97   list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();
98   for(int ii=0;ii<i;ii++)
99     iter++;
100   return *iter;
101 }
102
103 void ComposedEdge::reverse()
104 {
105   _sub_edges.reverse();
106   for(list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
107     (*iter)->reverse();
108 }
109
110 void ComposedEdge::initLocations() const
111 {
112   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
113     (*iter)->initLocations();
114 }
115
116 ComposedEdge *ComposedEdge::clone() const
117 {
118   return new ComposedEdge(*this);
119 }
120
121 bool ComposedEdge::isNodeIn(Node *n) const
122 {
123   bool ret=false;
124   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end() && !ret;iter++)
125     ret=(*iter)->isNodeIn(n);
126   return ret;
127 }
128
129 /*!
130  * This method computes the area of 'this'.
131  * By definition :
132  * \f[
133  * Area=\int_{Polygon} dS
134  * \f]
135  * Thanks to Green's theorem we have.
136  * \f[
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}}
138  * \f]
139  * Where \f$ AreaOfZone_{i} \f$ is computed virtually by INTERP_KERNEL::Edge::getAreaOfZone with following formula :
140  * \f[
141  * AreaOfZone_{i}=\int_{Edge_{i}} -ydx
142  * \f]
143  */
144 double ComposedEdge::getArea() const
145 {
146   double ret=0.;
147   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
148     ret+=(*iter)->getAreaOfZone();
149   return ret;
150 }
151
152 double ComposedEdge::getPerimeter() const
153 {
154   double ret=0.;
155   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
156     ret+=(*iter)->getCurveLength();
157   return ret;
158 }
159
160 double ComposedEdge::getHydraulicDiameter() const
161 {
162   return 4*fabs(getArea())/getPerimeter();
163 }
164
165 /*!
166  * This method computes barycenter of 'this' by returning xG in bary[0] and yG in bary[1].
167  * By definition :
168  * \f[
169  * Area \cdot x_{G}=\int_{Polygon} x \cdot dS
170  * \f]
171  * \f[
172  * Area \cdot y_{G}=\int_{Polygon} y \cdot dS
173  * \f]
174  * Thanks to Green's theorem we have.
175  * \f[
176  * \int_{Polygon} x \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}yxdx
177  * \f]
178  * \f[
179  * \int_{Polygon} y \cdot dS=\sum_{0 \leq i < nb of edges} -\int_{Edge_{i}}\frac{y^{2}}{2}dx
180  * \f]
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.
183  */
184 void ComposedEdge::getBarycenter(double *bary) const
185 {
186   bary[0]=0.;
187   bary[1]=0.;
188   double area=0.;
189   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
190     {
191       (*iter)->getBarycenterOfZone(bary);
192       area+=(*iter)->getAreaOfZone();
193     }
194   bary[0]/=area;
195   bary[1]/=area;
196 }
197
198 double ComposedEdge::normalize(ComposedEdge *other)
199 {
200   Bounds b;
201   b.prepareForAggregation();
202   fillBounds(b); 
203   other->fillBounds(b);
204   double dimChar=b.getCaracteristicDim();
205   double xBary,yBary;
206   b.getBarycenter(xBary,yBary);
207   applyGlobalSimilarity(xBary,yBary,dimChar);
208   other->applyGlobalSimilarity(xBary,yBary,dimChar);
209   return dimChar;
210 }
211
212 void ComposedEdge::dumpInXfigFile(std::ostream& stream, int resolution, const Bounds& box) const
213 {
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);
217 }
218
219 Node *ComposedEdge::getEndNode() const
220 {
221   return _sub_edges.back()->getEndNode();
222 }
223
224 Node *ComposedEdge::getStartNode() const
225 {
226   return _sub_edges.front()->getStartNode();
227 }
228
229 bool ComposedEdge::changeEndNodeWith(Node *node) const
230 {
231   return _sub_edges.back()->changeEndNodeWith(node);
232 }
233
234 bool ComposedEdge::changeStartNodeWith(Node *node) const
235 {
236   return _sub_edges.front()->changeStartNodeWith(node);
237 }
238
239 void ComposedEdge::fillBounds(Bounds& output) const
240 {
241   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
242     (*iter)->fillBounds(output);
243 }
244
245 /*!
246  * \b WARNING : applies similarity \b ONLY on edges without any change on Nodes. To perform a global similarity call applyGlobalSimilarity.
247  */
248 void ComposedEdge::applySimilarity(double xBary, double yBary, double dimChar)
249 {
250   for(list<ElementaryEdge *>::iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
251     (*iter)->applySimilarity(xBary,yBary,dimChar);
252 }
253
254 /*!
255  * Perform Similarity transformation on all elements of this Nodes and Edges.
256  */
257 void ComposedEdge::applyGlobalSimilarity(double xBary, double yBary, double dimChar)
258 {
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);
265 }
266
267 /*!
268  * This method append to param 'partConsidered' the part of length of subedges IN or ON.
269  * @param partConsidered INOUT param.
270  */
271 void ComposedEdge::dispatchPerimeter(double& partConsidered) const
272 {
273   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
274     {
275       TypeOfEdgeLocInPolygon loc=(*iter)->getLoc();
276       if(loc==FULL_IN_1 || loc==FULL_ON_1)
277         partConsidered+=(*iter)->getCurveLength();
278     }
279 }
280
281 /*!
282  * Idem dispatchPerimeterExcl except that when a subedge is declared as ON this subedge is counted in commonPart.
283  */
284 void ComposedEdge::dispatchPerimeterExcl(double& partConsidered, double& commonPart) const
285 {
286   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
287     {
288       TypeOfEdgeLocInPolygon loc=(*iter)->getLoc();
289       if(loc==FULL_IN_1)
290         partConsidered+=(*iter)->getCurveLength();
291       if(loc==FULL_ON_1)
292         commonPart+=(*iter)->getCurveLength();
293     }
294 }
295
296 void ComposedEdge::getAllNodes(std::set<Node *>& output) const
297 {
298   list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();
299   for(;iter!=_sub_edges.end();iter++)
300     (*iter)->getAllNodes(output);
301 }
302
303 void ComposedEdge::getBarycenter(double *bary, double& weigh) const
304 {
305   weigh=0.; bary[0]=0.; bary[1]=0.;
306   double tmp1,tmp2[2];
307   for(list<ElementaryEdge *>::const_iterator iter=_sub_edges.begin();iter!=_sub_edges.end();iter++)
308     {
309       (*iter)->getBarycenter(tmp2,tmp1);
310       weigh+=tmp1;
311       bary[0]+=tmp1*tmp2[0];
312       bary[1]+=tmp1*tmp2[1];
313     }
314   bary[0]/=weigh;
315   bary[1]/=weigh;
316 }
317
318 bool ComposedEdge::isInOrOut(Node *nodeToTest) const
319 {
320   Bounds b; b.prepareForAggregation();
321   fillBounds(b);
322   if(b.nearlyWhere((*nodeToTest)[0],(*nodeToTest)[1])==OUT)
323     return false;
324   // searching for e1
325   set<Node *> nodes;
326   getAllNodes(nodes);
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++)
345     {
346       ElementaryEdge *val=(*iter);
347       if(val)
348         {
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)
354             {
355               continue;
356             }
357           if(!areOverlapped)
358             {
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);
363               }
364           //if overlapped we can forget
365         }
366       else
367         throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
368     }
369   e1->decrRef();
370   bool ret=false;
371   for(set< IntersectElement >::iterator iter=inOutSwitch.begin();iter!=inOutSwitch.end();iter++)
372     {
373       if((*iter).getVal1()<ref)
374         {
375           if((*iter).getNodeOnly()->getLoc()==ON_1)
376             ret=!ret;
377         }
378       else
379         break;
380     }
381   return ret;
382 }
383
384 /*bool ComposedEdge::isInOrOut(Node *aNodeOn, Node *nodeToTest) const
385 {
386   
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++)
391     {
392       ElementaryEdge *val=dynamic_cast<ElementaryEdge *>(*iter);
393       if(val)
394         {
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)
400             {
401               continue;
402             }
403           if(!areOverlapped)
404             {
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);
409               }
410           //if overlapped we can forget
411         }
412       else
413         throw Exception("Invalid use of ComposedEdge::isInOrOut : only one level supported !");
414     }
415   e1->decrRef();
416   bool ret=false;
417   for(set< IntersectElement >::iterator iter=inOutSwitch.begin();iter!=inOutSwitch.end();iter++)
418     {
419       if((*iter).getVal1()<ref)
420         {
421           if((*iter).getNodeOnly()->getLoc()==ON_1)
422             ret=!ret;
423         }
424       else
425         break;
426     }
427   return ret;
428 }*/
429
430 bool ComposedEdge::getDirection() const
431 {
432   throw Exception("ComposedEdge::getDirection : no sense");
433 }
434
435 bool ComposedEdge::intresincEqCoarse(const Edge *other) const
436 {
437   if(_sub_edges.size()!=1)
438     return false;
439   return _sub_edges.front()->intresincEqCoarse(other);
440 }
441
442 void ComposedEdge::clearAll(list<ElementaryEdge *>::iterator startToDel)
443 {
444   for(list<ElementaryEdge *>::iterator iter=startToDel;iter!=_sub_edges.end();iter++)
445     delete (*iter);
446 }