ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/REPOS_ERICCA/magic/lib/CAD4FE/src/CAD4FE_MCSegment.cpp
Revision: 1158
Committed: Thu Jun 13 22:18:49 2024 UTC (11 months ago) by francois
File size: 37810 byte(s)
Log Message:
compatibilité Ubuntu 22.04
Suppression des refeences à Windows
Ajout d'une banière

File Contents

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