1 // Created by: Ekaterina SMIRNOVA
2 // Copyright (c) 2008-2012 OPEN CASCADE SAS
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
20 #include <BRepMesh_FastDiscretFace.ixx>
22 #include <Adaptor3d_IsoCurve.hxx>
23 #include <BRepAdaptor_Curve.hxx>
24 #include <BRepMesh_GeomTool.hxx>
25 #include <BRepMesh_ListOfXY.hxx>
26 #include <BRepMesh_Array1OfVertexOfDelaun.hxx>
27 #include <BRepMesh_ListIteratorOfListOfVertex.hxx>
28 #include <BRepMesh_ListIteratorOfListOfXY.hxx>
29 #include <BRepMesh_PairOfPolygon.hxx>
30 #include <BRepMesh_DataMapIteratorOfDataMapOfShapePairOfPolygon.hxx>
31 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
32 #include <BRepMesh_ClassifierPtr.hxx>
33 #include <BRep_Builder.hxx>
34 #include <BRep_PointRepresentation.hxx>
35 #include <BRep_TVertex.hxx>
36 #include <BRep_Tool.hxx>
37 #include <Geom_Surface.hxx>
39 #include <Standard_ErrorHandler.hxx>
40 #include <Standard_Failure.hxx>
41 #include <SortTools_ShellSortOfReal.hxx>
42 #include <Poly_PolygonOnTriangulation.hxx>
43 #include <Poly_Triangulation.hxx>
44 #include <TCollection_CompareOfReal.hxx>
45 #include <TColStd_Array1OfReal.hxx>
46 #include <TColStd_SequenceOfReal.hxx>
47 #include <TColStd_Array1OfInteger.hxx>
48 #include <TColStd_HArray1OfReal.hxx>
49 #include <TopExp_Explorer.hxx>
52 #include <TColgp_Array1OfPnt2d.hxx>
53 #include <NCollection_Map.hxx>
54 #include <Geom_BSplineSurface.hxx>
55 #include <GeomLib.hxx>
56 #include <Bnd_Box2d.hxx>
58 #define UVDEFLECTION 1.e-05
60 static Standard_Mutex DummyMutex;
62 static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen)
64 Standard_Integer i, j, n = 0;
65 Standard_Real p, result = 0.;
67 for(i = 1; i <= PLen; i++)
70 for(j = i + 1; j <= PLen; j++)
82 p = Abs(P(i) - P(i-1));
90 return (n? (result / (Standard_Real) n) : -1.);
93 //=======================================================================
94 //function : BRepMesh_FastDiscretFace
96 //=======================================================================
97 BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace
98 (const Standard_Real theAngle,
99 const Standard_Boolean theWithShare) :
100 myAngle(theAngle), myWithShare(theWithShare), myNbLocat(0),
101 myInternalVerticesMode(Standard_True)
103 myAllocator = new NCollection_IncAllocator(64000);
106 //=======================================================================
107 //function : Add(face)
109 //=======================================================================
111 void BRepMesh_FastDiscretFace::Add(const TopoDS_Face& theFace,
112 const Handle(BRepMesh_FaceAttribute)& theAttrib,
113 const TopTools_DataMapOfShapeReal& theMapDefle,
114 const TopTools_MutexForShapeProvider& theMutexProvider)
121 TopoDS_Face face = theFace;
124 const Handle(Poly_Triangulation)& aFaceTrigu = BRep_Tool::Triangulation(face, loc);
125 if ( aFaceTrigu.IsNull() )
128 myAttrib = theAttrib;
129 face.Orientation(TopAbs_FORWARD);
130 myStructure.Nullify();
131 Handle(NCollection_IncAllocator) anAlloc = Handle(NCollection_IncAllocator)::DownCast(myAllocator);
132 anAlloc->Reset(Standard_False);
133 myStructure=new BRepMesh_DataStructureOfDelaun(anAlloc);
135 Standard_Real umax = myAttrib->GetUMax();
136 Standard_Real umin = myAttrib->GetUMin();
137 Standard_Real vmax = myAttrib->GetVMax();
138 Standard_Real vmin = myAttrib->GetVMin();
140 Standard_Real aTolU = (umax - umin) * UVDEFLECTION;
141 Standard_Real aTolV = (vmax - vmin) * UVDEFLECTION;
142 Standard_Real uCellSize = 14 * aTolU;
143 Standard_Real vCellSize = 14 * aTolV;
145 myStructure->Data().SetCellSize ( uCellSize, vCellSize );
146 myStructure->Data().SetTolerance( aTolU, aTolV );
149 BRepAdaptor_Surface BS(face, Standard_False);
150 Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS);
152 GeomAbs_SurfaceType thetype;
153 thetype = BS.GetType();
155 TopAbs_Orientation orFace = face.Orientation();
162 myLocation2d.Clear();
163 myInternaledges.Clear();
165 Standard_Integer i = 1;
166 Standard_Integer ipn = 0;
168 TopoDS_Iterator exW(face);
169 for (; exW.More(); exW.Next()) {
170 const TopoDS_Shape& aWire = exW.Value();
171 if (aWire.ShapeType() != TopAbs_WIRE)
173 TopoDS_Iterator ex(aWire);
174 for(; ex.More(); ex.Next()) {
175 const TopoDS_Edge& edge = TopoDS::Edge(ex.Value());
178 RestoreStructureFromTriangulation(edge, face, gFace, aFaceTrigu, theMapDefle(edge), loc, theMutexProvider);
182 ////////////////////////////////////////////////////////////
183 //add internal vertices after self-intersection check
184 Standard_Integer nbVertices = 0;
185 if(myInternalVerticesMode) {
186 for(TopExp_Explorer ex(face,TopAbs_VERTEX ,TopAbs_EDGE); ex.More(); ex.Next()) {
187 const TopoDS_Vertex& aVert = TopoDS::Vertex(ex.Current());
188 Add(aVert,face,gFace);
190 nbVertices = myVemap.Extent();
193 // essai de determination de la longueur vraie:
194 // akm (bug OCC16) : We must calculate these measures in non-singular
195 // parts of face. Let`s try to compute average value of three
196 // (umin, (umin+umax)/2, umax), and respectively for v.
198 //Standard_Real longu = 0.0, longv = 0.0; //, last , first;
199 //gp_Pnt P11, P12, P21, P22, P31, P32;
201 Standard_Real deltaX = myAttrib->GetDeltaX();
202 Standard_Real deltaY = myAttrib->GetDeltaY();
204 TColStd_Array1OfInteger tabvert_corr(1, nbVertices);
207 // Check the necessity to fill the map of parameters
208 const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus ||
209 thetype == GeomAbs_BezierSurface ||
210 thetype == GeomAbs_BSplineSurface);
214 BRepMesh_VertexTool aMoveNodes(myVemap.Extent(), myAllocator);
216 aMoveNodes.SetCellSize ( uCellSize / deltaX, vCellSize / deltaY);
217 aMoveNodes.SetTolerance( aTolU / deltaX, aTolV / deltaY);
219 for (i = 1; i <= myStructure->NbNodes(); i++)
221 const BRepMesh_Vertex& v = myStructure->GetNode(i);
224 myUParam.Add(p2d.X());
225 myVParam.Add(p2d.Y());
228 res.SetCoord((p2d.X() - umin ) / deltaX,
229 (p2d.Y() - vmin ) / deltaY);
230 BRepMesh_Vertex v_new(res,v.Location3d(),v.Movability());
231 const BRepMesh_ListOfInteger& alist = myStructure->GetNodeList(i);
232 aMoveNodes.Add(v_new, alist);
235 myStructure->ReplaceNodes(aMoveNodes);
237 Standard_Boolean rajout;
239 BRepMesh_ClassifierPtr& classifier = theAttrib->GetClassifier();
245 rajout = Standard_True;
248 rajout = Standard_False;
251 BRepMesh_Delaun trigu(myStructure, tabvert_corr, orFace==TopAbs_FORWARD);
253 //removed all free edges from triangulation
254 Standard_Integer nbLinks = myStructure->NbNodes();
255 for(i = 1; i <= nbLinks; i++)
257 if(myStructure->ElemConnectedTo(i).Extent() < 1)
259 BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i);
260 if(anEdge.Movability()==BRepMesh_Deleted)
262 anEdge.SetMovability(BRepMesh_Free);
263 myStructure->RemoveLink(i);
267 Standard_Boolean isaline;
268 isaline = ((umax-umin) < UVDEFLECTION) || ((vmax-vmin) < UVDEFLECTION);
270 Standard_Real aDef = -1;
271 if (!isaline && myStructure->ElemOfDomain().Extent() > 0) {
272 TColStd_ListOfInteger badTri, nulTri;
276 aDef = Control(gFace, theAttrib->GetDefFace(), myListver, badTri, nulTri, trigu, Standard_True);
277 if( aDef > theAttrib->GetDefFace() || aDef < 0.)
278 rajout = Standard_True;
284 if(myVParam.Extent() > 2) {
285 rajout = Standard_True;
289 if(myUParam.Extent() > 2) {
290 rajout = Standard_True;
297 InternalVertices(gFace, myListver, theAttrib->GetDefFace(), classifier);
299 if (myListver.Extent() > 0) {
300 BRepMesh_Array1OfVertexOfDelaun verttab(1, myListver.Extent());
301 BRepMesh_ListIteratorOfListOfVertex itVer(myListver);
303 for (; itVer.More(); itVer.Next())
304 verttab(ipn++) = itVer.Value();
305 trigu.AddVertices(verttab);
307 //control internal points
308 BRepMesh_ListOfVertex vvlist;
309 aDef = Control(gFace, theAttrib->GetDefFace(), vvlist, badTri, nulTri, trigu, Standard_False);
310 myListver.Append(vvlist);
314 //modify myStructure back
315 aMoveNodes.SetCellSize ( uCellSize, vCellSize );
316 aMoveNodes.SetTolerance( aTolU , aTolV );
317 for (i = 1; i <= myStructure->NbNodes(); i++)
319 const BRepMesh_Vertex& v = myStructure->GetNode(i);
322 res.SetCoord(p2d.X() * deltaX + umin, p2d.Y() * deltaY + vmin);
323 BRepMesh_Vertex v_new(res,v.Location3d(),v.Movability());
324 const BRepMesh_ListOfInteger& alist = myStructure->GetNodeList(i);
325 aMoveNodes.Add(v_new, alist);
327 myStructure->ReplaceNodes(aMoveNodes);
329 AddInShape(face, (aDef < 0.0)? theAttrib->GetDefFace() : aDef, theMutexProvider);
332 catch(Standard_Failure)
335 Handle(Poly_Triangulation) TNull;
336 B.UpdateFace(theFace,TNull);
339 myStructure.Nullify();
343 //=======================================================================
344 //function : RestoreStructureFromTriangulation(edge)
345 //purpose : Restore structure of Delaun from triangulation on face
346 //=======================================================================
347 Standard_Boolean BRepMesh_FastDiscretFace::RestoreStructureFromTriangulation
348 (const TopoDS_Edge& theEdge,
349 const TopoDS_Face& theFace,
350 const Handle(BRepAdaptor_HSurface)& theSurf,
351 const Handle(Poly_Triangulation)& theTrigu,
352 const Standard_Real theDefEdge,
353 const TopLoc_Location& theLoc,
354 const TopTools_MutexForShapeProvider& theMutexProvider)
357 TopAbs_Orientation orEdge = theEdge.Orientation();
358 // Get end points on 2d curve
359 gp_Pnt2d uvFirst, uvLast;
360 // oan: changes for right restoring of triangulation data from face & edges
361 Handle(Poly_PolygonOnTriangulation) Poly;
364 // lock mutex during querying data from edge curves to prevent parallel change of the same data
365 Standard_Mutex* aMutex = theMutexProvider.GetMutex(theEdge);
366 Standard_Mutex::SentryNested aSentry(aMutex == NULL ? DummyMutex : *aMutex,
369 Poly = BRep_Tool::PolygonOnTriangulation(theEdge, theTrigu, theLoc);
370 if (Poly.IsNull() || !Poly->HasParameters())
371 return Standard_False;
373 BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast);
377 TopoDS_Vertex pBegin, pEnd;
378 TopExp::Vertices(theEdge,pBegin,pEnd);
380 const Standard_Boolean sameUV =
381 uvFirst.IsEqual(uvLast, Precision::PConfusion());
383 const TColgp_Array1OfPnt2d& UVNodes = theTrigu->UVNodes();
384 const TColgp_Array1OfPnt& Nodes = theTrigu->Nodes();
385 const TColStd_Array1OfInteger& Indices = Poly->Nodes();
387 const Standard_Integer nbnodes = Indices.Length();
388 TColStd_Array1OfInteger NewNodes(1, nbnodes);
393 // Process first vertex
394 Standard_Integer ipf;
395 if (myVertices.IsBound(pBegin))
397 ipf = myVertices.Find(pBegin);
401 if (sameUV && myVertices.IsBound(pEnd))
403 ipf = myVertices.Find(pEnd);
407 P3d = Nodes(Indices(1));
408 if (!theLoc.IsIdentity())
409 P3d.Transform(theLoc.Transformation());
411 myLocation3d.Bind(myNbLocat, P3d);
414 myVertices.Bind(pBegin,ipf);
417 //Controle vertice tolerances
418 gp_Pnt pFirst = theSurf->Value(uvFirst.X(), uvFirst.Y());
419 gp_Pnt pLast = theSurf->Value(uvLast.X(), uvLast.Y());
421 Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)),
422 pLast.Distance(BRep_Tool::Pnt(pEnd)));
424 if (mindist < BRep_Tool::Tolerance(pBegin) ||
425 mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge;
427 anUV = FindUV(pBegin, uvFirst, ipf, theSurf, mindist, myLocation2d);
428 Standard_Integer iv1, isv1;
429 BRepMesh_Vertex vf(anUV, ipf, BRepMesh_Frontier);
430 iv1 = myStructure->AddNode(vf);
431 isv1 = myVemap.FindIndex(iv1);
433 isv1 = myVemap.Add(iv1);
436 // Process last vertex
437 Standard_Integer ipl, ivl;
438 if (pEnd.IsSame(pBegin))
444 if (myVertices.IsBound(pEnd))
446 ipl = myVertices.Find(pEnd);
457 P3d = Nodes(Indices(nbnodes));
458 if (!theLoc.IsIdentity())
459 P3d.Transform(theLoc.Transformation());
461 myLocation3d.Bind(myNbLocat, P3d);
464 myVertices.Bind(pEnd,ipl);
468 anUV = FindUV(pEnd, uvLast, ipl, theSurf, mindist, myLocation2d);
469 BRepMesh_Vertex vl(anUV, ipl, BRepMesh_Frontier);
471 Standard_Integer isvl;
472 ivl = myStructure->AddNode(vl);
473 isvl = myVemap.FindIndex(ivl);
475 isvl = myVemap.Add(ivl);
476 NewNodes(nbnodes) = isvl;
481 for (i = 2; i < nbnodes; i++)
484 P3d = Nodes(Indices(i));
485 if (!theLoc.IsIdentity())
486 P3d.Transform(theLoc.Transformation());
488 myLocation3d.Bind(myNbLocat, P3d);
491 anUV = UVNodes(Indices(i)).Coord();
493 Standard_Integer iv2, isv;
494 v.Initialize(anUV, myNbLocat, BRepMesh_Frontier);
495 iv2 = myStructure->AddNode(v);
496 isv = myVemap.FindIndex(iv2);
498 isv = myVemap.Add(iv2);
502 if (orEdge == TopAbs_FORWARD)
503 myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier));
504 else if (orEdge == TopAbs_REVERSED)
505 myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier));
506 else if (orEdge == TopAbs_INTERNAL)
507 myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed));
513 if (orEdge == TopAbs_FORWARD)
514 myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier));
515 else if (orEdge == TopAbs_REVERSED)
516 myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier));
517 else if (orEdge == TopAbs_INTERNAL)
518 myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed));
521 Handle(Poly_PolygonOnTriangulation) P1 =
522 new Poly_PolygonOnTriangulation(NewNodes, Poly->Parameters()->Array1());
523 P1->Deflection(theDefEdge);
524 if (myInternaledges.IsBound(theEdge))
526 BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge);
527 if (theEdge.Orientation() == TopAbs_REVERSED)
534 BRepMesh_PairOfPolygon pair1;
536 myInternaledges.Bind(theEdge, pair1);
539 return Standard_True;
542 //=======================================================================
543 //function : InternalVertices
545 //=======================================================================
547 static void filterParameters(const TColStd_IndexedMapOfReal& theParams,
548 const Standard_Real theMinDist,
549 const Standard_Real theFilterDist,
550 TColStd_SequenceOfReal& theResult)
552 // Sort sequence of parameters
553 TColStd_SequenceOfReal aParamTmp;
554 Standard_Integer aParamLength = 1;
555 const Standard_Integer anInitLen = theParams.Extent();
557 TColStd_Array1OfReal aParamArray(1, anInitLen);
559 for (j = 1; j <= anInitLen; j++)
560 aParamArray(j) = theParams(j);
562 TCollection_CompareOfReal aCompare;
563 SortTools_ShellSortOfReal::Sort(aParamArray, aCompare);
565 // mandadory pre-filtering using the first (minimal) filter value
566 Standard_Real aP1, aP2;
567 aP1 = aParamArray(1);
568 aParamTmp.Append(aP1);
569 for (j = 2; j <= anInitLen; j++)
571 aP2 = aParamArray(j);
572 if ((aP2-aP1) > theMinDist)
574 aParamTmp.Append(aP2);
580 //add last point if required
581 if(aParamArray(anInitLen)-theParams(aParamLength) > theMinDist)
583 aParamTmp.Append(aParamArray(anInitLen));
587 //perform filtering on series
588 Standard_Real aLastAdded, aLastCandidate;
589 Standard_Boolean isCandidateDefined = Standard_False;
590 aLastAdded = aParamTmp.First();
591 aLastCandidate = aLastAdded;
592 theResult.Append(aParamTmp.First());
594 for(j=2;j<aParamTmp.Length();j++)
596 Standard_Real aVal = aParamTmp.Value(j);
597 if(aVal-aLastAdded > theFilterDist)
600 if(isCandidateDefined) {
601 aLastAdded = aLastCandidate;
602 isCandidateDefined = Standard_False;
609 theResult.Append(aLastAdded);
613 aLastCandidate = aVal;
614 isCandidateDefined = Standard_True;
616 theResult.Append(aParamTmp.Last());
618 if( theResult.Length() == 2 )
620 Standard_Real dist = theResult.Last() - theResult.First();
621 Standard_Integer nbint = (Standard_Integer)((dist / theFilterDist) + 0.5);
625 //Five points more is maximum
632 Standard_Real dU = dist / nbint;
633 for( i = 1; i < nbint; i++ )
635 theResult.InsertAfter(i, theResult.First()+i*dU);
641 void BRepMesh_FastDiscretFace::InternalVertices(const Handle(BRepAdaptor_HSurface)& theCaro,
642 BRepMesh_ListOfVertex& theInternalV,
643 const Standard_Real theDefFace,
644 const BRepMesh_ClassifierPtr& theClassifier)
646 BRepMesh_Vertex newV;
650 // work following the type of surface
651 const BRepAdaptor_Surface& BS = *(BRepAdaptor_Surface*)&(theCaro->Surface());
652 GeomAbs_SurfaceType thetype = theCaro->GetType();
654 Standard_Real umax = myAttrib->GetUMax();
655 Standard_Real umin = myAttrib->GetUMin();
656 Standard_Real vmax = myAttrib->GetVMax();
657 Standard_Real vmin = myAttrib->GetVMin();
658 Standard_Real deltaX = myAttrib->GetDeltaX();
659 Standard_Real deltaY = myAttrib->GetDeltaY();
661 if (thetype == GeomAbs_Sphere)
663 gp_Sphere S = BS.Sphere();
664 const Standard_Real R = S.Radius();
666 // Calculate parameters for iteration in V direction
667 Standard_Real Dv = 1.0 - (theDefFace/R);
668 if (Dv < 0.0) Dv = 0.0;
669 Standard_Real oldDv = 2.0 * ACos (Dv);
670 Dv = .7 * oldDv; //.7 ~= sqrt(2.) - Dv is hypotenuse of triangle when oldDv is legs
671 const Standard_Real sv = vmax - vmin;
672 Dv = sv/((Standard_Integer)(sv/Dv) + 1);
673 const Standard_Real pasvmax = vmax-Dv*0.5;
675 //Du can be defined from relation: 2*r*Sin(Du/2) = 2*R*Sin(Dv/2), r = R*Cos(v)
676 //here approximate relation r*Du = R*Dv is used
678 Standard_Real Du, pasu, pasv; //, ru;
679 const Standard_Real su = umax-umin;
680 Standard_Boolean Shift = Standard_False;
681 for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv)
683 // Calculate parameters for iteration in U direction
684 // 1.-.365*pasv*pasv is simple approximation of Cos(pasv)
685 // with condition that it gives ~.1 when pasv = pi/2
686 Du = Dv/(1.-.365*pasv*pasv);
687 Du = su/((Standard_Integer)(su/Du) + 1);
689 const Standard_Real d = (Shift)? Du*.5 : 0.;
690 const Standard_Real pasumax = umax-Du*0.5 + d;
691 for (pasu = umin + Du - d; pasu < pasumax; pasu += Du)
693 if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
696 #ifdef DEB_MESH_CHRONO
699 ElSLib::D0(pasu, pasv, S, p3d);
701 myLocation3d.Bind(myNbLocat, p3d);
703 p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
704 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
705 theInternalV.Append(newV);
710 else if (thetype == GeomAbs_Cylinder)
712 gp_Cylinder S = BS.Cylinder();
713 const Standard_Real R = S.Radius();
715 // Calculate parameters for iteration in U direction
716 Standard_Real Du = 1.0 - (theDefFace/R);
717 if (Du < 0.0) Du = 0.0;
718 Du = 2.0 * ACos (Du);
719 if (Du > myAngle) Du = myAngle;
720 const Standard_Real su = umax - umin;
721 const Standard_Integer nbU = (Standard_Integer)(su/Du);
724 // Calculate parameters for iteration in V direction
725 const Standard_Real sv = vmax - vmin;
726 Standard_Integer nbV = (Standard_Integer)( nbU*sv/(su*R) );
727 nbV = Min(nbV, 100*nbU);
728 Standard_Real Dv = sv/(nbV+1);
730 Standard_Real pasu, pasv, pasvmax = vmax-Dv*0.5, pasumax = umax-Du*0.5;
731 for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) {
732 for (pasu = umin + Du; pasu < pasumax; pasu += Du) {
733 if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
736 ElSLib::D0(pasu, pasv, S, p3d);
738 myLocation3d.Bind(myNbLocat, p3d);
740 p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
741 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
742 theInternalV.Append(newV);
747 else if (thetype == GeomAbs_Cone)
749 Standard_Real R, RefR, SAng;
750 gp_Cone C = BS.Cone();
751 RefR = C.RefRadius();
752 SAng = C.SemiAngle();
753 R = Max(Abs(RefR+vmin*Sin(SAng)), Abs(RefR+vmax*Sin(SAng)));
754 Standard_Real Du, Dv, pasu, pasv;
755 Du = Max(1.0e0 - (theDefFace/R),0.0e0);
756 Du = (2.0 * ACos (Du));
757 Standard_Integer nbU = (Standard_Integer) ( (umax-umin)/Du );
758 Standard_Integer nbV = (Standard_Integer) ( nbU*(vmax-vmin)/((umax-umin)*R) );
759 Du = (umax-umin)/(nbU+1);
760 Dv = (vmax-vmin)/(nbV+1);
762 Standard_Real pasvmax = vmax-Dv*0.5, pasumax = umax-Du*0.5;
763 for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) {
764 for (pasu = umin + Du; pasu < pasumax; pasu += Du) {
765 if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
768 ElSLib::D0(pasu, pasv, C, p3d);
770 myLocation3d.Bind(myNbLocat, p3d);
772 p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
773 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
774 theInternalV.Append(newV);
779 else if (thetype == GeomAbs_Torus)
781 gp_Torus T = BS.Torus();
783 Standard_Boolean insert;
784 Standard_Integer i, j, ParamULength, ParamVLength;
785 Standard_Real pp, pasu, pasv;
786 Standard_Real r = T.MinorRadius(), R = T.MajorRadius();
788 TColStd_SequenceOfReal ParamU, ParamV;
790 Standard_Real Du, Dv;//, pasu, pasv;
791 Dv = Max(1.0e0 - (theDefFace/r),0.0e0) ;
792 Standard_Real oldDv = 2.0 * ACos (Dv);
793 oldDv = Min(oldDv, myAngle);
794 Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
797 Standard_Integer nbV = Max((Standard_Integer)((vmax-vmin)/Dv), 2);
798 Dv = (vmax-vmin)/(nbV+1);
799 Standard_Real ru = R + r;
802 Du = 2.0 * ACos(Max(1.0 - (theDefFace/ru),0.0));
803 if (myAngle < Du) Du = myAngle;
804 Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
805 if(aa < gp::Resolution())
807 Du *= Min(oldDv, Du) / aa;
811 Standard_Integer nbU = Max((Standard_Integer)((umax-umin)/Du), 2);
812 nbU = Max(nbU , (int)(nbV*(umax-umin)*R/((vmax-vmin)*r)/5.));
813 Du = (umax-umin)/(nbU+1);
817 // As the points of edges are returned.
818 // in this case, the points are not representative.
820 //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid
821 for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du);
826 // Number of mapped U parameters
827 const Standard_Integer LenU = myUParam.Extent();
828 // Fill array of U parameters
829 TColStd_Array1OfReal Up(1,LenU);
830 for (j = 1; j <= LenU; j++) Up(j) = myUParam(j);
832 // Calculate DU, leave array of parameters
833 Standard_Real aDU = FUN_CalcAverageDUV(Up,LenU);
834 aDU = Max(aDU, Abs(umax - umin) / (Standard_Real) nbU / 2.);
835 Standard_Real dUstd = Abs(umax - umin) / (Standard_Real) LenU;
836 if (aDU > dUstd) dUstd = aDU;
838 for (j = 1; j <= LenU; j++)
841 insert = Standard_True;
842 ParamULength = ParamU.Length();
843 for (i = 1; i <= ParamULength && insert; i++)
845 insert = (Abs(ParamU.Value(i)-pp) > (0.5*dUstd));
847 if (insert) ParamU.Append(pp);
852 // Number of mapped V parameters
853 const Standard_Integer LenV = myVParam.Extent();
854 // Fill array of V parameters
855 TColStd_Array1OfReal Vp(1,LenV);
856 for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j);
857 // Calculate DV, sort array of parameters
858 Standard_Real aDV = FUN_CalcAverageDUV(Vp,LenV);
859 aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real) nbV / 2.);
861 Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real) LenV;
862 if (aDV > dVstd) dVstd = aDV;
864 for (j = 1; j <= LenV; j++)
868 insert = Standard_True;
869 ParamVLength = ParamV.Length();
870 for (i = 1; i <= ParamVLength && insert; i++)
872 insert = (Abs(ParamV.Value(i)-pp) > (dVstd*2./3.));
874 if (insert) ParamV.Append(pp);
877 Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
878 Standard_Real uminnew = umin+deltaY*0.1;
879 Standard_Real vminnew = vmin+deltaX*0.1;
880 Standard_Real umaxnew = umax-deltaY*0.1;
881 Standard_Real vmaxnew = vmax-deltaX*0.1;
883 for (i = 1; i <= Lu; i++)
885 pasu = ParamU.Value(i);
886 if (pasu >= uminnew && pasu < umaxnew)
888 for (j = 1; j <= Lv; j++)
890 pasv = ParamV.Value(j);
891 if (pasv >= vminnew && pasv < vmaxnew)
893 if (theClassifier->Perform(gp_Pnt2d(pasu, pasv)) == TopAbs_IN)
896 ElSLib::D0(pasu, pasv, T, p3d);
898 myLocation3d.Bind(myNbLocat, p3d);
900 p2d.SetCoord((pasu-umin)/deltaX, (pasv-vmin)/deltaY);
901 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
902 theInternalV.Append(newV);
909 else if (thetype == GeomAbs_BezierSurface || thetype == GeomAbs_BSplineSurface)
912 Standard_Real uRes = BS.UResolution(theDefFace);
913 Standard_Real vRes = BS.VResolution(theDefFace);
915 // Sort and filter sequence of parameters
916 Standard_Real aMinDu = Precision::PConfusion();
920 Standard_Real aDuMaxLim = 0.1*(umax-umin);
921 Standard_Real ddu = Min(aDuMaxLim,Max(0.005*(umax-umin),2.*uRes));
922 TColStd_SequenceOfReal ParamU;
923 filterParameters(myUParam,aMinDu,ddu,ParamU);
924 Standard_Integer ParamULength = ParamU.Length();
926 Standard_Real aMinDv = Precision::PConfusion();
930 Standard_Real aDvMaxLim = 0.1*(vmax-vmin);
931 Standard_Real ddv = Min(aDvMaxLim,Max(0.005*(vmax-vmin),2.*vRes));
932 TColStd_SequenceOfReal ParamV;
933 filterParameters(myVParam,aMinDv,ddv,ParamV);
934 Standard_Integer ParamVLength = ParamV.Length();
936 // check intermediate isolines
937 Handle(Geom_Surface) B;
938 if (thetype == GeomAbs_BezierSurface) {
945 gp_Pnt P1, P2, PControl;
946 Standard_Real u, v, dist;
948 // precision for compare square distances
949 double dPreci = Precision::Confusion()*Precision::Confusion();
951 // Insert V parameters by deflection criterion
952 Standard_Integer i,j;
953 Standard_Real V1, V2, U1, U2;
954 for (i = 1; i <= ParamULength; i++) {
955 Handle(Geom_Curve) IsoU = B->UIso(ParamU.Value(i));
956 V1 = ParamV.Value(1);
957 P1 = IsoU->Value(V1);
958 for (j = 2; j <= ParamVLength;) {
959 V2 = ParamV.Value(j);
960 P2 = IsoU->Value(V2);
962 PControl = IsoU->Value(v);
963 // 23.03.2010 skl for OCC21645 - change precision for comparison
964 if( P1.SquareDistance(P2) > dPreci ) {
965 gp_Lin L (P1, gp_Dir(gp_Vec(P1, P2)));
966 dist = L.Distance(PControl);
969 dist = P1.Distance(PControl);
971 if (dist > theDefFace) {
973 ParamV.InsertBefore(j, v);
977 //put regular grig for normals
978 gp_Dir N1(0,0,1),N2(0,0,1);
979 Standard_Boolean aSt1 = GeomLib::NormEstim(B, gp_Pnt2d(ParamU.Value(i),V1), Precision::Confusion(), N1);
980 Standard_Boolean aSt2 = GeomLib::NormEstim(B, gp_Pnt2d(ParamU.Value(i),v), Precision::Confusion(), N2);
982 Standard_Real anAngle1 = N2.Angle(N1);
983 if(aSt1 < 1 && aSt2 < 1 && anAngle1 > myAngle ) {
985 ParamV.InsertBefore(j, v);
997 for (i = 2; i < ParamVLength; i++) {
999 Handle(Geom_Curve) IsoV = B->VIso(v);
1000 U1 = ParamU.Value(1);
1001 P1 = IsoV->Value(U1);
1002 for (j = 2; j <= ParamULength;) {
1003 U2 = ParamU.Value(j);
1004 P2 = IsoV->Value(U2);
1006 PControl = IsoV->Value(u);
1007 // 23.03.2010 skl for OCC21645 - change precision for comparison
1008 if( P1.SquareDistance(P2) > dPreci ) {
1009 gp_Lin L (P1, gp_Dir(gp_Vec(P1, P2)));
1010 dist = L.Distance(PControl);
1013 dist = P1.Distance(PControl);
1015 if (dist > theDefFace) {
1017 ParamU.InsertBefore(j, u);
1022 //put regular grig for normals
1023 gp_Dir N1(0,0,1),N2(0,0,1);
1024 Standard_Boolean aSt1 = GeomLib::NormEstim(B, gp_Pnt2d(U1,v), Precision::Confusion(), N1);
1025 Standard_Boolean aSt2 = GeomLib::NormEstim(B, gp_Pnt2d(u,v), Precision::Confusion(), N2);
1027 Standard_Real anAngle1 = N2.Angle(N1);
1028 if(aSt1 < 1 && aSt2 < 1 && anAngle1 > myAngle) {
1030 ParamU.InsertBefore(j, u);
1036 if (j < ParamULength) {
1037 // Classify intersection point
1038 if (theClassifier->Perform(gp_Pnt2d(U1, v)) == TopAbs_IN)
1042 myLocation3d.Bind(myNbLocat, P1);
1044 p2d.SetCoord((U1-umin)/deltaX, (v-vmin)/deltaY);
1045 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
1046 theInternalV.Append(newV);
1056 const Standard_Real anAngle = 0.35;
1058 Standard_Integer i, j, nbpointsU = 10, nbpointsV = 10;
1059 Adaptor3d_IsoCurve tabu[11], tabv[11];
1061 TColStd_SequenceOfReal ParamU, ParamV;
1062 Standard_Real u, v, du, dv;
1063 Standard_Integer iu, iv;
1066 du = (umax-umin) / (nbpointsU+1); dv = (vmax-vmin) / (nbpointsV+1);
1068 for (iu = 0; iu <= nbpointsU; iu++) {
1070 tabu[iu].Load(theCaro);
1071 tabu[iu].Load(GeomAbs_IsoU, u);
1074 for (iv = 0; iv <= nbpointsV; iv++) {
1076 tabv[iv].Load(theCaro);
1077 tabv[iv].Load(GeomAbs_IsoV, v);
1080 Standard_Integer imax = 1, MaxV = 0;
1082 GCPnts_TangentialDeflection* tabGU = new GCPnts_TangentialDeflection[nbpointsU+1];
1084 for (i = 0; i <= nbpointsU; i++) {
1085 f = Max(vmin, tabu[i].FirstParameter());
1086 l = Min(vmax, tabu[i].LastParameter());
1087 GCPnts_TangentialDeflection theDeflection(tabu[i], f, l, anAngle, 0.7*theDefFace, 2);
1088 tabGU[i] = theDeflection;
1089 if (tabGU[i].NbPoints() > MaxV) {
1090 MaxV = tabGU[i].NbPoints();
1095 // return table of parameters V:
1096 Standard_Integer NV = tabGU[imax].NbPoints();
1097 for (i = 1; i <= NV; i++) {
1098 ParamV.Append(tabGU[imax].Parameter(i));
1103 Standard_Integer MaxU = 0;
1105 GCPnts_TangentialDeflection* tabGV = new GCPnts_TangentialDeflection[nbpointsV+1];
1107 for (i = 0; i <= nbpointsV; i++) {
1108 f = Max(umin, tabv[i].FirstParameter());
1109 l = Min(umax, tabv[i].LastParameter());
1110 GCPnts_TangentialDeflection thedeflection2(tabv[i], f, l, anAngle, 0.7*theDefFace, 2);
1111 tabGV[i] = thedeflection2;
1112 if (tabGV[i].NbPoints() > MaxU) {
1113 MaxU = tabGV[i].NbPoints();
1118 // return table of parameters U:
1119 Standard_Integer NU = tabGV[imax].NbPoints();
1120 for (i = 1; i <= NU; i++) {
1121 ParamU.Append(tabGV[imax].Parameter(i));
1125 if (ParamU.Length() == 2) {
1126 ParamU.InsertAfter(1, (umax+umin)*0.5);
1128 if (ParamV.Length() == 2) {
1129 ParamV.InsertAfter(1, (vmax+vmin)*0.5);
1132 TColStd_SequenceOfReal InsertV, InsertU;
1135 Adaptor3d_IsoCurve IsoV;
1138 Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length();
1140 for (i = 2; i < Lv; i++) {
1141 v = ParamV.Value(i);
1142 IsoV.Load(GeomAbs_IsoV, v);
1143 for (j = 2; j < Lu; j++) {
1144 u = ParamU.Value(j);
1145 if (theClassifier->Perform(gp_Pnt2d(u, v)) == TopAbs_IN)
1150 myLocation3d.Bind(myNbLocat, P1);
1152 p2d.SetCoord((u-umin)/deltaX, (v-vmin)/deltaY);
1153 newV.Initialize(p2d.XY(), myNbLocat, BRepMesh_Free);
1154 theInternalV.Append(newV);
1159 #ifdef DEB_MESH_CHRONO
1165 * Internal class Couple, moved from MeshData package
1168 class BRepMesh_Couple
1171 BRepMesh_Couple() { myI1 = myI2 = 0; }
1172 BRepMesh_Couple(const Standard_Integer I1,
1173 const Standard_Integer I2)
1174 { myI1 = I1; myI2 = I2; }
1176 Standard_Integer myI1;
1177 Standard_Integer myI2;
1180 inline Standard_Boolean IsEqual(const BRepMesh_Couple& one,
1181 const BRepMesh_Couple& other)
1183 if (one.myI1 == other.myI1 &&
1184 one.myI2 == other.myI2) return Standard_True;
1185 else return Standard_False;
1188 inline Standard_Integer HashCode(const BRepMesh_Couple& one,
1189 const Standard_Integer Upper)
1191 return ::HashCode((one.myI1+one.myI2), Upper);
1194 typedef NCollection_Map<BRepMesh_Couple> BRepMesh_MapOfCouple;
1196 //=======================================================================
1197 //function : Control
1199 //=======================================================================
1200 Standard_Real BRepMesh_FastDiscretFace::Control(const Handle(BRepAdaptor_HSurface)& theCaro,
1201 const Standard_Real theDefFace,
1202 BRepMesh_ListOfVertex& theInternalV,
1203 TColStd_ListOfInteger& theBadTriangles,
1204 TColStd_ListOfInteger& theNulTriangles,
1205 BRepMesh_Delaun& theTrigu,
1206 const Standard_Boolean theIsFirst)
1208 //IMPORTANT: Constants used in calculations
1209 const Standard_Real MinimalArea2d = 1.e-9;
1210 const Standard_Real MinimalSqLength3d = 1.e-12;
1212 // Define the number of iterations
1213 Standard_Integer myNbIterations = 11;
1214 const Standard_Integer nbPasses = (theIsFirst? 1 : myNbIterations);
1216 // Initialize stop condition
1217 Standard_Boolean allDegenerated = Standard_False;
1218 Standard_Integer nbInserted = 1;
1220 // Create map of links to skip already processed
1221 Standard_Integer nbtriangles;
1223 nbtriangles = myStructure->ElemOfDomain().Extent();
1224 if (nbtriangles <= 0) return -1.0;
1225 BRepMesh_MapOfCouple theCouples(3*nbtriangles);
1228 gp_XYZ vecEd1, vecEd2, vecEd3;
1230 Standard_Real dv = 0, defl = 0, maxdef = -1;
1231 Standard_Integer pass = 1, nf = 0, nl = 0;
1232 BRepMesh_Vertex InsVertex;
1233 Standard_Boolean caninsert;
1235 Standard_Real sqdefface = theDefFace * theDefFace;
1237 GeomAbs_SurfaceType thetype = theCaro->GetType();
1238 Handle(Geom_Surface) BSpl;
1239 Standard_Boolean isSpline = Standard_False;
1240 if (thetype == GeomAbs_BezierSurface || thetype == GeomAbs_BSplineSurface)
1242 isSpline = Standard_True;
1243 if (thetype == GeomAbs_BezierSurface)
1244 BSpl = theCaro->Bezier();
1246 BSpl = theCaro->BSpline();
1249 NCollection_DataMap<Standard_Integer,gp_Dir> aNorMap;
1250 NCollection_DataMap<Standard_Integer,Standard_Integer> aStatMap;
1252 // Perform refinement passes
1253 for (; pass <= nbPasses && nbInserted && !allDegenerated; pass++)
1255 theInternalV.Clear();
1256 theBadTriangles.Clear();
1258 // Reset stop condition
1259 allDegenerated = Standard_True;
1263 // Do not insert nodes in last pass in non-SharedMode
1264 caninsert = (myWithShare || pass < nbPasses);
1267 nbtriangles = myStructure->ElemOfDomain().Extent();
1268 if (nbtriangles <= 0) break;
1270 // Iterate on current triangles
1271 BRepMesh_MapOfInteger::Iterator triDom;
1272 const BRepMesh_MapOfInteger& TriMap = myStructure->ElemOfDomain();
1273 triDom.Initialize(TriMap);
1274 Standard_Integer aNbPnt = 0;
1275 Standard_Real umin = myAttrib->GetUMin();
1276 Standard_Real vmin = myAttrib->GetVMin();
1277 Standard_Real deltaX = myAttrib->GetDeltaX();
1278 Standard_Real deltaY = myAttrib->GetDeltaY();
1279 for (; triDom.More(); triDom.Next())
1281 Standard_Integer TriId = triDom.Key();
1282 const BRepMesh_Triangle& curTri=Triangle(TriId);
1283 if (curTri.Movability()==BRepMesh_Deleted) continue;
1285 Standard_Boolean o1, o2, o3;
1286 Standard_Integer v1 = 0, v2 = 0, v3 = 0, e1 = 0, e2 = 0, e3 = 0;
1287 curTri.Edges(e1, e2, e3, o1, o2, o3);
1289 const BRepMesh_Edge& edg1=Edge(e1);
1290 const BRepMesh_Edge& edg2=Edge(e2);
1291 const BRepMesh_Edge& edg3=Edge(e3);
1293 Standard_Boolean m1 = (edg1.Movability() == BRepMesh_Frontier);
1294 Standard_Boolean m2 = (edg2.Movability() == BRepMesh_Frontier);
1295 Standard_Boolean m3 = (edg3.Movability() == BRepMesh_Frontier);
1297 v1=edg1.FirstNode();
1302 v2=edg1.FirstNode();
1307 v3=edg2.FirstNode();
1309 const BRepMesh_Vertex& vert1=Vertex(v1);
1310 const BRepMesh_Vertex& vert2=Vertex(v2);
1311 const BRepMesh_Vertex& vert3=Vertex(v3);
1313 const gp_XYZ& p1=myLocation3d(vert1.Location3d()).Coord();
1314 const gp_XYZ& p2=myLocation3d(vert2.Location3d()).Coord();
1315 const gp_XYZ& p3=myLocation3d(vert3.Location3d()).Coord();
1321 // Check for degenerated triangle
1322 if (vecEd1.SquareModulus() < MinimalSqLength3d ||
1323 vecEd2.SquareModulus() < MinimalSqLength3d ||
1324 vecEd3.SquareModulus() < MinimalSqLength3d)
1326 theNulTriangles.Append(TriId);
1330 allDegenerated = Standard_False;
1332 gp_XY xy1(vert1.Coord().X()*deltaX+umin,vert1.Coord().Y()*deltaY+vmin);
1333 gp_XY xy2(vert2.Coord().X()*deltaX+umin,vert2.Coord().Y()*deltaY+vmin);
1334 gp_XY xy3(vert3.Coord().X()*deltaX+umin,vert3.Coord().Y()*deltaY+vmin);
1336 // Check triangle area in 2d
1337 if (Abs((xy2-xy1)^(xy3-xy1)) < MinimalArea2d)
1339 theNulTriangles.Append(TriId);
1343 // Check triangle normal
1344 gp_XYZ normal(vecEd1^vecEd2);
1345 dv = normal.Modulus();
1346 if (dv < Precision::Confusion())
1348 theNulTriangles.Append(TriId);
1353 // Check deflection on triangle
1354 mi2d = (xy1+xy2+xy3)/3.0;
1355 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1356 defl = Abs(normal*(pDef.XYZ()-p1));
1358 /*mi2d = (xy1+xy2+xy3)/3.0;
1359 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1360 defl = pDef.SquareDistance((p1+p2+p3)/3.);*/
1361 if (defl > maxdef) maxdef = defl;
1362 if (defl > sqdefface)
1364 if (theIsFirst) break;
1367 // Record new vertex
1370 myLocation3d.Bind(myNbLocat,pDef);
1371 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1372 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1373 theInternalV.Append(InsVertex);
1375 theBadTriangles.Append(TriId);
1378 if (!m2) // Not a boundary
1380 // Check if this link was already processed
1381 if (v2 < v3) { nf = v2; nl = v3; } else { nf = v3; nl = v2; }
1382 if (theCouples.Add(BRepMesh_Couple(nf,nl)))
1384 // Check deflection on edge 1
1385 mi2d = (xy2+xy3)*0.5;
1386 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1387 gp_Lin L (p2, gp_Vec(p2, p3));
1388 defl = L.SquareDistance(pDef);
1389 if (defl > maxdef) maxdef = defl;
1390 if (defl > sqdefface)
1392 if (theIsFirst) break;
1395 // Record new vertex
1398 myLocation3d.Bind(myNbLocat,pDef);
1399 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1400 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1401 theInternalV.Append(InsVertex);
1403 theBadTriangles.Append(TriId);
1408 if (!m3) // Not a boundary
1410 // Check if this link was already processed
1411 if (v1 < v3) { nf = v1; nl = v3; } else { nf = v3; nl = v1; }
1412 if (theCouples.Add(BRepMesh_Couple(nf,nl)))
1414 // Check deflection on edge 2
1415 mi2d = (xy3+xy1)*0.5;
1416 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1417 gp_Lin L (p1, gp_Vec(p1, p3));
1418 defl = L.SquareDistance(pDef);
1419 if (defl > maxdef) maxdef = defl;
1420 if (defl > sqdefface)
1422 if (theIsFirst) break;
1425 // Record new vertex
1428 myLocation3d.Bind(myNbLocat,pDef);
1429 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1430 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1431 theInternalV.Append(InsVertex);
1433 theBadTriangles.Append(TriId);
1438 if (!m1) // Not a boundary
1440 // Check if this link was already processed
1441 if (v1 < v2) { nf = v1; nl = v2; } else { nf = v2; nl = v1; }
1442 if (theCouples.Add(BRepMesh_Couple(nf,nl)))
1444 // Check deflection on edge 3
1445 mi2d = (xy1+xy2)*0.5;
1446 theCaro->D0(mi2d.X(), mi2d.Y(), pDef);
1447 gp_Lin L (p1, gp_Vec(p1, p2));
1448 defl = L.SquareDistance(pDef);
1449 if (defl > maxdef) maxdef = defl;
1450 if (defl > sqdefface)
1452 if (theIsFirst) break;
1455 // Record new vertex
1458 myLocation3d.Bind(myNbLocat,pDef);
1459 mi2d.SetCoord((mi2d.X()-umin)/deltaX,(mi2d.Y()-vmin)/deltaY);
1460 InsVertex.Initialize(mi2d,myNbLocat,BRepMesh_Free);
1461 theInternalV.Append(InsVertex);
1463 theBadTriangles.Append(TriId);
1468 //check normal on bsplines
1469 if(theIsFirst && isSpline && !BSpl.IsNull() )
1471 gp_Dir N1(0,0,1), N2(0,0,1), N3(0,0,1);
1472 Standard_Integer aSt1, aSt2, aSt3;
1473 if(aNorMap.IsBound(v1)) {
1474 aSt1 = aStatMap.Find(v1);
1475 N1 =aNorMap.Find(v1);
1478 aSt1 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy1), Precision::Confusion(), N1);
1479 aStatMap.Bind(v1,aSt1);
1480 aNorMap.Bind(v1,N1);
1483 if(aNorMap.IsBound(v2)) {
1484 aSt2 = aStatMap.Find(v2);
1485 N2 = aNorMap.Find(v2);
1488 aSt2 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy2), Precision::Confusion(), N2);
1489 aStatMap.Bind(v2,aSt2);
1490 aNorMap.Bind(v2,N2);
1493 if(aNorMap.IsBound(v3)) {
1494 aSt3 = aStatMap.Find(v3);
1495 N3 = aNorMap.Find(v3);
1498 aSt3 = GeomLib::NormEstim(BSpl, gp_Pnt2d(xy3), Precision::Confusion(), N3);
1499 aStatMap.Bind(v3,aSt3);
1500 aNorMap.Bind(v3,N3.XYZ());
1503 Standard_Real anAngle1 = N2.Angle(N1);
1504 Standard_Real anAngle2 = N3.Angle(N2);
1505 Standard_Real anAngle3 = N1.Angle(N3);
1506 if(aSt1 < 1 && aSt2 < 1 && aSt3 < 1 &&
1507 (anAngle1 > myAngle || anAngle2 > myAngle || anAngle3 > myAngle)) {
1515 if (!theIsFirst && theInternalV.Extent() > 0)
1517 BRepMesh_Array1OfVertexOfDelaun verttab(1, theInternalV.Extent());
1518 BRepMesh_ListIteratorOfListOfVertex itVer(theInternalV);
1519 Standard_Integer ipn = 1;
1520 for (; itVer.More(); itVer.Next())
1521 verttab(ipn++) = itVer.Value();
1523 theTrigu.AddVertices(verttab);
1530 return Sqrt(maxdef);
1533 //=======================================================================
1534 //function : AddInShape
1536 //=======================================================================
1537 void BRepMesh_FastDiscretFace::AddInShape(const TopoDS_Face& theFace,
1538 const Standard_Real theDefFace,
1539 const TopTools_MutexForShapeProvider& theMutexProvider)
1543 TopLoc_Location loc = theFace.Location();
1544 Handle(Poly_Triangulation) TOld = BRep_Tool::Triangulation(theFace, loc);
1545 Handle(Poly_Triangulation) TNull;
1546 Handle(Poly_PolygonOnTriangulation) NullPoly;
1547 B.UpdateFace(theFace,TNull);
1550 BRepMesh_MapOfInteger::Iterator it;
1552 Standard_Integer e1, e2, e3, nTri;
1553 Standard_Integer v1, v2, v3, iv1, iv2, iv3;
1554 Standard_Integer i, index;
1555 Standard_Boolean o1, o2, o3;
1556 TopAbs_Orientation orFace = theFace.Orientation();
1558 const BRepMesh_MapOfInteger& TriMap = myStructure->ElemOfDomain();
1559 it.Initialize(TriMap);
1561 nTri = TriMap.Extent();
1565 Poly_Array1OfTriangle Tri(1, nTri);
1569 for (; it.More(); it.Next()) {
1570 myStructure->GetElement(it.Key()).Edges(e1, e2, e3, o1, o2, o3);
1572 const BRepMesh_Edge& ve1=myStructure->GetLink(e1);
1573 const BRepMesh_Edge& ve2=myStructure->GetLink(e2);
1592 iv1 = myVemap.FindIndex(v1);
1593 if (iv1 == 0) iv1 = myVemap.Add(v1);
1594 iv2 = myVemap.FindIndex(v2);
1595 if (iv2 == 0) iv2 = myVemap.Add(v2);
1596 iv3 = myVemap.FindIndex(v3);
1597 if (iv3 == 0) iv3 = myVemap.Add(v3);
1599 if (orFace == TopAbs_REVERSED) Tri(i++).Set(iv1, iv3, iv2);
1600 else Tri(i++).Set(iv1, iv2, iv3);
1603 Standard_Integer nbVertices = myVemap.Extent();
1604 Handle(Poly_Triangulation) T = new Poly_Triangulation(nbVertices, nTri, Standard_True);
1605 Poly_Array1OfTriangle& Trian = T->ChangeTriangles();
1607 TColgp_Array1OfPnt& Nodes = T->ChangeNodes();
1608 TColgp_Array1OfPnt2d& Nodes2d = T->ChangeUVNodes();
1610 for (i = 1; i <= nbVertices; i++) {
1611 index = myVemap.FindKey(i);
1612 Nodes(i) = Pnt(index);
1613 Nodes2d(i).SetXY(Vertex(index).Coord());
1616 T->Deflection(theDefFace);
1618 // storage of triangulation in BRep.
1620 //TopLoc_Location loc = theFace.Location();
1621 if (!loc.IsIdentity()) {
1622 gp_Trsf tr = loc.Transformation();
1624 for (i = Nodes.Lower(); i <= Nodes.Upper(); i++)
1625 Nodes(i).Transform(tr);
1627 B1.UpdateFace(theFace, T);
1629 // implement polygons on triangulation in the face:
1630 BRepMesh_DataMapIteratorOfDataMapOfShapePairOfPolygon It(myInternaledges);
1632 for (; It.More(); It.Next()) {
1633 const BRepMesh_PairOfPolygon& pair = It.Value();
1634 const Handle(Poly_PolygonOnTriangulation)& NOD1 = pair.First();
1635 const Handle(Poly_PolygonOnTriangulation)& NOD2 = pair.Last();
1637 // lock mutex to prevent parallel change of the same data
1638 Standard_Mutex* aMutex = theMutexProvider.GetMutex(It.Key());
1639 Standard_Mutex::SentryNested aSentry(aMutex == NULL ? DummyMutex : *aMutex,
1642 if ( NOD1 == NOD2 ) {
1643 B.UpdateEdge(TopoDS::Edge(It.Key()), NullPoly, TOld,loc);
1644 B.UpdateEdge(TopoDS::Edge(It.Key()), NOD1, T, loc);
1647 B.UpdateEdge(TopoDS::Edge(It.Key()), NullPoly, TOld,loc);
1648 B.UpdateEdge(TopoDS::Edge(It.Key()), NOD1, NOD2, T, loc);
1654 catch(Standard_Failure)
1656 // MESH_FAILURE(theFace);
1661 //=======================================================================
1662 //function : Triangle
1664 //=======================================================================
1666 const BRepMesh_Triangle& BRepMesh_FastDiscretFace::Triangle(const Standard_Integer Index) const
1668 return myStructure->GetElement(Index);
1671 //=======================================================================
1672 //function : NbEdges
1674 //=======================================================================
1676 /*Standard_Integer BRepMesh_FastDiscretFace::NbEdges() const
1678 return myStructure->NbLinks();
1681 //=======================================================================
1684 //=======================================================================
1686 const BRepMesh_Edge& BRepMesh_FastDiscretFace::Edge(const Standard_Integer Index) const
1688 return myStructure->GetLink(Index);
1692 //=======================================================================
1695 //=======================================================================
1697 const BRepMesh_Vertex& BRepMesh_FastDiscretFace::Vertex(const Standard_Integer Index) const
1699 return myStructure->GetNode(Index);
1702 //=======================================================================
1705 //=======================================================================
1707 const gp_Pnt& BRepMesh_FastDiscretFace::Pnt(const Standard_Integer Index) const
1709 return myLocation3d(myStructure->GetNode(Index).Location3d());
1712 //=======================================================================
1715 //=======================================================================
1717 gp_XY BRepMesh_FastDiscretFace::FindUV(const TopoDS_Vertex& theV,
1718 const gp_Pnt2d& theXY,
1719 const Standard_Integer theIp,
1720 const Handle(BRepAdaptor_HSurface)& theSFace,
1721 const Standard_Real theMinDist,
1722 BRepMesh_DataMapOfIntegerListOfXY& theLocation2dMap)
1725 if (theLocation2dMap.IsBound(theIp))
1727 BRepMesh_ListOfXY& L = theLocation2dMap.ChangeFind(theIp);
1729 if (L.Extent() != 1)
1731 BRepMesh_ListIteratorOfListOfXY it(L);
1733 Standard_Real dd, dmin = theXY.Distance(gp_Pnt2d(anUV));
1734 for (; it.More(); it.Next())
1736 dd = theXY.Distance(gp_Pnt2d(it.Value()));
1745 const Standard_Real tol = Min(2. * BRep_Tool::Tolerance(theV), theMinDist);
1747 const Standard_Real Utol2d = .5 * (theSFace->LastUParameter() - theSFace->FirstUParameter());
1748 const Standard_Real Vtol2d = .5 * (theSFace->LastVParameter() - theSFace->FirstVParameter());
1750 const gp_Pnt p1 = theSFace->Value(anUV.X(), anUV.Y());
1751 const gp_Pnt p2 = theSFace->Value(theXY.X(), theXY.Y());
1753 if (Abs(anUV.X() - theXY.X()) > Utol2d ||
1754 Abs(anUV.Y() - theXY.Y()) > Vtol2d ||
1755 !p1.IsEqual(p2, tol))
1757 anUV = theXY.Coord();
1763 anUV = theXY.Coord();
1764 BRepMesh_ListOfXY L;
1766 theLocation2dMap.Bind(theIp, L);
1772 static Standard_Boolean GetVertexParameters(const TopoDS_Vertex& theVert,
1773 const TopoDS_Face& theFace,
1777 const Handle(Geom_Surface)& S = BRep_Tool::Surface(theFace,L);
1778 L = L.Predivided(theVert.Location());
1779 BRep_ListIteratorOfListOfPointRepresentation itpr =
1780 ((*((Handle(BRep_TVertex)*) &theVert.TShape()))->Points());
1781 // Check first if there are PointRepresentation (case non Manifold)
1783 while (itpr.More()) {
1784 if (itpr.Value()->IsPointOnSurface(S,L)) {
1785 thePoint.SetCoord(itpr.Value()->Parameter(),
1786 itpr.Value()->Parameter2());
1787 return Standard_True;
1791 return Standard_False;
1794 //=======================================================================
1796 //purpose : method intended to add internal myVertices in triangulation.
1797 //=======================================================================
1798 void BRepMesh_FastDiscretFace::Add(const TopoDS_Vertex& theVert,
1799 const TopoDS_Face& theFace,
1800 const Handle(BRepAdaptor_HSurface)& thegFace)
1802 const TopAbs_Orientation anOrient = theVert.Orientation();
1804 if( anOrient != TopAbs_INTERNAL || !GetVertexParameters(theVert,theFace,uvXY))
1806 Standard_Integer indVert =0;
1807 if (myVertices.IsBound(theVert))
1808 indVert = myVertices.Find(theVert);
1812 myLocation3d.Bind(myNbLocat, BRep_Tool::Pnt(theVert));
1813 indVert = myNbLocat;
1814 myVertices.Bind(theVert, indVert);
1816 Standard_Real mindist = BRep_Tool::Tolerance(theVert);
1817 // gp_Pnt2d uvXY = BRep_Tool::Parameters(theVert,theFace);
1818 gp_XY anUV = FindUV(theVert, uvXY, indVert, thegFace, mindist, myLocation2d);
1819 BRepMesh_Vertex vf(anUV, indVert, BRepMesh_Fixed);
1820 Standard_Integer ivff = myStructure->AddNode(vf);
1821 Standard_Integer isvf = myVemap.FindIndex(ivff);
1822 if (isvf == 0) isvf = myVemap.Add(ivff);