1 // Created on: 1992-11-19
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1992-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.
18 #include <BRep_Tool.hxx>
19 #include <BRepAdaptor_Curve2d.hxx>
20 #include <BRepAdaptor_Surface.hxx>
21 #include <BRepClass_Edge.hxx>
22 #include <BRepClass_Intersector.hxx>
24 #include <Extrema_ExtPC2d.hxx>
25 #include <GCE2d_MakeSegment.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom2d_Line.hxx>
28 #include <Geom2dInt_GInter.hxx>
29 #include <Geom2dLProp_CLProps2d.hxx>
30 #include <gp_Dir2d.hxx>
31 #include <gp_Lin2d.hxx>
32 #include <IntRes2d_Domain.hxx>
33 #include <IntRes2d_IntersectionPoint.hxx>
34 #include <IntRes2d_Transition.hxx>
35 #include <Precision.hxx>
37 #include <TopoDS_Vertex.hxx>
40 void GetTangentAsChord(const Handle(Geom2d_Curve)& thePCurve,
42 const Standard_Real theParam,
43 const Standard_Real theFirst,
44 const Standard_Real theLast);
47 void RefineTolerance(const TopoDS_Face& aF,
48 const Geom2dAdaptor_Curve& aC,
49 const Standard_Real aT,
50 Standard_Real& aTolZ);
53 Standard_Boolean CheckOn(IntRes2d_IntersectionPoint& thePntInter,
54 const TopoDS_Face& theF,
56 Geom2dAdaptor_Curve& theCur,
57 Standard_Real theTolZ,
59 Standard_Real theDeb);
62 void CheckSkip(Geom2dInt_GInter& theInter,
64 const BRepClass_Edge& theE,
65 const Handle(Geom2d_Curve)& theC2D,
66 const IntRes2d_Domain& theDL,
67 Geom2dAdaptor_Curve& theCur,
68 const Geom2dAdaptor_Curve& theCGA,
71 Standard_Real theMaxTol,
76 //=======================================================================
77 //function : BRepClass_Intersector
79 //=======================================================================
81 BRepClass_Intersector::BRepClass_Intersector() : myMaxTolerance(0.1)
85 //=======================================================================
88 //=======================================================================
89 Standard_Boolean CheckOn(IntRes2d_IntersectionPoint& thePntInter,
90 const TopoDS_Face& theF,
92 Geom2dAdaptor_Curve& theCur,
93 Standard_Real theTolZ,
97 Extrema_ExtPC2d anExtPC2d(theL.Location(), theCur);
98 Standard_Real aMinDist = RealLast();
99 Standard_Integer aMinInd = 0;
100 if (anExtPC2d.IsDone())
102 const Standard_Integer aNbPnts = anExtPC2d.NbExt();
103 for (Standard_Integer i = 1; i <= aNbPnts; ++i)
105 Standard_Real aDist = anExtPC2d.SquareDistance(i);
107 if (aDist < aMinDist)
116 aMinDist = Sqrt(aMinDist);
118 if (aMinDist <= theTolZ) {
119 gp_Pnt2d aPntExact = (anExtPC2d.Point(aMinInd)).Value();
120 Standard_Real aPar = (anExtPC2d.Point(aMinInd)).Parameter();
122 RefineTolerance(theF, theCur, aPar, theTolZ);
124 if (aMinDist <= theTolZ) {
125 IntRes2d_Transition aTrOnLin(IntRes2d_Head);
126 IntRes2d_Position aPosOnCurve = IntRes2d_Middle;
127 if (Abs(aPar - theDeb) <= Precision::Confusion()) {
128 aPosOnCurve = IntRes2d_Head;
130 else if (Abs(aPar - theFin) <= Precision::Confusion()) {
131 aPosOnCurve = IntRes2d_End;
134 IntRes2d_Transition aTrOnCurve(aPosOnCurve);
135 thePntInter = IntRes2d_IntersectionPoint(aPntExact, 0., aPar,
136 aTrOnLin, aTrOnCurve,
139 return Standard_True;
142 return Standard_False;
145 //=======================================================================
146 //function : CheckSkip
148 //=======================================================================
149 void CheckSkip(Geom2dInt_GInter& theInter,
150 const gp_Lin2d& theL,
151 const BRepClass_Edge& theE,
152 const Handle(Geom2d_Curve)& theC2D,
153 const IntRes2d_Domain& theDL,
154 Geom2dAdaptor_Curve& theCur,
155 const Geom2dAdaptor_Curve& theCGA,
156 Standard_Real theFin,
157 Standard_Real theDeb,
158 Standard_Real theMaxTol,
162 if (theE.Edge().IsNull() || theE.Face().IsNull())
166 Standard_Boolean anIsLSkip = Standard_False;
167 TopoDS_Vertex aVl; // the last vertex of current edge
169 Handle(Geom2d_Curve) aSkipC2D;
171 aVl = TopExp::LastVertex(theE.Edge(), Standard_True);
176 const TopoDS_Edge anEl = theE.NextEdge(); // the next edge
177 if (!(BRep_Tool::Tolerance(aVl) > theMaxTol) || theE.NextEdge().IsNull())
181 Standard_Real aLdeb = 0.0, aLfin = 0.0;
182 Handle(Geom2d_Curve) aLC2D; // the next curve
184 aLC2D = BRep_Tool::CurveOnSurface(theE.NextEdge(), theE.Face(), aLdeb, aLfin);
189 Standard_Real anA, aB, aC; // coefficients of the straight line
190 Standard_Real aX1, anY1, aX2, anY2; // coordinates of the ends of edges
191 gp_Pnt2d aP1, aP2; // the ends of edges
193 theL.Coefficients(anA, aB, aC);
195 Standard_Real at1 = theFin;
196 if (theE.Edge().Orientation() != TopAbs_FORWARD)
201 Standard_Real at2 = aLdeb;
202 if (theE.NextEdge().Orientation() != TopAbs_FORWARD)
207 aP1 = theC2D->Value(at1);
208 aP2 = aLC2D->Value(at2);
210 // Check if points belong to DL domain
211 Standard_Real aPar1 = ElCLib::Parameter(theL, aP1);
212 Standard_Real aPar2 = ElCLib::Parameter(theL, aP2);
214 if (!(aPar1 > theDL.FirstParameter() && aPar1 < theDL.LastParameter()) ||
215 !(aPar2 > theDL.FirstParameter() && aPar2 < theDL.LastParameter()))
219 aX1 = aP1.X(); anY1 = aP1.Y(); aX2 = aP2.X(); anY2 = aP2.Y();
220 Standard_Real aFV = anA * aX1 + aB * anY1 + aC;
221 Standard_Real aSV = anA * aX2 + aB * anY2 + aC;
223 // Check for getting into vertex with high tolerance
224 if ((aFV * aSV) >= 0)
226 anIsLSkip = Standard_False;
230 anIsLSkip = Standard_True;
231 GCE2d_MakeSegment aMkSeg(aP1, aP2);
232 if (!aMkSeg.IsDone())
236 aSkipC2D = aMkSeg.Value();
238 if (aSkipC2D.IsNull() || !anIsLSkip)
243 theCur.Load(aSkipC2D);
244 if (theCur.Curve().IsNull())
248 Standard_Real atoldeb = 1.e-5, atolfin = 1.e-5;
250 theDeb = theCur.FirstParameter();
251 theFin = theCur.LastParameter();
252 theCur.D0(theDeb, thePdeb);
253 theCur.D0(theFin, thePfin);
255 IntRes2d_Domain aDE(thePdeb, theDeb, atoldeb, thePfin, theFin, atolfin);
256 // temporary periodic domain
257 if (theCur.Curve()->IsPeriodic())
259 aDE.SetEquivalentParameters(theCur.FirstParameter(),
260 theCur.FirstParameter() +
261 theCur.Curve()->LastParameter() -
262 theCur.Curve()->FirstParameter());
265 theInter = Geom2dInt_GInter(theCGA, theDL, theCur, aDE,
266 Precision::PConfusion(),
267 Precision::PIntersection());
271 //=======================================================================
274 //=======================================================================
275 void BRepClass_Intersector::Perform(const gp_Lin2d& L,
276 const Standard_Real P,
277 const Standard_Real Tol,
278 const BRepClass_Edge& E)
280 Standard_Real deb = 0.0, fin = 0.0, aTolZ = Tol;
281 Handle(Geom2d_Curve) aC2D;
283 const TopoDS_Edge& EE = E.Edge();
284 const TopoDS_Face& F = E.Face();
287 aC2D=BRep_Tool::CurveOnSurface(EE, F, deb, fin);
289 done = Standard_False; // !IsDone()
293 Geom2dAdaptor_Curve C(aC2D, deb, fin);
295 deb = C.FirstParameter();
296 fin = C.LastParameter();
298 // Case of "ON": direct check of belonging to edge
299 // taking into account the tolerance
300 Standard_Boolean aStatusOn = Standard_False;
301 IntRes2d_IntersectionPoint aPntInter;
303 aStatusOn = CheckOn(aPntInter, F, L, C, aTolZ, fin, deb);
307 done = Standard_True;
315 Standard_Real toldeb = 1.e-5, tolfin = 1.e-5;
320 DL.SetValues(L.Location(),0.,Precision::PConfusion(),ElCLib::Value(P,L),P,Precision::PConfusion());
323 DL.SetValues(L.Location(),0.,Precision::PConfusion(),Standard_True);
326 IntRes2d_Domain DE(pdeb,deb,toldeb,pfin,fin,tolfin);
327 // temporary periodic domain
328 if (C.Curve()->IsPeriodic()) {
329 DE.SetEquivalentParameters(C.FirstParameter(),
331 C.Curve()->LastParameter() -
332 C.Curve()->FirstParameter());
335 Handle(Geom2d_Line) GL= new Geom2d_Line(L);
336 Geom2dAdaptor_Curve CGA(GL);
337 Geom2dInt_GInter Inter(CGA,DL,C,DE,
338 Precision::PConfusion(),
339 Precision::PIntersection());
341 // The check is for hitting the intersector to
342 // a vertex with high tolerance
345 CheckSkip(Inter, L, E, aC2D, DL,
346 C, CGA, fin, deb, MaxTolerance(), pdeb, pfin);
353 //=======================================================================
354 //function : LocalGeometry
356 //=======================================================================
357 void BRepClass_Intersector::LocalGeometry(const BRepClass_Edge& E,
358 const Standard_Real U,
361 Standard_Real& C) const
363 Standard_Real fpar, lpar;
364 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(E.Edge(), E.Face(), fpar, lpar);
365 Geom2dLProp_CLProps2d Prop(aPCurve, U, 2, Precision::PConfusion());
368 if (Prop.IsTangentDefined())
371 C = Prop.Curvature();
374 GetTangentAsChord(aPCurve, Tang, U, fpar, lpar);
376 if (C > Precision::PConfusion() &&
377 !Precision::IsInfinite(C))
380 Norm.SetCoord(Tang.Y(),-Tang.X());
383 //=======================================================================
384 //function : RefineTolerance
386 //=======================================================================
387 void RefineTolerance(const TopoDS_Face& aF,
388 const Geom2dAdaptor_Curve& aC,
389 const Standard_Real aT,
390 Standard_Real& aTolZ)
392 GeomAbs_SurfaceType aTypeS;
394 BRepAdaptor_Surface aBAS(aF, Standard_False);
396 aTypeS=aBAS.GetType();
397 if (aTypeS==GeomAbs_Cylinder) {
398 Standard_Real aURes, aVRes, aTolX;
402 aURes=aBAS.UResolution(aTolZ);
403 aVRes=aBAS.VResolution(aTolZ);
405 aC.D1(aT, aP2D, aV2D);
408 aTolX=aURes*aD2D.Y()+aVRes*aD2D.X();
413 if (aTolX < Precision::Confusion()) {
414 aTolX = Precision::Confusion();
423 //=======================================================================
424 //function : GetTangentAsChord
426 //=======================================================================
427 void GetTangentAsChord(const Handle(Geom2d_Curve)& thePCurve,
428 gp_Dir2d& theTangent,
429 const Standard_Real theParam,
430 const Standard_Real theFirst,
431 const Standard_Real theLast)
433 Standard_Real Offset = 0.1*(theLast - theFirst);
435 if (theLast - theParam < Precision::PConfusion()) //theParam == theLast
437 else if (theParam + Offset > theLast) //<theParam> is close to <theLast>
438 Offset = 0.5*(theLast - theParam);
440 gp_Pnt2d aPnt2d = thePCurve->Value(theParam);
441 gp_Pnt2d OffsetPnt2d = thePCurve->Value(theParam + Offset);
443 gp_Vec2d aChord(aPnt2d, OffsetPnt2d);
447 Standard_Real SqLength = aChord.SquareMagnitude();
448 if (SqLength > Precision::SquarePConfusion())