1 // File: BRepMesh_FastDiscretFace.cxx
3 // Author: Ekaterina SMIRNOVA
4 // Copyright: Open CASCADE SAS 2008
6 #include <BRepMesh_FastDiscretFace.ixx>
8 #include <Adaptor3d_IsoCurve.hxx>
9 #include <BRepAdaptor_Curve.hxx>
10 #include <BRepMesh_GeomTool.hxx>
11 #include <BRepMesh_ListOfXY.hxx>
12 #include <BRepMesh_Array1OfVertexOfDelaun.hxx>
13 #include <BRepMesh_ListIteratorOfListOfVertex.hxx>
14 #include <BRepMesh_ListIteratorOfListOfXY.hxx>
15 #include <BRepMesh_PairOfPolygon.hxx>
16 #include <BRepMesh_DataMapIteratorOfDataMapOfShapePairOfPolygon.hxx>
17 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
18 #include <BRepMesh_ClassifierPtr.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_PointRepresentation.hxx>
21 #include <BRep_TVertex.hxx>
22 #include <BRep_Tool.hxx>
23 #include <Geom_Surface.hxx>
25 #include <Standard_ErrorHandler.hxx>
26 #include <Standard_Failure.hxx>
27 #include <Poly_PolygonOnTriangulation.hxx>
28 #include <Poly_Triangulation.hxx>
29 #include <TColStd_Array1OfReal.hxx>
30 #include <TColStd_SequenceOfReal.hxx>
31 #include <TColStd_Array1OfInteger.hxx>
32 #include <TColStd_HArray1OfReal.hxx>
33 #include <TopExp_Explorer.hxx>
36 #include <TColgp_Array1OfPnt2d.hxx>
37 #include <NCollection_Map.hxx>
38 #include <Geom_BSplineSurface.hxx>
39 #include <GeomLib.hxx>
40 #include <Bnd_Box2d.hxx>
42 static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen)
44 Standard_Integer i, j, n = 0;
45 Standard_Real p, result = 0.;
47 for(i = 1; i <= PLen; i++)
50 for(j = i + 1; j <= PLen; j++)
62 p = Abs(P(i) - P(i-1));
70 return (n? (result / (Standard_Real) n) : -1.);
73 //=======================================================================
74 //function : BRepMesh_FastDiscretFace
76 //=======================================================================
77 BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace
78 (const Standard_Real theAngle,
79 const Standard_Boolean theWithShare) :
80 myAngle(theAngle), myWithShare(theWithShare), myNbLocat(0),
81 myInternalVerticesMode(Standard_True)
83 myAllocator = new NCollection_IncAllocator(64000);
86 //=======================================================================
87 //function : Add(face)
89 //=======================================================================
91 void BRepMesh_FastDiscretFace::Add(const TopoDS_Face& theFace,
92 const Handle(BRepMesh_FaceAttribute)& theAttrib,
93 const TopTools_DataMapOfShapeReal& theMapDefle)
100 TopoDS_Face face = theFace;
103 const Handle(Poly_Triangulation)& aFaceTrigu = BRep_Tool::Triangulation(face, loc);
104 if ( aFaceTrigu.IsNull() )
107 myAttrib = theAttrib;
108 face.Orientation(TopAbs_FORWARD);
109 myStructure.Nullify();
110 Handle(NCollection_IncAllocator) anAlloc = Handle(NCollection_IncAllocator)::DownCast(myAllocator);
111 anAlloc->Reset(Standard_False);
112 myStructure=new BRepMesh_DataStructureOfDelaun(anAlloc);
113 BRepAdaptor_Surface BS(face, Standard_False);
114 Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS);
116 GeomAbs_SurfaceType thetype;
117 thetype = BS.GetType();
119 TopAbs_Orientation orFace = face.Orientation();
126 myLocation2d.Clear();
127 myInternaledges.Clear();
129 Standard_Integer i = 1;
130 Standard_Integer ipn = 0;
132 TopoDS_Iterator exW(face);
133 for (; exW.More(); exW.Next()) {
134 const TopoDS_Shape& aWire = exW.Value();
135 if (aWire.ShapeType() != TopAbs_WIRE)
137 TopoDS_Iterator ex(aWire);
138 for(; ex.More(); ex.Next()) {
139 const TopoDS_Edge& edge = TopoDS::Edge(ex.Value());
143 RestoreStructureFromTriangulation(edge, face, gFace, aFaceTrigu, theMapDefle(edge), loc);
147 ////////////////////////////////////////////////////////////
148 //add internal vertices after self-intersection check
149 Standard_Integer nbVertices = 0;
150 if(myInternalVerticesMode) {
151 for(TopExp_Explorer ex(face,TopAbs_VERTEX ,TopAbs_EDGE); ex.More(); ex.Next()) {
152 const TopoDS_Vertex& aVert = TopoDS::Vertex(ex.Current());
153 Add(aVert,face,gFace);
155 nbVertices = myVemap.Extent();
158 // essai de determination de la longueur vraie:
159 // akm (bug OCC16) : We must calculate these measures in non-singular
160 // parts of face. Let`s try to compute average value of three
161 // (umin, (umin+umax)/2, umax), and respectively for v.
163 //Standard_Real longu = 0.0, longv = 0.0; //, last , first;
164 //gp_Pnt P11, P12, P21, P22, P31, P32;
166 Standard_Real umax = myAttrib->GetUMax();
167 Standard_Real umin = myAttrib->GetUMin();
168 Standard_Real vmax = myAttrib->GetVMax();
169 Standard_Real vmin = myAttrib->GetVMin();
171 TColStd_Array1OfInteger tabvert_corr(1, nbVertices);
174 // Check the necessity to fill the map of parameters
175 const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus ||
176 thetype == GeomAbs_BezierSurface ||
177 thetype == GeomAbs_BSplineSurface);
181 BRepMesh_IDMapOfNodeOfDataStructureOfDelaun aMoveNodes(myVemap.Extent());
183 for (i = 1; i <= myStructure->NbNodes(); i++)
185 const BRepMesh_Vertex& v = myStructure->GetNode(i);
188 myUParam.Add(p2d.X());
189 myVParam.Add(p2d.Y());
192 res.SetCoord((p2d.X()-(myAttrib->GetMinX()))/(myAttrib->GetDeltaX()),
193 (p2d.Y()-(myAttrib->GetMinY()))/(myAttrib->GetDeltaY()));
194 BRepMesh_Vertex v_new(res,v.Location3d(),v.Movability());
195 const BRepMesh_ListOfInteger& alist = myStructure->GetNodeList(i);
196 aMoveNodes.Add(v_new,alist);
199 myStructure->ReplaceNodes(aMoveNodes);
201 Standard_Boolean rajout;
203 BRepMesh_ClassifierPtr& classifier = theAttrib->GetClassifier();
208 rajout = !classifier->NaturalRestriction();
212 rajout = Standard_True;
215 rajout = Standard_False;
218 BRepMesh_Delaun trigu(myStructure, tabvert_corr, orFace==TopAbs_FORWARD);
220 //removed all free edges from triangulation
221 Standard_Integer nbLinks = myStructure->NbNodes();
222 for(i = 1; i <= nbLinks; i++)
224 if(myStructure->ElemConnectedTo(i).Extent() < 1)
226 BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i);
227 if(anEdge.Movability()==BRepMesh_Deleted)
229 anEdge.SetMovability(BRepMesh_Free);
230 myStructure->RemoveLink(i);
234 Standard_Boolean isaline;
235 isaline = ((umax-umin)<1.e-05) || ((vmax-vmin)<1.e-05);
237 Standard_Real aDef = -1;
238 if (!isaline && myStructure->ElemOfDomain().Extent() > 0) {
239 TColStd_ListOfInteger badTri, nulTri;
243 aDef = Control(gFace, theAttrib->GetDefFace(), myListver, badTri, nulTri, trigu, Standard_True);
244 if( aDef > theAttrib->GetDefFace() || aDef < 0.)
245 rajout = Standard_True;
251 if(myVParam.Extent() > 2) {
252 rajout = Standard_True;
256 if(myUParam.Extent() > 2) {
257 rajout = Standard_True;
264 InternalVertices(gFace, myListver, theAttrib->GetDefFace(), classifier);
266 if (myListver.Extent() > 0) {
267 BRepMesh_Array1OfVertexOfDelaun verttab(1, myListver.Extent());
268 BRepMesh_ListIteratorOfListOfVertex itVer(myListver);
270 for (; itVer.More(); itVer.Next())
271 verttab(ipn++) = itVer.Value();
272 trigu.AddVertices(verttab);
274 //control internal points
275 BRepMesh_ListOfVertex vvlist;
276 aDef = Control(gFace, theAttrib->GetDefFace(), vvlist, badTri, nulTri, trigu, Standard_False);
277 myListver.Append(vvlist);
281 //modify myStructure back
283 Standard_Real deltaX = myAttrib->GetDeltaX();
284 Standard_Real deltaY = myAttrib->GetDeltaY();
285 for (i = 1; i <= myStructure->NbNodes(); i++)
287 const BRepMesh_Vertex& v = myStructure->GetNode(i);
290 res.SetCoord(p2d.X()*deltaX+umin,p2d.Y()*deltaY+vmin);
291 BRepMesh_Vertex v_new(res,v.Location3d(),v.Movability());
292 const BRepMesh_ListOfInteger& alist = myStructure->GetNodeList(i);
293 aMoveNodes.Add(v_new,alist);
295 myStructure->ReplaceNodes(aMoveNodes);
297 AddInShape(face, (aDef < 0.0)? theAttrib->GetDefFace() : aDef);
300 catch(Standard_Failure)
303 Handle(Poly_Triangulation) TNull;
304 B.UpdateFace(theFace,TNull);
307 myStructure.Nullify();
311 //=======================================================================
312 //function : RestoreStructureFromTriangulation(edge)
313 //purpose : Restore structure of Delaun from triangulation on face
314 //=======================================================================
315 Standard_Boolean BRepMesh_FastDiscretFace::RestoreStructureFromTriangulation
316 (const TopoDS_Edge& theEdge,
317 const TopoDS_Face& theFace,
318 const Handle(BRepAdaptor_HSurface)& theSurf,
319 const Handle(Poly_Triangulation)& theTrigu,
320 const Standard_Real theDefEdge,
321 const TopLoc_Location& theLoc)
323 // oan: changes for right restoring of triangulation data from face & edges
324 Handle(Poly_PolygonOnTriangulation) Poly;
325 Poly = BRep_Tool::PolygonOnTriangulation(theEdge, theTrigu, theLoc);
327 if (Poly.IsNull() || !Poly->HasParameters())
329 return Standard_False;
333 TopAbs_Orientation orEdge = theEdge.Orientation();
334 // Get end points on 2d curve
335 gp_Pnt2d uvFirst, uvLast;
336 BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast);
339 TopoDS_Vertex pBegin, pEnd;
340 TopExp::Vertices(theEdge,pBegin,pEnd);
342 const Standard_Boolean sameUV =
343 uvFirst.IsEqual(uvLast, Precision::PConfusion());
345 const TColgp_Array1OfPnt2d& UVNodes = theTrigu->UVNodes();
346 const TColgp_Array1OfPnt& Nodes = theTrigu->Nodes();
347 const TColStd_Array1OfInteger& Indices = Poly->Nodes();
349 const Standard_Integer nbnodes = Indices.Length();
350 TColStd_Array1OfInteger NewNodes(1, nbnodes);
355 // Process first vertex
356 Standard_Integer ipf;
357 if (myVertices.IsBound(pBegin))
359 ipf = myVertices.Find(pBegin);
363 if (sameUV && myVertices.IsBound(pEnd))
365 ipf = myVertices.Find(pEnd);
369 P3d = Nodes(Indices(1));
370 if (!theLoc.IsIdentity())
371 P3d.Transform(theLoc.Transformation());
373 myLocation3d.Bind(myNbLocat, P3d);
376 myVertices.Bind(pBegin,ipf);
379 //Controle vertice tolerances
380 gp_Pnt pFirst = theSurf->Value(uvFirst.X(), uvFirst.Y());
381 gp_Pnt pLast = theSurf->Value(uvLast.X(), uvLast.Y());
383 Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)),
384 pLast.Distance(BRep_Tool::Pnt(pEnd)));
386 if (mindist < BRep_Tool::Tolerance(pBegin) ||
387 mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge;
389 anUV = FindUV(pBegin, uvFirst, ipf, theSurf, mindist, myLocation2d);
390 Standard_Integer iv1, isv1;
391 BRepMesh_Vertex vf(anUV, ipf, BRepMesh_Frontier);
392 iv1 = myStructure->AddNode(vf);
393 isv1 = myVemap.FindIndex(iv1);
395 isv1 = myVemap.Add(iv1);
398 // Process last vertex
399 Standard_Integer ipl, ivl;
400 if (pEnd.IsSame(pBegin))
406 if (myVertices.IsBound(pEnd))
408 ipl = myVertices.Find(pEnd);
419 P3d = Nodes(Indices(nbnodes));
420 if (!theLoc.IsIdentity())
421 P3d.Transform(theLoc.Transformation());
423 myLocation3d.Bind(myNbLocat, P3d);
426 myVertices.Bind(pEnd,ipl);
430 anUV = FindUV(pEnd, uvLast, ipl, theSurf, mindist, myLocation2d);
431 BRepMesh_Vertex vl(anUV, ipl, BRepMesh_Frontier);
433 Standard_Integer isvl;
434 ivl = myStructure->AddNode(vl);
435 isvl = myVemap.FindIndex(ivl);
437 isvl = myVemap.Add(ivl);
438 NewNodes(nbnodes) = isvl;
443 for (i = 2; i < nbnodes; i++)
446 P3d = Nodes(Indices(i));
447 if (!theLoc.IsIdentity())
448 P3d.Transform(theLoc.Transformation());
450 myLocation3d.Bind(myNbLocat, P3d);
453 anUV = UVNodes(Indices(i)).Coord();
455 Standard_Integer iv2, isv;
456 v.Initialize(anUV, myNbLocat, BRepMesh_Frontier);
457 iv2 = myStructure->AddNode(v);
458 isv = myVemap.FindIndex(iv2);
460 isv = myVemap.Add(iv2);
464 if (orEdge == TopAbs_FORWARD)
465 myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier));
466 else if (orEdge == TopAbs_REVERSED)
467 myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier));
468 else if (orEdge == TopAbs_INTERNAL)
469 myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed));
475 if (orEdge == TopAbs_FORWARD)
476 myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier));
477 else if (orEdge == TopAbs_REVERSED)
478 myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier));
479 else if (orEdge == TopAbs_INTERNAL)
480 myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed));
483 Handle(Poly_PolygonOnTriangulation) P1 =
484 new Poly_PolygonOnTriangulation(NewNodes, Poly->Parameters()->Array1());
485 P1->Deflection(theDefEdge);
486 if (myInternaledges.IsBound(theEdge))
488 BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge);
489 if (theEdge.Orientation() == TopAbs_REVERSED)
496 BRepMesh_PairOfPolygon pair1;
498 myInternaledges.Bind(theEdge, pair1);
501 return Standard_True;
504 //=======================================================================
505 //function : InternalVertices
507 //=======================================================================
508 void BRepMesh_FastDiscretFace::InternalVertices(const Handle(BRepAdaptor_HSurface)& theCaro,
509 BRepMesh_ListOfVertex& theInternalV,
510 const Standard_Real theDefFace,
511 const BRepMesh_ClassifierPtr& theClassifier)
513 BRepMesh_Vertex newV;
517 // travail suivant le type de surface
518 const BRepAdaptor_Surface& BS = *(BRepAdaptor_Surface*)&(theCaro->Surface());
519 GeomAbs_SurfaceType thetype = theCaro->GetType();
521 Standard_Real umax = myAttrib->GetUMax();
522 Standard_Real umin = myAttrib->GetUMin();
523 Standard_Real vmax = myAttrib->GetVMax();
524 Standard_Real vmin = myAttrib->GetVMin();
525 Standard_Real deltaX = myAttrib->GetDeltaX();
526 Standard_Real deltaY = myAttrib->GetDeltaY();
528 if (thetype == GeomAbs_Plane && !theClassifier->NaturalRestriction())
530 // rajout d`un seul point au milieu.
531 const Standard_Real U = 0.5*(umin+umax);
532 const Standard_Real V = 0.5*(vmin+vmax);
533 if (theClassifier->Perform(gp_Pnt2d(U, V)) == TopAbs_IN)
536 BRepMesh_GeomTool::D0(theCaro, U, V, p3d);
538 myLocation3d.Bind(myNbLocat, p3d);
540 p2d.SetCoord((U-umin)/deltaX, (V-vmin)/deltaY);
541 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
542 theInternalV.Append(newV);
545 else if (thetype == GeomAbs_Sphere)
547 gp_Sphere S = BS.Sphere();
548 const Standard_Real R = S.Radius();
550 // Calculate parameters for iteration in V direction
551 Standard_Real Dv = 1.0 - (theDefFace/R);
552 if (Dv < 0.0) Dv = 0.0;
553 Standard_Real oldDv = 2.0 * ACos (Dv);
554 Dv = .7 * oldDv; //.7 ~= sqrt(2.) - Dv is hypotenuse of triangle when oldDv is legs
555 const Standard_Real sv = vmax - vmin;
556 Dv = sv/((Standard_Integer)(sv/Dv) + 1);
557 const Standard_Real pasvmax = vmax-Dv*0.5;
559 //Du can be defined from relation: 2*r*Sin(Du/2) = 2*R*Sin(Dv/2), r = R*Cos(v)
560 //here approximate relation r*Du = R*Dv is used
562 Standard_Real Du, pasu, pasv; //, ru;
563 const Standard_Real su = umax-umin;
564 Standard_Boolean Shift = Standard_False;
565 for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
567 // Calculate parameters for iteration in U direction
568 // 1.-.365*pasv*pasv is simple approximation of Cos(pasv)
569 // with condition that it gives ~.1 when pasv = pi/2
570 Du = Dv/(1.-.365*pasv*pasv);
571 Du = su/((Standard_Integer)(su/Du) + 1);
573 const Standard_Real d = (Shift)? Du*.5 : 0.;
574 const Standard_Real pasumax = umax-Du*0.5 + d;
575 for (pasu = umin + Du - d; pasu < pasumax; pasu += Du)
577 if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
580 #ifdef DEB_MESH_CHRONO
583 ElSLib::D0(pasu, pasv, S, p3d);
585 myLocation3d.Bind(myNbLocat, p3d);
587 p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
588 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
589 theInternalV.Append(newV);
594 else if (thetype == GeomAbs_Cylinder)
596 gp_Cylinder S = BS.Cylinder();
597 const Standard_Real R = S.Radius();
599 // Calculate parameters for iteration in U direction
600 Standard_Real Du = 1.0 - (theDefFace/R);
601 if (Du < 0.0) Du = 0.0;
602 Du = 2.0 * ACos (Du);
603 if (Du > myAngle) Du = myAngle;
604 const Standard_Real su = umax - umin;
605 const Standard_Integer nbU = (Standard_Integer)(su/Du);
608 // Calculate parameters for iteration in V direction
609 const Standard_Real sv = vmax - vmin;
610 Standard_Integer nbV = (Standard_Integer)( nbU*sv/(su*R) );
611 nbV = Min(nbV, 100*nbU);
612 Standard_Real Dv = sv/(nbV+1);
614 Standard_Real pasu, pasv, pasvmax = vmax-Dv*0.5, pasumax = umax-Du*0.5;
615 for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) {
616 for (pasu = umin + Du; pasu < pasumax; pasu += Du) {
617 if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
620 ElSLib::D0(pasu, pasv, S, p3d);
622 myLocation3d.Bind(myNbLocat, p3d);
624 p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
625 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
626 theInternalV.Append(newV);
631 else if (thetype == GeomAbs_Cone)
633 Standard_Real R, RefR, SAng;
634 gp_Cone C = BS.Cone();
635 RefR = C.RefRadius();
636 SAng = C.SemiAngle();
637 R = Max(Abs(RefR+vmin*Sin(SAng)), Abs(RefR+vmax*Sin(SAng)));
638 Standard_Real Du, Dv, pasu, pasv;
639 Du = Max(1.0e0 - (theDefFace/R),0.0e0);
640 Du = (2.0 * ACos (Du));
641 Standard_Integer nbU = (Standard_Integer) ( (umax-umin)/Du );
642 Standard_Integer nbV = (Standard_Integer) ( nbU*(vmax-vmin)/((umax-umin)*R) );
643 Du = (umax-umin)/(nbU+1);
644 Dv = (vmax-vmin)/(nbV+1);
646 Standard_Real pasvmax = vmax-Dv*0.5, pasumax = umax-Du*0.5;
647 for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) {
648 for (pasu = umin + Du; pasu < pasumax; pasu += Du) {
649 if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
652 ElSLib::D0(pasu, pasv, C, p3d);
654 myLocation3d.Bind(myNbLocat, p3d);
656 p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
657 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
658 theInternalV.Append(newV);
663 else if (thetype == GeomAbs_Torus)
665 gp_Torus T = BS.Torus();
667 Standard_Boolean insert;
668 Standard_Integer i, j, ParamULength, ParamVLength;
669 Standard_Real pp, pasu, pasv;
670 Standard_Real r = T.MinorRadius(), R = T.MajorRadius();
672 TColStd_SequenceOfReal ParamU, ParamV;
674 Standard_Real Du, Dv;//, pasu, pasv;
675 Dv = Max(1.0e0 - (theDefFace/r),0.0e0) ;
676 Standard_Real oldDv = 2.0 * ACos (Dv);
677 oldDv = Min(oldDv, myAngle);
678 Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
681 Standard_Integer nbV = Max((Standard_Integer)((vmax-vmin)/Dv), 2);
682 Dv = (vmax-vmin)/(nbV+1);
683 Standard_Real ru = R + r;
686 Du = 2.0 * ACos(Max(1.0 - (theDefFace/ru),0.0));
687 if (myAngle < Du) Du = myAngle;
688 Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
689 if(aa < gp::Resolution())
691 Du *= Min(oldDv, Du) / aa;
695 Standard_Integer nbU = Max((Standard_Integer)((umax-umin)/Du), 2);
696 nbU = Max(nbU , (int)(nbV*(umax-umin)*R/((vmax-vmin)*r)/5.));
697 Du = (umax-umin)/(nbU+1);
701 // comme on recupere les points des edges.
702 // dans ce cas, les points ne sont pas representatifs.
704 //-- On choisit DeltaX et DeltaY de facon a ce qu on ne saute pas
705 //-- de points sur la grille
706 for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du);
711 // Number of mapped U parameters
712 const Standard_Integer LenU = myUParam.Extent();
713 // Fill array of U parameters
714 TColStd_Array1OfReal Up(1,LenU);
715 for (j = 1; j <= LenU; j++) Up(j) = myUParam(j);
717 // Calculate DU, sort array of parameters
718 Standard_Real aDU = FUN_CalcAverageDUV(Up,LenU);
719 aDU = Max(aDU, Abs(umax - umin) / (Standard_Real) nbU / 2.);
720 Standard_Real dUstd = Abs(umax - umin) / (Standard_Real) LenU;
721 if (aDU > dUstd) dUstd = aDU;
723 for (j = 1; j <= LenU; j++)
726 insert = Standard_True;
727 ParamULength = ParamU.Length();
728 for (i = 1; i <= ParamULength && insert; i++)
730 insert = (Abs(ParamU.Value(i)-pp) > (0.5*dUstd));
732 if (insert) ParamU.Append(pp);
737 // Number of mapped V parameters
738 const Standard_Integer LenV = myVParam.Extent();
739 // Fill array of V parameters
740 TColStd_Array1OfReal Vp(1,LenV);
741 for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j);
742 // Calculate DV, sort array of parameters
743 Standard_Real aDV = FUN_CalcAverageDUV(Vp,LenV);
744 aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real) nbV / 2.);
746 Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real) LenV;
747 if (aDV > dVstd) dVstd = aDV;
749 for (j = 1; j <= LenV; j++)
753 insert = Standard_True;
754 ParamVLength = ParamV.Length();
755 for (i = 1; i <= ParamVLength && insert; i++)
757 insert = (Abs(ParamV.Value(i)-pp) > (dVstd*2./3.));
759 if (insert) ParamV.Append(pp);
762 Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
763 Standard_Real uminnew = umin+deltaY*0.1;
764 Standard_Real vminnew = vmin+deltaX*0.1;
765 Standard_Real umaxnew = umax-deltaY*0.1;
766 Standard_Real vmaxnew = vmax-deltaX*0.1;
768 for (i = 1; i <= Lu; i++)
770 pasu = ParamU.Value(i);
771 if (pasu >= uminnew && pasu < umaxnew)
773 for (j = 1; j <= Lv; j++)
775 pasv = ParamV.Value(j);
776 if (pasv >= vminnew && pasv < vmaxnew)
778 if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
781 ElSLib::D0(pasu, pasv, T, p3d);
783 myLocation3d.Bind(myNbLocat, p3d);
785 p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
786 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
787 theInternalV.Append(newV);
794 else if (thetype == GeomAbs_BezierSurface || thetype == GeomAbs_BSplineSurface)
796 Standard_Integer i, j;
798 Handle(TColStd_HArray1OfReal) anUKnots, anVKnots;
799 Standard_Integer aNbUNkots,aNbVNkots;
800 Handle(Geom_Surface) B;
801 if (thetype == GeomAbs_BezierSurface) {
802 anUKnots = new TColStd_HArray1OfReal(1,2);
803 anVKnots = new TColStd_HArray1OfReal(1,2);
804 anUKnots->SetValue(1,0.);
805 anUKnots->SetValue(2,1.);
806 anVKnots->SetValue(1,0.);
807 anVKnots->SetValue(2,1.);
813 Handle(Geom_BSplineSurface) aSurf = BS.BSpline();
815 aNbUNkots = aSurf->NbUKnots();
816 aNbVNkots = aSurf->NbVKnots();
817 anUKnots = new TColStd_HArray1OfReal(1,aNbUNkots);
818 anVKnots = new TColStd_HArray1OfReal(1,aNbVNkots);
820 aSurf->UKnots(anUKnots->ChangeArray1());
821 aSurf->VKnots(anVKnots->ChangeArray1());
824 Standard_Real ddu = theCaro->UResolution(theDefFace)*5.;
825 Standard_Real aDUmin = (umax-umin)/5.;
829 // Sort sequence of U parameters
830 TColStd_SequenceOfReal ParamU;
831 Standard_Integer anUdegree = theCaro->UDegree();
833 Standard_Real aU1 = anUKnots->Value(1);
834 for( i = 1; i < aNbUNkots; i++)
836 Standard_Real aStart = anUKnots->Value(i);
837 Standard_Real aEnd = anUKnots->Value(i+1);
838 Standard_Integer aNbPoints = anUdegree-1;
839 Standard_Real aStep = (aEnd-aStart)/(aNbPoints+1);
841 for( Standard_Integer anInd = 0; anInd<= aNbPoints; anInd++)
843 Standard_Real aU2 = aStart+anInd*aStep;
844 if((aU2 - aU1) > ddu)
851 ParamU.Append(anUKnots->Value(aNbUNkots));
852 Standard_Integer ParamULength = ParamU.Length();
854 Standard_Real ddv = theCaro->VResolution(theDefFace)*5.;
855 Standard_Real aDVmin = (vmax-vmin)/5.;
858 // Sort sequence of V parameters
859 TColStd_SequenceOfReal ParamV;
860 Standard_Integer anVdegree = theCaro->VDegree();
862 Standard_Real aV1 = anVKnots->Value(1);
863 for( i = 1; i < aNbVNkots; i++)
865 Standard_Real aStart = anVKnots->Value(i);
866 Standard_Real aEnd = anVKnots->Value(i+1);
867 Standard_Integer aNbPoints = anVdegree-1;
868 Standard_Real aStep = (aEnd-aStart)/(aNbPoints+1);
870 for( Standard_Integer anInd = 0; anInd<= aNbPoints; anInd++)
872 Standard_Real aV2 = aStart+anInd*aStep;
873 if ((aV2 - aV1) > ddv)
880 ParamV.Append(anVKnots->Value(aNbVNkots));
881 Standard_Integer ParamVLength = ParamV.Length();
883 // controle des isos U et insertion eventuelle:
885 gp_Pnt P1, P2, PControl;
886 Standard_Real u, v, dist, V1, V2, U1, U2;
888 // precision for compare square distances
889 double dPreci = Precision::Confusion()*Precision::Confusion();
891 // Insert V parameters by deflection criterion
892 for (i = 1; i <= ParamULength; i++) {
893 Handle(Geom_Curve) IsoU = B->UIso(ParamU.Value(i));
894 V1 = ParamV.Value(1);
895 P1 = IsoU->Value(V1);
896 for (j = 2; j <= ParamVLength;) {
897 V2 = ParamV.Value(j);
898 P2 = IsoU->Value(V2);
900 PControl = IsoU->Value(v);
901 // 23.03.2010 skl for OCC21645 - change precision for comparison
902 if( P1.SquareDistance(P2) > dPreci ) {
903 gp_Lin L (P1, gp_Dir(gp_Vec(P1, P2)));
904 dist = L.Distance(PControl);
907 dist = P1.Distance(PControl);
909 if (dist > theDefFace) {
911 ParamV.InsertBefore(j, v);
922 for (i = 2; i < ParamVLength; i++) {
924 Handle(Geom_Curve) IsoV = B->VIso(v);
925 U1 = ParamU.Value(1);
926 P1 = IsoV->Value(U1);
927 for (j = 2; j <= ParamULength;) {
928 U2 = ParamU.Value(j);
929 P2 = IsoV->Value(U2);
931 PControl = IsoV->Value(u);
932 // 23.03.2010 skl for OCC21645 - change precision for comparison
933 if( P1.SquareDistance(P2) > dPreci ) {
934 gp_Lin L (P1, gp_Dir(gp_Vec(P1, P2)));
935 dist = L.Distance(PControl);
938 dist = P1.Distance(PControl);
940 if (dist > theDefFace) {
942 ParamU.InsertBefore(j, u);
949 if (j < ParamULength) {
950 // Classify intersection point
951 if (theClassifier->Perform(gp_Pnt2d(U1, v)) == TopAbs_IN)
955 myLocation3d.Bind(myNbLocat, P1);
957 p2d.SetCoord((U1-umin)/deltaX, (v-vmin)/deltaY);
958 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
959 theInternalV.Append(newV);
968 const Standard_Real anAngle = 0.35;
970 Standard_Integer i, j, nbpointsU = 10, nbpointsV = 10;
971 Adaptor3d_IsoCurve tabu[10], tabv[10];
973 TColStd_SequenceOfReal ParamU, ParamV;
974 Standard_Real u, v, du, dv;
975 Standard_Integer iu, iv;
978 du = (umax-umin) / (nbpointsU+1); dv = (vmax-vmin) / (nbpointsV+1);
980 for (iu = 1; iu <= nbpointsU; iu++) {
982 tabu[iu-1].Load(theCaro);
983 tabu[iu-1].Load(GeomAbs_IsoU, u);
986 for (iv = 1; iv <= nbpointsV; iv++) {
988 tabv[iv-1].Load(theCaro);
989 tabv[iv-1].Load(GeomAbs_IsoV, v);
992 Standard_Integer imax = 1, MaxV = 0;
994 GCPnts_TangentialDeflection* tabGU = new GCPnts_TangentialDeflection[nbpointsU];
996 for (i = 0; i <= nbpointsU-1; i++) {
997 f = Max(vmin, tabu[i].FirstParameter());
998 l = Min(vmax, tabu[i].LastParameter());
999 GCPnts_TangentialDeflection theDeflection(tabu[i], f, l, anAngle, 0.7*theDefFace, 2);
1000 tabGU[i] = theDeflection;
1001 if (tabGU[i].NbPoints() > MaxV) {
1002 MaxV = tabGU[i].NbPoints();
1007 // recuperation du tableau de parametres V:
1008 Standard_Integer NV = tabGU[imax].NbPoints();
1009 for (i = 1; i <= NV; i++) {
1010 ParamV.Append(tabGU[imax].Parameter(i));
1015 Standard_Integer MaxU = 0;
1017 GCPnts_TangentialDeflection* tabGV = new GCPnts_TangentialDeflection[nbpointsV];
1019 for (i = 0; i <= nbpointsV-1; i++) {
1020 f = Max(umin, tabv[i].FirstParameter());
1021 l = Min(umax, tabv[i].LastParameter());
1022 GCPnts_TangentialDeflection thedeflection2(tabv[i], f, l, anAngle, 0.7*theDefFace, 2);
1023 tabGV[i] = thedeflection2;
1024 if (tabGV[i].NbPoints() > MaxU) {
1025 MaxU = tabGV[i].NbPoints();
1030 // recuperation du tableau de parametres U:
1031 Standard_Integer NU = tabGV[imax].NbPoints();
1032 for (i = 1; i <= NU; i++) {
1033 ParamU.Append(tabGV[imax].Parameter(i));
1037 if (ParamU.Length() == 2) {
1038 ParamU.InsertAfter(1, (umax+umin)*0.5);
1040 if (ParamV.Length() == 2) {
1041 ParamV.InsertAfter(1, (vmax+vmin)*0.5);
1044 TColStd_SequenceOfReal InsertV, InsertU;
1047 Adaptor3d_IsoCurve IsoV;
1050 Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
1052 for (i = 2; i < Lv; i++) {
1053 v = ParamV.Value(i);
1054 IsoV.Load(GeomAbs_IsoV, v);
1055 for (j = 2; j < Lu; j++) {
1056 u = ParamU.Value(j);
1057 if (theClassifier->Perform(gp_Pnt2d(u, v)) == TopAbs_IN)
1062 myLocation3d.Bind(myNbLocat, P1);
1064 p2d.SetCoord((u-umin)/deltaX, (v-vmin)/deltaY);
1065 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
1066 theInternalV.Append(newV);
1071 #ifdef DEB_MESH_CHRONO
1077 * Internal class Couple, moved from MeshData package
1080 class BRepMesh_Couple
1083 BRepMesh_Couple() { myI1 = myI2 = 0; }
1084 BRepMesh_Couple(const Standard_Integer I1,
1085 const Standard_Integer I2)
1086 { myI1 = I1; myI2 = I2; }
1088 Standard_Integer myI1;
1089 Standard_Integer myI2;
1092 inline Standard_Boolean IsEqual(const BRepMesh_Couple& one,
1093 const BRepMesh_Couple& other)
1095 if (one.myI1 == other.myI1 &&
1096 one.myI2 == other.myI2) return Standard_True;
1097 else return Standard_False;
1100 inline Standard_Integer HashCode(const BRepMesh_Couple& one,
1101 const Standard_Integer Upper)
1103 return ::HashCode((one.myI1+one.myI2), Upper);
1106 typedef NCollection_Map<BRepMesh_Couple> BRepMesh_MapOfCouple;
1108 //=======================================================================
1109 //function : Control
1111 //=======================================================================
1112 Standard_Real BRepMesh_FastDiscretFace::Control(const Handle(BRepAdaptor_HSurface)& theCaro,
1113 const Standard_Real theDefFace,
1114 BRepMesh_ListOfVertex& theInternalV,
1115 TColStd_ListOfInteger& theBadTriangles,
1116 TColStd_ListOfInteger& theNulTriangles,
1117 BRepMesh_Delaun& theTrigu,
1118 const Standard_Boolean theIsFirst)
1120 //IMPORTANT: Constants used in calculations
1121 const Standard_Real MinimalArea2d = 1.e-9;
1122 const Standard_Real MinimalSqLength3d = 1.e-12;
1123 const Standard_Real aDef2 = theDefFace*theDefFace;
1125 // Define the number of iterations
1126 Standard_Integer myNbIterations = 11;
1127 const Standard_Integer nbPasses = (theIsFirst? 1 : myNbIterations);
1129 // Initialize stop condition
1130 Standard_Boolean allDegenerated = Standard_False;
1131 Standard_Integer nbInserted = 1;
1133 // Create map of links to skip already processed
1134 Standard_Integer nbtriangles = myStructure->ElemOfDomain().Extent();
1135 if (nbtriangles <= 0) return -1.0;
1136 BRepMesh_MapOfCouple theCouples(3*nbtriangles);
1139 gp_XYZ vecEd1, vecEd2, vecEd3;
1141 Standard_Real dv = 0, defl = 0, maxdef = -1;
1142 Standard_Integer pass = 1, nf = 0, nl = 0;
1143 BRepMesh_Vertex InsVertex;
1144 Standard_Boolean caninsert;
1146 Standard_Real sqdefface = theDefFace * theDefFace;
1147 Standard_Real ddu = theCaro->UResolution(theDefFace);
1148 Standard_Real ddv = theCaro->VResolution(theDefFace);
1150 GeomAbs_SurfaceType thetype = theCaro->GetType();
1151 Handle(Geom_Surface) BSpl;
1152 Standard_Boolean isSpline = Standard_False;
1153 if (thetype == GeomAbs_BezierSurface || thetype == GeomAbs_BSplineSurface)
1155 isSpline = Standard_True;
1156 if (thetype == GeomAbs_BezierSurface)
1157 BSpl = theCaro->Bezier();
1159 BSpl = theCaro->BSpline();
1162 NCollection_DataMap<Standard_Integer,gp_Dir> aNorMap;
1163 NCollection_DataMap<Standard_Integer,Standard_Integer> aStatMap;
1165 // Perform refinement passes
1166 for (; pass <= nbPasses && nbInserted && !allDegenerated; pass++)
1168 theInternalV.Clear();
1169 theBadTriangles.Clear();
1171 // Reset stop condition
1172 allDegenerated = Standard_True;
1176 // Do not insert nodes in last pass in non-SharedMode
1177 caninsert = (myWithShare || pass < nbPasses);
1180 nbtriangles = myStructure->ElemOfDomain().Extent();
1181 if (nbtriangles <= 0) break;
1183 // Iterate on current triangles
1184 BRepMesh_MapOfInteger::Iterator triDom;
1185 const BRepMesh_MapOfInteger& TriMap = myStructure->ElemOfDomain();
1186 triDom.Initialize(TriMap);
1187 Standard_Integer aNbPnt = 0;
1188 Standard_Real umin = myAttrib->GetUMin();
1189 Standard_Real vmin = myAttrib->GetVMin();
1190 Standard_Real deltaX = myAttrib->GetDeltaX();
1191 Standard_Real deltaY = myAttrib->GetDeltaY();
1192 for (; triDom.More(); triDom.Next())
1194 Standard_Integer TriId = triDom.Key();
1195 const BRepMesh_Triangle& curTri=Triangle(TriId);
1196 if (curTri.Movability()==BRepMesh_Deleted) continue;
1198 Standard_Boolean o1, o2, o3;
1199 Standard_Integer v1 = 0, v2 = 0, v3 = 0, e1 = 0, e2 = 0, e3 = 0;
1200 curTri.Edges(e1, e2, e3, o1, o2, o3);
1202 const BRepMesh_Edge& edg1=Edge(e1);
1203 const BRepMesh_Edge& edg2=Edge(e2);
1204 const BRepMesh_Edge& edg3=Edge(e3);
1206 Standard_Boolean m1 = (edg1.Movability() == BRepMesh_Frontier);
1207 Standard_Boolean m2 = (edg2.Movability() == BRepMesh_Frontier);
1208 Standard_Boolean m3 = (edg3.Movability() == BRepMesh_Frontier);
1210 v1=edg1.FirstNode();
1215 v2=edg1.FirstNode();
1220 v3=edg2.FirstNode();
1222 const BRepMesh_Vertex& vert1=Vertex(v1);
1223 const BRepMesh_Vertex& vert2=Vertex(v2);
1224 const BRepMesh_Vertex& vert3=Vertex(v3);
1226 const gp_XYZ& p1=myLocation3d(vert1.Location3d()).Coord();
1227 const gp_XYZ& p2=myLocation3d(vert2.Location3d()).Coord();
1228 const gp_XYZ& p3=myLocation3d(vert3.Location3d()).Coord();
1234 // Check for degenerated triangle
1235 if (vecEd1.SquareModulus() < MinimalSqLength3d ||
1236 vecEd2.SquareModulus() < MinimalSqLength3d ||
1237 vecEd3.SquareModulus() < MinimalSqLength3d)
1239 theNulTriangles.Append(TriId);
1243 allDegenerated = Standard_False;
1245 gp_XY xy1(vert1.Coord().X()*deltaX+umin,vert1.Coord().Y()*deltaY+vmin);
1246 gp_XY xy2(vert2.Coord().X()*deltaX+umin,vert2.Coord().Y()*deltaY+vmin);
1247 gp_XY xy3(vert3.Coord().X()*deltaX+umin,vert3.Coord().Y()*deltaY+vmin);
1249 // Check triangle area in 2d
1250 if (Abs((xy2-xy1)^(xy3-xy1)) < MinimalArea2d)
1252 theNulTriangles.Append(TriId);
1256 // Check triangle normal
1257 gp_XYZ normal(vecEd1^vecEd2);
1258 dv = normal.Modulus();
1259 if (dv < Precision::Confusion())
1261 theNulTriangles.Append(TriId);
1266 // Check deflection on triangle
1267 mi2d = (xy1+xy2+xy3)/3.0;
1268 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1269 defl = pDef.SquareDistance((p1+p2+p3)/3.);
1270 if (defl > maxdef) maxdef = defl;
1271 if (defl > sqdefface)
1273 if (theIsFirst) break;
1276 // Record new vertex
1279 myLocation3d.Bind(myNbLocat,pDef);
1280 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1281 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1282 theInternalV.Append(InsVertex);
1284 theBadTriangles.Append(TriId);
1287 if (!m2) // Not a boundary
1289 // Check if this link was already processed
1290 if (v2 < v3) { nf = v2; nl = v3; } else { nf = v3; nl = v2; }
1291 if (theCouples.Add(BRepMesh_Couple(nf,nl)))
1293 // Check deflection on edge 1
1294 mi2d = (xy2+xy3)*0.5;
1295 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1296 defl = pDef.SquareDistance((p2+p3)/2.);
1297 if (defl > maxdef) maxdef = defl;
1298 if (defl > sqdefface)
1300 if (theIsFirst) break;
1303 // Record new vertex
1306 myLocation3d.Bind(myNbLocat,pDef);
1307 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1308 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1309 theInternalV.Append(InsVertex);
1311 theBadTriangles.Append(TriId);
1316 if (!m3) // Not a boundary
1318 // Check if this link was already processed
1319 if (v1 < v3) { nf = v1; nl = v3; } else { nf = v3; nl = v1; }
1320 if (theCouples.Add(BRepMesh_Couple(nf,nl)))
1322 // Check deflection on edge 2
1323 mi2d = (xy3+xy1)*0.5;
1324 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1325 defl = pDef.SquareDistance((p1+p3)/2.);
1326 if (defl > maxdef) maxdef = defl;
1327 if (defl > sqdefface)
1329 if (theIsFirst) break;
1332 // Record new vertex
1335 myLocation3d.Bind(myNbLocat,pDef);
1336 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1337 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1338 theInternalV.Append(InsVertex);
1340 theBadTriangles.Append(TriId);
1345 if (!m1) // Not a boundary
1347 // Check if this link was already processed
1348 if (v1 < v2) { nf = v1; nl = v2; } else { nf = v2; nl = v1; }
1349 if (theCouples.Add(BRepMesh_Couple(nf,nl)))
1351 // Check deflection on edge 3
1352 mi2d = (xy1+xy2)*0.5;
1353 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1354 defl = pDef.SquareDistance((p1+p2)/2.);
1355 if (defl > maxdef) maxdef = defl;
1356 if (defl > sqdefface)
1358 if (theIsFirst) break;
1361 // Record new vertex
1364 myLocation3d.Bind(myNbLocat,pDef);
1365 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1366 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1367 theInternalV.Append(InsVertex);
1369 theBadTriangles.Append(TriId);
1375 if(isSpline && !BSpl.IsNull() && (theBadTriangles.IsEmpty() || theBadTriangles.Last() != TriId))
1377 gp_Dir N1(0,0,1), N2(0,0,1), N3(0,0,1);
1378 Standard_Integer aSt1, aSt2, aSt3;
1379 if(aNorMap.IsBound(v1)) {
1380 aSt1 = aStatMap.Find(v1);
1381 N1 =aNorMap.Find(v1);
1384 aSt1 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy1), Precision::Confusion(), N1);
1385 aStatMap.Bind(v1,aSt1);
1386 aNorMap.Bind(v1,N1);
1389 if(aNorMap.IsBound(v2)) {
1390 aSt2 = aStatMap.Find(v2);
1391 N2 = aNorMap.Find(v2);
1394 aSt2 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy2), Precision::Confusion(), N2);
1395 aStatMap.Bind(v2,aSt2);
1396 aNorMap.Bind(v2,N2);
1399 if(aNorMap.IsBound(v3)) {
1400 aSt3 = aStatMap.Find(v3);
1401 N3 = aNorMap.Find(v3);
1404 aSt3 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy3), Precision::Confusion(), N3);
1405 aStatMap.Bind(v3,aSt3);
1406 aNorMap.Bind(v3,N3.XYZ());
1409 Standard_Real anAngle1 = N2.Angle(N1);
1410 Standard_Real anAngle2 = N3.Angle(N2);
1411 Standard_Real anAngle3 = N1.Angle(N3);
1412 if(aSt1 < 1 && aSt2 < 1 && aSt3 < 1 &&
1413 (anAngle1 > myAngle || anAngle2 > myAngle || anAngle3 > myAngle)) {
1419 // Record new vertex
1422 mi2d = (xy1+xy2+xy3)/3.;
1423 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1424 myLocation3d.Bind(myNbLocat,pDef);
1425 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1426 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1427 theInternalV.Append(InsVertex);
1428 theBadTriangles.Append(TriId);
1431 //In case if triangle is considerd as OK, we have to check three intermediate
1432 //points to be sure that we free from wave effect. If it is OK triangle passed if not split in middle point
1433 if(theBadTriangles.IsEmpty() || theBadTriangles.Last() != TriId)
1437 aB2d.Add(gp_Pnt2d(xy1)); aB2d.Add(gp_Pnt2d(xy2)); aB2d.Add(gp_Pnt2d(xy3));
1439 Standard_Real aXMin1, aXMax1, aYMin1, aYMax1;
1440 aB2d.Get(aXMin1, aYMin1, aXMax1, aYMax1);
1442 if(aXMax1 - aXMin1 < ddu && aYMax1 - aYMin1 < ddv)
1445 mi2d = (xy1+xy2+xy3)/3.;
1446 gp_Pnt2d aP[3] = {mi2d+(xy1-mi2d)*2/3., mi2d+(xy2-mi2d)*2/3, mi2d+(xy3-mi2d)*2/3.};
1447 gp_Dir midDir(0,0,1);
1448 Standard_Integer aSt[4];
1449 aSt[0] = GeomLib::NormEstim(BSpl, gp_Pnt2d(mi2d), Precision::Confusion(), midDir);
1450 Standard_Integer i = 0;
1451 gp_Dir dir[3] = {gp_Dir(0,0,1), gp_Dir(0,0,1), gp_Dir(0,0,1)};
1452 Standard_Real anAngle[3];
1456 aSt[i+1] = GeomLib::NormEstim(BSpl, aP[i], Precision::Confusion(), dir);
1457 anAngle[i] = dir.Angle(midDir);
1460 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1461 aB2d.Add(gp_Pnt2d(xy1)); aB2d.Add(gp_Pnt2d(xy2)); aB2d.Add(gp_Pnt2d(xy3));
1462 if(aSt[0] < 1 && aSt[1] < 1 && aSt[2] < 1 && aSt[3] < 1 &&
1463 (anAngle[0] > myAngle || anAngle[1] > myAngle || anAngle[2] > myAngle) &&
1464 (aXMax1 - aXMin1 > ddu || aYMax1 - aYMin1 > ddv))
1472 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1473 myLocation3d.Bind(myNbLocat,pDef);
1474 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1475 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1476 theInternalV.Append(InsVertex);
1477 theBadTriangles.Append(TriId);
1483 if (!theIsFirst && theInternalV.Extent() > 0)
1485 BRepMesh_Array1OfVertexOfDelaun verttab(1, theInternalV.Extent());
1486 BRepMesh_ListIteratorOfListOfVertex itVer(theInternalV);
1487 Standard_Integer ipn = 1;
1488 for (; itVer.More(); itVer.Next())
1489 verttab(ipn++) = itVer.Value();
1491 theTrigu.AddVertices(verttab);
1497 return Sqrt(maxdef);
1500 //=======================================================================
1501 //function : AddInShape
1503 //=======================================================================
1504 void BRepMesh_FastDiscretFace::AddInShape(const TopoDS_Face& theFace,
1505 const Standard_Real theDefFace)
1509 TopLoc_Location loc = theFace.Location();
1510 Handle(Poly_Triangulation) TOld = BRep_Tool::Triangulation(theFace, loc);
1511 Handle(Poly_Triangulation) TNull;
1512 Handle(Poly_PolygonOnTriangulation) NullPoly;
1513 B.UpdateFace(theFace,TNull);
1516 BRepMesh_MapOfInteger::Iterator it;
1518 Standard_Integer e1, e2, e3, nTri;
1519 Standard_Integer v1, v2, v3, iv1, iv2, iv3;
1520 Standard_Integer i, index;
1521 Standard_Boolean o1, o2, o3;
1522 TopAbs_Orientation orFace = theFace.Orientation();
1524 const BRepMesh_MapOfInteger& TriMap = myStructure->ElemOfDomain();
1525 it.Initialize(TriMap);
1527 nTri = TriMap.Extent();
1531 Poly_Array1OfTriangle Tri(1, nTri);
1535 for (; it.More(); it.Next()) {
1536 myStructure->GetElement(it.Key()).Edges(e1, e2, e3, o1, o2, o3);
1538 const BRepMesh_Edge& ve1=myStructure->GetLink(e1);
1539 const BRepMesh_Edge& ve2=myStructure->GetLink(e2);
1540 const BRepMesh_Edge& ve3=myStructure->GetLink(e3);
1559 iv1 = myVemap.FindIndex(v1);
1560 if (iv1 == 0) iv1 = myVemap.Add(v1);
1561 iv2 = myVemap.FindIndex(v2);
1562 if (iv2 == 0) iv2 = myVemap.Add(v2);
1563 iv3 = myVemap.FindIndex(v3);
1564 if (iv3 == 0) iv3 = myVemap.Add(v3);
1566 if (orFace == TopAbs_REVERSED) Tri(i++).Set(iv1, iv3, iv2);
1567 else Tri(i++).Set(iv1, iv2, iv3);
1570 Standard_Integer nbVertices = myVemap.Extent();
1571 Handle(Poly_Triangulation) T = new Poly_Triangulation(nbVertices, nTri, Standard_True);
1572 Poly_Array1OfTriangle& Trian = T->ChangeTriangles();
1574 TColgp_Array1OfPnt& Nodes = T->ChangeNodes();
1575 TColgp_Array1OfPnt2d& Nodes2d = T->ChangeUVNodes();
1577 for (i = 1; i <= nbVertices; i++) {
1578 index = myVemap.FindKey(i);
1579 Nodes(i) = Pnt(index);
1580 Nodes2d(i).SetXY(Vertex(index).Coord());
1583 T->Deflection(theDefFace);
1585 // stockage de la triangulation dans la BRep.
1587 //TopLoc_Location loc = theFace.Location();
1588 if (!loc.IsIdentity()) {
1589 gp_Trsf tr = loc.Transformation();
1591 for (i = Nodes.Lower(); i <= Nodes.Upper(); i++)
1592 Nodes(i).Transform(tr);
1594 B1.UpdateFace(theFace, T);
1596 // mise en place des polygones sur triangulation dans la face:
1597 BRepMesh_DataMapIteratorOfDataMapOfShapePairOfPolygon It(myInternaledges);
1599 for (; It.More(); It.Next()) {
1600 const BRepMesh_PairOfPolygon& pair = It.Value();
1601 const Handle(Poly_PolygonOnTriangulation)& NOD1 = pair.First();
1602 const Handle(Poly_PolygonOnTriangulation)& NOD2 = pair.Last();
1603 if ( NOD1 == NOD2 ) {
1604 B.UpdateEdge(TopoDS::Edge(It.Key()), NullPoly, TOld,loc);
1605 B.UpdateEdge(TopoDS::Edge(It.Key()), NOD1, T, loc);
1608 B.UpdateEdge(TopoDS::Edge(It.Key()), NullPoly, TOld,loc);
1609 B.UpdateEdge(TopoDS::Edge(It.Key()), NOD1, NOD2, T, loc);
1614 catch(Standard_Failure)
1616 // MESH_FAILURE(theFace);
1621 //=======================================================================
1622 //function : Triangle
1624 //=======================================================================
1626 const BRepMesh_Triangle& BRepMesh_FastDiscretFace::Triangle(const Standard_Integer Index) const
1628 return myStructure->GetElement(Index);
1631 //=======================================================================
1632 //function : NbEdges
1634 //=======================================================================
1636 /*Standard_Integer BRepMesh_FastDiscretFace::NbEdges() const
1638 return myStructure->NbLinks();
1641 //=======================================================================
1644 //=======================================================================
1646 const BRepMesh_Edge& BRepMesh_FastDiscretFace::Edge(const Standard_Integer Index) const
1648 return myStructure->GetLink(Index);
1652 //=======================================================================
1655 //=======================================================================
1657 const BRepMesh_Vertex& BRepMesh_FastDiscretFace::Vertex(const Standard_Integer Index) const
1659 return myStructure->GetNode(Index);
1662 //=======================================================================
1665 //=======================================================================
1667 const gp_Pnt& BRepMesh_FastDiscretFace::Pnt(const Standard_Integer Index) const
1669 return myLocation3d(myStructure->GetNode(Index).Location3d());
1672 //=======================================================================
1675 //=======================================================================
1677 gp_XY BRepMesh_FastDiscretFace::FindUV(const TopoDS_Vertex& theV,
1678 const gp_Pnt2d& theXY,
1679 const Standard_Integer theIp,
1680 const Handle(BRepAdaptor_HSurface)& theSFace,
1681 const Standard_Real theMinDist,
1682 BRepMesh_DataMapOfIntegerListOfXY& theLocation2dMap)
1685 if (theLocation2dMap.IsBound(theIp))
1687 BRepMesh_ListOfXY& L = theLocation2dMap.ChangeFind(theIp);
1689 if (L.Extent() != 1)
1691 BRepMesh_ListIteratorOfListOfXY it(L);
1693 Standard_Real dd, dmin = theXY.Distance(gp_Pnt2d(anUV));
1694 for (; it.More(); it.Next())
1696 dd = theXY.Distance(gp_Pnt2d(it.Value()));
1705 const Standard_Real tol = Min(2. * BRep_Tool::Tolerance(theV), theMinDist);
1707 const Standard_Real Utol2d = .5 * (theSFace->LastUParameter() - theSFace->FirstUParameter());
1708 const Standard_Real Vtol2d = .5 * (theSFace->LastVParameter() - theSFace->FirstVParameter());
1710 const gp_Pnt p1 = theSFace->Value(anUV.X(), anUV.Y());
1711 const gp_Pnt p2 = theSFace->Value(theXY.X(), theXY.Y());
1713 if (Abs(anUV.X() - theXY.X()) > Utol2d ||
1714 Abs(anUV.Y() - theXY.Y()) > Vtol2d ||
1715 !p1.IsEqual(p2, tol))
1717 anUV = theXY.Coord();
1723 anUV = theXY.Coord();
1724 BRepMesh_ListOfXY L;
1726 theLocation2dMap.Bind(theIp, L);
1732 static Standard_Boolean GetVertexParameters(const TopoDS_Vertex& theVert,
1733 const TopoDS_Face& theFace,
1737 const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace,L);
1738 L = L.Predivided(theVert.Location());
1739 BRep_ListIteratorOfListOfPointRepresentation itpr =
1740 ((*((Handle(BRep_TVertex)*) &theVert.TShape()))->Points());
1741 // On regarde dabord si il y des PointRepresentation (cas non Manifold)
1743 while (itpr.More()) {
1744 if (itpr.Value()->IsPointOnSurface(S,L)) {
1745 thePoint.SetCoord(itpr.Value()->Parameter(),
1746 itpr.Value()->Parameter2());
1747 return Standard_True;
1751 return Standard_False;
1754 //=======================================================================
1756 //purpose : method intended to addition internal myVertices in triangulation.
1757 //=======================================================================
1758 void BRepMesh_FastDiscretFace::Add(const TopoDS_Vertex& theVert,
1759 const TopoDS_Face& theFace,
1760 const Handle(BRepAdaptor_HSurface)& thegFace)
1762 const TopAbs_Orientation anOrient = theVert.Orientation();
1764 if( anOrient != TopAbs_INTERNAL || !GetVertexParameters(theVert,theFace,uvXY))
1766 Standard_Integer indVert =0;
1767 if (myVertices.IsBound(theVert))
1768 indVert = myVertices.Find(theVert);
1772 myLocation3d.Bind(myNbLocat, BRep_Tool::Pnt(theVert));
1773 indVert = myNbLocat;
1774 myVertices.Bind(theVert, indVert);
1776 Standard_Real mindist = BRep_Tool::Tolerance(theVert);
1777 // gp_Pnt2d uvXY = BRep_Tool::Parameters(theVert,theFace);
1778 gp_XY anUV = FindUV(theVert, uvXY, indVert, thegFace, mindist, myLocation2d);
1779 BRepMesh_Vertex vf(anUV, indVert, BRepMesh_Fixed);
1780 Standard_Integer ivff = myStructure->AddNode(vf);
1781 Standard_Integer isvf = myVemap.FindIndex(ivff);
1782 if (isvf == 0) isvf = myVemap.Add(ivff);