1 // Created on: 1993-11-26
2 // Created by: Modelistation
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 <IntPatch_ALineToWLine.hxx>
19 #include <Adaptor3d_HSurface.hxx>
21 #include <IntPatch_ALine.hxx>
22 #include <IntPatch_Point.hxx>
23 #include <IntPatch_SpecialPoints.hxx>
24 #include <IntPatch_WLine.hxx>
25 #include <IntSurf.hxx>
26 #include <IntSurf_LineOn2S.hxx>
28 //=======================================================================
29 //function : AddPointIntoLine
31 //=======================================================================
32 static inline void AddPointIntoLine(Handle(IntSurf_LineOn2S) theLine,
33 const Standard_Real* const theArrPeriods,
34 IntSurf_PntOn2S &thePoint,
35 IntPatch_Point* theVertex = 0)
37 if(theLine->NbPoints() > 0)
39 if(thePoint.IsSame(theLine->Value(theLine->NbPoints()), Precision::Confusion()))
42 IntPatch_SpecialPoints::AdjustPointAndVertex(theLine->Value(theLine->NbPoints()),
43 theArrPeriods, thePoint, theVertex);
46 theLine->Add(thePoint);
49 //=======================================================================
50 //function : AddVertexPoint
51 //purpose : Extracts IntSurf_PntOn2S from theVertex and adds result in theLine.
52 //=======================================================================
53 static void AddVertexPoint(Handle(IntSurf_LineOn2S)& theLine,
54 IntPatch_Point &theVertex,
55 const Standard_Real* const theArrPeriods)
57 IntSurf_PntOn2S anApexPoint = theVertex.PntOn2S();
58 AddPointIntoLine(theLine, theArrPeriods, anApexPoint, &theVertex);
61 //=======================================================================
62 //function : IsPoleOrSeam
63 //purpose : Processes theVertex depending on its type
64 // (pole/apex/point on boundary etc.) and adds it in theLine.
65 // theSingularSurfaceID contains the ID of surface with
66 // special point (0 - none, 1 - theS1, 2 - theS2)
67 //=======================================================================
68 static IntPatch_SpecPntType IsPoleOrSeam(const Handle(Adaptor3d_HSurface)& theS1,
69 const Handle(Adaptor3d_HSurface)& theS2,
70 Handle(IntSurf_LineOn2S)& theLine,
71 IntPatch_Point &theVertex,
72 const Standard_Real* const theArrPeriods,
73 const Standard_Real theTol3d,
74 Standard_Integer& theSingularSurfaceID)
76 const Standard_Integer aNbPnts = theLine->NbPoints();
78 return IntPatch_SPntNone;
80 theSingularSurfaceID = 0;
82 for(Standard_Integer i = 0; i < 2; i++)
84 const Standard_Boolean isReversed = (i > 0);
85 const GeomAbs_SurfaceType aType = isReversed? theS2->GetType() : theS1->GetType();
87 IntPatch_SpecPntType anAddedPType = IntPatch_SPntNone;
88 IntSurf_PntOn2S anApexPoint;
95 if(IntPatch_SpecialPoints::
96 AddSingularPole((isReversed? theS2 : theS1), (isReversed? theS1 : theS2),
97 theLine->Value(aNbPnts), theTol3d, theVertex,
98 anApexPoint, isReversed, Standard_True))
100 anAddedPType = IntPatch_SPntPole;
105 if(aType == GeomAbs_Torus)
107 if(IntPatch_SpecialPoints::
108 AddCrossUVIsoPoint((isReversed? theS2 : theS1), (isReversed? theS1 : theS2),
109 theLine->Value(aNbPnts), theTol3d,
110 anApexPoint, isReversed))
112 anAddedPType = IntPatch_SPntSeamUV;
116 case GeomAbs_Cylinder:
117 theSingularSurfaceID = i + 1;
118 AddVertexPoint(theLine, theVertex, theArrPeriods);
119 return IntPatch_SPntSeamU;
125 if(anAddedPType != IntPatch_SPntNone)
127 theSingularSurfaceID = i + 1;
128 AddPointIntoLine(theLine, theArrPeriods, anApexPoint, &theVertex);
133 return IntPatch_SPntNone;
136 //=======================================================================
137 //function : IntPatch_ALineToWLine
139 //=======================================================================
140 IntPatch_ALineToWLine::IntPatch_ALineToWLine(const Handle(Adaptor3d_HSurface)& theS1,
141 const Handle(Adaptor3d_HSurface)& theS2,
142 const Standard_Integer theNbPoints) :
145 myNbPointsInWline(theNbPoints),
146 myTolOpenDomain(1.e-9),
147 myTolTransition(1.e-8),
148 myTol3D(Precision::Confusion())
150 const GeomAbs_SurfaceType aTyps1 = theS1->GetType();
151 const GeomAbs_SurfaceType aTyps2 = theS2->GetType();
156 myQuad1.SetValue(theS1->Plane());
159 case GeomAbs_Cylinder:
160 myQuad1.SetValue(theS1->Cylinder());
164 myQuad1.SetValue(theS1->Sphere());
168 myQuad1.SetValue(theS1->Cone());
172 myQuad1.SetValue(theS1->Torus());
182 myQuad2.SetValue(theS2->Plane());
184 case GeomAbs_Cylinder:
185 myQuad2.SetValue(theS2->Cylinder());
189 myQuad2.SetValue(theS2->Sphere());
193 myQuad2.SetValue(theS2->Cone());
197 myQuad2.SetValue(theS2->Torus());
205 //=======================================================================
206 //function : SetTol3D
208 //=======================================================================
209 void IntPatch_ALineToWLine::SetTol3D(const Standard_Real aTol)
213 //=======================================================================
216 //=======================================================================
217 Standard_Real IntPatch_ALineToWLine::Tol3D()const
221 //=======================================================================
222 //function : SetTolTransition
224 //=======================================================================
225 void IntPatch_ALineToWLine::SetTolTransition(const Standard_Real aTol)
227 myTolTransition = aTol;
229 //=======================================================================
230 //function : TolTransition
232 //=======================================================================
233 Standard_Real IntPatch_ALineToWLine::TolTransition()const
235 return myTolTransition;
237 //=======================================================================
238 //function : SetTolOpenDomain
240 //=======================================================================
241 void IntPatch_ALineToWLine::SetTolOpenDomain(const Standard_Real aTol)
243 myTolOpenDomain = aTol;
245 //=======================================================================
246 //function : TolOpenDomain
248 //=======================================================================
249 Standard_Real IntPatch_ALineToWLine::TolOpenDomain()const
251 return myTolOpenDomain;
253 //=======================================================================
254 //function : MakeWLine
256 //=======================================================================
257 void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theAline,
258 IntPatch_SequenceOfLine& theLines) const
260 Standard_Boolean included;
261 Standard_Real f = theAline->FirstParameter(included);
265 Standard_Real l = theAline->LastParameter(included);
270 MakeWLine(theAline, f, l, theLines);
273 //=======================================================================
274 //function : MakeWLine
276 //=======================================================================
277 void IntPatch_ALineToWLine::MakeWLine(const Handle(IntPatch_ALine)& theALine,
278 const Standard_Real theFPar,
279 const Standard_Real theLPar,
280 IntPatch_SequenceOfLine& theLines) const
282 const Standard_Integer aNbVert = theALine->NbVertex();
286 const Standard_Real aTol = 2.0*myTol3D+Precision::Confusion();
287 IntPatch_SpecPntType aPrePointExist = IntPatch_SPntNone;
289 NCollection_Array1<Standard_Real> aVertexParams(1, aNbVert);
290 NCollection_Array1<IntPatch_Point> aSeqVertex(1, aNbVert);
292 //It is possible to have several vertices with equal parameters.
293 NCollection_Array1<Standard_Boolean> hasVertexBeenChecked(1, aNbVert);
295 Handle(IntSurf_LineOn2S) aLinOn2S;
296 Standard_Real aParameter = theFPar;
298 for(Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++)
300 const Standard_Real aPar = theALine->Vertex(i).ParameterOnLine();
301 aVertexParams(i) = aPar;
302 hasVertexBeenChecked(i) = Standard_False;
305 Standard_Integer aSingularSurfaceID = 0;
306 Standard_Real anArrPeriods[] = { 0.0, //U1
311 IntSurf::SetPeriod(myS1, myS2, anArrPeriods);
313 IntSurf_PntOn2S aPrevLPoint;
315 while(aParameter < theLPar)
317 Standard_Real aStep = (theLPar - aParameter) / (Standard_Real)(myNbPointsInWline - 1);
318 if(aStep < Epsilon(theLPar))
321 Standard_Integer aNewVertID = 0;
322 aLinOn2S = new IntSurf_LineOn2S;
324 const Standard_Real aStepMin = 0.1*aStep, aStepMax = 10.0*aStep;
326 Standard_Boolean isLast = Standard_False;
327 Standard_Real aPrevParam = aParameter;
328 for(; !isLast; aParameter += aStep)
330 IntSurf_PntOn2S aPOn2S;
332 if(theLPar <= aParameter)
334 isLast = Standard_True;
335 if(aPrePointExist != IntPatch_SPntNone)
341 aParameter = theLPar;
345 Standard_Real aTgMagn = 0.0;
349 theALine->D1(aParameter, aPnt3d, aTg);
350 aTgMagn = aTg.Magnitude();
351 Standard_Real u1 = 0.0, v1 = 0.0, u2 = 0.0, v2 = 0.0;
352 myQuad1.Parameters(aPnt3d, u1, v1);
353 myQuad2.Parameters(aPnt3d, u2, v2);
354 aPOn2S.SetValue(aPnt3d, u1, v1, u2, v2);
357 if(aPrePointExist != IntPatch_SPntNone)
359 const Standard_Real aURes = Max(myS1->UResolution(myTol3D),
360 myS2->UResolution(myTol3D)),
361 aVRes = Max(myS1->VResolution(myTol3D),
362 myS2->VResolution(myTol3D));
364 const Standard_Real aTol2d = (aPrePointExist == IntPatch_SPntPole) ? -1.0 :
365 (aPrePointExist == IntPatch_SPntSeamV)? aVRes :
366 (aPrePointExist == IntPatch_SPntSeamUV)? Max(aURes, aVRes) : aURes;
368 IntSurf_PntOn2S aRPT = aPOn2S;
370 if (aPrePointExist == IntPatch_SPntPole)
372 Standard_Real aPrt = 0.5*(aPrevParam + theLPar);
373 for (Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++)
375 const Standard_Real aParam = aVertexParams(i);
377 if (aParam <= aPrevParam)
380 aPrt = 0.5*(aParam + aPrevParam);
384 const gp_Pnt aPnt3d(theALine->Value(aPrt));
385 Standard_Real u1, v1, u2, v2;
386 myQuad1.Parameters(aPnt3d, u1, v1);
387 myQuad2.Parameters(aPnt3d, u2, v2);
388 aRPT.SetValue(aPnt3d, u1, v1, u2, v2);
390 if (aPOn2S.IsSame(aPrevLPoint, Max(Precision::Approximation(), aTol)))
392 //Set V-parameter as precise value found on the previous step.
393 if (aSingularSurfaceID == 1)
395 aPOn2S.ParametersOnS1(u2, v2);
396 aPOn2S.SetValue(Standard_True, u1, v2);
398 else //if (aSingularSurfaceID == 2)
400 aPOn2S.ParametersOnS2(u1, v1);
401 aPOn2S.SetValue(Standard_False, u2, v1);
406 if(IntPatch_SpecialPoints::
407 ContinueAfterSpecialPoint(myS1, myS2, aRPT,
408 aPrePointExist, aTol2d,
409 aPrevLPoint, Standard_False))
411 AddPointIntoLine(aLinOn2S, anArrPeriods, aPrevLPoint);
413 else if(aParameter == theLPar)
414 {// Strictly equal!!!
419 aPrePointExist = IntPatch_SPntNone;
421 Standard_Integer aVertexNumber = -1;
422 for(Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++)
424 if(hasVertexBeenChecked(i))
427 const Standard_Real aParam = aVertexParams(i);
428 if( ((aPrevParam < aParam) && (aParam <= aParameter)) ||
429 ((aPrevParam == aParameter) && (aParam == aParameter)))
436 aPrevParam = aParameter;
438 if(aVertexNumber < 0)
440 StepComputing(theALine, aPOn2S, theLPar, aParameter, aTgMagn,
441 aStepMin, aStepMax, myTol3D, aStep);
442 AddPointIntoLine(aLinOn2S, anArrPeriods, aPOn2S);
443 aPrevLPoint = aPOn2S;
447 IntPatch_Point aVtx = theALine->Vertex(aVertexNumber);
448 const Standard_Real aNewVertexParam = aLinOn2S->NbPoints() + 1;
451 // IsPoleOrSeam inserts new point in aLinOn2S if aVtx respects
452 //to some special point. Otherwise, aLinOn2S is not changed.
454 aPrePointExist = IsPoleOrSeam(myS1, myS2, aLinOn2S, aVtx,
455 anArrPeriods, aTol, aSingularSurfaceID);
457 const Standard_Real aCurVertParam = aVtx.ParameterOnLine();
458 if(aPrePointExist != IntPatch_SPntNone)
460 aPrevParam = aParameter = aCurVertParam;
464 if(aVtx.Tolerance() > aTol)
466 aVtx.SetValue(aPOn2S);
467 AddPointIntoLine(aLinOn2S, anArrPeriods, aPOn2S);
471 AddVertexPoint(aLinOn2S, aVtx, anArrPeriods);
475 aPrevLPoint = aPOn2S = aLinOn2S->Value(aLinOn2S->NbPoints());
478 Standard_Boolean isFound = Standard_False;
479 const Standard_Real aSqTol = aTol*aTol;
480 const gp_Pnt aP1(theALine->Value(aCurVertParam));
481 const IntSurf_PntOn2S& aVertP2S = aVtx.PntOn2S();
482 const Standard_Real aVertToler = aVtx.Tolerance();
484 for(Standard_Integer i = aVertexParams.Lower(); i <= aVertexParams.Upper(); i++)
486 if(hasVertexBeenChecked(i))
489 const gp_Pnt aP2(theALine->Value(aVertexParams(i)));
491 if(aP1.SquareDistance(aP2) < aSqTol)
493 IntPatch_Point aLVtx = theALine->Vertex(i);
494 aLVtx.SetValue(aVertP2S);
495 aLVtx.SetTolerance(aVertToler);
496 aLVtx.SetParameter(aNewVertexParam);
497 aSeqVertex(++aNewVertID) = aLVtx;
498 hasVertexBeenChecked(i) = Standard_True;
499 isFound = Standard_True;
508 if(aPrePointExist != IntPatch_SPntNone)
510 }//for(; !isLast; aParameter += aStep)
512 if(aLinOn2S->NbPoints() < 2)
518 //-----------------------------------------------------------------
519 //-- Computation of transitions of the line on two surfaces ---
520 //-----------------------------------------------------------------
521 IntSurf_TypeTrans trans1,trans2;
523 Standard_Integer indice1;
524 Standard_Real dotcross;
527 trans1=IntSurf_Undecided;
528 trans2=IntSurf_Undecided;
530 indice1 = aLinOn2S->NbPoints()/3;
535 aPP1=aLinOn2S->Value(indice1).Value();
536 aPP0=aLinOn2S->Value(indice1-1).Value();
538 gp_Vec tgvalid(aPP0, aPP1);
539 gp_Vec aNQ1 = myQuad1.Normale(aPP0);
540 gp_Vec aNQ2 = myQuad2.Normale(aPP0);
542 dotcross = tgvalid.DotCross(aNQ2, aNQ1);
543 if (dotcross > myTolTransition) {
544 trans1 = IntSurf_Out;
547 else if(dotcross < -myTolTransition) {
549 trans2 = IntSurf_Out;
553 //-----------------------------------------------------------------
554 //-- W L i n e c r e a t i o n ---
555 //-----------------------------------------------------------------
556 Handle(IntPatch_WLine) aWLine;
558 if(theALine->TransitionOnS1() == IntSurf_Touch) {
559 aWLine = new IntPatch_WLine(aLinOn2S,
560 theALine->IsTangent(),
561 theALine->SituationS1(),
562 theALine->SituationS2());
564 else if(theALine->TransitionOnS1() == IntSurf_Undecided) {
565 aWLine = new IntPatch_WLine(aLinOn2S, theALine->IsTangent());
568 aWLine = new IntPatch_WLine(aLinOn2S, theALine->IsTangent(),
569 trans1, // aline->TransitionOnS1(),
570 trans2); //aline->TransitionOnS2());
573 for(Standard_Integer i = aSeqVertex.Lower(); i <= aNewVertID; i++)
575 const IntPatch_Point& aVtx = aSeqVertex(i);
576 aWLine->AddVertex(aVtx);
579 aWLine->SetPeriod(anArrPeriods[0],anArrPeriods[1],anArrPeriods[2],anArrPeriods[3]);
581 //the method ComputeVertexParameters can reduce the number of points in <aWLine>
582 aWLine->ComputeVertexParameters(myTol3D);
584 if (aWLine->NbPnts() > 1)
586 aWLine->EnablePurging(Standard_False);
587 theLines.Append(aWLine);
589 }//while(aParameter < theLPar)
592 //=======================================================================
593 //function : CheckDeflection
595 // -1 - step is too small
596 // 0 - step is normal
597 // +1 - step is too big
598 //=======================================================================
599 Standard_Integer IntPatch_ALineToWLine::CheckDeflection(const gp_XYZ& theMidPt,
600 const Standard_Real theMaxDeflection) const
602 Standard_Real aDist = Abs(myQuad1.Distance(theMidPt));
603 if(aDist > theMaxDeflection)
606 aDist = Max(Abs(myQuad2.Distance(theMidPt)), aDist);
608 if(aDist > theMaxDeflection)
611 if((aDist + aDist) < theMaxDeflection)
617 //=======================================================================
618 //function : StepComputing
620 //=======================================================================
621 Standard_Boolean IntPatch_ALineToWLine::
622 StepComputing(const Handle(IntPatch_ALine)& theALine,
623 const IntSurf_PntOn2S& thePOn2S,
624 const Standard_Real theLastParOfAline,
625 const Standard_Real theCurParam,
626 const Standard_Real theTgMagnitude,
627 const Standard_Real theStepMin,
628 const Standard_Real theStepMax,
629 const Standard_Real theMaxDeflection,
630 Standard_Real& theStep) const
632 if(theTgMagnitude < Precision::Confusion())
633 return Standard_False;
635 const Standard_Real anEps = myTol3D;
637 //Indeed, 1.0e+15 < 2^50 < 1.0e+16. Therefore,
638 //if we apply bisection method to the range with length
639 //1.0e+6 then we will be able to find solution with max error ~1.0e-9.
640 const Standard_Integer aNbIterMax = 50;
642 const Standard_Real aNotFilledRange = theLastParOfAline - theCurParam;
643 Standard_Real aMinStep = theStepMin, aMaxStep = Min(theStepMax, aNotFilledRange);
645 if(aMinStep > aMaxStep)
648 return Standard_True;
651 const Standard_Real aR = IntPatch_PointLine::
652 CurvatureRadiusOfIntersLine(myS1, myS2, thePOn2S);
656 return Standard_False;
660 //The 3D-step is defined as length of the tangent to the osculating circle
661 //by the condition that the distance from end point of the tangent to the
662 //circle is no greater than anEps. theStep is the step in
663 //parameter space of intersection curve (must be converted from 3D-step).
665 theStep = Min(sqrt(anEps*(2.0*aR + anEps))/theTgMagnitude, aMaxStep);
666 theStep = Max(theStep, aMinStep);
669 //The step value has been computed for osculating circle.
670 //Now it should be checked for real intersection curve
671 //and is made more precise in case of necessity.
673 Standard_Integer aNbIter = 0;
678 const gp_XYZ& aP1 = thePOn2S.Value().XYZ();
679 const gp_XYZ aP2(theALine->Value(theCurParam + theStep).XYZ());
680 const Standard_Integer aStatus = CheckDeflection(0.5*(aP1 + aP2), theMaxDeflection);
689 else //if(aStatus > 0)
694 theStep = 0.5*(aMinStep + aMaxStep);
696 while(((aMaxStep - aMinStep) > Precision::PConfusion()) && (aNbIter <= aNbIterMax));
698 if(aNbIter > aNbIterMax)
699 return Standard_False;
701 return Standard_True;