1 // Created on: 1993-09-29
2 // Created by: Isabelle GRIGNON
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <BRepMesh_GeomTool.hxx>
19 #include <BRepMesh_DefaultRangeSplitter.hxx>
21 #include <TopAbs_Orientation.hxx>
23 #include <Precision.hxx>
24 #include <Adaptor3d_IsoCurve.hxx>
25 #include <Adaptor3d_HCurve.hxx>
26 #include <BRepAdaptor_Curve.hxx>
27 #include <BRepAdaptor_HSurface.hxx>
28 #include <Geom2d_Curve.hxx>
29 #include <BRep_Tool.hxx>
33 void ComputeErrFactors (const Standard_Real theDeflection,
34 const Handle(Adaptor3d_HSurface)& theFace,
35 Standard_Real& theErrFactorU,
36 Standard_Real& theErrFactorV)
38 theErrFactorU = theDeflection * 10.;
39 theErrFactorV = theDeflection * 10.;
41 switch (theFace->GetType ())
43 case GeomAbs_Cylinder:
49 case GeomAbs_SurfaceOfExtrusion:
50 case GeomAbs_SurfaceOfRevolution:
52 Handle(Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
53 if (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () > 2)
55 theErrFactorV /= (aCurve->Degree () * aCurve->NbKnots ());
59 case GeomAbs_BezierSurface:
61 if (theFace->UDegree () > 2)
63 theErrFactorU /= (theFace->UDegree ());
65 if (theFace->VDegree () > 2)
67 theErrFactorV /= (theFace->VDegree ());
71 case GeomAbs_BSplineSurface:
73 if (theFace->UDegree () > 2)
75 theErrFactorU /= (theFace->UDegree () * theFace->NbUKnots ());
77 if (theFace->VDegree () > 2)
79 theErrFactorV /= (theFace->VDegree () * theFace->NbVKnots ());
86 theErrFactorU = theErrFactorV = 1.;
90 void AdjustCellsCounts (const Handle(Adaptor3d_HSurface)& theFace,
91 const Standard_Integer theNbVertices,
92 Standard_Integer& theCellsCountU,
93 Standard_Integer& theCellsCountV)
95 const GeomAbs_SurfaceType aType = theFace->GetType ();
96 if (aType == GeomAbs_OtherSurface)
98 // fallback to the default behavior
99 theCellsCountU = theCellsCountV = -1;
103 Standard_Real aSqNbVert = theNbVertices;
104 if (aType == GeomAbs_Plane)
106 theCellsCountU = theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
108 else if (aType == GeomAbs_Cylinder || aType == GeomAbs_Cone)
110 theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
112 else if (aType == GeomAbs_SurfaceOfExtrusion || aType == GeomAbs_SurfaceOfRevolution)
114 Handle (Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
115 if (aCurve->GetType () == GeomAbs_Line ||
116 (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () < 2))
118 // planar, cylindrical, conical cases
119 if (aType == GeomAbs_SurfaceOfExtrusion)
120 theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
122 theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
124 if (aType == GeomAbs_SurfaceOfExtrusion)
126 // V is always a line
127 theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
130 else if (aType == GeomAbs_BezierSurface || aType == GeomAbs_BSplineSurface)
132 if (theFace->UDegree () < 2)
134 theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
136 if (theFace->VDegree () < 2)
138 theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
142 theCellsCountU = Max (theCellsCountU, 2);
143 theCellsCountV = Max (theCellsCountV, 2);
147 //=======================================================================
148 //function : Constructor
150 //=======================================================================
151 BRepMesh_GeomTool::BRepMesh_GeomTool(
152 const BRepAdaptor_Curve& theCurve,
153 const Standard_Real theFirstParam,
154 const Standard_Real theLastParam,
155 const Standard_Real theLinDeflection,
156 const Standard_Real theAngDeflection,
157 const Standard_Integer theMinPointsNb,
158 const Standard_Real theMinSize)
159 : myEdge(&theCurve.Edge()),
160 myIsoType(GeomAbs_NoneIso)
162 myDiscretTool.Initialize(theCurve, theFirstParam, theLastParam,
163 theAngDeflection, theLinDeflection, theMinPointsNb,
164 Precision::PConfusion(), theMinSize);
167 //=======================================================================
168 //function : Constructor
170 //=======================================================================
171 BRepMesh_GeomTool::BRepMesh_GeomTool(
172 const Handle(BRepAdaptor_HSurface)& theSurface,
173 const GeomAbs_IsoType theIsoType,
174 const Standard_Real theParamIso,
175 const Standard_Real theFirstParam,
176 const Standard_Real theLastParam,
177 const Standard_Real theLinDeflection,
178 const Standard_Real theAngDeflection,
179 const Standard_Integer theMinPointsNb,
180 const Standard_Real theMinSize)
182 myIsoType(theIsoType)
184 Adaptor3d_IsoCurve aIso(theSurface, theIsoType, theParamIso,
185 theFirstParam, theLastParam);
187 myDiscretTool.Initialize(aIso, theFirstParam, theLastParam,
188 theAngDeflection, theLinDeflection, theMinPointsNb,
189 Precision::PConfusion(), theMinSize);
192 //=======================================================================
195 //=======================================================================
196 Standard_Boolean BRepMesh_GeomTool::Value(
197 const Standard_Integer theIndex,
198 const Handle(BRepAdaptor_HSurface)& theSurface,
199 Standard_Real& theParam,
201 gp_Pnt2d& theUV) const
203 if (theIndex < 1 || theIndex > NbPoints())
204 return Standard_False;
207 return Standard_False;
209 thePoint = myDiscretTool.Value(theIndex);
210 theParam = myDiscretTool.Parameter(theIndex);
212 const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face();
214 Standard_Real aFirst, aLast;
215 Handle(Geom2d_Curve) aCurve =
216 BRep_Tool::CurveOnSurface(*myEdge, aFace, aFirst, aLast);
218 aCurve->D0(theParam, theUV);
220 return Standard_True;
223 //=======================================================================
226 //=======================================================================
227 Standard_Boolean BRepMesh_GeomTool::Value(
228 const Standard_Integer theIndex,
229 const Standard_Real theIsoParam,
230 Standard_Real& theParam,
232 gp_Pnt2d& theUV) const
234 if (theIndex < 1 || theIndex > NbPoints())
235 return Standard_False;
237 thePoint = myDiscretTool.Value(theIndex);
238 theParam = myDiscretTool.Parameter(theIndex);
240 if (myIsoType == GeomAbs_IsoU)
241 theUV.SetCoord(theIsoParam, theParam);
243 theUV.SetCoord(theParam, theIsoParam);
245 return Standard_True;
248 //=======================================================================
251 //=======================================================================
252 Standard_Boolean BRepMesh_GeomTool::Normal(
253 const Handle(BRepAdaptor_HSurface)& theSurface,
254 const Standard_Real theParamU,
255 const Standard_Real theParamV,
259 Standard_Boolean isOK = Standard_True;
262 theSurface->D1(theParamU, theParamV, thePoint, aD1U, aD1V);
264 CSLib_DerivativeStatus aStatus;
265 CSLib::Normal(aD1U, aD1V, Precision::Angular(), aStatus, theNormal);
266 if (aStatus != CSLib_Done)
268 gp_Vec aD2U,aD2V,aD2UV;
269 theSurface->D2(theParamU, theParamV, thePoint, aD1U, aD1V, aD2U, aD2V, aD2UV);
270 CSLib_NormalStatus aNormalStatus;
271 CSLib::Normal(aD1U, aD1V, aD2U, aD2V, aD2UV, Precision::Angular(),
272 isOK, aNormalStatus, theNormal);
276 return Standard_False;
278 const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face();
279 TopAbs_Orientation aOri = aFace.Orientation();
280 if (aOri == TopAbs_REVERSED)
283 return Standard_True;
286 //=============================================================================
287 //function : IntLinLin
289 //=============================================================================
290 BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntLinLin(
291 const gp_XY& theStartPnt1,
292 const gp_XY& theEndPnt1,
293 const gp_XY& theStartPnt2,
294 const gp_XY& theEndPnt2,
296 Standard_Real (&theParamOnSegment)[2])
298 gp_XY aVec1 = theEndPnt1 - theStartPnt1;
299 gp_XY aVec2 = theEndPnt2 - theStartPnt2;
300 gp_XY aVecO1O2 = theStartPnt2 - theStartPnt1;
302 Standard_Real aCrossD1D2 = aVec1 ^ aVec2;
303 Standard_Real aCrossD1D3 = aVecO1O2 ^ aVec2;
305 const Standard_Real aPrec = gp::Resolution();
306 // Are edgegs codirectional
307 if ( Abs( aCrossD1D2 ) < aPrec )
309 // Just a parallel case?
310 if( Abs( aCrossD1D3 ) < aPrec )
311 return BRepMesh_GeomTool::Same;
313 return BRepMesh_GeomTool::NoIntersection;
316 theParamOnSegment[0] = aCrossD1D3 / aCrossD1D2;
317 theIntPnt = theStartPnt1 + theParamOnSegment[0] * aVec1;
319 Standard_Real aCrossD2D3 = aVecO1O2 ^ aVec1;
320 theParamOnSegment[1] = aCrossD2D3 / aCrossD1D2;
322 return BRepMesh_GeomTool::Cross;
325 //=============================================================================
326 //function : IntSegSeg
328 //=============================================================================
329 BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntSegSeg(
330 const gp_XY& theStartPnt1,
331 const gp_XY& theEndPnt1,
332 const gp_XY& theStartPnt2,
333 const gp_XY& theEndPnt2,
334 const Standard_Boolean isConsiderEndPointTouch,
335 const Standard_Boolean isConsiderPointOnSegment,
338 Standard_Integer aPointHash[] = {
339 classifyPoint(theStartPnt1, theEndPnt1, theStartPnt2),
340 classifyPoint(theStartPnt1, theEndPnt1, theEndPnt2 ),
341 classifyPoint(theStartPnt2, theEndPnt2, theStartPnt1),
342 classifyPoint(theStartPnt2, theEndPnt2, theEndPnt1 )
345 // Consider case when edges have shared vertex
346 if ( aPointHash[0] < 0 || aPointHash[1] < 0 )
348 if ( isConsiderEndPointTouch )
349 return BRepMesh_GeomTool::EndPointTouch;
351 return BRepMesh_GeomTool::NoIntersection;
354 Standard_Integer aPosHash =
355 aPointHash[0] + aPointHash[1] + aPointHash[2] + aPointHash[3];
357 /*=========================================*/
358 /* 1) hash code == 1:
368 a) +----+========+---+
371 b) +-------+===+=====+
374 /*=========================================*/
377 if (isConsiderPointOnSegment)
379 if (aPointHash[0] == 1)
380 theIntPnt = theStartPnt1;
381 else if (aPointHash[1] == 1)
382 theIntPnt = theEndPnt1;
383 else if (aPointHash[2] == 1)
384 theIntPnt = theStartPnt2;
386 theIntPnt = theEndPnt2;
388 return BRepMesh_GeomTool::PointOnSegment;
391 return BRepMesh_GeomTool::NoIntersection;
393 else if ( aPosHash == 2 )
394 return BRepMesh_GeomTool::Glued;
396 Standard_Real aParam[2];
397 IntFlag aIntFlag = IntLinLin(theStartPnt1, theEndPnt1,
398 theStartPnt2, theEndPnt2, theIntPnt.ChangeCoord(), aParam);
400 if (aIntFlag == BRepMesh_GeomTool::NoIntersection)
401 return BRepMesh_GeomTool::NoIntersection;
403 if (aIntFlag == BRepMesh_GeomTool::Same)
406 return BRepMesh_GeomTool::Same;
407 else if ( aPosHash == -1 )
408 return BRepMesh_GeomTool::Glued;
410 return BRepMesh_GeomTool::NoIntersection;
414 // Intersection is out of segments ranges
415 const Standard_Real aPrec = Precision::PConfusion();
416 const Standard_Real aEndPrec = 1 - aPrec;
417 for (Standard_Integer i = 0; i < 2; ++i)
419 if(aParam[i] < aPrec || aParam[i] > aEndPrec )
420 return BRepMesh_GeomTool::NoIntersection;
423 return BRepMesh_GeomTool::Cross;
426 //=============================================================================
427 //function : CellsCount
429 //=============================================================================
430 std::pair<Standard_Integer, Standard_Integer> BRepMesh_GeomTool::CellsCount (
431 const Handle (Adaptor3d_HSurface)& theSurface,
432 const Standard_Integer theVerticesNb,
433 const Standard_Real theDeflection,
434 const BRepMesh_DefaultRangeSplitter* theRangeSplitter)
436 if (theRangeSplitter == NULL)
437 return std::pair<Standard_Integer, Standard_Integer>(-1, -1);
439 const GeomAbs_SurfaceType aType = theSurface->GetType ();
441 Standard_Real anErrFactorU, anErrFactorV;
442 ComputeErrFactors(theDeflection, theSurface, anErrFactorU, anErrFactorV);
444 const std::pair<Standard_Real, Standard_Real>& aRangeU = theRangeSplitter->GetRangeU();
445 const std::pair<Standard_Real, Standard_Real>& aRangeV = theRangeSplitter->GetRangeV();
446 const std::pair<Standard_Real, Standard_Real>& aDelta = theRangeSplitter->GetDelta ();
448 Standard_Integer aCellsCountU, aCellsCountV;
449 if (aType == GeomAbs_Torus)
451 aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
452 (aRangeU.second - aRangeU.first) / aDelta.first)));
453 aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
454 (aRangeV.second - aRangeV.first) / aDelta.second)));
456 else if (aType == GeomAbs_Cylinder)
458 aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
459 (aRangeU.second - aRangeU.first) / aDelta.first /
460 (aRangeV.second - aRangeV.first))));
461 aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
462 (aRangeV.second - aRangeV.first) / anErrFactorV)));
466 aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
467 (aRangeU.second - aRangeU.first) / aDelta.first / anErrFactorU)));
468 aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
469 (aRangeV.second - aRangeV.first) / aDelta.second / anErrFactorV)));
472 AdjustCellsCounts(theSurface, theVerticesNb, aCellsCountU, aCellsCountV);
473 return std::pair<Standard_Integer, Standard_Integer>(aCellsCountU, aCellsCountV);
476 //=============================================================================
477 //function : classifyPoint
479 //=============================================================================
480 Standard_Integer BRepMesh_GeomTool::classifyPoint(
481 const gp_XY& thePoint1,
482 const gp_XY& thePoint2,
483 const gp_XY& thePointToCheck)
485 gp_XY aP1 = thePoint2 - thePoint1;
486 gp_XY aP2 = thePointToCheck - thePoint1;
488 const Standard_Real aPrec = Precision::PConfusion();
489 const Standard_Real aSqPrec = aPrec * aPrec;
490 Standard_Real aDist = Abs(aP1 ^ aP2);
493 aDist = (aDist * aDist) / aP1.SquareModulus();
498 gp_XY aMult = aP1.Multiplied(aP2);
499 if ( aMult.X() < 0.0 || aMult.Y() < 0.0 )
502 if (aP1.SquareModulus() < aP2.SquareModulus())
505 if (thePointToCheck.IsEqual(thePoint1, aPrec) ||
506 thePointToCheck.IsEqual(thePoint2, aPrec))
508 return -1; //coinsides with an end point