1 // Created on: 2014-08-13
2 // Created by: Oleg AGASHIN
3 // Copyright (c) 2011-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <BRepMesh_EdgeTessellator.hxx>
17 #include <Geom_Surface.hxx>
18 #include <Geom_Plane.hxx>
19 #include <Geom2d_Curve.hxx>
20 #include <TopoDS_Edge.hxx>
21 #include <TopoDS_Face.hxx>
22 #include <BRepAdaptor_HSurface.hxx>
23 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
24 #include <TopLoc_Location.hxx>
25 #include <BRep_Tool.hxx>
26 #include <TColStd_Array1OfReal.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopoDS_Vertex.hxx>
30 #include <TopTools_ListIteratorOfListOfShape.hxx>
31 #include <TopTools_ListOfShape.hxx>
32 #include <TColStd_Array1OfReal.hxx>
34 IMPLEMENT_STANDARD_HANDLE (BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)
35 IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)
37 //=======================================================================
38 //function : Constructor
40 //=======================================================================
41 BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
42 const TopoDS_Edge& theEdge,
43 const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
44 const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
45 const Standard_Real theLinDeflection,
46 const Standard_Real theAngDeflection)
47 : mySurface(theFaceAttribute->Surface())
49 Standard_Real aPreciseAngDef = 0.5 * theAngDeflection;
50 Standard_Real aPreciseLinDef = 0.5 * theLinDeflection;
51 if (theEdge.Orientation() == TopAbs_INTERNAL)
52 aPreciseLinDef *= 0.5;
54 mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
56 Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge);
58 myCOnS.Initialize(theEdge);
60 myCOnS.Initialize(theEdge, theFaceAttribute->Face());
63 const GeomAbs_CurveType aCurveType = myCOnS.GetType();
64 Standard_Integer aMinPntNb = (aCurveType == GeomAbs_Circle) ? 4 : 2; //OCC287
66 // Get range on 2d curve
67 Standard_Real aFirstParam, aLastParam;
68 BRep_Tool::Range(theEdge, theFaceAttribute->Face(), aFirstParam, aLastParam);
69 myTool = new BRepMesh_GeomTool(myCOnS, aFirstParam, aLastParam,
70 aPreciseLinDef, aPreciseAngDef, aMinPntNb);
72 if (aCurveType == GeomAbs_BSplineCurve)
74 // TODO: remove this code block when #24959 is fixed
75 const Standard_Integer aNbInt = myCOnS.NbIntervals(GeomAbs_C1);
78 TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 );
79 myCOnS.Intervals(anIntervals, GeomAbs_C1);
80 for (Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt)
82 const Standard_Real& aStartInt = anIntervals.Value( aIntIt );
83 const Standard_Real& anEndInt = anIntervals.Value( aIntIt + 1 );
85 BRepMesh_GeomTool aDetalizator(myCOnS, aStartInt, anEndInt,
86 aPreciseLinDef, aPreciseAngDef, aMinPntNb);
88 Standard_Integer aNbAddNodes = aDetalizator.NbPoints();
89 for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt )
94 aDetalizator.Value( aNodeIt, mySurface, aParam, aPoint3d, aPoint2d );
95 myTool->AddPoint( aPoint3d, aParam, Standard_False );
101 // PTv, chl/922/G9, Take into account internal vertices
102 // it is necessary for internal edges, which do not split other edges, by their vertex
103 TopExp_Explorer aVertexIt(theEdge, TopAbs_VERTEX);
104 for (; aVertexIt.More(); aVertexIt.Next())
106 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aVertexIt.Current());
107 if (aVertex.Orientation() != TopAbs_INTERNAL)
110 myTool->AddPoint(BRep_Tool::Pnt(aVertex),
111 BRep_Tool::Parameter(aVertex, theEdge), Standard_True);
114 Standard_Integer aNodesNb = myTool->NbPoints();
115 //Check deflection in 2d space for improvement of edge tesselation.
116 if( isSameParam && aNodesNb > 1)
118 const TopTools_ListOfShape& aSharedFaces = theMapOfSharedFaces.FindFromKey(theEdge);
119 TopTools_ListIteratorOfListOfShape aFaceIt(aSharedFaces);
120 for (; aFaceIt.More(); aFaceIt.Next())
122 TopLoc_Location aLoc;
123 const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Value());
124 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc);
126 if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
129 Standard_Real aF, aL;
130 Handle(Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL);
131 if ( Abs(aF - aFirstParam) > Precision::PConfusion() ||
132 Abs(aL - aLastParam ) > Precision::PConfusion() )
137 aNodesNb = myTool->NbPoints();
138 TColStd_Array1OfReal aParamArray(1, aNodesNb);
139 for (Standard_Integer i = 1; i <= aNodesNb; ++i)
143 Standard_Real aParam;
144 myTool->Value(i, mySurface, aParam, aTmpPnt, aTmpUV);
145 aParamArray.SetValue(i, aParam);
148 for (Standard_Integer i = 1; i < aNodesNb; ++i)
149 splitSegment(aSurf, aCurve2d, aParamArray(i), aParamArray(i + 1), 1);
154 //=======================================================================
157 //=======================================================================
158 void BRepMesh_EdgeTessellator::Value(const Standard_Integer theIndex,
159 Standard_Real& theParameter,
163 myTool->Value(theIndex, mySurface, theParameter, thePoint, theUV);
166 //=======================================================================
167 //function : splitSegment
169 //=======================================================================
170 void BRepMesh_EdgeTessellator::splitSegment(
171 const Handle(Geom_Surface)& theSurf,
172 const Handle(Geom2d_Curve)& theCurve2d,
173 const Standard_Real theFirst,
174 const Standard_Real theLast,
175 const Standard_Integer theNbIter)
177 // limit iteration depth
181 gp_Pnt2d uvf, uvl, uvm;
182 gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf;
183 Standard_Real midpar;
185 if(Abs(theLast - theFirst) < 2 * Precision::PConfusion())
188 theCurve2d->D0(theFirst, uvf);
189 theCurve2d->D0(theLast, uvl);
191 P3dF = theSurf->Value(uvf.X(), uvf.Y());
192 P3dL = theSurf->Value(uvl.X(), uvl.Y());
194 if(P3dF.SquareDistance(P3dL) < mySquareEdgeDef)
197 uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5);
198 midP3dFromSurf = theSurf->Value(uvm.X(), uvm.Y());
200 gp_XYZ aVec = P3dL.XYZ() - P3dF.XYZ();
203 gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ();
204 Standard_Real aModulus = Vec1.Dot(aVec);
205 gp_XYZ aProj = aVec * aModulus;
206 gp_XYZ aDist = Vec1 - aProj;
208 if(aDist.SquareModulus() < mySquareEdgeDef)
211 midpar = (theFirst + theLast) * 0.5;
212 myCOnS.D0(midpar, midP3d);
213 myTool->AddPoint(midP3d, midpar, Standard_False);
215 splitSegment(theSurf, theCurve2d, theFirst, midpar, theNbIter + 1);
216 splitSegment(theSurf, theCurve2d, midpar, theLast, theNbIter + 1);