0031662: Modeling Algorithms - Incomplete result of section operation
[occt.git] / src / BRepClass / BRepClass_Intersector.cxx
CommitLineData
b311480e 1// Created on: 1992-11-19
2// Created by: Remi LEQUETTE
3// Copyright (c) 1992-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
42cf5bc1 17
7fd59977 18#include <BRep_Tool.hxx>
19#include <BRepAdaptor_Curve2d.hxx>
20#include <BRepAdaptor_Surface.hxx>
42cf5bc1 21#include <BRepClass_Edge.hxx>
22#include <BRepClass_Intersector.hxx>
7fd59977 23#include <ElCLib.hxx>
42cf5bc1 24#include <Extrema_ExtPC2d.hxx>
25#include <Geom2d_Curve.hxx>
7fd59977 26#include <Geom2d_Line.hxx>
7fd59977 27#include <Geom2dInt_GInter.hxx>
42cf5bc1 28#include <Geom2dLProp_CLProps2d.hxx>
29#include <gp_Dir2d.hxx>
30#include <gp_Lin2d.hxx>
31#include <IntRes2d_Domain.hxx>
312cd1f5 32#include <IntRes2d_IntersectionPoint.hxx>
42cf5bc1 33#include <IntRes2d_Transition.hxx>
34#include <Precision.hxx>
35#include <TopExp.hxx>
36#include <TopoDS_Vertex.hxx>
312cd1f5 37
5a2f31c8 38static
39void GetTangentAsChord(const Handle(Geom2d_Curve)& thePCurve,
40 gp_Dir2d& theTangent,
41 const Standard_Real theParam,
42 const Standard_Real theFirst,
43 const Standard_Real theLast);
44
8f9a9b9d 45static
73cd8a8a 46void RefineTolerance(const TopoDS_Face& aF,
47cd8af2 47 const Geom2dAdaptor_Curve& aC,
73cd8a8a 48 const Standard_Real aT,
49 Standard_Real& aTolZ);
8f9a9b9d 50
7fd59977 51//=======================================================================
52//function : BRepClass_Intersector
53//purpose :
54//=======================================================================
55
56BRepClass_Intersector::BRepClass_Intersector()
57{
58}
59
60//=======================================================================
61//function : Perform
62//purpose :
63//=======================================================================
7fd59977 64void BRepClass_Intersector::Perform(const gp_Lin2d& L,
73cd8a8a 65 const Standard_Real P,
66 const Standard_Real Tol,
67 const BRepClass_Edge& E)
7fd59977 68{
73cd8a8a 69 Standard_Real deb = 0.0, fin = 0.0, aTolZ = Tol;
8f9a9b9d 70 Handle(Geom2d_Curve) aC2D;
71 //
8f9a9b9d 72 const TopoDS_Edge& EE = E.Edge();
73 const TopoDS_Face& F = E.Face();
73cd8a8a 74
8f9a9b9d 75 //
76 aC2D=BRep_Tool::CurveOnSurface(EE, F, deb, fin);
77 if (aC2D.IsNull()) {
7fd59977 78 done = Standard_False; // !IsDone()
8f9a9b9d 79 return;
7fd59977 80 }
8f9a9b9d 81 //
47cd8af2 82 Geom2dAdaptor_Curve C(aC2D, deb, fin);
8f9a9b9d 83 //
84 deb = C.FirstParameter();
85 fin = C.LastParameter();
86 //
87 // Case of "ON": direct check of belonging to edge
88 // taking into account the tolerance
73cd8a8a 89 Extrema_ExtPC2d anExtPC2d(L.Location(), C);
8f9a9b9d 90 Standard_Real MinDist = RealLast(), aDist;
91 Standard_Integer MinInd = 0, i;
73cd8a8a 92 if (anExtPC2d.IsDone())
93 {
94 const Standard_Integer aNbPnts = anExtPC2d.NbExt();
95 for (i = 1; i <= aNbPnts; ++i)
96 {
97 aDist = anExtPC2d.SquareDistance(i);
98
99 if (aDist < MinDist)
100 {
101 MinDist = aDist;
102 MinInd = i;
312cd1f5 103 }
104 }
8f9a9b9d 105 }
73cd8a8a 106
8f9a9b9d 107 if (MinInd) {
108 MinDist = sqrt(MinDist);
109 }
110 if (MinDist <= aTolZ) {
73cd8a8a 111 gp_Pnt2d pnt_exact = (anExtPC2d.Point(MinInd)).Value();
112 Standard_Real par = (anExtPC2d.Point(MinInd)).Parameter();
8f9a9b9d 113 //
114 RefineTolerance(F, C, par, aTolZ);
115 //
116 if (MinDist <= aTolZ) {
312cd1f5 117 IntRes2d_Transition tr_on_lin(IntRes2d_Head);
118 IntRes2d_Position pos_on_curve = IntRes2d_Middle;
8f9a9b9d 119 if (Abs(par - deb) <= Precision::Confusion()) {
73cd8a8a 120 pos_on_curve = IntRes2d_Head;
8f9a9b9d 121 }
122 else if (Abs(par - fin) <= Precision::Confusion()) {
73cd8a8a 123 pos_on_curve = IntRes2d_End;
8f9a9b9d 124 }
125 //
312cd1f5 126 IntRes2d_Transition tr_on_curve(pos_on_curve);
127 IntRes2d_IntersectionPoint pnt_inter(pnt_exact, 0., par,
73cd8a8a 128 tr_on_lin, tr_on_curve,
129 Standard_False);
8f9a9b9d 130 //
131 Append(pnt_inter);
312cd1f5 132 done = Standard_True;
133 return;
134 }
7fd59977 135 }
8f9a9b9d 136 //
137 gp_Pnt2d pdeb,pfin;
138 C.D0(deb,pdeb);
139 C.D0(fin,pfin);
140 Standard_Real toldeb = 1.e-5, tolfin = 1.e-5;
73cd8a8a 141
8f9a9b9d 142 IntRes2d_Domain DL;
143 //
144 if(P!=RealLast()) {
4680b22c 145 DL.SetValues(L.Location(),0.,Precision::PConfusion(),ElCLib::Value(P,L),P,Precision::PConfusion());
8f9a9b9d 146 }
147 else {
4680b22c 148 DL.SetValues(L.Location(),0.,Precision::PConfusion(),Standard_True);
8f9a9b9d 149 }
73cd8a8a 150
8f9a9b9d 151 IntRes2d_Domain DE(pdeb,deb,toldeb,pfin,fin,tolfin);
152 // temporary periodic domain
153 if (C.Curve()->IsPeriodic()) {
154 DE.SetEquivalentParameters(C.FirstParameter(),
73cd8a8a 155 C.FirstParameter() +
156 C.Curve()->LastParameter() -
157 C.Curve()->FirstParameter());
8f9a9b9d 158 }
73cd8a8a 159
8f9a9b9d 160 Handle(Geom2d_Line) GL= new Geom2d_Line(L);
161 Geom2dAdaptor_Curve CGA(GL);
162 Geom2dInt_GInter Inter(CGA,DL,C,DE,
73cd8a8a 163 Precision::PConfusion(),
164 Precision::PIntersection());
8f9a9b9d 165 //
166 SetValues(Inter);
7fd59977 167}
168
169//=======================================================================
170//function : LocalGeometry
171//purpose :
172//=======================================================================
7fd59977 173void BRepClass_Intersector::LocalGeometry(const BRepClass_Edge& E,
73cd8a8a 174 const Standard_Real U,
175 gp_Dir2d& Tang,
176 gp_Dir2d& Norm,
177 Standard_Real& C) const
7fd59977 178{
5a2f31c8 179 Standard_Real fpar, lpar;
180 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(E.Edge(), E.Face(), fpar, lpar);
181 Geom2dLProp_CLProps2d Prop(aPCurve, U, 2, Precision::PConfusion());
182
183 C = 0.;
184 if (Prop.IsTangentDefined())
185 {
186 Prop.Tangent(Tang);
187 C = Prop.Curvature();
188 }
189 else
190 GetTangentAsChord(aPCurve, Tang, U, fpar, lpar);
191
192 if (C > Precision::PConfusion() &&
193 !Precision::IsInfinite(C))
7fd59977 194 Prop.Normal(Norm);
195 else
196 Norm.SetCoord(Tang.Y(),-Tang.X());
197}
198
8f9a9b9d 199//=======================================================================
200//function : RefineTolerance
201//purpose :
202//=======================================================================
203void RefineTolerance(const TopoDS_Face& aF,
47cd8af2 204 const Geom2dAdaptor_Curve& aC,
73cd8a8a 205 const Standard_Real aT,
206 Standard_Real& aTolZ)
8f9a9b9d 207{
208 GeomAbs_SurfaceType aTypeS;
209 //
210 BRepAdaptor_Surface aBAS(aF, Standard_False);
211 //
212 aTypeS=aBAS.GetType();
213 if (aTypeS==GeomAbs_Cylinder) {
214 Standard_Real aURes, aVRes, aTolX;
215 gp_Pnt2d aP2D;
216 gp_Vec2d aV2D;
217 //
218 aURes=aBAS.UResolution(aTolZ);
219 aVRes=aBAS.VResolution(aTolZ);
220 //
221 aC.D1(aT, aP2D, aV2D);
222 gp_Dir2d aD2D(aV2D);
223 //
224 aTolX=aURes*aD2D.Y()+aVRes*aD2D.X();
225 if (aTolX<0.) {
226 aTolX=-aTolX;
227 }
228 //
ce101cac 229 if (aTolX < Precision::Confusion()) {
230 aTolX = Precision::Confusion();
231 }
232 //
8f9a9b9d 233 if (aTolX<aTolZ) {
234 aTolZ=aTolX;
235 }
236 }
237}
7fd59977 238
5a2f31c8 239//=======================================================================
240//function : GetTangentAsChord
241//purpose :
242//=======================================================================
243void GetTangentAsChord(const Handle(Geom2d_Curve)& thePCurve,
244 gp_Dir2d& theTangent,
245 const Standard_Real theParam,
246 const Standard_Real theFirst,
247 const Standard_Real theLast)
248{
249 Standard_Real Offset = 0.1*(theLast - theFirst);
250
251 if (theLast - theParam < Precision::PConfusion()) //theParam == theLast
252 Offset *= -1;
253 else if (theParam + Offset > theLast) //<theParam> is close to <theLast>
254 Offset = 0.5*(theLast - theParam);
7fd59977 255
5a2f31c8 256 gp_Pnt2d aPnt2d = thePCurve->Value(theParam);
257 gp_Pnt2d OffsetPnt2d = thePCurve->Value(theParam + Offset);
258
259 gp_Vec2d aChord(aPnt2d, OffsetPnt2d);
260 if (Offset < 0.)
261 aChord.Reverse();
262
263 Standard_Real SqLength = aChord.SquareMagnitude();
264 if (SqLength > Precision::SquarePConfusion())
265 theTangent = aChord;
266}