0031939: Coding - correction of spelling errors in comments [part 4]
[occt.git] / src / IntTools / IntTools_EdgeEdge.cxx
CommitLineData
ec0cdc0e 1// Created by: Eugeny MALTCHIKOV
d5f74e42 2// Copyright (c) 2013-2014 OPEN CASCADE SAS
7fd59977 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
b311480e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
b311480e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
b311480e 14
7fd59977 15
ec0cdc0e 16#include <Bnd_Box.hxx>
17#include <BndLib_Add3dCurve.hxx>
1155d05a 18#include <TColStd_MapOfInteger.hxx>
42cf5bc1 19#include <BRep_Tool.hxx>
20#include <BRepAdaptor_Curve.hxx>
21#include <ElCLib.hxx>
a4e383e1 22#include <Geom_BezierCurve.hxx>
23#include <Geom_BSplineCurve.hxx>
e91a710c 24#include <Geom_Line.hxx>
42cf5bc1 25#include <Geom_Circle.hxx>
26#include <Geom_Curve.hxx>
27#include <Geom_Ellipse.hxx>
e91a710c 28#include <Geom_OffsetCurve.hxx>
fa9681ca 29#include <GeomAPI_ProjectPointOnCurve.hxx>
42cf5bc1 30#include <gp_Dir.hxx>
31#include <gp_Lin.hxx>
ec0cdc0e 32#include <IntTools_CommonPrt.hxx>
42cf5bc1 33#include <IntTools_EdgeEdge.hxx>
34#include <IntTools_Range.hxx>
3510db62 35#include <IntTools_Tools.hxx>
42cf5bc1 36#include <TopoDS_Edge.hxx>
37#include <TopoDS_Iterator.hxx>
ba7f665d 38#include <BRepExtrema_DistShapeShape.hxx>
6b1fe48c 39
ec0cdc0e 40static
41 void BndBuildBox(const BRepAdaptor_Curve& theBAC,
42 const Standard_Real aT1,
43 const Standard_Real aT2,
44 const Standard_Real theTol,
45 Bnd_Box& theBox);
6b1fe48c 46static
47 Standard_Real PointBoxDistance(const Bnd_Box& aB,
48 const gp_Pnt& aP);
ec0cdc0e 49static
bd28b2af 50 Standard_Integer SplitRangeOnSegments(const Standard_Real aT1,
51 const Standard_Real aT2,
52 const Standard_Real theResolution,
53 const Standard_Integer theNbSeg,
54 IntTools_SequenceOfRanges& theSegments);
ec0cdc0e 55static
56 Standard_Integer DistPC(const Standard_Real aT1,
57 const Handle(Geom_Curve)& theC1,
58 const Standard_Real theCriteria,
59 GeomAPI_ProjectPointOnCurve& theProjector,
60 Standard_Real& aD,
61 Standard_Real& aT2,
62 const Standard_Integer iC = 1);
63static
64 Standard_Integer DistPC(const Standard_Real aT1,
65 const Handle(Geom_Curve)& theC1,
66 const Standard_Real theCriteria,
67 GeomAPI_ProjectPointOnCurve& theProjector,
68 Standard_Real& aD,
69 Standard_Real& aT2,
70 Standard_Real& aDmax,
71 Standard_Real& aT1max,
72 Standard_Real& aT2max,
73 const Standard_Integer iC = 1);
74static
75 Standard_Integer FindDistPC(const Standard_Real aT1A,
76 const Standard_Real aT1B,
77 const Handle(Geom_Curve)& theC1,
78 const Standard_Real theCriteria,
79 const Standard_Real theEps,
80 GeomAPI_ProjectPointOnCurve& theProjector,
81 Standard_Real& aDmax,
82 Standard_Real& aT1max,
83 Standard_Real& aT2max,
84 const Standard_Boolean bMaxDist = Standard_True);
a4e383e1 85static
86 Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC,
87 const IntTools_Range& theRange);
88static
89 Standard_Real Resolution(const Handle(Geom_Curve)& theCurve,
90 const GeomAbs_CurveType theCurveType,
91 const Standard_Real theResCoeff,
92 const Standard_Real theR3D);
93static
94 Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC,
95 const IntTools_Range& theRange);
3e594885 96static
dde68833 97 Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve,
3e594885 98 const Standard_Real aT1,
99 const Standard_Real aT2,
100 const Standard_Real theTol,
101 const Standard_Real theRes);
ec0cdc0e 102static
103 Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType);
7fd59977 104
105//=======================================================================
ec0cdc0e 106//function : Prepare
7fd59977 107//purpose :
108//=======================================================================
ec0cdc0e 109void IntTools_EdgeEdge::Prepare()
7fd59977 110{
ec0cdc0e 111 GeomAbs_CurveType aCT1, aCT2;
112 Standard_Integer iCT1, iCT2;
113 //
114 myCurve1.Initialize(myEdge1);
115 myCurve2.Initialize(myEdge2);
116 //
117 if (myRange1.First() == 0. && myRange1.Last() == 0.) {
118 myRange1.SetFirst(myCurve1.FirstParameter());
119 myRange1.SetLast (myCurve1.LastParameter());
120 }
121 //
122 if (myRange2.First() == 0. && myRange2.Last() == 0.) {
123 myRange2.SetFirst(myCurve2.FirstParameter());
124 myRange2.SetLast (myCurve2.LastParameter());
125 }
126 //
127 aCT1 = myCurve1.GetType();
128 aCT2 = myCurve2.GetType();
129 //
130 iCT1 = TypeToInteger(aCT1);
131 iCT2 = TypeToInteger(aCT2);
132 //
133 if (iCT1 == iCT2) {
134 if (iCT1 != 0) {
135 //compute deflection
a4e383e1 136 Standard_Real aC1, aC2;
ec0cdc0e 137 //
a4e383e1 138 aC2 = CurveDeflection(myCurve2, myRange2);
139 aC1 = (aC2 > Precision::Confusion()) ?
140 CurveDeflection(myCurve1, myRange1) : 1.;
ec0cdc0e 141 //
142 if (aC1 < aC2) {
143 --iCT1;
144 }
145 }
146 }
147 //
148 if (iCT1 < iCT2) {
149 TopoDS_Edge tmpE = myEdge1;
150 myEdge1 = myEdge2;
151 myEdge2 = tmpE;
152 //
153 BRepAdaptor_Curve tmpC = myCurve1;
154 myCurve1 = myCurve2;
155 myCurve2 = tmpC;
156 //
157 IntTools_Range tmpR = myRange1;
158 myRange1 = myRange2;
159 myRange2 = tmpR;
160 //
161 mySwap = Standard_True;
162 }
163 //
0d0481c7 164 Standard_Real aTolAdd = myFuzzyValue / 2.;
3510db62 165 myTol1 = myCurve1.Tolerance() + aTolAdd;
166 myTol2 = myCurve2.Tolerance() + aTolAdd;
ec0cdc0e 167 myTol = myTol1 + myTol2;
168 //
ec0cdc0e 169 if (iCT1 != 0 || iCT2 != 0) {
a743e2e5 170 Standard_Real f, l, aTM;
171 //
ec0cdc0e 172 myGeom1 = BRep_Tool::Curve(myEdge1, f, l);
173 myGeom2 = BRep_Tool::Curve(myEdge2, f, l);
a743e2e5 174 //
a4e383e1 175 myResCoeff1 = ResolutionCoeff(myCurve1, myRange1);
176 myResCoeff2 = ResolutionCoeff(myCurve2, myRange2);
177 //
524a5f7a 178 myRes1 = Resolution(myCurve1.Curve().Curve(), myCurve1.GetType(), myResCoeff1, myTol1);
179 myRes2 = Resolution(myCurve2.Curve().Curve(), myCurve2.GetType(), myResCoeff2, myTol2);
a4e383e1 180 //
a743e2e5 181 myPTol1 = 5.e-13;
182 aTM = Max(fabs(myRange1.First()), fabs(myRange1.Last()));
183 if (aTM > 999.) {
184 myPTol1 = 5.e-16 * aTM;
185 }
186 //
187 myPTol2 = 5.e-13;
188 aTM = Max(fabs(myRange2.First()), fabs(myRange2.Last()));
189 if (aTM > 999.) {
190 myPTol2 = 5.e-16 * aTM;
191 }
ec0cdc0e 192 }
7fd59977 193}
7fd59977 194
7fd59977 195//=======================================================================
196//function : Perform
197//purpose :
198//=======================================================================
ec0cdc0e 199void IntTools_EdgeEdge::Perform()
7fd59977 200{
ec0cdc0e 201 //1. Check data
7fd59977 202 CheckData();
7fd59977 203 if (myErrorStatus) {
204 return;
205 }
206 //
ec0cdc0e 207 //2. Prepare Data
208 Prepare();
f793011e 209 //
ec0cdc0e 210 //3.1. Check Line/Line case
211 if (myCurve1.GetType() == GeomAbs_Line &&
212 myCurve2.GetType() == GeomAbs_Line) {
7fd59977 213 ComputeLineLine();
7fd59977 214 return;
215 }
f793011e 216 //
6dc83e21 217 if (myQuickCoincidenceCheck) {
218 if (IsCoincident()) {
219 Standard_Real aT11, aT12, aT21, aT22;
220 //
221 myRange1.Range(aT11, aT12);
222 myRange2.Range(aT21, aT22);
223 AddSolution(aT11, aT12, aT21, aT22, TopAbs_EDGE);
224 return;
225 }
226 }
227 //
ba7f665d 228 if ((myCurve1.GetType() <= GeomAbs_Parabola && myCurve2.GetType() <= GeomAbs_Parabola) &&
229 (myCurve1.GetType() == GeomAbs_Line || myCurve2.GetType() == GeomAbs_Line))
230 {
231 //Improvement of performance for cases of searching common parts between line
232 //and analytical curve. This code allows to define that edges have no
233 //common parts more fast, then regular algorithm (FindSolution(...))
234 //Check minimal distance between edges
235 BRepExtrema_DistShapeShape aMinDist(myEdge1, myEdge2, Extrema_ExtFlag_MIN);
236 if (aMinDist.IsDone())
237 {
238 Standard_Real d = aMinDist.Value();
239 if (d > 1.1 * myTol)
240 {
241 return;
242 }
243 }
244 }
245
6b1fe48c 246 IntTools_SequenceOfRanges aRanges1, aRanges2;
247 //
0177fe26 248 //3.2. Find ranges containing solutions
3e594885 249 Standard_Boolean bSplit2;
250 FindSolutions(aRanges1, aRanges2, bSplit2);
6b1fe48c 251 //
a743e2e5 252 //4. Merge solutions and save common parts
3e594885 253 MergeSolutions(aRanges1, aRanges2, bSplit2);
254}
255
6dc83e21 256//=======================================================================
257//function : IsCoincident
258//purpose :
259//=======================================================================
260Standard_Boolean IntTools_EdgeEdge::IsCoincident()
261{
262 Standard_Integer i, iCnt, aNbSeg, aNbP2;
263 Standard_Real dT, aT1, aCoeff, aTresh, aD;
264 Standard_Real aT11, aT12, aT21, aT22;
265 GeomAPI_ProjectPointOnCurve aProjPC;
266 gp_Pnt aP1;
267 //
268 aTresh=0.5;
269 aNbSeg=23;
270 myRange1.Range(aT11, aT12);
271 myRange2.Range(aT21, aT22);
272 //
273 aProjPC.Init(myGeom2, aT21, aT22);
274 //
275 dT=(aT12-aT11)/aNbSeg;
276 //
277 iCnt=0;
278 for(i=0; i <= aNbSeg; ++i) {
279 aT1 = aT11+i*dT;
280 myGeom1->D0(aT1, aP1);
281 //
282 aProjPC.Perform(aP1);
283 aNbP2=aProjPC.NbPoints();
284 if (!aNbP2) {
285 continue;
286 }
287 //
288 aD=aProjPC.LowerDistance();
289 if(aD < myTol) {
290 ++iCnt;
291 }
292 }
293 //
294 aCoeff=(Standard_Real)iCnt/((Standard_Real)aNbSeg+1);
295 return aCoeff > aTresh;
296}
3e594885 297//=======================================================================
298//function : FindSolutions
299//purpose :
300//=======================================================================
301void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
302 IntTools_SequenceOfRanges& theRanges2,
303 Standard_Boolean& bSplit2)
304{
305 Standard_Boolean bIsClosed2;
306 Standard_Real aT11, aT12, aT21, aT22;
88c3accd 307 Bnd_Box aB1, aB2;
3e594885 308 //
309 bSplit2 = Standard_False;
310 myRange1.Range(aT11, aT12);
311 myRange2.Range(aT21, aT22);
312 //
313 bIsClosed2 = IsClosed(myGeom2, aT21, aT22, myTol2, myRes2);
314 //
315 if (bIsClosed2) {
3e594885 316 BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
317 //
318 gp_Pnt aP = myGeom2->Value(aT21);
319 bIsClosed2 = !aB1.IsOut(aP);
320 }
321 //
322 if (!bIsClosed2) {
88c3accd 323 BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
3e594885 324 BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
88c3accd 325 FindSolutions(myRange1, aB1, myRange2, aB2, theRanges1, theRanges2);
3e594885 326 return;
327 }
328 //
524a5f7a 329 if (!CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1)) {
330 theRanges1.Append(myRange1);
331 theRanges2.Append(myRange2);
332 return;
333 }
334 //
3e594885 335 Standard_Integer i, j, aNb1, aNb2;
336 IntTools_SequenceOfRanges aSegments1, aSegments2;
337 //
338 aNb1 = IsClosed(myGeom1, aT11, aT12, myTol1, myRes1) ? 2 : 1;
339 aNb2 = 2;
340 //
bd28b2af 341 aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, aNb1, aSegments1);
342 aNb2 = SplitRangeOnSegments(aT21, aT22, myRes2, aNb2, aSegments2);
3e594885 343 //
3e594885 344 for (i = 1; i <= aNb1; ++i) {
345 const IntTools_Range& aR1 = aSegments1(i);
88c3accd 346 BndBuildBox(myCurve1, aR1.First(), aR1.Last(), myTol1, aB1);
3e594885 347 for (j = 1; j <= aNb2; ++j) {
348 const IntTools_Range& aR2 = aSegments2(j);
349 BndBuildBox(myCurve2, aR2.First(), aR2.Last(), myTol2, aB2);
88c3accd 350 FindSolutions(aR1, aB1, aR2, aB2, theRanges1, theRanges2);
3e594885 351 }
352 }
353 //
354 bSplit2 = aNb2 > 1;
0d19eb34 355}
356
357//=======================================================================
358//function : FindSolutions
359//purpose :
360//=======================================================================
361void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
88c3accd 362 const Bnd_Box& theBox1,
0d19eb34 363 const IntTools_Range& theR2,
3e594885 364 const Bnd_Box& theBox2,
365 IntTools_SequenceOfRanges& theRanges1,
0d19eb34 366 IntTools_SequenceOfRanges& theRanges2)
367{
ec0cdc0e 368 Standard_Boolean bOut, bStop, bThin;
0d19eb34 369 Standard_Real aT11, aT12, aT21, aT22;
370 Standard_Real aTB11, aTB12, aTB21, aTB22;
524a5f7a 371 Standard_Real aSmallStep1, aSmallStep2;
ec0cdc0e 372 Standard_Integer iCom;
0d19eb34 373 Bnd_Box aB1, aB2;
374 //
375 theR1.Range(aT11, aT12);
376 theR2.Range(aT21, aT22);
a743e2e5 377 //
88c3accd 378 aB1 = theBox1;
3e594885 379 aB2 = theBox2;
f793011e 380 //
ec0cdc0e 381 bThin = Standard_False;
382 bStop = Standard_False;
ec0cdc0e 383 iCom = 1;
384 //
385 do {
a4e383e1 386 aTB11 = aT11;
387 aTB12 = aT12;
388 aTB21 = aT21;
389 aTB22 = aT22;
390 //
88c3accd 391 //1. Find parameters of the second edge in the box of first one
a4e383e1 392 bOut = aB1.IsOut(aB2);
ec0cdc0e 393 if (bOut) {
394 break;
395 }
f793011e 396 //
a4e383e1 397 bThin = ((aT12 - aT11) < myRes1) ||
524a5f7a 398 (aB1.IsXThin(myTol) && aB1.IsYThin(myTol) && aB1.IsZThin(myTol));
a4e383e1 399 //
3510db62 400 bOut = !FindParameters(myCurve2, aTB21, aTB22, myTol2, myRes2, myPTol2,
a4e383e1 401 myResCoeff2, aB1, aT21, aT22);
402 if (bOut || bThin) {
0d19eb34 403 break;
404 }
405 //
a4e383e1 406 //2. Build box for second edge and find parameters
407 // of the first one in that box
408 BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
409 bOut = aB1.IsOut(aB2);
0d19eb34 410 if (bOut) {
411 break;
412 }
413 //
524a5f7a 414 bThin = ((aT22 - aT21) < myRes2) ||
415 (aB2.IsXThin(myTol) && aB2.IsYThin(myTol) && aB2.IsZThin(myTol));
0d19eb34 416 //
3510db62 417 bOut = !FindParameters(myCurve1, aTB11, aTB12, myTol1, myRes1, myPTol1,
a4e383e1 418 myResCoeff1, aB2, aT11, aT12);
419 //
420 if (bOut || bThin) {
421 break;
7fd59977 422 }
ec0cdc0e 423 //
a4e383e1 424 //3. Check if it makes sense to continue
425 aSmallStep1 = (aTB12 - aTB11) / 250.;
426 aSmallStep2 = (aTB22 - aTB21) / 250.;
427 //
428 if (aSmallStep1 < myRes1) {
429 aSmallStep1 = myRes1;
430 }
431 if (aSmallStep2 < myRes2) {
432 aSmallStep2 = myRes2;
433 }
434 //
435 if (((aT11 - aTB11) < aSmallStep1) && ((aTB12 - aT12) < aSmallStep1) &&
436 ((aT21 - aTB21) < aSmallStep2) && ((aTB22 - aT22) < aSmallStep2)) {
437 bStop = Standard_True;
438 }
88c3accd 439 else
440 BndBuildBox (myCurve1, aT11, aT12, myTol1, aB1);
441
a4e383e1 442 } while (!bStop);
ec0cdc0e 443 //
444 if (bOut) {
445 //no intersection;
446 return;
7fd59977 447 }
f793011e 448 //
ec0cdc0e 449 if (!bThin) {
450 //check curves for coincidence on the ranges
451 iCom = CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1);
452 if (!iCom) {
453 bThin = Standard_True;
a4e383e1 454 }
7fd59977 455 }
456 //
ec0cdc0e 457 if (bThin) {
458 if (iCom != 0) {
459 //check intermediate points
524a5f7a 460 Standard_Boolean bSol;
461 Standard_Real aT1;
462 gp_Pnt aP1;
463 GeomAPI_ProjectPointOnCurve aProjPC;
f793011e 464 //
3e594885 465 aT1 = (aT11 + aT12) * .5;
6b1fe48c 466 myGeom1->D0(aT1, aP1);
f793011e 467 //
524a5f7a 468 aProjPC.Init(myGeom2, aT21, aT22);
469 aProjPC.Perform(aP1);
470 //
471 if (aProjPC.NbPoints()) {
472 bSol = aProjPC.LowerDistance() <= myTol;
473 }
474 else {
475 Standard_Real aT2;
476 gp_Pnt aP2;
477 //
478 aT2 = (aT21 + aT22) * .5;
479 myGeom2->D0(aT2, aP2);
480 //
481 bSol = aP1.IsEqual(aP2, myTol);
482 }
483 //
484 if (!bSol) {
ec0cdc0e 485 return;
7fd59977 486 }
487 }
ec0cdc0e 488 //add common part
489 IntTools_Range aR1(aT11, aT12), aR2(aT21, aT22);
490 //
491 theRanges1.Append(aR1);
492 theRanges2.Append(aR2);
493 return;
7fd59977 494 }
f793011e 495 //
ec0cdc0e 496 if (!IsIntersection(aT11, aT12, aT21, aT22)) {
497 return;
7fd59977 498 }
f793011e 499 //
ec0cdc0e 500 //split ranges on segments and repeat
501 Standard_Integer i, aNb1;
502 IntTools_SequenceOfRanges aSegments1;
503 //
88c3accd 504 // Build box for first curve to compare
505 // the boxes of the splits with this one
506 BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
507 const Standard_Real aB1SqExtent = aB1.SquareExtent();
508 //
ec0cdc0e 509 IntTools_Range aR2(aT21, aT22);
3e594885 510 BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
0d19eb34 511 //
bd28b2af 512 aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1);
ec0cdc0e 513 for (i = 1; i <= aNb1; ++i) {
514 const IntTools_Range& aR1 = aSegments1(i);
88c3accd 515 BndBuildBox(myCurve1, aR1.First(), aR1.Last(), myTol1, aB1);
516 if (!aB1.IsOut(aB2) && (aNb1 == 1 || aB1.SquareExtent() < aB1SqExtent))
517 FindSolutions(aR1, aB1, aR2, aB2, theRanges1, theRanges2);
7fd59977 518 }
7fd59977 519}
ec0cdc0e 520
7fd59977 521//=======================================================================
ec0cdc0e 522//function : FindParameters
7fd59977 523//purpose :
524//=======================================================================
ec0cdc0e 525Standard_Boolean IntTools_EdgeEdge::FindParameters(const BRepAdaptor_Curve& theBAC,
526 const Standard_Real aT1,
3510db62 527 const Standard_Real aT2,
528 const Standard_Real theTol,
ec0cdc0e 529 const Standard_Real theRes,
a743e2e5 530 const Standard_Real thePTol,
a4e383e1 531 const Standard_Real theResCoeff,
ec0cdc0e 532 const Bnd_Box& theCBox,
533 Standard_Real& aTB1,
534 Standard_Real& aTB2)
7fd59977 535{
ec0cdc0e 536 Standard_Boolean bRet;
28c08a7d 537 Standard_Integer aC, i;
6b1fe48c 538 Standard_Real aCf, aDiff, aDt, aT, aTB, aTOut, aTIn;
28c08a7d 539 Standard_Real aDist, aDistP;
ec0cdc0e 540 gp_Pnt aP;
541 Bnd_Box aCBx;
7fd59977 542 //
ec0cdc0e 543 bRet = Standard_False;
544 aCf = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))/2.;
ec0cdc0e 545 aCBx = theCBox;
28c08a7d 546 aCBx.SetGap(aCBx.GetGap() + theTol);
7fd59977 547 //
a4e383e1 548 const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve();
549 const GeomAbs_CurveType aCurveType = theBAC.GetType();
28c08a7d 550 Standard_Real aMaxDt = (aT2 - aT1) * 0.01;
a4e383e1 551 //
ec0cdc0e 552 for (i = 0; i < 2; ++i) {
553 aTB = !i ? aT1 : aT2;
554 aT = !i ? aT2 : aTB1;
555 aC = !i ? 1 : -1;
28c08a7d 556 aDt = theRes;
557 aDistP = 0.;
ec0cdc0e 558 bRet = Standard_False;
28c08a7d 559 Standard_Real k = 1;
ec0cdc0e 560 //looking for the point on the edge which is in the box;
561 while (aC*(aT-aTB) >= 0) {
6b1fe48c 562 theBAC.D0(aTB, aP);
563 aDist = PointBoxDistance(theCBox, aP);
3510db62 564 if (aDist > theTol) {
28c08a7d 565 if (aDistP > 0.) {
566 Standard_Boolean toGrow = Standard_False;
567 if (Abs(aDistP - aDist) / aDistP < 0.1) {
568 aDt = Resolution(aCurve, aCurveType, theResCoeff, k*aDist);
569 if (aDt < aMaxDt)
570 {
571 toGrow = Standard_True;
572 k *= 2;
573 }
574 }
575 if (!toGrow) {
576 k = 1;
577 aDt = Resolution(aCurve, aCurveType, theResCoeff, aDist);
578 }
6b1fe48c 579 }
ec0cdc0e 580 aTB += aC*aDt;
581 } else {
582 bRet = Standard_True;
583 break;
584 }
585 aDistP = aDist;
586 }
587 //
588 if (!bRet) {
589 if (!i) {
590 //edge is out of the box;
591 return bRet;
592 } else {
593 bRet = !bRet;
594 aTB = aTB1;
595 aDt = aT2 - aTB1;
596 }
597 }
598 //
599 aT = !i ? aT1 : aT2;
600 if (aTB != aT) {
601 //one point IN, one point OUT; looking for the bounding point;
602 aTIn = aTB;
603 aTOut = aTB - aC*aDt;
604 aDiff = aTIn - aTOut;
a743e2e5 605 while (fabs(aDiff) > thePTol) {
ec0cdc0e 606 aTB = aTOut + aDiff*aCf;
6b1fe48c 607 theBAC.D0(aTB, aP);
ec0cdc0e 608 if (aCBx.IsOut(aP)) {
609 aTOut = aTB;
610 } else {
611 aTIn = aTB;
612 }
613 aDiff = aTIn - aTOut;
614 }
615 }
616 if (!i) {
617 aTB1 = aTB;
618 } else {
619 aTB2 = aTB;
7fd59977 620 }
621 }
ec0cdc0e 622 return bRet;
7fd59977 623}
624
625//=======================================================================
ec0cdc0e 626//function : MergeSolutions
7fd59977 627//purpose :
628//=======================================================================
ec0cdc0e 629void IntTools_EdgeEdge::MergeSolutions(const IntTools_SequenceOfRanges& theRanges1,
3e594885 630 const IntTools_SequenceOfRanges& theRanges2,
631 const Standard_Boolean bSplit2)
7fd59977 632{
3e594885 633 Standard_Integer aNbCP = theRanges1.Length();
634 if (aNbCP == 0) {
635 return;
636 }
637 //
ec0cdc0e 638 IntTools_Range aRi1, aRi2, aRj1, aRj2;
524a5f7a 639 Standard_Boolean bCond;
3e594885 640 Standard_Integer i, j;
ec0cdc0e 641 TopAbs_ShapeEnum aType;
524a5f7a 642 Standard_Real aT11, aT12, aT21, aT22;
643 Standard_Real aTi11, aTi12, aTi21, aTi22;
644 Standard_Real aTj11, aTj12, aTj21, aTj22;
645 Standard_Real aRes1, aRes2, dTR1, dTR2;
1155d05a 646 TColStd_MapOfInteger aMI;
ec0cdc0e 647 //
524a5f7a 648 aRes1 = Resolution(myCurve1.Curve().Curve(),
649 myCurve1.GetType(), myResCoeff1, myTol);
650 aRes2 = Resolution(myCurve2.Curve().Curve(),
651 myCurve2.GetType(), myResCoeff2, myTol);
652 //
653 myRange1.Range(aT11, aT12);
654 myRange2.Range(aT21, aT22);
655 dTR1 = 20*aRes1;
656 dTR2 = 20*aRes2;
ec0cdc0e 657 aType = TopAbs_VERTEX;
658 //
3e594885 659 for (i = 1; i <= aNbCP;) {
660 if (aMI.Contains(i)) {
661 ++i;
662 continue;
663 }
664 //
ec0cdc0e 665 aRi1 = theRanges1(i);
666 aRi2 = theRanges2(i);
667 //
668 aRi1.Range(aTi11, aTi12);
669 aRi2.Range(aTi21, aTi22);
670 //
3e594885 671 aMI.Add(i);
672 //
ec0cdc0e 673 for (j = i+1; j <= aNbCP; ++j) {
3e594885 674 if (aMI.Contains(j)) {
675 continue;
676 }
677 //
ec0cdc0e 678 aRj1 = theRanges1(j);
679 aRj2 = theRanges2(j);
680 //
681 aRj1.Range(aTj11, aTj12);
682 aRj2.Range(aTj21, aTj22);
524a5f7a 683 //
684 bCond = (fabs(aTi12 - aTj11) < dTR1) ||
c08fd127 685 (aTj11 > aTi11 && aTj11 < aTi12) ||
686 (aTi11 > aTj11 && aTi11 < aTj12) ||
524a5f7a 687 (bSplit2 && (fabs(aTj12 - aTi11) < dTR1));
688 if (bCond && bSplit2) {
689 bCond = (fabs((Max(aTi22, aTj22) - Min(aTi21, aTj21)) -
c08fd127 690 ((aTi22 - aTi21) + (aTj22 - aTj21))) < dTR2) ||
691 (aTj21 > aTi21 && aTj21 < aTi22) ||
692 (aTi21 > aTj21 && aTi21 < aTj22);
524a5f7a 693 }
694 //
695 if (bCond) {
ec0cdc0e 696 aTi11 = Min(aTi11, aTj11);
697 aTi12 = Max(aTi12, aTj12);
698 aTi21 = Min(aTi21, aTj21);
699 aTi22 = Max(aTi22, aTj22);
3e594885 700 aMI.Add(j);
701 }
702 else if (!bSplit2) {
703 i = j;
ec0cdc0e 704 break;
7fd59977 705 }
706 }
ec0cdc0e 707 //
524a5f7a 708 if (((fabs(aT11 - aTi11) < myRes1) && (fabs(aT12 - aTi12) < myRes1)) ||
709 ((fabs(aT21 - aTi21) < myRes2) && (fabs(aT22 - aTi22) < myRes2))) {
ec0cdc0e 710 aType = TopAbs_EDGE;
3e594885 711 myCommonParts.Clear();
ec0cdc0e 712 }
713 //
714 AddSolution(aTi11, aTi12, aTi21, aTi22, aType);
3e594885 715 if (aType == TopAbs_EDGE) {
716 break;
717 }
718 //
719 if (bSplit2) {
720 ++i;
721 }
7fd59977 722 }
7fd59977 723}
724
725//=======================================================================
ec0cdc0e 726//function : AddSolution
7fd59977 727//purpose :
728//=======================================================================
ec0cdc0e 729void IntTools_EdgeEdge::AddSolution(const Standard_Real aT11,
730 const Standard_Real aT12,
731 const Standard_Real aT21,
732 const Standard_Real aT22,
733 const TopAbs_ShapeEnum theType)
7fd59977 734{
ec0cdc0e 735 IntTools_CommonPrt aCPart;
736 //
737 aCPart.SetType(theType);
738 if (!mySwap) {
739 aCPart.SetEdge1(myEdge1);
740 aCPart.SetEdge2(myEdge2);
741 aCPart.SetRange1(aT11, aT12);
742 aCPart.AppendRange2(aT21, aT22);
743 } else {
744 aCPart.SetEdge1(myEdge2);
745 aCPart.SetEdge2(myEdge1);
746 aCPart.SetRange1(aT21, aT22);
747 aCPart.AppendRange2(aT11, aT12);
0d19eb34 748 }
ec0cdc0e 749 //
750 if (theType == TopAbs_VERTEX) {
751 Standard_Real aT1, aT2;
752 //
753 FindBestSolution(aT11, aT12, aT21, aT22, aT1, aT2);
754 //
755 if (!mySwap) {
756 aCPart.SetVertexParameter1(aT1);
757 aCPart.SetVertexParameter2(aT2);
758 } else {
759 aCPart.SetVertexParameter1(aT2);
760 aCPart.SetVertexParameter2(aT1);
761 }
762 }
763 myCommonParts.Append(aCPart);
7fd59977 764}
765
7fd59977 766//=======================================================================
ec0cdc0e 767//function : FindBestSolution
768//purpose :
7fd59977 769//=======================================================================
ec0cdc0e 770void IntTools_EdgeEdge::FindBestSolution(const Standard_Real aT11,
771 const Standard_Real aT12,
772 const Standard_Real aT21,
773 const Standard_Real aT22,
774 Standard_Real& aT1,
775 Standard_Real& aT2)
7fd59977 776{
0d19eb34 777 Standard_Integer i, aNbS, iErr;
bd28b2af 778 Standard_Real aDMin, aD, aRes1, aSolCriteria, aTouchCriteria;
779 Standard_Real aT1A, aT1B, aT1Min, aT2Min;
bd28b2af 780 GeomAPI_ProjectPointOnCurve aProjPC;
781 IntTools_SequenceOfRanges aRanges;
0d19eb34 782 //
bd28b2af 783 aDMin = Precision::Infinite();
784 aSolCriteria = 5.e-16;
785 aTouchCriteria = 5.e-13;
28c08a7d 786 Standard_Boolean bTouch = Standard_False;
787 Standard_Boolean bTouchConfirm = Standard_False;
ec0cdc0e 788 //
524a5f7a 789 aRes1 = Resolution(myCurve1.Curve().Curve(),
790 myCurve1.GetType(), myResCoeff1, myTol);
0d19eb34 791 aNbS = 10;
bd28b2af 792 aNbS = SplitRangeOnSegments(aT11, aT12, 3*aRes1, aNbS, aRanges);
793 //
794 aProjPC.Init(myGeom2, aT21, aT22);
795 //
28c08a7d 796 Standard_Real aT11Touch = aT11, aT12Touch = aT12;
797 Standard_Real aT21Touch = aT21, aT22Touch = aT22;
798 Standard_Boolean isSolFound = Standard_False;
0d19eb34 799 for (i = 1; i <= aNbS; ++i) {
bd28b2af 800 const IntTools_Range& aR1 = aRanges(i);
801 aR1.Range(aT1A, aT1B);
0d19eb34 802 //
bd28b2af 803 aD = myTol;
804 iErr = FindDistPC(aT1A, aT1B, myGeom1, aSolCriteria, myPTol1,
805 aProjPC, aD, aT1Min, aT2Min, Standard_False);
806 if (iErr != 1) {
807 if (aD < aDMin) {
808 aT1 = aT1Min;
809 aT2 = aT2Min;
810 aDMin = aD;
28c08a7d 811 isSolFound = Standard_True;
bd28b2af 812 }
813 //
814 if (aD < aTouchCriteria) {
815 if (bTouch) {
28c08a7d 816 aT12Touch = aT1Min;
817 aT22Touch = aT2Min;
818 bTouchConfirm = Standard_True;
bd28b2af 819 }
820 else {
28c08a7d 821 aT11Touch = aT1Min;
822 aT21Touch = aT2Min;
bd28b2af 823 bTouch = Standard_True;
824 }
7fd59977 825 }
826 }
7fd59977 827 }
28c08a7d 828 if (!isSolFound || bTouchConfirm)
829 {
830 aT1 = (aT11Touch + aT12Touch) * 0.5;
831 iErr = DistPC(aT1, myGeom1, aSolCriteria, aProjPC, aD, aT2, -1);
832 if (iErr == 1) {
833 aT2 = (aT21Touch + aT22Touch) * 0.5;
834 }
835 }
7fd59977 836}
837
838//=======================================================================
ec0cdc0e 839//function : ComputeLineLine
7fd59977 840//purpose :
841//=======================================================================
ec0cdc0e 842void IntTools_EdgeEdge::ComputeLineLine()
7fd59977 843{
115d350e 844 Standard_Real aTol = myTol * myTol;
845
846 gp_Lin aL1 = myCurve1.Line();
847 gp_Lin aL2 = myCurve2.Line();
848
849 gp_Dir aD1 = aL1.Direction();
850 gp_Dir aD2 = aL2.Direction();
851
852 Standard_Real anAngle = aD1.Angle (aD2);
853 Standard_Boolean IsCoincide = anAngle < Precision::Angular();
854 if (IsCoincide)
855 {
856 if (aL1.SquareDistance (aL2.Location()) > aTol)
857 return;
7fd59977 858 }
115d350e 859
860 Standard_Real aT11, aT12, aT21, aT22;
861 myRange1.Range (aT11, aT12);
862 myRange2.Range (aT21, aT22);
863
864 gp_Pnt aP11 = ElCLib::Value (aT11, aL1);
865 gp_Pnt aP12 = ElCLib::Value (aT12, aL1);
866
867 if (!IsCoincide)
868 {
869 gp_Pnt O2 (aL2.Location());
870 if (!Precision::IsInfinite (aT21) && !Precision::IsInfinite (aT22))
871 O2 = ElCLib::Value ((aT21 + aT22) / 2., aL2);
872
873 gp_Vec aVec1 = gp_Vec (O2, aP11).Crossed (aD2);
874 gp_Vec aVec2 = gp_Vec (O2, aP12).Crossed (aD2);
875
876 Standard_Real aSqDist1 = aVec1.SquareMagnitude();
877 Standard_Real aSqDist2 = aVec2.SquareMagnitude();
878
879 IsCoincide = (aSqDist1 <= aTol && aSqDist2 <= aTol);
880
881 if (!IsCoincide && aVec1.Dot (aVec2) > 0)
882 // the lines do not intersect
883 return;
7fd59977 884 }
115d350e 885
886 IntTools_CommonPrt aCommonPrt;
887 aCommonPrt.SetEdge1 (myEdge1);
888 aCommonPrt.SetEdge2 (myEdge2);
889
890 if (IsCoincide)
891 {
892 Standard_Real t21 = ElCLib::Parameter (aL2, aP11);
893 Standard_Real t22 = ElCLib::Parameter (aL2, aP12);
894
895 if ((t21 > aT22 && t22 > aT22) || (t21 < aT21 && t22 < aT21))
896 // projections are out of range
ec0cdc0e 897 return;
115d350e 898
899 if (t21 > t22)
900 std::swap (t21, t22);
901
902 if (t21 >= aT21)
903 {
904 if (t22 <= aT22)
905 {
906 aCommonPrt.SetRange1 (aT11, aT12);
907 aCommonPrt.SetAllNullFlag (Standard_True);
908 aCommonPrt.AppendRange2 (t21, t22);
ec0cdc0e 909 }
115d350e 910 else
911 {
912 aCommonPrt.SetRange1 (aT11, aT12 - (t22 - aT22));
913 aCommonPrt.AppendRange2 (t21, aT22);
ec0cdc0e 914 }
7fd59977 915 }
115d350e 916 else
917 {
918 aCommonPrt.SetRange1 (aT11 + (aT21 - t21), aT12);
919 aCommonPrt.AppendRange2 (aT21, t22);
7fd59977 920 }
115d350e 921 aCommonPrt.SetType (TopAbs_EDGE);
922 myCommonParts.Append (aCommonPrt);
ec0cdc0e 923 return;
924 }
115d350e 925
926
927 gp_Vec O1O2 (aL1.Location(), aL2.Location());
928 gp_XYZ aCross = aD1.XYZ().Crossed (aD2.XYZ());
929 Standard_Real aDistLL = O1O2.Dot (gp_Vec (aCross.Normalized()));
930 if (Abs (aDistLL) > myTol)
ec0cdc0e 931 return;
115d350e 932
ec0cdc0e 933 {
115d350e 934 // Fast check that no intersection needs to be added
935 for (TopoDS_Iterator it1 (myEdge1); it1.More(); it1.Next())
936 {
937 for (TopoDS_Iterator it2 (myEdge2); it2.More(); it2.Next())
938 {
939 if (it1.Value().IsSame (it2.Value()))
ec0cdc0e 940 return;
ec0cdc0e 941 }
7fd59977 942 }
7fd59977 943 }
115d350e 944
945 Standard_Real aSqSin = aCross.SquareModulus();
946 Standard_Real aT2 = (aD1.XYZ() * (O1O2.Dot (aD1)) - (O1O2.XYZ())).Dot (aD2.XYZ());
947 aT2 /= aSqSin;
948
949 if (aT2 < aT21 || aT2 > aT22)
950 // out of range
ec0cdc0e 951 return;
115d350e 952
953 gp_Pnt aP2 = ElCLib::Value (aT2, aL2);
954 Standard_Real aT1 = gp_Vec (aL1.Location(), aP2).Dot (aD1);
955
956 if (aT1 < aT11 || aT1 > aT12)
957 // out of range
ec0cdc0e 958 return;
115d350e 959
960 gp_Pnt aP1 = ElCLib::Value (aT1, aL1);
961 Standard_Real aDist = aP1.SquareDistance (aP2);
962
963 if (aDist > aTol)
964 // no intersection
ec0cdc0e 965 return;
115d350e 966
3510db62 967 // compute correct range on the edges
115d350e 968 Standard_Real aDt1 = IntTools_Tools::ComputeIntRange (myTol1, myTol2, anAngle);
969 Standard_Real aDt2 = IntTools_Tools::ComputeIntRange (myTol2, myTol1, anAngle);
970
971 aCommonPrt.SetRange1 (aT1 - aDt1, aT1 + aDt1);
972 aCommonPrt.AppendRange2 (aT2 - aDt2, aT2 + aDt2);
973 aCommonPrt.SetType (TopAbs_VERTEX);
974 aCommonPrt.SetVertexParameter1 (aT1);
975 aCommonPrt.SetVertexParameter2 (aT2);
976 myCommonParts.Append (aCommonPrt);
7fd59977 977}
ec0cdc0e 978
7fd59977 979//=======================================================================
ec0cdc0e 980//function : IsIntersection
7fd59977 981//purpose :
982//=======================================================================
ec0cdc0e 983Standard_Boolean IntTools_EdgeEdge::IsIntersection(const Standard_Real aT11,
984 const Standard_Real aT12,
985 const Standard_Real aT21,
986 const Standard_Real aT22)
7fd59977 987{
ec0cdc0e 988 Standard_Boolean bRet;
989 gp_Pnt aP11, aP12, aP21, aP22;
990 gp_Vec aV11, aV12, aV21, aV22;
991 Standard_Real aD11_21, aD11_22, aD12_21, aD12_22, aCriteria, aCoef;
992 Standard_Boolean bSmall_11_21, bSmall_11_22, bSmall_12_21, bSmall_12_22;
993 //
994 bRet = Standard_True;
995 aCoef = 1.e+5;
996 if (((aT12 - aT11) > aCoef*myRes1) && ((aT22 - aT21) > aCoef*myRes2)) {
997 aCoef = 5000;
998 } else {
999 Standard_Real aTRMin = Min((aT12 - aT11)/myRes1, (aT22 - aT21)/myRes2);
1000 aCoef = aTRMin / 100.;
1001 if (aCoef < 1.) {
1002 aCoef = 1.;
7fd59977 1003 }
1004 }
ec0cdc0e 1005 aCriteria = aCoef * myTol;
1006 aCriteria *= aCriteria;
7fd59977 1007 //
ec0cdc0e 1008 myGeom1->D1(aT11, aP11, aV11);
1009 myGeom1->D1(aT12, aP12, aV12);
1010 myGeom2->D1(aT21, aP21, aV21);
1011 myGeom2->D1(aT22, aP22, aV22);
1012 //
1013 aD11_21 = aP11.SquareDistance(aP21);
1014 aD11_22 = aP11.SquareDistance(aP22);
1015 aD12_21 = aP12.SquareDistance(aP21);
1016 aD12_22 = aP12.SquareDistance(aP22);
1017 //
1018 bSmall_11_21 = aD11_21 < aCriteria;
1019 bSmall_11_22 = aD11_22 < aCriteria;
1020 bSmall_12_21 = aD12_21 < aCriteria;
1021 bSmall_12_22 = aD12_22 < aCriteria;
1022 //
1023 if ((bSmall_11_21 && bSmall_12_22) ||
1024 (bSmall_11_22 && bSmall_12_21)) {
1025 if (aCoef == 1.) {
1026 return bRet;
7fd59977 1027 }
ec0cdc0e 1028 //
1029 Standard_Real anAngleCriteria;
90f0fdad 1030 Standard_Real anAngle1 = 0.0,
1031 anAngle2 = 0.0;
ec0cdc0e 1032 //
1033 anAngleCriteria = 5.e-3;
90f0fdad 1034 if (aV11.SquareMagnitude() > Precision::SquareConfusion() &&
1035 aV12.SquareMagnitude() > Precision::SquareConfusion() &&
1036 aV21.SquareMagnitude() > Precision::SquareConfusion() &&
1037 aV22.SquareMagnitude() > Precision::SquareConfusion() )
1038 {
1039 if (bSmall_11_21 && bSmall_12_22) {
1040 anAngle1 = aV11.Angle(aV21);
1041 anAngle2 = aV12.Angle(aV22);
1042 } else {
1043 anAngle1 = aV11.Angle(aV22);
1044 anAngle2 = aV12.Angle(aV21);
1045 }
7fd59977 1046 }
ec0cdc0e 1047 //
1048 if (((anAngle1 < anAngleCriteria) || ((M_PI - anAngle1) < anAngleCriteria)) ||
1049 ((anAngle2 < anAngleCriteria) || ((M_PI - anAngle2) < anAngleCriteria))) {
bd28b2af 1050 GeomAPI_ProjectPointOnCurve aProjPC;
ec0cdc0e 1051 Standard_Integer iErr;
bd28b2af 1052 Standard_Real aD, aT1Min, aT2Min;
ec0cdc0e 1053 //
bd28b2af 1054 aD = Precision::Infinite();
1055 aProjPC.Init(myGeom2, aT21, aT22);
1056 iErr = FindDistPC(aT11, aT12, myGeom1, myTol, myRes1,
1057 aProjPC, aD, aT1Min, aT2Min, Standard_False);
ec0cdc0e 1058 bRet = (iErr == 2);
7fd59977 1059 }
7fd59977 1060 }
ec0cdc0e 1061 return bRet;
7fd59977 1062}
1063
1064//=======================================================================
ec0cdc0e 1065//function : CheckCoincidence
7fd59977 1066//purpose :
1067//=======================================================================
ec0cdc0e 1068Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
1069 const Standard_Real aT12,
1070 const Standard_Real aT21,
1071 const Standard_Real aT22,
1072 const Standard_Real theCriteria,
0d19eb34 1073 const Standard_Real theCurveRes1)
7fd59977 1074{
6b1fe48c 1075 Standard_Integer iErr, aNb, aNb1, i;
0d19eb34 1076 Standard_Real aT1A, aT1B, aT1max, aT2max, aDmax;
ec0cdc0e 1077 GeomAPI_ProjectPointOnCurve aProjPC;
bd28b2af 1078 IntTools_SequenceOfRanges aRanges;
ec0cdc0e 1079 //
1080 iErr = 0;
1081 aDmax = -1.;
1082 aProjPC.Init(myGeom2, aT21, aT22);
1083 //
1084 // 1. Express evaluation
1085 aNb = 10; // Number of intervals on the curve #1
bd28b2af 1086 aNb1 = SplitRangeOnSegments(aT11, aT12, theCurveRes1, aNb, aRanges);
6b1fe48c 1087 for (i = 1; i < aNb1; ++i) {
bd28b2af 1088 const IntTools_Range& aR1 = aRanges(i);
0d19eb34 1089 aR1.Range(aT1A, aT1B);
ec0cdc0e 1090 //
0d19eb34 1091 iErr = DistPC(aT1B, myGeom1, theCriteria, aProjPC, aDmax, aT2max);
ec0cdc0e 1092 if (iErr) {
1093 return iErr;
7fd59977 1094 }
1095 }
ec0cdc0e 1096 //
bd28b2af 1097 // if the ranges in aRanges are less than theCurveRes1,
0d19eb34 1098 // there is no need to do step 2 (deep evaluation)
6b1fe48c 1099 if (aNb1 < aNb) {
0d19eb34 1100 return iErr;
1101 }
1102 //
ec0cdc0e 1103 // 2. Deep evaluation
6b1fe48c 1104 for (i = 2; i < aNb1; ++i) {
bd28b2af 1105 const IntTools_Range& aR1 = aRanges(i);
0d19eb34 1106 aR1.Range(aT1A, aT1B);
ec0cdc0e 1107 //
0d19eb34 1108 iErr = FindDistPC(aT1A, aT1B, myGeom1, theCriteria, theCurveRes1,
ec0cdc0e 1109 aProjPC, aDmax, aT1max, aT2max);
1110 if (iErr) {
1111 return iErr;
7fd59977 1112 }
7fd59977 1113 }
ec0cdc0e 1114 // Possible values:
1115 // iErr == 0 - the patches are coincided
1116 // iErr == 1 - a point from aC1 can not be projected on aC2
1117 // iErr == 2 - the distance is too big
1118 return iErr;
7fd59977 1119}
ec0cdc0e 1120
7fd59977 1121//=======================================================================
ec0cdc0e 1122//function : FindDistPC
7fd59977 1123//purpose :
1124//=======================================================================
ec0cdc0e 1125Standard_Integer FindDistPC(const Standard_Real aT1A,
1126 const Standard_Real aT1B,
1127 const Handle(Geom_Curve)& theC1,
1128 const Standard_Real theCriteria,
1129 const Standard_Real theEps,
1130 GeomAPI_ProjectPointOnCurve& theProjPC,
1131 Standard_Real& aDmax,
1132 Standard_Real& aT1max,
1133 Standard_Real& aT2max,
1134 const Standard_Boolean bMaxDist)
7fd59977 1135{
ec0cdc0e 1136 Standard_Integer iErr, iC;
1137 Standard_Real aGS, aXP, aA, aB, aXL, aYP, aYL, aT2P, aT2L;
1138 //
1139 iC = bMaxDist ? 1 : -1;
1140 iErr = 0;
04e93070 1141 aT1max = aT2max = 0.; // silence GCC warning
ec0cdc0e 1142 //
1143 aGS = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))-1.;
1144 aA = aT1A;
1145 aB = aT1B;
1146 //
1147 // check bounds
bd28b2af 1148 iErr = DistPC(aA, theC1, theCriteria, theProjPC,
1149 aYP, aT2P, aDmax, aT1max, aT2max, iC);
ec0cdc0e 1150 if (iErr == 2) {
1151 return iErr;
7fd59977 1152 }
ec0cdc0e 1153 //
bd28b2af 1154 iErr = DistPC(aB, theC1, theCriteria, theProjPC,
1155 aYL, aT2L, aDmax, aT1max, aT2max, iC);
ec0cdc0e 1156 if (iErr == 2) {
1157 return iErr;
7fd59977 1158 }
ec0cdc0e 1159 //
1160 aXP = aA + (aB - aA)*aGS;
1161 aXL = aB - (aB - aA)*aGS;
1162 //
bd28b2af 1163 iErr = DistPC(aXP, theC1, theCriteria, theProjPC,
1164 aYP, aT2P, aDmax, aT1max, aT2max, iC);
ec0cdc0e 1165 if (iErr) {
1166 return iErr;
7fd59977 1167 }
ec0cdc0e 1168 //
bd28b2af 1169 iErr = DistPC(aXL, theC1, theCriteria, theProjPC,
1170 aYL, aT2L, aDmax, aT1max, aT2max, iC);
ec0cdc0e 1171 if (iErr) {
1172 return iErr;
7fd59977 1173 }
7fd59977 1174 //
28c08a7d 1175 Standard_Real anEps = Max(theEps, Epsilon(Max(Abs(aA), Abs(aB))) * 10.);
ec0cdc0e 1176 for (;;) {
1177 if (iC*(aYP - aYL) > 0) {
1178 aA = aXL;
1179 aXL = aXP;
1180 aYL = aYP;
1181 aXP = aA + (aB - aA)*aGS;
bd28b2af 1182 iErr = DistPC(aXP, theC1, theCriteria, theProjPC,
1183 aYP, aT2P, aDmax, aT1max, aT2max, iC);
ec0cdc0e 1184 }
1185 else {
1186 aB = aXP;
1187 aXP = aXL;
1188 aYP = aYL;
1189 aXL = aB - (aB - aA)*aGS;
bd28b2af 1190 iErr = DistPC(aXL, theC1, theCriteria, theProjPC,
1191 aYL, aT2L, aDmax, aT1max, aT2max, iC);
1192 }
1193 //
1194 if (iErr) {
1195 if ((iErr == 2) && !bMaxDist) {
1196 aXP = (aA + aB) * 0.5;
1197 DistPC(aXP, theC1, theCriteria, theProjPC,
1198 aYP, aT2P, aDmax, aT1max, aT2max, iC);
ec0cdc0e 1199 }
bd28b2af 1200 return iErr;
7fd59977 1201 }
ec0cdc0e 1202 //
28c08a7d 1203 if ((aB - aA) < anEps) {
ec0cdc0e 1204 break;
7fd59977 1205 }
ec0cdc0e 1206 }// for (;;) {
7fd59977 1207 //
ec0cdc0e 1208 return iErr;
7fd59977 1209}
7fd59977 1210//=======================================================================
ec0cdc0e 1211//function : DistPC
1212//purpose :
7fd59977 1213//=======================================================================
ec0cdc0e 1214Standard_Integer DistPC(const Standard_Real aT1,
1215 const Handle(Geom_Curve)& theC1,
1216 const Standard_Real theCriteria,
1217 GeomAPI_ProjectPointOnCurve& theProjPC,
1218 Standard_Real& aD,
1219 Standard_Real& aT2,
1220 Standard_Real& aDmax,
1221 Standard_Real& aT1max,
1222 Standard_Real& aT2max,
1223 const Standard_Integer iC)
7fd59977 1224{
ec0cdc0e 1225 Standard_Integer iErr;
7fd59977 1226 //
ec0cdc0e 1227 iErr = DistPC(aT1, theC1, theCriteria, theProjPC, aD, aT2, iC);
bd28b2af 1228 if (iErr == 1) {
ec0cdc0e 1229 return iErr;
7fd59977 1230 }
1231 //
ec0cdc0e 1232 if (iC*(aD - aDmax) > 0) {
1233 aDmax = aD;
1234 aT1max = aT1;
1235 aT2max = aT2;
7fd59977 1236 }
1237 //
ec0cdc0e 1238 return iErr;
1239}
1240//=======================================================================
1241//function : DistPC
1242//purpose :
1243//=======================================================================
1244Standard_Integer DistPC(const Standard_Real aT1,
1245 const Handle(Geom_Curve)& theC1,
1246 const Standard_Real theCriteria,
1247 GeomAPI_ProjectPointOnCurve& theProjPC,
1248 Standard_Real& aD,
1249 Standard_Real& aT2,
1250 const Standard_Integer iC)
1251{
1252 Standard_Integer iErr, aNbP2;
1253 gp_Pnt aP1;
1254 //
1255 iErr = 0;
1256 theC1->D0(aT1, aP1);
1257 //
1258 theProjPC.Perform(aP1);
1259 aNbP2 = theProjPC.NbPoints();
1260 if (!aNbP2) {
1261 iErr = 1;// the point from aC1 can not be projected on aC2
1262 return iErr;
7fd59977 1263 }
1264 //
ec0cdc0e 1265 aD = theProjPC.LowerDistance();
1266 aT2 = theProjPC.LowerDistanceParameter();
1267 if (iC*(aD - theCriteria) > 0) {
1268 iErr = 2;// the distance is too big or small
7fd59977 1269 }
1270 //
ec0cdc0e 1271 return iErr;
7fd59977 1272}
ec0cdc0e 1273
7fd59977 1274//=======================================================================
ec0cdc0e 1275//function : SplitRangeOnSegments
7fd59977 1276//purpose :
1277//=======================================================================
bd28b2af 1278Standard_Integer SplitRangeOnSegments(const Standard_Real aT1,
1279 const Standard_Real aT2,
1280 const Standard_Real theResolution,
1281 const Standard_Integer theNbSeg,
1282 IntTools_SequenceOfRanges& theSegments)
7fd59977 1283{
6b1fe48c 1284 Standard_Real aDiff = aT2 - aT1;
a4e383e1 1285 if (aDiff < theResolution || theNbSeg == 1) {
0d19eb34 1286 theSegments.Append(IntTools_Range(aT1, aT2));
bd28b2af 1287 return 1;
0d19eb34 1288 }
1289 //
ec0cdc0e 1290 Standard_Real aDt, aT1x, aT2x, aSeg;
1291 Standard_Integer aNbSegments, i;
1292 //
1293 aNbSegments = theNbSeg;
6b1fe48c 1294 aDt = aDiff / aNbSegments;
ec0cdc0e 1295 if (aDt < theResolution) {
6b1fe48c 1296 aSeg = aDiff / theResolution;
0d19eb34 1297 aNbSegments = Standard_Integer(aSeg) + 1;
6b1fe48c 1298 aDt = aDiff / aNbSegments;
7fd59977 1299 }
ec0cdc0e 1300 //
ec0cdc0e 1301 aT1x = aT1;
6b1fe48c 1302 for (i = 1; i < aNbSegments; ++i) {
ec0cdc0e 1303 aT2x = aT1x + aDt;
ec0cdc0e 1304 //
1305 IntTools_Range aR(aT1x, aT2x);
1306 theSegments.Append(aR);
1307 //
1308 aT1x = aT2x;
7fd59977 1309 }
0d19eb34 1310 //
6b1fe48c 1311 IntTools_Range aR(aT1x, aT2);
1312 theSegments.Append(aR);
bd28b2af 1313 //
1314 return aNbSegments;
ec0cdc0e 1315}
7fd59977 1316
ec0cdc0e 1317//=======================================================================
1318//function : BndBuildBox
1319//purpose :
1320//=======================================================================
1321void BndBuildBox(const BRepAdaptor_Curve& theBAC,
1322 const Standard_Real aT1,
1323 const Standard_Real aT2,
1324 const Standard_Real theTol,
1325 Bnd_Box& theBox)
1326{
1327 Bnd_Box aB;
1328 BndLib_Add3dCurve::Add(theBAC, aT1, aT2, theTol, aB);
1329 theBox = aB;
1330}
7fd59977 1331
6b1fe48c 1332//=======================================================================
1333//function : PointBoxDistance
1334//purpose :
1335//=======================================================================
1336Standard_Real PointBoxDistance(const Bnd_Box& aB,
1337 const gp_Pnt& aP)
1338{
1339 Standard_Real aPCoord[3];
1340 Standard_Real aBMinCoord[3], aBMaxCoord[3];
1341 Standard_Real aDist, aR1, aR2;
1342 Standard_Integer i;
1343 //
1344 aP.Coord(aPCoord[0], aPCoord[1], aPCoord[2]);
1345 aB.Get(aBMinCoord[0], aBMinCoord[1], aBMinCoord[2],
1346 aBMaxCoord[0], aBMaxCoord[1], aBMaxCoord[2]);
1347 //
1348 aDist = 0.;
1349 for (i = 0; i < 3; ++i) {
1350 aR1 = aBMinCoord[i] - aPCoord[i];
1351 if (aR1 > 0.) {
1352 aDist += aR1*aR1;
1353 continue;
1354 }
1355 //
1356 aR2 = aPCoord[i] - aBMaxCoord[i];
1357 if (aR2 > 0.) {
1358 aDist += aR2*aR2;
1359 }
1360 }
1361 //
1362 aDist = Sqrt(aDist);
1363 return aDist;
1364}
1365
ec0cdc0e 1366//=======================================================================
1367//function : TypeToInteger
1368//purpose :
1369//=======================================================================
1370Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType)
1371{
1372 Standard_Integer iRet;
bd05fabf 1373 //
ec0cdc0e 1374 switch(theCType) {
1375 case GeomAbs_Line:
1376 iRet=0;
1377 break;
ec0cdc0e 1378 case GeomAbs_Hyperbola:
1379 case GeomAbs_Parabola:
3e594885 1380 iRet=1;
1381 break;
1382 case GeomAbs_Circle:
1383 case GeomAbs_Ellipse:
ec0cdc0e 1384 iRet=2;
1385 break;
1386 case GeomAbs_BezierCurve:
1387 case GeomAbs_BSplineCurve:
1388 iRet=3;
1389 break;
1390 default:
1391 iRet=4;
1392 break;
1393 }
1394 return iRet;
7fd59977 1395}
ec0cdc0e 1396
a4e383e1 1397//=======================================================================
1398//function : ResolutionCoeff
1399//purpose :
1400//=======================================================================
1401Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC,
1402 const IntTools_Range& theRange)
1403{
e91a710c 1404 Standard_Real aResCoeff = 0.;
a4e383e1 1405 //
1406 const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve();
1407 const GeomAbs_CurveType aCurveType = theBAC.GetType();
1408 //
1409 switch (aCurveType) {
1410 case GeomAbs_Circle :
c5f3a425 1411 aResCoeff = 1. / (2 * Handle(Geom_Circle)::DownCast (aCurve)->Circ().Radius());
a4e383e1 1412 break;
1413 case GeomAbs_Ellipse :
c5f3a425 1414 aResCoeff = 1. / Handle(Geom_Ellipse)::DownCast (aCurve)->MajorRadius();
a4e383e1 1415 break;
e91a710c 1416 case GeomAbs_OffsetCurve : {
1417 const Handle(Geom_OffsetCurve)& anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(aCurve);
1418 const Handle(Geom_Curve)& aBasisCurve = anOffsetCurve->BasisCurve();
a318d719 1419 GeomAdaptor_Curve aGBasisCurve(aBasisCurve);
1420 const GeomAbs_CurveType aBCType = aGBasisCurve.GetType();
e91a710c 1421 if (aBCType == GeomAbs_Line) {
1422 break;
1423 }
1424 else if (aBCType == GeomAbs_Circle) {
a318d719 1425 aResCoeff = 1. / (2 * (anOffsetCurve->Offset() + aGBasisCurve.Circle().Radius()));
e91a710c 1426 break;
1427 }
1428 else if (aBCType == GeomAbs_Ellipse) {
a318d719 1429 aResCoeff = 1. / (anOffsetCurve->Offset() + aGBasisCurve.Ellipse().MajorRadius());
e91a710c 1430 break;
1431 }
1432 }
b1811c1d 1433 Standard_FALLTHROUGH
a4e383e1 1434 case GeomAbs_Hyperbola :
1435 case GeomAbs_Parabola :
1436 case GeomAbs_OtherCurve :{
1437 Standard_Real k, kMin, aDist, aDt, aT1, aT2, aT;
1438 Standard_Integer aNbP, i;
1439 gp_Pnt aP1, aP2;
1440 //
1441 aNbP = 30;
1442 theRange.Range(aT1, aT2);
1443 aDt = (aT2 - aT1) / aNbP;
1444 aT = aT1;
1445 kMin = 10.;
1446 //
1447 theBAC.D0(aT1, aP1);
1448 for (i = 1; i <= aNbP; ++i) {
1449 aT += aDt;
1450 theBAC.D0(aT, aP2);
1451 aDist = aP1.Distance(aP2);
1452 k = aDt / aDist;
1453 if (k < kMin) {
1454 kMin = k;
1455 }
1456 aP1 = aP2;
1457 }
1458 //
1459 aResCoeff = kMin;
1460 break;
1461 }
1462 default:
a4e383e1 1463 break;
1464 }
1465 //
1466 return aResCoeff;
1467}
1468
1469//=======================================================================
1470//function : Resolution
1471//purpose :
1472//=======================================================================
1473Standard_Real Resolution(const Handle(Geom_Curve)& theCurve,
1474 const GeomAbs_CurveType theCurveType,
1475 const Standard_Real theResCoeff,
1476 const Standard_Real theR3D)
1477{
1478 Standard_Real aRes;
1479 //
1480 switch (theCurveType) {
1481 case GeomAbs_Line :
1482 aRes = theR3D;
1483 break;
1484 case GeomAbs_Circle: {
1485 Standard_Real aDt = theResCoeff * theR3D;
1486 aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI;
1487 break;
1488 }
1489 case GeomAbs_BezierCurve:
c5f3a425 1490 Handle(Geom_BezierCurve)::DownCast (theCurve)->Resolution(theR3D, aRes);
a4e383e1 1491 break;
1492 case GeomAbs_BSplineCurve:
c5f3a425 1493 Handle(Geom_BSplineCurve)::DownCast (theCurve)->Resolution(theR3D, aRes);
a4e383e1 1494 break;
e91a710c 1495 case GeomAbs_OffsetCurve: {
1496 const Handle(Geom_Curve)& aBasisCurve =
1497 Handle(Geom_OffsetCurve)::DownCast(theCurve)->BasisCurve();
1498 const GeomAbs_CurveType aBCType = GeomAdaptor_Curve(aBasisCurve).GetType();
1499 if (aBCType == GeomAbs_Line) {
1500 aRes = theR3D;
1501 break;
1502 }
1503 else if (aBCType == GeomAbs_Circle) {
1504 Standard_Real aDt = theResCoeff * theR3D;
1505 aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI;
1506 break;
1507 }
1508 }
b1811c1d 1509 Standard_FALLTHROUGH
a4e383e1 1510 default:
1511 aRes = theResCoeff * theR3D;
1512 break;
1513 }
1514 //
1515 return aRes;
1516}
1517
1518//=======================================================================
1519//function : CurveDeflection
1520//purpose :
1521//=======================================================================
1522Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC,
1523 const IntTools_Range& theRange)
1524{
1525 Standard_Real aDt, aT, aT1, aT2, aDefl;
1526 Standard_Integer i, aNbP;
1527 gp_Vec aV1, aV2;
1528 gp_Pnt aP;
1529 //
1530 aDefl = 0;
1531 aNbP = 10;
1532 theRange.Range(aT1, aT2);
1533 aDt = (aT2 - aT1) / aNbP;
1534 aT = aT1;
1535 //
1536 theBAC.D1(aT1, aP, aV1);
1537 for (i = 1; i <= aNbP; ++i) {
1538 aT += aDt;
1539 theBAC.D1(aT, aP, aV2);
1540 if (aV1.Magnitude() > gp::Resolution() &&
1541 aV2.Magnitude() > gp::Resolution()) {
1542 gp_Dir aD1(aV1), aD2(aV2);
1543 aDefl += aD1.Angle(aD2);
1544 }
1545 aV1 = aV2;
1546 }
1547 //
1548 return aDefl;
1549}
1550
3e594885 1551//=======================================================================
1552//function : IsClosed
1553//purpose :
1554//=======================================================================
dde68833 1555Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve,
3e594885 1556 const Standard_Real aT1,
1557 const Standard_Real aT2,
1558 const Standard_Real theTol,
1559 const Standard_Real theRes)
1560{
dde68833 1561 if (Abs(aT1 - aT2) < theRes)
1562 {
1563 return Standard_False;
3e594885 1564 }
dde68833 1565
1566 gp_Pnt aP1, aP2;
3e594885 1567 theCurve->D0(aT1, aP1);
1568 theCurve->D0(aT2, aP2);
1569 //
dde68833 1570 Standard_Real aD = aP1.Distance(aP2);
1571 return aD < theTol;
3e594885 1572}