1 // Created on: 2016-04-19
2 // Copyright (c) 2016 OPEN CASCADE SAS
3 // Created by: Oleg AGASHIN
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_CurveTessellator.hxx>
18 #include <BRep_Tool.hxx>
19 #include <TopoDS_Edge.hxx>
20 #include <IMeshData_Edge.hxx>
21 #include <IMeshData_PCurve.hxx>
22 #include <IMeshTools_Parameters.hxx>
23 #include <TopExp_Explorer.hxx>
24 #include <Geom_Plane.hxx>
26 #include <Adaptor3d_HCurveOnSurface.hxx>
27 #include <Adaptor2d_HCurve2d.hxx>
28 #include <Standard_Failure.hxx>
30 //=======================================================================
31 //function : Constructor
33 //=======================================================================
34 BRepMesh_CurveTessellator::BRepMesh_CurveTessellator(
35 const IMeshData::IEdgeHandle& theEdge,
36 const IMeshTools_Parameters& theParameters)
38 myParameters(theParameters),
39 myEdge(theEdge->GetEdge()),
45 //=======================================================================
46 //function : Constructor
48 //=======================================================================
49 BRepMesh_CurveTessellator::BRepMesh_CurveTessellator (
50 const IMeshData::IEdgeHandle& theEdge,
51 const TopAbs_Orientation theOrientation,
52 const IMeshData::IFaceHandle& theFace,
53 const IMeshTools_Parameters& theParameters)
55 myParameters(theParameters),
56 myEdge(TopoDS::Edge(theEdge->GetEdge().Oriented(theOrientation))),
57 myCurve(myEdge, theFace->GetFace())
62 //=======================================================================
65 //=======================================================================
66 void BRepMesh_CurveTessellator::init()
68 if (myParameters.MinSize <= 0.0)
70 Standard_Failure::Raise ("The structure \"myParameters\" is not initialized");
73 TopExp::Vertices(myEdge, myFirstVertex, myLastVertex);
75 Standard_Real aPreciseAngDef = 0.5 * myDEdge->GetAngularDeflection();
76 Standard_Real aPreciseLinDef = 0.5 * myDEdge->GetDeflection();
77 if (myEdge.Orientation() == TopAbs_INTERNAL)
79 aPreciseLinDef *= 0.5;
82 aPreciseLinDef = Max(aPreciseLinDef, Precision::Confusion());
83 aPreciseAngDef = Max(aPreciseAngDef, Precision::Angular());
85 mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
86 mySquareMinSize = Max(mySquareEdgeDef, myParameters.MinSize * myParameters.MinSize);
88 myEdgeSqTol = BRep_Tool::Tolerance(myEdge);
89 myEdgeSqTol *= myEdgeSqTol;
91 const Standard_Integer aMinPntNb = (myCurve.GetType() == GeomAbs_Circle) ? 4 : 2; //OCC287
93 myDiscretTool.Initialize(myCurve,
94 myCurve.FirstParameter(), myCurve.LastParameter(),
95 aPreciseAngDef, aPreciseLinDef, aMinPntNb,
96 Precision::PConfusion(), myParameters.MinSize);
98 if (myCurve.IsCurveOnSurface())
100 const Adaptor3d_CurveOnSurface& aCurve = myCurve.CurveOnSurface();
101 const Handle(Adaptor3d_HSurface)& aSurface = aCurve.GetSurface();
103 const Standard_Real aTol = Precision::Confusion();
104 const Standard_Real aDu = aSurface->UResolution(aTol);
105 const Standard_Real aDv = aSurface->VResolution(aTol);
107 myFaceRangeU[0] = aSurface->FirstUParameter() - aDu;
108 myFaceRangeU[1] = aSurface->LastUParameter() + aDu;
110 myFaceRangeV[0] = aSurface->FirstVParameter() - aDv;
111 myFaceRangeV[1] = aSurface->LastVParameter() + aDv;
114 addInternalVertices();
115 splitByDeflection2d();
118 //=======================================================================
119 //function : Destructor
121 //=======================================================================
122 BRepMesh_CurveTessellator::~BRepMesh_CurveTessellator ()
126 //=======================================================================
127 //function : NbPoints
129 //=======================================================================
130 Standard_Integer BRepMesh_CurveTessellator::PointsNb () const
132 return myDiscretTool.NbPoints ();
135 //=======================================================================
136 //function : splitByDeflection2d
138 //=======================================================================
139 void BRepMesh_CurveTessellator::splitByDeflection2d ()
141 const Standard_Integer aNodesNb = myDiscretTool.NbPoints ();
142 if (!myDEdge->IsFree () &&
143 myDEdge->GetSameParam () &&
144 myDEdge->GetSameRange () &&
147 for (Standard_Integer aPCurveIt = 0; aPCurveIt < myDEdge->PCurvesNb (); ++aPCurveIt)
149 TopLoc_Location aLoc;
150 const IMeshData::IPCurveHandle& aPCurve = myDEdge->GetPCurve(aPCurveIt);
151 const TopoDS_Face& aFace = aPCurve->GetFace ()->GetFace ();
152 const Handle (Geom_Surface)& aSurface = BRep_Tool::Surface (aFace, aLoc);
153 if (aSurface->IsInstance(STANDARD_TYPE(Geom_Plane)))
158 const TopoDS_Edge aCurrEdge = TopoDS::Edge(myEdge.Oriented(aPCurve->GetOrientation()));
160 Standard_Real aF, aL;
161 Handle (Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface (aCurrEdge, aFace, aF, aL);
162 TColStd_Array1OfReal aParamArray (1, aNodesNb);
163 for (Standard_Integer i = 1; i <= aNodesNb; ++i)
164 aParamArray.SetValue (i, myDiscretTool.Parameter (i));
166 for (Standard_Integer i = 1; i < aNodesNb; ++i)
167 splitSegment (aSurface, aCurve2d, aParamArray (i), aParamArray (i + 1), 1);
172 //=======================================================================
173 //function : addInternalVertices
175 //=======================================================================
176 void BRepMesh_CurveTessellator::addInternalVertices ()
178 // PTv, chl/922/G9, Take into account internal vertices
179 // it is necessary for internal edges, which do not split other edges, by their vertex
180 TopExp_Explorer aVertexIt (myEdge, TopAbs_VERTEX);
181 for (; aVertexIt.More (); aVertexIt.Next ())
183 const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVertexIt.Current ());
184 if (aVertex.Orientation() != TopAbs_INTERNAL)
189 myDiscretTool.AddPoint (BRep_Tool::Pnt (aVertex),
190 BRep_Tool::Parameter (aVertex, myEdge), Standard_True);
194 //=======================================================================
195 //function : isInToleranceOfVertex
197 //=======================================================================
198 Standard_Boolean BRepMesh_CurveTessellator::isInToleranceOfVertex (
199 const gp_Pnt& thePoint,
200 const TopoDS_Vertex& theVertex) const
202 const gp_Pnt aPoint = BRep_Tool::Pnt(theVertex);
203 const Standard_Real aTolerance = BRep_Tool::Tolerance(theVertex);
205 return (thePoint.SquareDistance (aPoint) < aTolerance * aTolerance);
208 //=======================================================================
211 //=======================================================================
212 Standard_Boolean BRepMesh_CurveTessellator::Value (
213 const Standard_Integer theIndex,
215 Standard_Real& theParameter) const
217 thePoint = myDiscretTool.Value (theIndex);
218 theParameter = myDiscretTool.Parameter (theIndex);
220 /*if (!isInToleranceOfVertex(thePoint, myFirstVertex) &&
221 !isInToleranceOfVertex(thePoint, myLastVertex))
223 if (!myCurve.IsCurveOnSurface())
225 return Standard_True;
228 // If point coordinates are out of surface range,
229 // it is necessary to re-project point.
230 const Adaptor3d_CurveOnSurface& aCurve = myCurve.CurveOnSurface();
231 const Handle(Adaptor3d_HSurface)& aSurface = aCurve.GetSurface();
232 if (aSurface->GetType() != GeomAbs_BSplineSurface &&
233 aSurface->GetType() != GeomAbs_BezierSurface &&
234 aSurface->GetType() != GeomAbs_OtherSurface)
236 return Standard_True;
239 // Let skip periodic case.
240 if (aSurface->IsUPeriodic() || aSurface->IsVPeriodic())
242 return Standard_True;
246 aCurve.GetCurve()->D0(theParameter, aUV);
247 // Point lies within the surface range - nothing to do.
248 if (aUV.X() > myFaceRangeU[0] && aUV.X() < myFaceRangeU[1] &&
249 aUV.Y() > myFaceRangeV[0] && aUV.Y() < myFaceRangeV[1])
251 return Standard_True;
255 aSurface->D0(aUV.X(), aUV.Y(), aPntOnSurf);
257 return (thePoint.SquareDistance(aPntOnSurf) < myEdgeSqTol);
260 return Standard_False;*/
263 //=======================================================================
264 //function : splitSegment
266 //=======================================================================
267 void BRepMesh_CurveTessellator::splitSegment (
268 const Handle (Geom_Surface)& theSurf,
269 const Handle (Geom2d_Curve)& theCurve2d,
270 const Standard_Real theFirst,
271 const Standard_Real theLast,
272 const Standard_Integer theNbIter)
274 // limit iteration depth
280 gp_Pnt2d uvf, uvl, uvm;
281 gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf;
282 Standard_Real midpar;
284 if (Abs(theLast - theFirst) < 2 * Precision::PConfusion())
289 if ((theCurve2d->FirstParameter() - theFirst > Precision::PConfusion()) ||
290 (theLast - theCurve2d->LastParameter() > Precision::PConfusion()))
292 // E.g. test bugs moddata_3 bug30133
296 theCurve2d->D0 (theFirst, uvf);
297 theCurve2d->D0 (theLast, uvl);
299 P3dF = theSurf->Value (uvf.X (), uvf.Y ());
300 P3dL = theSurf->Value (uvl.X (), uvl.Y ());
302 if (P3dF.SquareDistance(P3dL) < mySquareMinSize)
307 uvm = gp_Pnt2d ((uvf.XY () + uvl.XY ())*0.5);
308 midP3dFromSurf = theSurf->Value (uvm.X (), uvm.Y ());
310 gp_XYZ Vec1 = midP3dFromSurf.XYZ () - P3dF.XYZ ();
311 if (Vec1.SquareModulus() < mySquareMinSize)
316 gp_XYZ aVec = P3dL.XYZ () - P3dF.XYZ ();
319 Standard_Real aModulus = Vec1.Dot (aVec);
320 gp_XYZ aProj = aVec * aModulus;
321 gp_XYZ aDist = Vec1 - aProj;
323 if (aDist.SquareModulus() < mySquareEdgeDef)
328 midpar = (theFirst + theLast) * 0.5;
329 myCurve.D0 (midpar, midP3d);
330 myDiscretTool.AddPoint (midP3d, midpar, Standard_False);
332 splitSegment (theSurf, theCurve2d, theFirst, midpar, theNbIter + 1);
333 splitSegment (theSurf, theCurve2d, midpar, theLast, theNbIter + 1);