1 // File: BRepMesh_FastDiscret.cxx
2 // Created: Tue Feb 27 16:39:53 1996
3 // Author: Ekaterina SMIRNOVA
4 // Copyright: Open CASCADE SAS 2008
6 #include <BRepMesh_FastDiscret.ixx>
8 #include <BRepMesh_FastDiscretFace.hxx>
9 #include <BRepMesh_FaceAttribute.hxx>
10 #include <BRepMesh_DataStructureOfDelaun.hxx>
11 #include <BRepMesh_ClassifierPtr.hxx>
12 #include <BRepMesh_GeomTool.hxx>
13 #include <BRepMesh_PairOfPolygon.hxx>
14 #include <BRepMesh_DataMapOfShapePairOfPolygon.hxx>
15 #include <BRepMesh_DataMapIteratorOfDataMapOfShapePairOfPolygon.hxx>
16 #include <GeomAbs_IsoType.hxx>
17 #include <GeomAbs_SurfaceType.hxx>
19 #include <TColStd_HArray1OfReal.hxx>
20 #include <Precision.hxx>
22 #include <BRep_Builder.hxx>
23 #include <BRep_Tool.hxx>
24 #include <Poly_Triangulation.hxx>
25 #include <Poly_PolygonOnTriangulation.hxx>
26 #include <Poly_Connect.hxx>
27 #include <TColStd_SequenceOfInteger.hxx>
28 #include <TColStd_Array1OfInteger.hxx>
29 #include <TColStd_HArray1OfInteger.hxx>
31 #include <TColgp_Array1OfPnt.hxx>
32 #include <TColgp_Array1OfPnt2d.hxx>
33 #include <Precision.hxx>
35 #include <BRepAdaptor_Curve.hxx>
36 #include <BRepAdaptor_Surface.hxx>
37 #include <BRepAdaptor_HSurface.hxx>
38 #include <BRepTools.hxx>
39 #include <BndLib_Add3dCurve.hxx>
40 #include <BRepBndLib.hxx>
41 #include <Bnd_Box.hxx>
44 #include <TopExp_Explorer.hxx>
46 #include <Geom2d_Curve.hxx>
48 #include <TColStd_DataMapOfIntegerInteger.hxx>
49 #include <BRepMesh_ShapeTool.hxx>
51 #include <Geom_Surface.hxx>
52 #include <Adaptor3d_IsoCurve.hxx>
53 #include <BRepMesh_IndexedMapOfVertex.hxx>
54 #include <Extrema_LocateExtPC.hxx>
56 #include <BRepMesh_ListOfXY.hxx>
57 #include <BRepMesh_ListIteratorOfListOfXY.hxx>
59 #include <TColStd_Array1OfInteger.hxx>
60 #include <BRepMesh_IDMapOfNodeOfDataStructureOfDelaun.hxx>
61 #include <Standard_ErrorHandler.hxx>
62 #include <Standard_Failure.hxx>
63 //#include <TColStd_DataMapOfInteger.hxx>
64 #include <TColGeom2d_SequenceOfCurve.hxx>
65 #include <TopTools_SequenceOfShape.hxx>
66 #include <NCollection_IncAllocator.hxx>
68 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
69 #include <BRep_PointRepresentation.hxx>
70 #include <BRep_TVertex.hxx>
71 #include <TColStd_MapOfInteger.hxx>
72 #include <SortTools_ShellSortOfReal.hxx>
73 #include <TCollection_CompareOfReal.hxx>
75 #include <TopTools_HArray1OfShape.hxx>
76 #include <TopTools_ListIteratorOfListOfShape.hxx>
80 // NOTE: replaced by more correct check
81 // #if defined(WNT) || defined(LIN)
85 // paralleling with Intel TBB
87 #include <tbb/parallel_for_each.h>
90 inline Standard_Real MaxFaceTol (const TopoDS_Face& theFace)
92 Standard_Real T, TMax = BRep_Tool::Tolerance(theFace);
95 for (Ex.Init(theFace,TopAbs_EDGE); Ex.More(); Ex.Next())
97 T = BRep_Tool::Tolerance(TopoDS::Edge(Ex.Current()));
98 if (T > TMax) TMax = T;
101 for (Ex.Init(theFace,TopAbs_VERTEX); Ex.More(); Ex.Next())
103 T = BRep_Tool::Tolerance(TopoDS::Vertex(Ex.Current()));
104 if (T > TMax) TMax = T;
111 //=======================================================================
112 //function : BRepMesh_FastDiscret
114 //=======================================================================
115 BRepMesh_FastDiscret::BRepMesh_FastDiscret(const Standard_Real theDefle,
116 const Standard_Real theAngl,
117 const Bnd_Box& theBox,
118 const Standard_Boolean theWithShare,
119 const Standard_Boolean theInshape,
120 const Standard_Boolean theRelative,
121 const Standard_Boolean theShapetrigu) :
122 myAngle(theAngl), myDeflection(theDefle),myWithShare(theWithShare),
123 myNbLocat(0), myRelative(theRelative), myShapetrigu(theShapetrigu),
124 myInshape(theInshape)
126 myAllocator = new NCollection_IncAllocator(64000);
129 Standard_Real TXmin, TYmin, TZmin, TXmax, TYmax, TZmax;
130 theBox.Get(TXmin, TYmin, TZmin, TXmax, TYmax, TZmax);
131 myDtotale = TXmax-TXmin;
132 const Standard_Real dy = TYmax-TYmin;
133 const Standard_Real dz = TZmax-TZmin;
134 if (dy > myDtotale) myDtotale = dy;
135 if (dz > myDtotale) myDtotale = dz;
139 //=======================================================================
140 //function : BRepMesh_FastDiscret
142 //=======================================================================
144 BRepMesh_FastDiscret::BRepMesh_FastDiscret(const Standard_Real theDefle,
145 const TopoDS_Shape& theShape,
146 const Bnd_Box& theBox,
147 const Standard_Real theAngl,
148 const Standard_Boolean theWithShare,
149 const Standard_Boolean theInshape,
150 const Standard_Boolean theRelative,
151 const Standard_Boolean theShapetrigu):
152 myAngle(theAngl), myDeflection(theDefle),myWithShare(theWithShare),
153 myNbLocat(0), myRelative(theRelative), myShapetrigu(theShapetrigu),
154 myInshape(theInshape)
156 myAllocator = new NCollection_IncAllocator(64000);
159 Standard_Real TXmin, TYmin, TZmin, TXmax, TYmax, TZmax;
160 theBox.Get(TXmin, TYmin, TZmin, TXmax, TYmax, TZmax);
161 myDtotale = TXmax-TXmin;
162 const Standard_Real dy = TYmax-TYmin;
163 const Standard_Real dz = TZmax-TZmin;
164 if (dy > myDtotale) myDtotale = dy;
165 if (dz > myDtotale) myDtotale = dz;
170 //=======================================================================
171 //function : Perform(shape)
173 //=======================================================================
175 void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
177 std::vector<TopoDS_Face> aFaces;
178 for (TopExp_Explorer ex(theShape, TopAbs_FACE); ex.More(); ex.Next()) {
179 TopoDS_Face aF = TopoDS::Face(ex.Current());
181 aFaces.push_back(aF);
184 // mesh faces in parallel threads using TBB
186 if (Standard::IsReentrant())
187 tbb::parallel_for_each (aFaces.begin(), aFaces.end(), *this);
190 for (std::vector<TopoDS_Face>::iterator it(aFaces.begin()); it != aFaces.end(); it++)
195 //=======================================================================
198 //=======================================================================
200 void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const
202 //cout << "START face " << theFace.TShape().operator->() << endl << flush;
203 Handle(BRepMesh_FaceAttribute) fattribute;
204 if ( GetFaceAttribute (theFace, fattribute) )
206 BRepMesh_FastDiscretFace aTool (GetAngle(), WithShare());
207 aTool.Add (theFace, fattribute, GetMapOfDefEdge());
209 //cout << "END face " << theFace.TShape().operator->() << endl << flush;
212 //=======================================================================
213 //function : Add(face)
215 //=======================================================================
217 #define MESH_FAILURE(theface) \
219 myFacestate = BRepMesh_Failure; \
220 myNottriangulated.Append(theface); \
224 void BRepMesh_FastDiscret::Add(const TopoDS_Face& theface)
231 TopoDS_Face face = theface;
232 BRepTools::Update(face);
233 face.Orientation(TopAbs_FORWARD);
234 myStructure.Nullify();
235 Handle(NCollection_IncAllocator) anAlloc = Handle(NCollection_IncAllocator)::DownCast(myAllocator);
236 anAlloc->Reset(Standard_False);
237 myStructure=new BRepMesh_DataStructureOfDelaun(anAlloc);
238 BRepAdaptor_Surface BS(face, Standard_False);
239 Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS);
241 GeomAbs_SurfaceType thetype;
242 thetype = BS.GetType();
244 gp_Pnt2d uvFirst, uvLast;
246 TopAbs_Orientation orFace = face.Orientation();
247 Handle(Poly_Triangulation) T;
256 myLocation2d.Clear();
257 myInternaledges.Clear();
262 Standard_Real defedge, defface;
263 Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dx, dy, dz;
264 Standard_Integer nbEdge = 0;
265 Standard_Real savangle = myAngle;
267 Standard_Real maxdef = 2.* MaxFaceTol(theface);
270 if (!myRelative) defface = Max(myDeflection, maxdef);
272 TColStd_SequenceOfReal aFSeq, aLSeq;
273 TColGeom2d_SequenceOfCurve aCSeq;
274 TopTools_SequenceOfShape aShSeq;
276 TopoDS_Iterator exW(face);
278 for (; exW.More(); exW.Next()) {
279 const TopoDS_Shape& aWire = exW.Value();
280 if (aWire.ShapeType() != TopAbs_WIRE)
282 TopoDS_Iterator ex(aWire);
283 for(; ex.More(); ex.Next()) {
284 const TopoDS_Edge& edge = TopoDS::Edge(ex.Value());
286 if (!myMapdefle.IsBound(edge)) {
288 if (myEdges.IsBound(edge)) {
289 const BRepMesh_PairOfPolygon& pair = myEdges.Find(edge);
290 const Handle(Poly_PolygonOnTriangulation)& P = pair.First();
291 defedge = P->Deflection();
295 BRepBndLib::Add(edge, B);
296 B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
301 if (defedge < dy) defedge = dy;
302 if (defedge < dz) defedge = dz;
303 // adjusted in relation to the total size:
304 cdef = myDtotale/(2*defedge);
305 if (cdef < 0.5) cdef = 0.5;
306 if (cdef > 2.) cdef = 2.;
307 defedge = cdef * defedge * myDeflection;
308 myAngle = savangle * cdef;
310 defface = defface + defedge;
311 defface = Max(maxdef, defface);
313 else defedge = myDeflection;
315 defedge = Max(maxdef, defedge);
316 defedge = Max(1.e-05 , defedge);
317 myMapdefle.Bind(edge, defedge);
320 defedge = myMapdefle(edge);
321 if (myRelative) {defface = defface + defedge; defface = Max(maxdef, defface);}
324 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(edge, face, f1, l1);
325 if (C.IsNull()) continue;
331 Add(edge, face, gFace, C, defedge, f1, l1);
336 if (nbEdge == 0 || myVemap.Extent() < 3)
338 MESH_FAILURE(theface);
341 if (myRelative ) defface = defface / nbEdge;
342 else defface = myDeflection;
344 if (myWithShare) defface = Max(maxdef, defface);
346 T = BRep_Tool::Triangulation(face, loc);
348 if (!myShapetrigu || T.IsNull()) {
350 Standard_Real xCur, yCur;
351 Standard_Real maxX, minX, maxY, minY;
355 Standard_Integer ipn = 0;
356 Standard_Integer i1 =1;
357 for (i1 = 1; i1 <= myVemap.Extent(); i1++) {
358 const BRepMesh_Vertex& aV = myStructure->GetNode(myVemap.FindKey(i1));
362 minX=Min(xCur, minX);
363 maxX=Max(xCur, maxX);
364 minY=Min(yCur, minY);
365 maxY=Max(yCur, maxY);
367 Standard_Real myumin = minX;
368 Standard_Real myumax = maxX;
369 Standard_Real myvmin = minY;
370 Standard_Real myvmax = maxY;
372 const Standard_Real umin = BS.FirstUParameter();
373 const Standard_Real umax = BS.LastUParameter();
374 const Standard_Real vmin = BS.FirstVParameter();
375 const Standard_Real vmax = BS.LastVParameter();
377 if (myumin < umin || myumax > umax)
379 if (BS.IsUPeriodic())
381 if ((myumax - myumin) > (umax - umin))
383 myumax = myumin + (umax - umin);
388 if (umin > myumin) myumin = umin;
389 if (umax < myumax) myumax = umax;
393 if (myvmin < vmin || myvmax > vmax)
395 if (BS.IsVPeriodic())
397 if ((myvmax - myvmin) > (vmax - vmin))
399 myvmax = myvmin + (vmax - vmin);
404 if (vmin > myvmin) myvmin = vmin;
405 if (vmax < myvmax) myvmax = vmax;
409 // fast verification of the validity of calculated limits. If wrong,
410 // sure a problem of pcurve.
411 if (thetype == GeomAbs_BezierSurface &&
412 (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5))
414 MESH_FAILURE(theface);
417 //define parameters for correct parametrics
419 Standard_Real deltaX = 1.0;
420 Standard_Real deltaY = 1.0;
421 Standard_Integer nbVertices = myVemap.Extent();
422 const Standard_Real tolclass = Precision::PConfusion(); //0.03*Max(myumax-myumin, myvmax-myvmin);
424 BRepMesh_ClassifierPtr classifier (
425 new BRepMesh_Classifier(face, tolclass, myInternaledges, myVemap,
426 myStructure, myumin, myumax, myvmin, myvmax) );
428 myFacestate = classifier->State();
429 if (myFacestate == BRepMesh_SelfIntersectingWire)
431 Standard_Integer nbmaill = 0;
432 Standard_Real eps = Precision::Confusion();
433 while (nbmaill < 5 && myFacestate != BRepMesh_ReMesh)
437 //clear the structure of links
438 myStructure.Nullify();
439 myStructure = new BRepMesh_DataStructureOfDelaun(anAlloc);
442 myLocation2d.Clear();
443 myInternaledges.Clear();
446 for(j1 = 1; j1 <= aShSeq.Length(); j1++)
448 const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
449 if (myEdges.IsBound(edge))
451 myEdges.UnBind(edge);
452 myInternaledges.UnBind(edge);
457 for( j1 = 1; j1 <= aShSeq.Length(); j1++)
459 const TopoDS_Edge& edge = TopoDS::Edge(aShSeq.Value(j1));
460 defedge = myMapdefle(edge) / 3.;
461 defedge = Max(defedge, eps);
462 myMapdefle.Bind(edge, defedge);
463 const Handle(Geom2d_Curve)& C = aCSeq.Value(j1);
464 Add(edge, face, gFace, C, defedge, aFSeq.Value(j1), aLSeq.Value(j1));
467 classifier.Nullify();
469 classifier = new BRepMesh_Classifier(face, tolclass, myInternaledges, myVemap,
470 myStructure, myumin, myumax, myvmin, myvmax);
472 if (classifier->State() == BRepMesh_NoError)
474 myFacestate = BRepMesh_ReMesh;
476 nbVertices = myVemap.Extent();
480 if (myFacestate != BRepMesh_NoError && myFacestate != BRepMesh_ReMesh)
482 myNottriangulated.Append(face);
483 classifier.Nullify();
487 // try to find the real length:
488 // akm (bug OCC16) : We must calculate these measures in non-singular
489 // parts of face. Let's try to compute average value of three
490 // (umin, (umin+umax)/2, umax), and respectively for v.
492 Standard_Real longu = 0.0, longv = 0.0; //, last , first;
493 gp_Pnt P11, P12, P21, P22, P31, P32;
495 Standard_Real du = (myumax-myumin)/20;
496 Standard_Real dv = (myvmax-myvmin)/20;
497 Standard_Real dfuave=(myumin+myumax)/2, dfucur;
498 Standard_Real dfvave=(myvmin+myvmax)/2, dfvcur;
500 BS.D0 (myumin, myvmin, P11);
501 BS.D0 (myumin, dfvave, P21);
502 BS.D0 (myumin, myvmax, P31);
503 for (i1=0, dfucur=myumin; i1 <= 20; i1++, dfucur+=du) {
504 BS.D0 (dfucur, myvmin, P12);
505 BS.D0 (dfucur, dfvave, P22);
506 BS.D0 (dfucur, myvmax, P32);
507 longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
513 BS.D0(myumin, myvmin, P11);
514 BS.D0(dfuave, myvmin, P21);
515 BS.D0(myumax, myvmin, P31);
516 for (i1=0, dfvcur=myvmin; i1 <= 20; i1++, dfvcur+=dv) {
517 BS.D0 (myumin, dfvcur, P12);
518 BS.D0 (dfuave, dfvcur, P22);
519 BS.D0 (myumax, dfvcur, P32);
520 longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
527 // akm (bug OCC16) ^^^^^
529 if (longu <= 1.e-16 || longv <= 1.e-16) {
531 #ifdef DEB_MESH_CHRONO
533 MESH_CHRONO_TSTOP(thetype);
535 MESH_FAILURE(theface);
539 if (thetype == GeomAbs_Torus) {
540 gp_Torus Tor = BS.Torus();
541 Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius();
542 Standard_Real Du, Dv;//, pasu, pasv;
544 Dv = Max(1.0e0 - (defface/r),0.0e0) ;
545 Standard_Real oldDv = 2.0 * ACos (Dv);
546 oldDv = Min(oldDv, myAngle);
547 Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
550 Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2);
551 Dv = (myvmax-myvmin)/(nbV+1);
553 Standard_Real ru = R + r;
555 Du = Max(1.0e0 - (defface/ru),0.0e0);
556 Du = (2.0 * ACos (Du));
557 Du = Min(Du, myAngle);
558 Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
559 if(aa < gp::Resolution())
562 Du = Du * Min(oldDv, Du) / aa;
566 Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2);
567 nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.));
569 Du = (myumax-myumin)/(nbU+1);
570 //-- DeltaX and DeltaY are chosen so that to avoid "jumping"
571 //-- of points on the grid
575 else if (thetype == GeomAbs_Cylinder) {
576 /*Standard_Real aMax = Max(myumax,myvmax);
577 deltaX = 0.01; //1./aMax; //0.01;
579 gp_Cylinder Cyl = BS.Cylinder();
580 Standard_Real R = Cyl.Radius();
581 // Calculate parameters for iteration in U direction
582 Standard_Real Du = 1.0 - (defface/R);
583 if (Du < 0.0) Du = 0.0;
584 Du = 2.0 * ACos (Du);
585 if (Du > GetAngle()) Du = GetAngle();
590 deltaX = (myumax-myumin)/longu;
591 deltaY = (myvmax-myvmin)/longv;
594 if(!myMapattrib.IsBound(theface))
596 Handle(BRepMesh_FaceAttribute) aFA = new BRepMesh_FaceAttribute();
597 aFA->GetDefFace() = defface;
598 aFA->GetUMax() = myumax;
599 aFA->GetVMax() = myvmax;
600 aFA->GetUMin() = myumin;
601 aFA->GetVMin() = myvmin;
602 aFA->GetDeltaX() = deltaX;
603 aFA->GetDeltaY() = deltaY;
604 aFA->GetMinX() = minX;
605 aFA->GetMinY() = minY;
606 aFA->GetClassifier() = classifier;
607 myMapattrib.Bind(theface, aFA);
610 //Standard_Integer nbVertices = myVemap.Extent();
611 T = new Poly_Triangulation(nbVertices, 1, Standard_True);
612 TColgp_Array1OfPnt& Nodes = T->ChangeNodes();
613 TColgp_Array1OfPnt2d& Nodes2d = T->ChangeUVNodes();
615 Standard_Integer index;
616 for (i = 1; i <= nbVertices; i++) {
617 index = myVemap.FindKey(i);
618 Nodes(i) = Pnt(index);
619 Nodes2d(i).SetXY(Vertex(index).Coord());
622 // storage of triangulation in the BRep.
623 //TopLoc_Location loc = face.Location();
624 if (!loc.IsIdentity()) {
625 gp_Trsf tr = loc.Transformation();
627 for (i = Nodes.Lower(); i <= Nodes.Upper(); i++)
628 Nodes(i).Transform(tr);
632 B.UpdateFace(face, T);
634 BRepMesh_DataMapIteratorOfDataMapOfShapePairOfPolygon It(myInternaledges);
635 for (; It.More(); It.Next()) {
636 const BRepMesh_PairOfPolygon& pair = It.Value();
637 const Handle(Poly_PolygonOnTriangulation)& NOD1 = pair.First();
638 const Handle(Poly_PolygonOnTriangulation)& NOD2 = pair.Last();
640 B.UpdateEdge(TopoDS::Edge(It.Key()), NOD1, T, loc);
642 B.UpdateEdge(TopoDS::Edge(It.Key()), NOD1, NOD2, T, loc);
648 catch(Standard_Failure)
650 MESH_FAILURE(theface);
653 myStructure.Nullify();
657 //=======================================================================
660 //=======================================================================
661 void BRepMesh_FastDiscret::Add( const TopoDS_Edge& theEdge,
662 const TopoDS_Face& theFace,
663 const Handle(BRepAdaptor_HSurface)& theGFace,
664 const Handle(Geom2d_Curve)& theC2d,
665 const Standard_Real theDefEdge,
666 const Standard_Real theFirst,
667 const Standard_Real theLast)
669 const TopAbs_Orientation orEdge = theEdge.Orientation();
670 if (orEdge == TopAbs_EXTERNAL) return;
672 const Standard_Boolean isEdgeBound = myEdges.IsBound(theEdge);
676 if (Update(theEdge, theFace, theC2d, theDefEdge, theFirst, theLast))
682 TopoDS_Vertex pBegin, pEnd;
683 TopExp::Vertices(theEdge, pBegin, pEnd);
684 if (pBegin.IsNull() || pEnd.IsNull())
689 Standard_Real wFirst, wLast;
690 BRep_Tool::Range(theEdge, theFace, wFirst, wLast);
692 gp_Pnt2d uvFirst, uvLast;
693 BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast);
695 const Standard_Boolean sameUV = uvFirst.IsEqual(uvLast, Precision::PConfusion());
697 //Control vertexes tolerances
698 gp_Pnt pFirst = theGFace->Value(uvFirst.X(), uvFirst.Y());
699 gp_Pnt pLast = theGFace->Value(uvLast.X(), uvLast.Y());
701 Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)),
702 pLast.Distance(BRep_Tool::Pnt(pEnd)));
704 if(mindist < BRep_Tool::Tolerance(pBegin) ||
705 mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge;
707 // control of degenerated non-coded edges.
709 Standard_Boolean degener = BRep_Tool::Degenerated(theEdge);
713 if (pBegin.IsSame(pEnd))
715 // calculation of the length of the edge in 3D
716 Standard_Real longueur = 0.0;
717 Standard_Real du = (wLast-wFirst)/20;
719 BRepAdaptor_Curve BC(theEdge);
721 Standard_Real tolV = BRep_Tool::Tolerance(pBegin);
722 Standard_Real tolV2 = 1.2*tolV;
723 for (Standard_Integer l = 1; l <= 20; l++) {
724 BC.D0(wFirst + l*du, P2);
725 longueur += P1.Distance(P2);
726 if (longueur > tolV2) break;
730 if (longueur < tolV2)
732 degener = Standard_True;
740 // 1. is it really sameUV without being degenerated
742 theC2d->D0(theFirst, uvF);
743 theC2d->D0(theLast, uvL);
744 if (!uvFirst.IsEqual(uvF, Precision::PConfusion()))
748 if (!uvLast.IsEqual(uvL, Precision::PConfusion()))
756 // Process first vertex
757 Standard_Integer ipf;
758 if (myVertices.IsBound(pBegin))
760 ipf = myVertices.Find(pBegin);
764 if (sameUV && myVertices.IsBound(pEnd))
766 ipf = myVertices.Find(pEnd);
772 myLocation3d.Bind(ipf, BRep_Tool::Pnt(pBegin));
774 myVertices.Bind(pBegin, ipf);
776 theUV = BRepMesh_FastDiscretFace::FindUV(pBegin, uvFirst, ipf, theGFace, mindist, myLocation2d);
777 BRepMesh_Vertex vf(theUV, ipf, BRepMesh_Frontier);
778 Standard_Integer ivf = myStructure->AddNode(vf);
780 // Process last vertex
781 Standard_Integer ipl;
782 if (pEnd.IsSame(pBegin))
788 if (myVertices.IsBound(pEnd))
790 ipl = myVertices.Find(pEnd);
802 myLocation3d.Bind(ipl, BRep_Tool::Pnt(pEnd));
804 myVertices.Bind(pEnd,ipl);
807 theUV = BRepMesh_FastDiscretFace::FindUV(pEnd, uvLast, ipl, theGFace, mindist, myLocation2d);
808 BRepMesh_Vertex vl(theUV, ipl, BRepMesh_Frontier);
809 Standard_Integer ivl= myStructure->AddNode(vl);
811 Standard_Integer isvf = myVemap.FindIndex(ivf);
812 if (isvf == 0) isvf = myVemap.Add(ivf);
813 Standard_Integer isvl = myVemap.FindIndex(ivl);
814 if (isvl == 0) isvl = myVemap.Add(ivl);
816 Standard_Real otherdefedge = 0.5*theDefEdge;
821 Handle(Poly_PolygonOnTriangulation) P1;
825 Handle(Poly_PolygonOnTriangulation) P2;
830 TColStd_Array1OfInteger Nodes(1, 2), NodInStruct(1, 2);
831 TColStd_Array1OfReal Param(1, 2);
833 NodInStruct(1) = ipf;
837 NodInStruct(2) = ipl;
841 P1 = new Poly_PolygonOnTriangulation(Nodes, Param);
842 P2 = new Poly_PolygonOnTriangulation(NodInStruct, Param);
846 if (orEdge == TopAbs_INTERNAL) otherdefedge *= 0.5;
848 BRepAdaptor_Curve cons;
849 if (BRep_Tool::SameParameter(theEdge))
851 cons.Initialize(theEdge);
855 cons.Initialize(theEdge, theFace);
859 Standard_Integer nbpmin = 2;
860 if (cons.GetType() == GeomAbs_Circle) nbpmin = 4; //OCC287
861 BRepMesh_GeomTool GT(cons, wFirst, wLast, 0.5*myAngle, otherdefedge, nbpmin);
863 // PTv, chl/922/G9, Take into account internal vertices
864 // it is necessary for internal edges, which do not split other edges, by their vertex
865 TopoDS_Iterator exV(theEdge);
866 for ( ; exV.More(); exV.Next() )
868 TopoDS_Vertex aIntV = TopoDS::Vertex(exV.Value());
869 if ( aIntV.Orientation() == TopAbs_INTERNAL )
870 GT.AddPoint(BRep_Tool::Pnt(aIntV),
871 BRep_Tool::Parameter(aIntV, theEdge),
875 // Creation des polygones sur triangulation:
878 Standard_Real aEdgeLen = 0., a2dEdgeLen = 0.;
881 GT.Value(cons, theGFace, 1, puv, P3dPrev, uvPrev);
882 for (i = 2; i <= GT.NbPoints(); i++)
885 GT.Value(cons, theGFace, i, puv, P3d, uv);
886 aEdgeLen += P3d.SquareDistance(P3dPrev);
887 a2dEdgeLen += uv.SquareDistance(uvPrev);
892 Standard_Integer nbnodes = GT.NbPoints();
893 Standard_Real aMinToler = Min(theDefEdge, myDeflection);
894 if(aEdgeLen < aMinToler*aMinToler)
896 //check 2D resolution
897 Standard_Real ddu = theGFace->UResolution(aMinToler);
898 Standard_Real ddv = theGFace->VResolution(aMinToler);
899 Standard_Real aMin = Min(ddu, ddv);
901 if(a2dEdgeLen < aMin*aMin)
904 TColStd_Array1OfInteger Nodes(1, nbnodes);
905 TColStd_Array1OfInteger NodInStruct(1, nbnodes);
906 TColStd_Array1OfReal Param(1, nbnodes);
908 // processing of the 1st point:
910 NodInStruct(1) = ipf;
914 Nodes(nbnodes) = isvl;
915 NodInStruct(nbnodes) = ipl;
916 Param(nbnodes) = wLast;
920 Standard_Integer iv2;
921 for (i = 2; i < GT.NbPoints(); i++)
924 GT.Value(cons, theGFace, i, puv, P3d, uv);
926 myLocation3d.Bind(myNbLocat, P3d);
927 NodInStruct(i) = myNbLocat;
929 v2.Initialize(uv.Coord(), myNbLocat, BRepMesh_OnCurve);
930 iv2=myStructure->AddNode(v2);
932 Standard_Integer isv = myVemap.FindIndex(iv2);
933 if (isv == 0) isv = myVemap.Add(iv2);
935 NodInStruct(i) = myNbLocat;
938 if (orEdge == TopAbs_FORWARD)
939 myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier));
940 else if (orEdge == TopAbs_REVERSED)
941 myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier));
942 else if (orEdge == TopAbs_INTERNAL)
943 myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed));
948 P1 = new Poly_PolygonOnTriangulation(Nodes, Param);
949 P2 = new Poly_PolygonOnTriangulation(NodInStruct, Param);
952 P2->Deflection(otherdefedge);
953 BRepMesh_PairOfPolygon pair;
955 myEdges.Bind(theEdge, pair);
958 if (orEdge == TopAbs_FORWARD)
959 myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Frontier));
960 else if (orEdge == TopAbs_REVERSED)
961 myStructure->AddLink(BRepMesh_Edge(ivl, ivf, BRepMesh_Frontier));
962 else if (orEdge == TopAbs_INTERNAL)
963 myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Fixed));
968 // If this Edge has been already checked and it is not degenerated,
969 // the points of the polygon calculated at the first check are retrieved :
974 // Create 2d polygon for degenerated edge
975 TColStd_Array1OfInteger Nodes(1, 2);
976 TColStd_Array1OfReal PPar(1, 2);
984 P1 = new Poly_PolygonOnTriangulation(Nodes, PPar);
988 // retrieve the polygone:
989 const BRepMesh_PairOfPolygon& pair = myEdges.Find(theEdge);
990 const Handle(Poly_PolygonOnTriangulation)& P = pair.First();
991 const TColStd_Array1OfInteger& NOD = P->Nodes();
992 Handle(TColStd_HArray1OfReal) Par = P->Parameters();
995 const Standard_Integer nbnodes = NOD.Length();
996 TColStd_Array1OfInteger Nodes(1, nbnodes);
997 TColStd_Array1OfReal PPar(1, nbnodes);
998 Standard_Integer iv2;
1003 Nodes(nbnodes) = isvl;
1004 PPar(nbnodes) = wLast;
1009 if (BRep_Tool::SameParameter(theEdge))
1011 for (i = 2; i < nbnodes; i++)
1013 const Standard_Real puv = Par->Value(i);
1014 theC2d->D0(puv, uv);
1015 v2.Initialize(uv.Coord(), NOD(i), BRepMesh_OnCurve);
1016 iv2 = myStructure->AddNode(v2);
1018 Standard_Integer isv = myVemap.FindIndex(iv2);
1019 if (isv == 0) isv = myVemap.Add(iv2);
1023 if (orEdge==TopAbs_FORWARD)
1024 myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier));
1025 else if (orEdge == TopAbs_REVERSED)
1026 myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier));
1027 else if (orEdge == TopAbs_INTERNAL)
1028 myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed));
1035 const Standard_Real wFold = Par->Value(Par->Lower());
1036 const Standard_Real wLold = Par->Value(Par->Upper());
1038 Standard_Real wKoef = 1.;
1039 if ((wFold != wFirst || wLold != wLast) && wLold != wFold)
1041 wKoef = (wLast - wFirst) / (wLold - wFold);
1044 BRepAdaptor_Curve cons(theEdge, theFace);
1045 Extrema_LocateExtPC pcos;
1046 pcos.Initialize(cons, cons.FirstParameter(),
1047 cons.LastParameter(), Precision::PConfusion());
1049 Standard_Real wPrev;
1050 Standard_Real wCur = wFirst;
1051 Standard_Real wCurFound = wFirst;
1052 for (i = 2; i < nbnodes; i++)
1054 P3d = myLocation3d(NOD(i));
1057 wCur = wFirst + wKoef*(Par->Value(i) - wFold);
1058 wCurFound += (wCur - wPrev);
1059 pcos.Perform(P3d, wCurFound);
1060 if (pcos.IsDone()) wCurFound = pcos.Point().Parameter();
1061 theC2d->D0(wCurFound, uv);
1062 v2.Initialize(uv.Coord(), NOD(i), BRepMesh_OnCurve);
1063 iv2 = myStructure->AddNode(v2);
1065 Standard_Integer isv = myVemap.FindIndex(iv2);
1066 if (isv == 0) isv = myVemap.Add(iv2);
1068 PPar(i) = wCurFound;
1070 if (orEdge==TopAbs_FORWARD)
1071 myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Frontier));
1072 else if (orEdge == TopAbs_REVERSED)
1073 myStructure->AddLink(BRepMesh_Edge(iv2, ivf, BRepMesh_Frontier));
1074 else if (orEdge == TopAbs_INTERNAL)
1075 myStructure->AddLink(BRepMesh_Edge(ivf, iv2, BRepMesh_Fixed));
1082 P1 = new Poly_PolygonOnTriangulation(Nodes, PPar);
1085 if (orEdge == TopAbs_FORWARD)
1086 myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Frontier));
1087 else if (orEdge == TopAbs_REVERSED)
1088 myStructure->AddLink(BRepMesh_Edge(ivl, ivf, BRepMesh_Frontier));
1089 else if (orEdge == TopAbs_INTERNAL)
1090 myStructure->AddLink(BRepMesh_Edge(ivf, ivl, BRepMesh_Fixed));
1095 P1->Deflection(theDefEdge);
1096 if (myInternaledges.IsBound(theEdge))
1098 BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge);
1099 if (orEdge == TopAbs_REVERSED)
1106 BRepMesh_PairOfPolygon pair1;
1108 myInternaledges.Bind(theEdge, pair1);
1113 //=======================================================================
1114 //function : Update(edge)
1116 //=======================================================================
1117 Standard_Boolean BRepMesh_FastDiscret::Update(const TopoDS_Edge& theEdge,
1118 const TopoDS_Face& theFace,
1119 const Handle(Geom2d_Curve)& theC2d,
1120 const Standard_Real theDefEdge,
1121 const Standard_Real theFirst,
1122 const Standard_Real theLast)
1124 TopLoc_Location Loc;
1125 Handle(Poly_Triangulation) T, TNull;
1126 Handle(Poly_PolygonOnTriangulation) Poly, NullPoly;
1128 Standard_Integer i = 1;
1129 Standard_Boolean found = Standard_False;
1132 BRep_Tool::PolygonOnTriangulation(theEdge,Poly,T,Loc,i);
1134 if (!found && !T.IsNull() && T->HasUVNodes() &&
1135 !Poly.IsNull() && Poly->HasParameters())
1137 if (Poly->Deflection() <= 1.1*theDefEdge)
1139 // 2d vertex indices
1140 TopAbs_Orientation orEdge = theEdge.Orientation();
1141 Standard_Integer iv1, iv2, ivl;
1142 Standard_Integer isv1, isv, isvl;
1144 // Get range on 2d curve
1145 Standard_Real wFirst, wLast;
1146 BRep_Tool::Range(theEdge, theFace, wFirst, wLast);
1148 // Get end points on 2d curve
1149 gp_Pnt2d uvFirst, uvLast;
1150 BRep_Tool::UVPoints(theEdge, theFace, uvFirst, uvLast);
1153 TopoDS_Vertex pBegin, pEnd;
1154 TopExp::Vertices(theEdge,pBegin,pEnd);
1156 const Standard_Boolean sameUV =
1157 uvFirst.IsEqual(uvLast, Precision::PConfusion());
1159 //Controle vertice tolerances
1160 BRepAdaptor_Surface BS(theFace, Standard_False);
1161 Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS);
1164 gp_Pnt pFirst = gFace->Value(uvFirst.X(), uvFirst.Y());
1165 gp_Pnt pLast = gFace->Value(uvLast.X(), uvLast.Y());
1167 Standard_Real mindist = 10. * Max(pFirst.Distance(BRep_Tool::Pnt(pBegin)),
1168 pLast.Distance(BRep_Tool::Pnt(pEnd)));
1170 if (mindist < BRep_Tool::Tolerance(pBegin) ||
1171 mindist < BRep_Tool::Tolerance(pEnd) ) mindist = theDefEdge;
1175 // 1. is it really sameUV without being degenerated
1177 theC2d->D0(theFirst, uvF);
1178 theC2d->D0(theLast, uvL);
1179 if (!uvFirst.IsEqual(uvF, Precision::PConfusion())) {
1182 if (!uvLast.IsEqual(uvL, Precision::PConfusion())) {
1187 const TColgp_Array1OfPnt& Nodes = T->Nodes();
1188 const TColStd_Array1OfInteger& Indices = Poly->Nodes();
1189 Handle(TColStd_HArray1OfReal) Param = Poly->Parameters();
1191 const Standard_Integer nbnodes = Indices.Length();
1192 TColStd_Array1OfInteger NewNodes(1, nbnodes);
1193 TColStd_Array1OfInteger NewNodInStruct(1, nbnodes);
1198 // Process first vertex
1199 Standard_Integer ipf;
1200 if (myVertices.IsBound(pBegin))
1202 ipf = myVertices.Find(pBegin);
1206 if (sameUV && myVertices.IsBound(pEnd))
1208 ipf = myVertices.Find(pEnd);
1212 P3d = Nodes(Indices(1));
1213 if (!Loc.IsIdentity())
1214 P3d.Transform(Loc.Transformation());
1216 myLocation3d.Bind(myNbLocat,P3d);
1219 myVertices.Bind(pBegin,ipf);
1221 NewNodInStruct(1) = ipf;
1222 theUV = BRepMesh_FastDiscretFace::FindUV(pBegin, uvFirst, ipf, gFace, mindist, myLocation2d);
1223 BRepMesh_Vertex vf(theUV,ipf,BRepMesh_Frontier);
1224 iv1 = myStructure->AddNode(vf);
1225 isv1 = myVemap.FindIndex(iv1);
1226 if (isv1 == 0) isv1 = myVemap.Add(iv1);
1229 // Process last vertex
1230 Standard_Integer ipl;
1231 if (pEnd.IsSame(pBegin))
1237 if (myVertices.IsBound(pEnd))
1239 ipl = myVertices.Find(pEnd);
1252 myLocation3d.Bind(myNbLocat,Nodes(Indices(nbnodes)).Transformed(Loc.Transformation()));
1255 myVertices.Bind(pEnd,ipl);
1258 NewNodInStruct(nbnodes) = ipl;
1259 theUV = BRepMesh_FastDiscretFace::FindUV(pEnd, uvLast, ipl, gFace, mindist, myLocation2d);
1260 BRepMesh_Vertex vl(theUV,ipl,BRepMesh_Frontier);
1262 ivl = myStructure->AddNode(vl);
1263 isvl = myVemap.FindIndex(ivl);
1264 if (isvl == 0) isvl = myVemap.Add(ivl);
1266 NewNodes(nbnodes) = isvl;
1271 if (BRep_Tool::SameParameter(theEdge))
1273 for (i = 2; i < Indices.Length(); i++)
1276 P3d = Nodes(Indices(i));
1277 if (!Loc.IsIdentity())
1278 P3d.Transform(Loc.Transformation());
1280 myLocation3d.Bind(myNbLocat, P3d);
1281 NewNodInStruct(i) = myNbLocat;
1283 uv = theC2d->Value(Param->Value(i));
1284 v.Initialize(uv.Coord(), myNbLocat, BRepMesh_Frontier);
1285 iv2 = myStructure->AddNode(v);
1286 isv = myVemap.FindIndex(iv2);
1287 if (isv == 0) isv = myVemap.Add(iv2);
1291 if (orEdge == TopAbs_FORWARD)
1292 myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier));
1293 else if (orEdge == TopAbs_REVERSED)
1294 myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier));
1295 else if (orEdge == TopAbs_INTERNAL)
1296 myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed));
1302 if (orEdge == TopAbs_FORWARD)
1303 myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier));
1304 else if (orEdge == TopAbs_REVERSED)
1305 myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier));
1306 else if (orEdge == TopAbs_INTERNAL)
1307 myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed));
1314 const Standard_Real wFold = Param->Value(Param->Lower());
1315 const Standard_Real wLold = Param->Value(Param->Upper());
1317 Standard_Real wKoef = 1.;
1318 if ((wFold != wFirst || wLold != wLast) && wLold != wFold)
1320 wKoef = (wLast - wFirst) / (wLold - wFold);
1323 BRepAdaptor_Curve cons(theEdge, theFace);
1324 Extrema_LocateExtPC pcos;
1325 pcos.Initialize(cons, cons.FirstParameter(),
1326 cons.LastParameter(), Precision::PConfusion());
1328 Standard_Real wPrev;
1329 Standard_Real wCur = wFirst;
1330 Standard_Real wCurFound = wFirst;
1331 for (i = 2; i < Indices.Length(); i++)
1334 P3d = Nodes(Indices(i));
1335 if (!Loc.IsIdentity())
1336 P3d.Transform(Loc.Transformation());
1338 myLocation3d.Bind(myNbLocat, P3d);
1339 NewNodInStruct(i) = myNbLocat;
1342 wCur = wFirst + wKoef*(Param->Value(i) - wFold);
1343 wCurFound += (wCur - wPrev);
1344 pcos.Perform(P3d, wCurFound);
1345 if (pcos.IsDone()) wCurFound = pcos.Point().Parameter();
1346 theC2d->D0(wCurFound, uv);
1347 v.Initialize(uv.Coord(), myNbLocat, BRepMesh_Frontier);
1348 iv2 = myStructure->AddNode(v);
1349 isv = myVemap.FindIndex(iv2);
1350 if (isv == 0) isv = myVemap.Add(iv2);
1355 if (orEdge == TopAbs_FORWARD)
1356 myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Frontier));
1357 else if (orEdge == TopAbs_REVERSED)
1358 myStructure->AddLink(BRepMesh_Edge(iv2,iv1,BRepMesh_Frontier));
1359 else if (orEdge == TopAbs_INTERNAL)
1360 myStructure->AddLink(BRepMesh_Edge(iv1,iv2,BRepMesh_Fixed));
1366 if (orEdge == TopAbs_FORWARD)
1367 myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Frontier));
1368 else if (orEdge == TopAbs_REVERSED)
1369 myStructure->AddLink(BRepMesh_Edge(ivl,iv1,BRepMesh_Frontier));
1370 else if (orEdge == TopAbs_INTERNAL)
1371 myStructure->AddLink(BRepMesh_Edge(iv1,ivl,BRepMesh_Fixed));
1375 Handle(Poly_PolygonOnTriangulation) P1 =
1376 new Poly_PolygonOnTriangulation(NewNodes, Param->Array1());
1377 P1->Deflection(theDefEdge);
1378 if (myInternaledges.IsBound(theEdge))
1380 BRepMesh_PairOfPolygon& pair = myInternaledges.ChangeFind(theEdge);
1381 if (theEdge.Orientation() == TopAbs_REVERSED)
1388 BRepMesh_PairOfPolygon pair1;
1390 myInternaledges.Bind(theEdge, pair1);
1393 Handle(Poly_PolygonOnTriangulation) P2 =
1394 new Poly_PolygonOnTriangulation(NewNodInStruct, Param->Array1());
1395 P2->Deflection(theDefEdge);
1396 BRepMesh_PairOfPolygon pair;
1398 myEdges.Bind(theEdge, pair);
1400 found = Standard_True;
1405 B.UpdateEdge(theEdge,NullPoly,T,Loc);
1406 B.UpdateFace(theFace,TNull);
1409 else if (!T.IsNull() && !T->HasUVNodes())
1412 B.UpdateEdge(theEdge,NullPoly,T,Loc);
1413 B.UpdateFace(theFace,TNull);
1416 while (!Poly.IsNull());
1421 //=======================================================================
1424 //=======================================================================
1425 Standard_Integer BRepMesh_FastDiscret::NbTriangles() const
1427 return myStructure->NbElements();
1430 //=======================================================================
1431 //function : Triangle
1433 //=======================================================================
1435 const BRepMesh_Triangle& BRepMesh_FastDiscret::Triangle
1436 (const Standard_Integer Index) const
1438 return myStructure->GetElement(Index);
1441 //=======================================================================
1442 //function : NbEdges
1444 //=======================================================================
1446 Standard_Integer BRepMesh_FastDiscret::NbEdges() const
1448 return myStructure->NbLinks();
1451 //=======================================================================
1454 //=======================================================================
1456 const BRepMesh_Edge& BRepMesh_FastDiscret::Edge(const Standard_Integer Index) const
1458 return myStructure->GetLink(Index);
1461 //=======================================================================
1462 //function : NbVertices
1464 //=======================================================================
1466 Standard_Integer BRepMesh_FastDiscret::NbVertices() const
1468 return myStructure->NbNodes();
1471 //=======================================================================
1474 //=======================================================================
1476 const BRepMesh_Vertex& BRepMesh_FastDiscret::Vertex
1477 (const Standard_Integer Index) const
1479 return myStructure->GetNode(Index);
1482 //=======================================================================
1485 //=======================================================================
1487 const gp_Pnt& BRepMesh_FastDiscret::Pnt(const Standard_Integer Index) const
1489 return myLocation3d(myStructure->GetNode(Index).Location3d());
1492 //=======================================================================
1493 //function : VerticesOfDomain
1495 //=======================================================================
1497 void BRepMesh_FastDiscret::VerticesOfDomain(BRepMesh_MapOfInteger& Indices) const
1501 // recuperate from the map of edges.
1502 const BRepMesh_MapOfInteger& edmap = myStructure->LinkOfDomain();
1504 // iterator on edges.
1505 BRepMesh_MapOfInteger::Iterator iter(edmap);
1507 Standard_Integer ind_edge;
1508 for (iter.Reset(); iter.More(); iter.Next()) {
1509 ind_edge = iter.Key();
1510 const BRepMesh_Edge& Ed = Edge(ind_edge);
1511 Indices.Add(Ed.FirstNode());
1512 Indices.Add(Ed.LastNode());
1516 BRepMesh_Status BRepMesh_FastDiscret::CurrentFaceStatus() const
1521 //=======================================================================
1522 //function : GetFaceAttribute
1524 //=======================================================================
1526 Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(const TopoDS_Face& theFace,
1527 Handle(BRepMesh_FaceAttribute)& theFattrib) const
1529 if(myMapattrib.IsBound(theFace))
1531 theFattrib = myMapattrib(theFace);
1532 return Standard_True;
1534 return Standard_False;
1537 //=======================================================================
1538 //function : RemoveFaceAttribute
1540 //=======================================================================
1542 void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace)
1544 if(myMapattrib.IsBound(theFace))
1545 myMapattrib.UnBind(theFace);