ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/REPOS_ERICCA/magic/lib/CAD4FE/src/CAD4FE_MCSegment.cpp
Revision: 569
Committed: Thu Oct 16 14:36:31 2014 UTC (10 years, 6 months ago) by foucault
File size: 38526 byte(s)
Log Message:
Mise à jour pour CAD4FE (Gilles) : operation 1 (tentative)

File Contents

# User Rev Content
1 foucault 27 //---------------------------------------------------------------------------
2    
3     #include <fstream>
4    
5     #pragma hdrstop
6    
7     #include "gestionversion.h"
8     #include "CAD4FE_MCSegment.h"
9     #include "CAD4FE_MCFace.h"
10     #include "CAD4FE_MCEdge.h"
11    
12     #include "ot_algorithme_geometrique.h"
13     #include "ot_decalage_parametre.h"
14     #include "CAD4FE_MCNode.h"
15     #include "CAD4FE_PolySurface.h"
16     #include "CAD4FE_PolyCurve.h"
17     #include "CAD4FE_MCVertex.h"
18     #include "CAD4FE_MCEdge.h"
19     #include "CAD4FE_Intersection_Plane_PolySurface.h"
20     #include "CAD4FE_ShortestPathByClosestPointOnEdge.h"
21     #include "CAD4FE_MCNodePolyline.h"
22 foucault 569 #include "CAD4FE_Geometric_Tools.h"
23 foucault 27 #include "CAD4FE_InventorText_MG_MAILLAGE.h"
24     #include "ot_root_find.h"
25     #include "CAD4FE_mailleur2d.h"
26    
27     //---------------------------------------------------------------------------
28    
29     #pragma package(smart_init)
30    
31     using namespace CAD4FE;
32    
33     //---------------------------------------------------------------------------
34     MCSegment::MCSegment (unsigned long num, MG_ELEMENT_TOPOLOGIQUE *topo, MCNode *mgnoeud1, MCNode *mgnoeud2, double longue)
35     : MG_SEGMENT(num,topo,mgnoeud1,mgnoeud2,longue),_polylineEvaluator(0),_sense(1), _saveFormat(0)
36     {
37     _cstrMCFaceScheme = CstrMCFaceByPlaneIntr;
38     ConstructGeometry();
39     }
40     //---------------------------------------------------------------------------
41     MCSegment::MCSegment (MG_ELEMENT_TOPOLOGIQUE *topo, MCNode *mgnoeud1, MCNode *mgnoeud2, double longue, long __cstrMCFaceScheme)
42     : MG_SEGMENT(topo,mgnoeud1,mgnoeud2,longue),_polylineEvaluator(0),_sense(1),_cstrMCFaceScheme(__cstrMCFaceScheme), _saveFormat(0)
43     {
44     ConstructGeometry();
45     }
46     //---------------------------------------------------------------------------
47     MCSegment::MCSegment( MCSegment & __s)
48     : MG_SEGMENT(0,__s.liaison_topologique,__s.get_noeud1(),__s.get_noeud2(),__s.get_longueur()), _saveFormat(0)
49     {
50     unsigned i;
51     for (FMapCIterator itF = __s.F.begin(); itF != __s.F.end(); itF++)
52     {
53     MG_FACE * face = itF->first;
54     F.insert(std::make_pair(face,itF->second));
55     }
56     for (EMapCIterator itE = __s.E.begin(); itE != __s.E.end(); itE++)
57     {
58     MG_ARETE * edge = itE->first;
59     E.insert(std::make_pair(edge,itE->second));
60     }
61     //V = __s.V;
62     _polylineEvaluator=new MCNodePolyline(*__s._polylineEvaluator);
63     _sense = __s._sense;
64     }
65     //---------------------------------------------------------------------------
66     MCSegment::FMap & MCSegment::GetRefFaceMapping()
67     {
68     return F;
69     }
70     //---------------------------------------------------------------------------
71     MCSegment::EMap & MCSegment::GetRefEdgeMapping()
72     {
73     return E;
74     }
75     //---------------------------------------------------------------------------
76     MCSegment::~MCSegment()
77     {
78     unsigned i,j;
79     if (_polylineEvaluator) delete _polylineEvaluator;
80     }
81     //---------------------------------------------------------------------------
82     std::vector <MCNode*> MCSegment::GetPolylineNodes()
83     {
84     return _polylineEvaluator->GetPolylineNodes();
85     }
86     //---------------------------------------------------------------------------
87     MCNode* MCSegment::GetPolylineNode(unsigned __index)
88     {
89     return _polylineEvaluator->GetPolylineNode(__index);
90     }
91     //---------------------------------------------------------------------------
92     std::vector <MG_ELEMENT_TOPOLOGIQUE*> MCSegment::GetPolylineTopos()
93     {
94     return _polylineEvaluator->GetPolylineTopos();
95     }
96     //---------------------------------------------------------------------------
97     MG_ELEMENT_TOPOLOGIQUE* MCSegment::GetPolylineTopo(unsigned __index)
98     {
99     return _polylineEvaluator->GetPolylineTopo(__index);
100     }
101     //---------------------------------------------------------------------------
102     unsigned MCSegment::GetPolylineNodeCount()
103     {
104     return _polylineEvaluator->GetPolylineNodes().size();
105     }
106     //---------------------------------------------------------------------------
107     double MCSegment::get_longueur_geo()
108     {
109     double length = _polylineEvaluator->GetLength();
110     return length;
111     }
112     //---------------------------------------------------------------------------
113     void MCSegment::evaluer_geo(double __t, MCNode * __result, double * tangent, double * curvature)
114     {
115     double t,L;
116     if (_sense == -1)
117     t = (1-__t);
118     else
119     t = __t;
120    
121     L=get_longueur_geo();
122     * __result = _polylineEvaluator->Evaluate( t * L, tangent, curvature );
123     if (tangent)
124     for (int i=0; i<3; i++) tangent[i] *= L;
125     if (_sense == -1)
126     {
127     if (tangent)
128     for (int i=0; i<3; i++) tangent[i]*=-1;
129     }
130     }
131     //---------------------------------------------------------------------------
132     void MCSegment::inverser_geo(double & __t, MCNode * __node)
133     {
134     _polylineEvaluator->Inverse(__t, __node);
135     double length = _polylineEvaluator->GetLength();
136     __t = __t/length;
137    
138     if (_sense == -1)
139     __t = (1-__t);
140     }
141     //---------------------------------------------------------------------------
142     int MCSegment::get_orientation()
143     {
144     return _sense;
145     }
146     //---------------------------------------------------------------------------
147     void MCSegment::change_orientation(int __sense)
148     {
149     _sense = __sense;
150     }
151     //---------------------------------------------------------------------------
152     void MCSegment::UpdateGeometry ()
153     {
154     calcule_longueur();
155     F.clear();
156     E.clear();
157     //V.clear();
158     delete _polylineEvaluator;
159     _polylineEvaluator = 0;
160     ConstructGeometry ();
161     }
162     //---------------------------------------------------------------------------
163     void MCSegment::ConstructGeometry ()
164     {
165     MCNode * mcNode1 = (MCNode*)get_noeud1();
166     MCNode * mcNode2 = (MCNode*)get_noeud2();
167     CAD4FE::MCFace * mcFace = NULL;
168     CAD4FE::MCEdge * mcEdge = NULL;
169     if (get_lien_topologie()->get_dimension() == 2)
170     {
171     mcFace = (MCFace*)get_lien_topologie();
172     }
173     if (get_lien_topologie()->get_dimension() == 1)
174     {
175     mcEdge = ((CAD4FE::MCEdge*)get_lien_topologie());
176     }
177     if (mcEdge)
178     {
179     Construct_MCEdge(mcEdge);
180     Construct_MergedVertices(mcNode1);
181     Construct_MergedVertices(mcNode2);
182     }
183     else if (mcFace)
184     {
185     int res;
186     if (_cstrMCFaceScheme == CstrMCFaceByPlaneIntr )
187     {
188     res = Construct_MCFace(mcFace,mcNode1,mcNode2);
189     if (res != 1 )
190     {
191     res = Construct_MCFaceByShortestPath(mcFace,mcNode1,mcNode2);
192     if (res == 1) _cstrMCFaceScheme = CstrMCFaceByShortestPath;
193     }
194     }
195     else if (_cstrMCFaceScheme == CstrMCFaceByPlaneIntrNormalByShortestPath)
196     {
197     res = Construct_MCFace(mcFace,mcNode1,mcNode2);
198     if (res != 1)
199     {
200     res = Construct_MCFaceByShortestPath(mcFace,mcNode1,mcNode2);
201     if (res == 1)
202     _cstrMCFaceScheme = CstrMCFaceByShortestPath;
203     }
204     }
205     else if (_cstrMCFaceScheme == CstrMCFaceByShortestPath )
206     {
207     res = Construct_MCFaceByShortestPath(mcFace,mcNode1,mcNode2);
208     if (res != 1)
209     {
210     res = Construct_MCFace(mcFace,mcNode1,mcNode2);
211     if (res == 1)
212     _cstrMCFaceScheme = CstrMCFaceByPlaneIntr;
213     }
214     }
215     else if (_cstrMCFaceScheme == CstrNoRefTopologyMapping)
216     {
217     res = Construct_NoTopology(mcNode1,mcNode2);
218     }
219     }
220    
221     _sense = 1;
222     ConstructBoundaryBox();
223     }
224    
225     void MCSegment::ConstructBoundaryBox()
226     {
227     for (unsigned j=0; j<_polylineEvaluator->GetPolylineNodes().size();j++)
228     {
229     MCNode * n = _polylineEvaluator->GetPolylineNode(j);
230     double * x = n->get_coord();
231     if (j == 0)
232     {
233     for (int i=0;i<3;i++)
234     _bbox[i] = _bbox[i+3] = x[i];
235     }
236     else
237     {
238     for (int i=0;i<3;i++)
239     {
240     if (_bbox[i]>x[i])
241     _bbox[i] = x[i];
242     else if (_bbox[i+3]<x[i])
243     _bbox[i+3] = x[i];
244     }
245     }
246     }
247     for (double t=.25; t<=.75; t+=.25)
248     {
249     MCNode n = _polylineEvaluator->Evaluate(t);
250     double * x = n.get_coord();
251    
252     for (int i=0;i<3;i++)
253     {
254     if (_bbox[i]>x[i])
255     _bbox[i] = x[i];
256     else if (_bbox[i+3]<x[i])
257     _bbox[i+3] = x[i];
258     }
259     }
260     }
261    
262     extern MG_MAILLAGE * debugMesh;
263    
264     int MCSegment::Construct_MCFaceByShortestPath(MCFace * __mcFace, MCNode* __n1, MCNode* __n2)
265     {
266     unsigned i,j;
267     double dN1N2=OT_ALGORITHME_GEOMETRIQUE::VEC3_DISTANCE_VEC3(__n1->get_coord(),__n2->get_coord());
268     int shortestPathOptions = 0;
269     ShortestPathByClosestPointOnEdge shortestPath(__mcFace,__n1,__n2,dN1N2, shortestPathOptions);
270     ShortestPathByClosestPointOnEdge *shortestPathDoubleDist = NULL;
271     std::vector<MCNode*> vecPts;
272     std::vector<MG_ELEMENT_TOPOLOGIQUE*> vecTopo;
273     double distance = shortestPath.Find(&vecPts,&vecTopo);
274    
275     if (distance > 100) // failure, second try with 2*dist(n1,n2)
276     {
277     unsigned maxNbTries = 4;
278     unsigned maxDistFactor = 1;
279     for (i=0; i<maxNbTries; i++)
280     {
281     maxDistFactor *= 2;
282     vecPts.clear();vecTopo.clear();
283     shortestPathDoubleDist = new ShortestPathByClosestPointOnEdge (__mcFace,__n1,__n2,maxDistFactor*dN1N2, shortestPathOptions);
284     distance = shortestPathDoubleDist->Find(&vecPts,&vecTopo);
285     if (distance > 100)
286     {
287     delete shortestPathDoubleDist;
288     vecPts.clear();vecTopo.clear();
289     shortestPathOptions=ShortestPathByClosestPointOnEdge::NoCheckFaceIntr;
290     shortestPathDoubleDist = new ShortestPathByClosestPointOnEdge (__mcFace,__n1,__n2,maxDistFactor*dN1N2, shortestPathOptions);
291     distance = shortestPathDoubleDist->Find(&vecPts,&vecTopo);
292     if (distance > 100)
293     {
294     delete shortestPathDoubleDist;
295     shortestPathDoubleDist = NULL;
296     }
297     }
298     else
299     {
300     break;
301     }
302     }
303     }
304    
305     if (distance > 100)
306     {
307     printf("Warning : Construct_MCFaceByShortestPath failed !\n");
308     distance = shortestPath.Find(&vecPts,&vecTopo);
309     Construct_MCFace(__mcFace,__n1,__n2);
310     return 0;
311     }
312     if (distance < .8*dN1N2)
313     {
314     printf("Warning : %d < .8*%f in Construct_MCFaceByShortestPath !\n", distance, dN1N2);
315     }
316    
317     if (_polylineEvaluator == NULL) _polylineEvaluator = new MCNodePolyline(liaison_topologique);
318    
319     for (i=0;i+1<vecPts.size();i++)
320     {
321     MCNode * xi=vecPts[i], *xii=vecPts[i+1];
322     MG_ELEMENT_TOPOLOGIQUE * topo = vecTopo[i];
323    
324     if (topo->get_dimension() == 2)
325     {
326     MG_FACE * face = (MG_FACE *) topo;
327     std::vector<MCNode*> Ci;
328     OT_VECTEUR_3D normalXi,normalXii,normalAvg,dir,v,xi_xyz(xi->get_coord()),xii_xyz(xii->get_coord());
329     xi->NormalMCFace(__mcFace, normalXi);
330     xii->NormalMCFace(__mcFace, normalXii);
331     normalAvg = .5*normalXi+.5*normalXii;
332     dir=xii_xyz-xi_xyz;
333     v=normalAvg&dir;
334     double L=dir.get_longueur();
335     Intersection_Plane_MG_FACE * intr = NULL;
336     if (L > 1E-6 && ((shortestPathOptions&ShortestPathByClosestPointOnEdge::NoCheckFaceIntr)==0))
337     {
338     intr = new Intersection_Plane_MG_FACE(xi,v,face,__mcFace);
339     intr->MakeSegment(xi,xii,L/50,L/3000,3,dir);
340     Ci = intr->Get()[0];
341     if (Ci.size()<2||Ci[Ci.size()-1]!=xii||Ci[0]!=xi)
342     {
343     delete intr;
344     intr = 0;
345     Ci.clear();
346     Ci.push_back(xi);
347     Ci.push_back(xii);
348     }
349     }
350     else
351     {
352     Ci.push_back(xi);
353     Ci.push_back(xii);
354     }
355     F.insert( std::make_pair(face, Ci) );
356    
357     for (j=0; j<Ci.size(); j++)
358     {
359     _polylineEvaluator->Add(Ci[j],face);
360     }
361     if (intr != NULL)
362     delete intr;
363     }
364     if (topo->get_dimension() == 1)
365     {
366     MG_ARETE * edge = (MG_ARETE *) topo;
367    
368     //double dist = OT_ALGORITHME_GEOMETRIQUE::VEC3_DISTANCE_VEC3(xi->get_coord(), xii->get_coord());
369     //double epsilon = dist*1E-2;
370     //int insertedNodeCount = RefineInRefEdge(__mcFace, edge, xi, xii, epsilon, 1E300, refinedNodes, refinedEdges );
371    
372     VPts Ci;
373     Ci.push_back(xi);
374     Ci.push_back(xii);
375    
376     E.insert (std::make_pair(edge, Ci));
377     for (int itF = 0; itF < edge->get_nb_mg_coarete(); itF++)
378     {
379     MG_FACE * face = edge->get_mg_coarete(itF)->get_boucle()->get_mg_face();
380     F.insert(std::make_pair(face, Ci));
381     }
382    
383     for (j=0; j<Ci.size(); j++)
384     {
385     _polylineEvaluator->Add(Ci[j],edge);
386     }
387     }
388     if (topo->get_dimension() == 0)
389     {
390    
391     }
392     }
393    
394     if (shortestPathDoubleDist != NULL)
395     delete shortestPathDoubleDist;
396    
397     return 1;
398     }
399    
400     int MCSegment::Construct_NoTopology(MCNode * __n1, MCNode * __n2)
401     {
402     _polylineEvaluator = new MCNodePolyline(liaison_topologique);
403     _polylineEvaluator->Add(__n1,NULL);
404     _polylineEvaluator->Add(__n2,NULL);
405     return 1;
406     }
407    
408     int MCSegment::Construct_MCFace(MCFace * __mcFace, MCNode* __n1, MCNode* __n2)
409     {
410     unsigned i,j;
411     PolySurface * polysurface = __mcFace->GetPolySurface();
412    
413     OT_VECTEUR_3D normal1, normal2, xyz1, xyz2, v1, v2;
414     if ( _cstrMCFaceScheme != CstrMCFaceByPlaneIntrNormalByShortestPath )
415     {
416     int nbRefFaces;
417     polysurface->calcul_normale_unitaire(__n1->GetRefFaceMapping(),normal1,&nbRefFaces);
418     polysurface->calcul_normale_unitaire(__n2->GetRefFaceMapping(),normal2,&nbRefFaces);
419     v2 = .5*(normal1+normal2);
420     if (v2.get_longueur2() < 1E-100)
421     {
422     printf("Warning: surface's normal at node 1 is opposite to surface's normal at node 2\n");
423     printf("\t trying to evaluate surface's normal with the shortest path algorithm\n");
424     _cstrMCFaceScheme = CstrMCFaceByPlaneIntrNormalByShortestPath;
425     }
426     }
427     if (_cstrMCFaceScheme==CstrMCFaceByPlaneIntrNormalByShortestPath)
428     {
429     double maxDistBetween3DSegmentAndShortestPath=OT_ALGORITHME_GEOMETRIQUE::VEC3_DISTANCE_VEC3(__n1->get_coord(),__n2->get_coord());
430     ShortestPathByClosestPointOnEdge * shortestPath = new ShortestPathByClosestPointOnEdge(__mcFace,__n1,__n2,maxDistBetween3DSegmentAndShortestPath);
431     std::vector<MCNode*> vecPts;
432     std::vector<MG_ELEMENT_TOPOLOGIQUE*> vecTopo;
433     double distance=shortestPath->Find(&vecPts, &vecTopo);
434     if (distance > 100)
435     {
436     // delete shortestPath;
437     // vecPts.clear(); vecTopo.clear();
438     // shortestPath = new ShortestPathByClosestPointOnEdge(__mcFace,__n1,__n2,100);
439     double *x1=__n1->get_coord(),*x2=__n2->get_coord();
440     printf("%f %f %f %f %f %f ",x1[0],x1[1],x1[2],x2[0],x2[1],x2[2]);
441     // double distance = shortestPath->Find(&vecPts, &vecTopo);
442     if (distance > 100)
443     printf("Error in average normal\n");
444    
445     }
446     if (distance == 0.0)
447     {
448     delete shortestPath;
449     return 0;
450     }
451     // estimation of the face normal by the average of the normals
452     // in the polyline
453     OT_VECTEUR_3D avgNormal(0,0,0);
454     MCNodePolyline polyline(liaison_topologique,vecPts,vecTopo);
455     unsigned nb_points=10, real_nb_points=0;
456     double s_max=polyline.GetLength();
457     for (double s=0; real_nb_points < 1 || s < s_max; s+=.9999*(s_max/nb_points))
458     {
459     real_nb_points++;
460     MCNode mcNode=polyline.Evaluate(s);
461     OT_VECTEUR_3D tmpNormal;
462     int nbRefFaces;
463     polysurface->calcul_normale_unitaire(mcNode.GetRefFaceMapping(),tmpNormal,&nbRefFaces);
464     avgNormal += tmpNormal;
465     }
466     avgNormal /= real_nb_points;
467     v2=avgNormal;
468     delete shortestPath;
469     }
470    
471     xyz1=OT_VECTEUR_3D(__n1->get_coord());
472     xyz2=OT_VECTEUR_3D(__n2->get_coord());
473     v1=xyz2-xyz1;
474    
475     // Make a special treatment to manage nodes of merged vertices
476     MCNode * polysurfaceNodes[2]={__n1,__n2};
477     MCNode * n[2]={__n1,__n2};
478     VPts MergedVertexCurveNodes[2];
479     std::vector < MG_ELEMENT_TOPOLOGIQUE * > MergedVertexCurveTopo[2];
480     for (int i=0;i<2;i++)
481     if (n[i]->GetRefVertexMapping().size() > 1) // if node is in a merged vertex
482     {
483     MCVertex * mcVertex = (MCVertex*) n[i]->get_lien_topologie();
484     MG_SOMMET * refVertex = (MG_SOMMET*) n[i]->get_lien_topologie_reference();
485     MG_SOMMET * mergedVertex = NULL;
486     if (GeometricTools::PolySurface_Contains_RefVertex(polysurface,refVertex) == false)
487     {
488     for (MCNode::VMapIterator itV = n[i]->GetRefVertexMapping().begin();
489     itV != n[i]->GetRefVertexMapping().end();
490     itV++)
491     if ( GeometricTools::PolySurface_Contains_RefVertex(polysurface,*itV) )
492     {
493     mergedVertex = *itV;
494     break;
495     }
496    
497     double xyz[3];mergedVertex->get_point()->evaluer(xyz);
498     double d=OT_ALGORITHME_GEOMETRIQUE::VEC3_DISTANCE_VEC3(xyz,n[i]->get_coord());
499     MCNode * mergedVertexNode = new MCNode(mcVertex,mergedVertex,xyz[0],xyz[1],xyz[2]);
500     polysurfaceNodes[i] = mergedVertexNode;
501    
502     MCFace * mcFacePath = NULL;
503     std::set<MG_FACE*> mergedVertexMCFaces;
504     GeometricTools::MG_SOMMET_GetAdjacent_MG_FACE(mcVertex,mergedVertexMCFaces);
505     for (std::set<MG_FACE*>::iterator itF=mergedVertexMCFaces.begin();
506     itF != mergedVertexMCFaces.end(); itF++)
507     {
508     MCFace* adjacentMCFace = (MCFace*)(*itF);
509     if (GeometricTools::PolySurface_Contains_RefVertex(adjacentMCFace->GetPolySurface(),mergedVertex)
510     && GeometricTools::PolySurface_Contains_RefVertex(adjacentMCFace->GetPolySurface(),refVertex)
511     )
512     {
513     mcFacePath = adjacentMCFace;
514     break;
515     }
516     }
517     ShortestPathByClosestPointOnEdge shortestPath(mcFacePath,n[i],mergedVertexNode,d);
518     double distance = shortestPath.Find(&(MergedVertexCurveNodes[i]),&(MergedVertexCurveTopo[i]));
519    
520     if (distance < 100)
521     for (unsigned j=0; j<MergedVertexCurveNodes[i].size();j++)
522     MergedVertexCurveNodes[i][j]->incrementer();
523     }
524     }
525    
526     Intersection_Plane_PolySurface intrPolySurface (polysurfaceNodes[0], v2&v1, __mcFace, polysurfaceNodes[1]);
527     MCNodePolyline * intersectionPlaneMCFace = intrPolySurface.MakeSegment(polysurfaceNodes[0], polysurfaceNodes[1], v1);
528    
529     if (intersectionPlaneMCFace != NULL)
530     {
531     _polylineEvaluator = intersectionPlaneMCFace;
532     _polylineEvaluator->incrementer();
533    
534     Intersection_Plane_PolySurface::FMapIterator it;
535     Intersection_Plane_MG_FACE * intr = NULL;
536     for (intr = intrPolySurface.GetFirstCurve(it); intr; intr = intrPolySurface.GetNextCurve(it) )
537     {
538     MG_FACE * face = intr->GetFace();
539     VPts nodes = intr->Get()[0];
540     F.insert(std::make_pair(face, nodes));
541     }
542    
543     for ( unsigned i=0;1+i<GetPolylineNodeCount();i++)
544     {
545     MG_ELEMENT_TOPOLOGIQUE * topo = GetPolylineTopo(i);
546     if ( topo != NULL && topo->get_dimension()==1)
547     {
548     MCNode * xi = GetPolylineNode(i);
549     MCNode * xii = GetPolylineNode(i+1);
550     MG_ARETE * edge = (MG_ARETE *) topo;
551     VPts Ci;
552     Ci.push_back(xi);
553     Ci.push_back(xii);
554    
555     E.insert (std::make_pair(edge, Ci));
556     for (int itF = 0; itF < edge->get_nb_mg_coarete(); itF++)
557     {
558     MG_FACE * face = edge->get_mg_coarete(itF)->get_boucle()->get_mg_face();
559     F.insert(std::make_pair(face, Ci));
560     }
561     }
562     }
563    
564     return 1;
565     }
566     else
567     {
568     return 0;
569     }
570     }
571    
572 foucault 569 int MCSegment::RefineInRefEdge(MCEdge * __mcEdge, MG_ARETE * __refEdge, MCNode * __n1, MCNode * __n2, double __epsilon, double __lastDistanceToEdge, std::map < double , MCNode * > & __mapMCEdgeNodesBySParameter, std::map < double , MG_ARETE * > & __mapMCEdgeRefEdgesBySParameter, int __iRecursiveCalls)
573 foucault 27 {
574 foucault 569 static const int RefineInRefEdge_MAX_RECURSIVE_CALL_COUNT = 100;
575     if (__iRecursiveCalls > RefineInRefEdge_MAX_RECURSIVE_CALL_COUNT)
576     {
577     printf("Warning : RefineInRefEdge : The number of recursive calls has been reached (%d)\n",RefineInRefEdge_MAX_RECURSIVE_CALL_COUNT);
578     return 0;
579     }
580    
581 foucault 27 int insertedNodeCount = 0;
582     MCNode * n[2] = { __n1, __n2};
583     for (int i=0; i<2; i++)
584     {
585     MG_SOMMET * v = 0;
586     if (n[i]->get_lien_topologie_reference()->get_dimension() == 0)
587     v = (MG_SOMMET * ) n[i]->get_lien_topologie_reference();
588     if (v)
589     if (__mcEdge->GetPolyCurve()->Contains( v ) == false )
590     return 0;
591     if (n[i]->IsInEdge(__refEdge) == false)
592     return 0;
593     // nodes have merged ref vertices
594     if (n[(i+1)%2]->IsInVertex(v))
595     return 0;
596     }
597     __n1->incrementer();__n2->incrementer();
598     double t1 = __n1->T(__refEdge);
599     double t2 = __n2->T(__refEdge);
600     if (fabs(t2-t1) < 1E-6*(__refEdge->get_tmax()-__refEdge->get_tmin()))
601     return 0;
602    
603     double period = __refEdge->get_courbe()->get_periode();
604     if (period != 0.0 && fabs(t2 - t1) > .5*period)
605     if (t2<t1)
606     t2 += period;
607     else t1 += period;
608     double t3 = t1 + (t2-t1)*.5;
609     double s3;
610     double xyz[3]; __refEdge->evaluer(t3,xyz);
611     MCNode edgeNode (__mcEdge, __refEdge, t3, xyz);
612     for (int i=0; i<__refEdge->get_nb_mg_coarete(); i++)
613     {
614     MG_FACE * face = __refEdge->get_mg_coarete(i)->get_boucle()->get_mg_face();
615    
616     MCNodePolyline faceLine(liaison_topologique);
617     faceLine.Add(__n1,face);
618     faceLine.Add(__n2,face);
619     double L = faceLine.GetLength();
620     MCNode faceNode = faceLine.Evaluate(L*.5);
621     double distanceToEdge = OT_ALGORITHME_GEOMETRIQUE::VEC3_DISTANCE_VEC3(faceNode.get_coord(),edgeNode.get_coord());
622     double ratioConvergence = distanceToEdge / __lastDistanceToEdge;
623     double distN1N2 = OT_ALGORITHME_GEOMETRIQUE::VEC3_DISTANCE_VEC3(__n2->get_coord(),__n1->get_coord());
624     bool testConvergence = ( fabs(ratioConvergence - 1) < .001 || distN1N2 < __epsilon );
625     if ( (distanceToEdge > __epsilon )
626     && testConvergence == false )
627     {
628     insertedNodeCount++;
629     __mcEdge->GetPolyCurve()->Parameter_RefEdgeTToS ( t3, __refEdge, &s3, false);
630     if (__mcEdge->GetPolyCurve()->est_periodique()
631     && __mcEdge->get_tmin() > s3+1E-5*(__mcEdge->GetPolyCurve()->get_periode())
632     )
633     s3 += __mcEdge->GetPolyCurve()->get_periode();
634     MCNode * newMCNode = new MCNode ( edgeNode );
635     __mapMCEdgeNodesBySParameter.insert(std::make_pair(s3,newMCNode));
636     __mapMCEdgeRefEdgesBySParameter.insert(std::make_pair(s3, __refEdge));
637     newMCNode->incrementer();
638 foucault 569 insertedNodeCount += RefineInRefEdge(__mcEdge, __refEdge, __n1, newMCNode, __epsilon, distanceToEdge, __mapMCEdgeNodesBySParameter,__mapMCEdgeRefEdgesBySParameter, __iRecursiveCalls+1);
639     insertedNodeCount += RefineInRefEdge(__mcEdge, __refEdge, newMCNode, __n2, __epsilon, distanceToEdge, __mapMCEdgeNodesBySParameter,__mapMCEdgeRefEdgesBySParameter, __iRecursiveCalls+1);
640 foucault 27 newMCNode->decrementer();
641     break;
642     }
643     }
644     __n1->decrementer();__n2->decrementer();
645     return insertedNodeCount;
646     }
647    
648     int MCSegment::Construct_MCEdge(MCEdge * __mcEdge)
649     {
650     double s[2];
651     double t,dt;
652     int i,j;
653     unsigned iEdge;
654     MG_ARETE * edge;
655     PolyCurve * polycurve = __mcEdge->GetPolyCurve();
656     double period = polycurve->get_periode();
657     double smin = __mcEdge->get_tmin();
658     double smax = __mcEdge->get_tmax();
659    
660     VPts CurveNodes;
661     std::vector < MG_ELEMENT_TOPOLOGIQUE * > CurveTopo;
662    
663     MCNode * n[2];
664     n[0]=(MCNode *)get_noeud1();
665     n[1]=(MCNode *)get_noeud2();
666    
667     std::map < double , MCNode * > nodes;
668     std::map < double , MG_ARETE * > edges;
669    
670     // get the parameter of extremities n1 n2 of the segment
671     for (i=0; i<2; i++)
672     {
673     if (n[i]->GetRefVertexMapping().size() >= 1) // MC node is on a ref vertex
674     {
675     MG_SOMMET * refVertex = (MG_SOMMET*)n[i]->get_lien_topologie_reference();
676     if (polycurve->ContainsRefVertex(refVertex) == false)
677     {
678     for (std::set<MG_SOMMET*>::iterator itV = n[i]->GetRefVertexMapping().begin();
679     itV != n[i]->GetRefVertexMapping().end();
680     itV++)
681     {
682     MG_SOMMET * v = *itV;
683     if (polycurve->ContainsRefVertex(v))
684     {
685     s[i] = polycurve->RefVertex_GetS(v);
686     if (n[i]->get_lien_topologie_reference() != v)
687     {
688     double xyzV[3]; v->get_point()->evaluer(xyzV);
689     n[i] = new MCNode (__mcEdge,v,xyzV[0],xyzV[1],xyzV[2]);
690     //n[i]->incrementer();
691     }
692     break;
693     }
694     }
695     }
696     else
697     {
698     s[i] = polycurve->RefVertex_GetS(refVertex);
699     }
700     }
701     else if (n[i]->GetRefEdgeMapping().size() == 1) // MC node is in a ref edge
702     {
703     polycurve->inverser(s[i], n[i]->get_coord(), 1E-6);
704     }
705     }
706    
707     if (period != 0.0)
708     {
709     for (i=0;i<2;i++){
710     if (s[i] > smax + fabs(smax-smin)*1E-6)
711     s[i] -= period;
712     if (s[i] < smin - fabs(smax-smin)*1E-6)
713     s[i] += period; }
714     }
715    
716     if (period != 0.0 && fabs(s[1] - s[0]) > .5*period)
717     if (s[1]<s[0])
718     s[1] += period;
719     else s[1] += period;
720    
721     for (i=0; i<2; i++)
722     {
723     nodes[s[i]] = n[i];
724     }
725    
726     {
727     MG_ARETE * edge; double t,dt;
728     double si = std::min(s[0],s[1]);
729     polycurve->Parameter_SToRefEdgeT ( si+1E-6*fabs(s[1]-s[0]), &edge,&t,&dt,false);
730     edges [ si ] = edge;
731     }
732    
733    
734     for (int i=0; i<2; i++)
735     {
736     OT_VECTEUR_3D v, v_node(n[i]->get_coord());
737     polycurve->evaluer(s[i], v);
738     double dist = (v_node-v).get_longueur();
739     if (dist > .001*__mcEdge->GetPolyCurve()->get_longueur())
740     {
741     printf("Distance between projection and node = %f\n", dist);
742     polycurve->inverser(s[i], n[i]->get_coord(), 1E-6);
743     polycurve->evaluer(s[i], v);
744     }
745     }
746    
747     // Create nodes in vertices between n1 and n2
748     double si=0;
749     for (i=0;si<std::max(s[1],s[0]);i++)
750     {
751     int iEdge = i%polycurve->GetRefEdgeCount();
752     int iVertex = (period != 0.0)? i%(polycurve->GetRefVertexCount()-1): i%polycurve->GetRefVertexCount();
753     if ((si-s[0])*(s[1]-si) > 0)
754     {
755     MG_SOMMET * vertex = polycurve->GetRefVertex(iVertex);
756     double xyz[3];vertex->get_point()->evaluer(xyz);
757     MCNode * ni = new MCNode ( __mcEdge, vertex, xyz[0], xyz[1], xyz[2] );
758     nodes [ si ] = ni;
759     edges [ si ] = polycurve->GetRefEdge(iEdge);
760     //ni->incrementer();
761     }
762     si += polycurve->GetLength(iEdge);
763     }
764    
765     std::map < double , MCNode * > refinedNodes = nodes;
766     std::map < double , MG_ARETE * > refinedEdges = edges;
767    
768     for (std::map<double, MCNode * >::iterator itN = nodes.begin();
769     itN != nodes.end();
770     itN++)
771     {
772     std::map<double, MCNode * >::iterator itNii = itN;
773     itNii++;
774     if (itNii == nodes.end())
775     break;
776     MCNode * ni = itN->second;
777     MCNode * nii = itNii->second;
778     double si = itN->first;
779     double sii = itNii->first;
780     double smid = .5*(si+sii);
781    
782     if (ni->get_lien_topologie_reference()->get_dimension() == 0)
783     {
784     MG_SOMMET * vi = (MG_SOMMET*)ni->get_lien_topologie_reference();
785     if (nii->IsInVertex(vi))
786     continue;
787     }
788    
789     if (nii->get_lien_topologie_reference()->get_dimension() == 0)
790     {
791     MG_SOMMET * vii = (MG_SOMMET*)nii->get_lien_topologie_reference();
792     if (ni->IsInVertex(vii))
793     continue;
794     }
795    
796     MG_ARETE * refEdge=0; double tMid; double dtMid;
797     polycurve->Parameter_SToRefEdgeT(smid,&refEdge,&tMid,&dtMid,false);
798     // and if the edge is periodic and tii-ti > period/2 then insert a node in the middle
799     {
800     if (refEdge->get_courbe()->est_periodique() != 0 )
801     {
802     MG_ARETE * refEdgei=0, * refEdgeii=0;
803     double tii, dtii, ti, dti;
804     polycurve->Parameter_SToRefEdgeT(si,&refEdgei,&ti,&dti,false);
805     polycurve->Parameter_SToRefEdgeT(sii,&refEdgeii,&tii,&dtii,false);
806    
807     if (fabs(tii-ti) > .5*refEdge->get_courbe()->get_periode())
808     {
809     double xyz[3];
810     refEdge->evaluer(tMid,xyz);
811     MCNode * newMCNode = new MCNode(__mcEdge, refEdge, tMid, xyz);
812     //newMCNode->incrementer();
813     refinedNodes[smid] = newMCNode;
814     refinedEdges[smid] = refEdge;
815     }
816     }
817     }
818     }
819     nodes = refinedNodes;
820     edges = refinedEdges;
821    
822     for (std::map<double, MCNode * >::iterator itN = nodes.begin();
823     itN != nodes.end();
824     itN++)
825     {
826     std::map<double, MCNode * >::iterator itNii = itN;
827     itNii++;
828     if (itNii == nodes.end())
829     break;
830     MCNode * ni = itN->second;
831     MCNode * nii = itNii->second;
832     double si = itN->first;
833    
834     MG_ARETE * refEdge=edges[si];
835    
836     // Refine the mc segment discretization with discretization error in faces < segment length / 1000
837     double deltaMax = get_longueur()*1E-2;
838 foucault 569 if (deltaMax < 1E-7)
839     deltaMax = 1E-7;
840 foucault 27 RefineInRefEdge(__mcEdge, refEdge, ni, nii, deltaMax, 1E300, refinedNodes, refinedEdges );
841     }
842     nodes=refinedNodes;
843     edges=refinedEdges;
844    
845    
846     // detect edges which contain nodes, and make segments of this edge on these nodes
847     for (std::map<double, MCNode * >::iterator itN = nodes.begin();
848     itN != nodes.end();
849     itN++)
850     {
851     std::map<double, MCNode * >::iterator itNii = itN;
852     itNii++;
853     if (itNii == nodes.end())
854     break;
855    
856     MCNode * ni = itN->second;
857     MCNode * nii = itNii->second;
858     double si = itN->first;
859     std::map<double, MG_ARETE*>::iterator itRefEdge = edges.find(si);
860     if (itRefEdge != edges.end())
861     edge = itRefEdge->second;
862     else
863     edge = 0;
864     if (ni->IsInEdge(edge) == false ||
865     nii->IsInEdge(edge) == false )
866     {
867     for (MCNode::EMapIterator itNiRefEdge = ni->GetRefEdgeMapping().begin();
868     itNiRefEdge != ni->GetRefEdgeMapping().end();
869     itNiRefEdge++)
870     {
871     edge = itNiRefEdge->first;
872     if ( nii->IsInEdge(edge) )
873     {
874     break;
875     }
876     }
877     }
878    
879     double params[2];
880     params[0]=itN->first;
881     params[1]=itNii->first;
882    
883     for (int i=0;i<2;i++)
884     if ((s[1]-params[i])*(s[0]-params[i])>0)
885     printf("pb\n");
886    
887     std::vector < MCNode * > segEdge;
888     segEdge.push_back (ni);
889     segEdge.push_back (nii);
890    
891     E.insert(std::make_pair(edge, segEdge));
892     // copy the curve in adjacent faces
893     for (int itF = 0; itF < edge->get_nb_mg_coarete(); itF++)
894     {
895     MG_FACE * face = edge->get_mg_coarete(itF)->get_boucle()->get_mg_face();
896     F.insert(std::make_pair(face, segEdge));
897     }
898    
899     if (CurveNodes.size () == 0 || CurveNodes[CurveNodes.size()-1] != ni)
900     CurveNodes.push_back(ni);
901     CurveNodes.push_back(nii);
902     CurveTopo.push_back(edge);
903     }
904    
905     if (_polylineEvaluator == NULL) _polylineEvaluator = new MCNodePolyline(liaison_topologique,CurveNodes,CurveTopo);
906     else
907     for (unsigned i=0;i<CurveNodes.size();i++)
908     _polylineEvaluator->Add(CurveNodes[i],CurveTopo[i]);
909    
910     return 1;
911     }
912    
913     MCFace * MCSegment::Find_MCFace(MCEdge * __mcEdge, MG_SOMMET * __refVertex1, MG_SOMMET * __refVertex2)
914     {
915     for (int itF = 0; itF != __mcEdge->get_nb_mg_coarete(); itF++)
916     {
917     MCFace * F = (MCFace*)__mcEdge->get_mg_coarete(itF)->get_boucle()->get_mg_face();
918     bool v1Found = false, v2Found = false;
919     for (int itFLoop = 0; itFLoop != F->get_nb_mg_boucle(); itFLoop ++)
920     {
921     MG_BOUCLE * loop = F->get_mg_boucle(itFLoop);
922     for (int itFLoopEdge = 0; itFLoopEdge != loop->get_nb_mg_coarete(); itFLoopEdge++)
923     {
924     MCEdge * mcEdge = (MCEdge *)loop->get_mg_coarete( itFLoopEdge )->get_arete();
925     if ( mcEdge->GetPolyCurve()->ContainsRefVertex(__refVertex1) )
926     v1Found = true;
927     if ( mcEdge->GetPolyCurve()->ContainsRefVertex(__refVertex2) )
928     v2Found = true;
929     if (v1Found && v2Found)
930     return F;
931     }
932     }
933     }
934     return NULL;
935     }
936    
937     int MCSegment::Construct_MergedVertices(MCNode * __mcNode)
938     {
939     if (get_lien_topologie()->get_dimension() != 1)
940     {
941     printf("Warning: MCSegment topology is not a MCEdge ! then it's not possible to construct a mapping on a merged vertex\n");
942     return 0;
943     }
944     MCEdge * mcEdge = (MCEdge*)get_lien_topologie();
945     MG_SOMMET * polycurveRefVertex = NULL;
946     MG_SOMMET * mcVertexRefVertex = (MG_SOMMET*)__mcNode->get_lien_topologie();
947     MCFace * mcFace;
948     for (std::set<MG_SOMMET*>::iterator itV = __mcNode->GetRefVertexMapping().begin();
949     itV != __mcNode->GetRefVertexMapping().end();
950     itV++ )
951     {
952     MG_SOMMET * v = *itV;
953     if (v != mcVertexRefVertex)
954     {
955     polycurveRefVertex = v;
956     mcFace = Find_MCFace(mcEdge, polycurveRefVertex, mcVertexRefVertex);
957     if (mcFace)
958     {
959     MCNode * polycurve_mcNode = NULL;
960     double v_xyz[3];
961     v->get_point()->evaluer(v_xyz);
962    
963     polycurve_mcNode = new MCNode (get_lien_topologie(), v, v_xyz[0],v_xyz[1],v_xyz[2]);
964    
965     polycurve_mcNode->incrementer();
966     if (polycurve_mcNode)
967     Construct_MCFaceByShortestPath(mcFace, __mcNode, polycurve_mcNode);
968    
969     break;
970     }
971     }
972     }
973    
974     return 1;
975     }
976    
977     BOITE_3D MCSegment::get_boite_3D(void)
978     {
979     return BOITE_3D(_bbox[0],_bbox[1],_bbox[2],_bbox[3],_bbox[4],_bbox[5]);
980     }
981    
982     void MCSegment::SetSaveFormat(char __format)
983     {
984     _saveFormat=__format;
985     if (__format == 2)
986     {
987     MG_ELEMENT_TOPOLOGIQUE * refTopo = 0;
988     switch (liaison_topologique->get_dimension())
989     {
990     case 1:
991     {
992     refTopo = ((MCEdge*)liaison_topologique)->GetPolyCurve()->GetRefEdge(0);
993     break;
994     }
995     case 2:
996     {
997     refTopo = ((MCFace*)liaison_topologique)->GetPolySurface()->GetRefFace(0);
998     break;
999     }
1000     }
1001     change_lien_topologie(refTopo);
1002     }
1003     }
1004    
1005     void MCSegment::enregistrer(std::ostream& o)
1006     {
1007     if (_saveFormat == 0) // Save as CAD4FE_MC_SEGMENT in magic file
1008     {
1009     if(liaison_topologique->get_dimension()==1) o << "%" << get_id() << "=CAD4FE_MCSEGMENT($"<< get_lien_topologie()->get_id() << ",$" << noeud1->get_id() << ",$" << noeud2->get_id() << ");" << std::endl;
1010     }
1011     else if (_saveFormat == 1) // Save as MG_SEGMENT in magic file
1012     {
1013     MG_SEGMENT::enregistrer(o);
1014     }
1015     else if (_saveFormat == 2)
1016     {
1017     MG_SEGMENT::enregistrer(o);
1018     }
1019     }
1020     int MCSegment::get_type_entite()
1021     {
1022     return IDMCSEGMENT;
1023     }
1024    
1025