1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #include <IntPatch_WLineTool.hxx>
16 #include <Adaptor3d_HSurface.hxx>
17 #include <Adaptor3d_TopolTool.hxx>
18 #include <Bnd_Range.hxx>
21 #include <IntPatch_SpecialPoints.hxx>
22 #include <NCollection_IncAllocator.hxx>
23 #include <TopAbs_State.hxx>
25 // It is pure empirical value.
26 const Standard_Real IntPatch_WLineTool::myMaxConcatAngle = M_PI/6;
28 //Bit-mask is used for information about
29 //the operation made in
30 //IntPatch_WLineTool::ExtendTwoWLines(...) method.
33 IntPatchWT_EnAll = 0x00,
34 IntPatchWT_DisLastLast = 0x01,
35 IntPatchWT_DisLastFirst = 0x02,
36 IntPatchWT_DisFirstLast = 0x04,
37 IntPatchWT_DisFirstFirst = 0x08
40 enum IntPatchWT_WLsConnectionType
42 IntPatchWT_NotConnected,
48 //=======================================================================
50 //purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
51 // theParMAX = MAX(theParMIN, theParMAX).
53 // Static subfunction in IsSeamOrBound.
54 //=======================================================================
55 static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
57 if(theParMIN > theParMAX)
59 const Standard_Real aTmp = theParMAX;
60 theParMAX = theParMIN;
65 //=========================================================================
66 // function : FillPointsHash
67 // purpose : Fill points hash by input data.
68 // Static subfunction in ComputePurgedWLine.
69 //=========================================================================
70 static void FillPointsHash(const Handle(IntPatch_WLine) &theWLine,
71 NCollection_Array1<Standard_Integer> &thePointsHash)
75 // -1 - Vertex point (not delete).
76 Standard_Integer i, v;
78 for(i = 1; i <= theWLine->NbPnts(); i++)
79 thePointsHash.SetValue(i, 0);
81 for(v = 1; v <= theWLine->NbVertex(); v++)
83 IntPatch_Point aVertex = theWLine->Vertex(v);
84 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
85 thePointsHash.SetValue(avertexindex, -1);
89 //=========================================================================
90 // function : MakeNewWLine
91 // purpose : Makes new walking line according to the points hash
92 // Static subfunction in ComputePurgedWLine and DeleteOuter.
93 //=========================================================================
94 static Handle(IntPatch_WLine) MakeNewWLine(const Handle(IntPatch_WLine) &theWLine,
95 NCollection_Array1<Standard_Integer> &thePointsHash,
96 const Standard_Boolean theIsOuter)
100 Handle(IntSurf_LineOn2S) aPurgedLineOn2S = new IntSurf_LineOn2S();
101 Handle(IntPatch_WLine) aLocalWLine = new IntPatch_WLine(aPurgedLineOn2S, Standard_False);
102 aLocalWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
103 Standard_Integer anOldLineIdx = 1, aVertexIdx = 1, anIndexPrev = -1, anIdxOld = -1;
104 gp_Pnt aPPrev, aPOld;
105 for(i = 1; i <= thePointsHash.Upper(); i++)
107 if (thePointsHash(i) == 0)
109 // Point has to be added
111 const gp_Pnt aP = theWLine->Point(i).Value();
112 const Standard_Real aSqDistPrev = aPPrev.SquareDistance(aPOld);
113 const Standard_Real aSqDist = aPPrev.SquareDistance(aP);
115 const Standard_Real aRatio = (aSqDistPrev < gp::Resolution()) ? 0.0 : 9.0*aSqDist / aSqDistPrev;
118 (aRatio < gp::Resolution()) ||
119 ((1.0 < aRatio) && (aRatio < 81.0)) ||
120 (i - anIndexPrev <= 1) ||
123 // difference in distances is satisfactory
124 // (1/9 < aSqDist/aSqDistPrev < 9)
127 aPurgedLineOn2S->Add(theWLine->Point(i));
131 anIdxOld = anIndexPrev;
134 else if(aSqDist >= aSqDistPrev*9.0)
136 // current segment is much more longer
137 // (aSqDist/aSqDistPrev >= 9)
139 i = (i + anIndexPrev)/2;
140 thePointsHash(i) = 0;
145 //previous segment is much more longer
146 //(aSqDist/aSqDistPrev <= 1/9)
148 if(anIndexPrev - anIdxOld > 1)
150 //Delete aPPrev from WL
151 aPurgedLineOn2S->RemovePoint(aPurgedLineOn2S->NbPoints());
154 // Insert point between aPOld and aPPrev
155 i = (anIdxOld + anIndexPrev) / 2;
156 thePointsHash(i) = 0;
159 anIndexPrev = anIdxOld;
164 anIdxOld = anIndexPrev;
167 //Next iterations will start from this inserted point.
171 else if (thePointsHash(i) == -1)
174 IntPatch_Point aVertex = theWLine->Vertex(aVertexIdx++);
175 aVertex.SetParameter(anOldLineIdx++);
176 aLocalWLine->AddVertex(aVertex);
177 aPurgedLineOn2S->Add(theWLine->Point(i));
178 aPPrev = aPOld = theWLine->Point(i).Value();
179 anIndexPrev = anIdxOld = i;
182 //Other points will be rejected by purger.
188 //=========================================================================
189 // function : MovePoint
190 // purpose : Move point into surface param space. No interpolation used
191 // because walking algorithm should care for closeness to the param space.
192 // Static subfunction in ComputePurgedWLine.
193 //=========================================================================
194 static void MovePoint(const Handle(Adaptor3d_HSurface) &theS1,
195 Standard_Real &U1, Standard_Real &V1)
197 if (U1 < theS1->FirstUParameter())
198 U1 = theS1->FirstUParameter();
200 if (U1 > theS1->LastUParameter())
201 U1 = theS1->LastUParameter();
203 if (V1 < theS1->FirstVParameter())
204 V1 = theS1->FirstVParameter();
206 if (V1 > theS1->LastVParameter())
207 V1 = theS1->LastVParameter();
210 //=========================================================================
211 // function : DeleteOuterPoints
212 // purpose : Check and delete out of bounds points on walking line.
213 // Static subfunction in ComputePurgedWLine.
214 //=========================================================================
215 static Handle(IntPatch_WLine)
216 DeleteOuterPoints(const Handle(IntPatch_WLine) &theWLine,
217 const Handle(Adaptor3d_HSurface) &theS1,
218 const Handle(Adaptor3d_HSurface) &theS2,
219 const Handle(Adaptor3d_TopolTool) &theDom1,
220 const Handle(Adaptor3d_TopolTool) &theDom2)
224 NCollection_Array1<Standard_Integer> aDelOuterPointsHash(1, theWLine->NbPnts());
225 FillPointsHash(theWLine, aDelOuterPointsHash);
227 if (theS1->IsUPeriodic() || theS1->IsVPeriodic() ||
228 theS2->IsUPeriodic() || theS2->IsVPeriodic() )
231 gp_Pnt2d aPntOnF1, aPntOnF2;
232 Standard_Real aX1, aY1, aX2, aY2;
234 // Iterate over points in walking line and delete which are out of bounds.
236 Standard_Boolean isAllDeleted = Standard_True;
237 Standard_Boolean aChangedFirst = Standard_False;
238 Standard_Integer aFirstGeomIdx = 1;
239 for(i = 1; i <= theWLine->NbPnts(); i++)
241 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
242 aPntOnF1.SetCoord(aX1, aY1);
243 aPntOnF2.SetCoord(aX2, aY2);
245 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
246 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
248 if (aState1 == TopAbs_OUT ||
249 aState2 == TopAbs_OUT )
251 aDelOuterPointsHash(i) = 1;
252 aChangedFirst = Standard_True;
256 isAllDeleted = Standard_False;
258 aFirstGeomIdx = Max (i - 1, 1);
259 if (aDelOuterPointsHash(i) == -1)
260 aFirstGeomIdx = i; // Use data what lies in (i) point / vertex.
262 aDelOuterPointsHash(i) = -1;
269 // ALL points are out of bounds:
270 // case boolean bcut_complex F5 and similar.
275 Standard_Boolean aChangedLast = Standard_False;
276 Standard_Integer aLastGeomIdx = theWLine->NbPnts();
277 for(i = theWLine->NbPnts(); i >= 1; i--)
279 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
280 aPntOnF1.SetCoord(aX1, aY1);
281 aPntOnF2.SetCoord(aX2, aY2);
283 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
284 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
286 if (aState1 == TopAbs_OUT ||
287 aState2 == TopAbs_OUT )
289 aDelOuterPointsHash(i) = 1;
290 aChangedLast = Standard_True; // Move vertex to first good point
294 aLastGeomIdx = Min (i + 1, theWLine->NbPnts());
295 if (aDelOuterPointsHash(i) == -1)
296 aLastGeomIdx = i; // Use data what lies in (i) point / vertex.
298 aDelOuterPointsHash(i) = -1;
303 if (!aChangedFirst && !aChangedLast)
305 // Nothing is done, return input.
309 // Build new line and modify geometry of necessary vertexes.
310 Handle(IntPatch_WLine) aLocalWLine = MakeNewWLine(theWLine, aDelOuterPointsHash, Standard_True);
315 IntPatch_Point aVertex = aLocalWLine->Vertex(1);
316 aVertex.SetValue(theWLine->Point(aFirstGeomIdx).Value());
317 Standard_Real aU1, aU2, aV1, aV2;
318 theWLine->Point(aFirstGeomIdx).Parameters(aU1, aV1, aU2, aV2);
319 MovePoint(theS1, aU1, aV1);
320 MovePoint(theS2, aU2, aV2);
321 aVertex.SetParameters(aU1, aV1, aU2, aV2);
322 aLocalWLine->Replace(1, aVertex);
323 // Change point in walking line.
324 aLocalWLine->SetPoint(1, aVertex);
330 IntPatch_Point aVertex = aLocalWLine->Vertex(aLocalWLine->NbVertex());
331 aVertex.SetValue(theWLine->Point(aLastGeomIdx).Value());
332 Standard_Real aU1, aU2, aV1, aV2;
333 theWLine->Point(aLastGeomIdx).Parameters(aU1, aV1, aU2, aV2);
334 MovePoint(theS1, aU1, aV1);
335 MovePoint(theS2, aU2, aV2);
336 aVertex.SetParameters(aU1, aV1, aU2, aV2);
337 aLocalWLine->Replace(aLocalWLine->NbVertex(), aVertex);
338 // Change point in walking line.
339 aLocalWLine->SetPoint(aLocalWLine->NbPnts(), aVertex);
346 //=========================================================================
347 // function : IsInsideIn2d
348 // purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
349 // In 2d space. Static subfunction in DeleteByTube.
350 //=========================================================================
351 static Standard_Boolean IsInsideIn2d(const gp_Pnt2d& aBasePnt,
352 const gp_Vec2d& aBaseVec,
353 const gp_Pnt2d& aNextPnt,
354 const Standard_Real aSquareMaxDist)
356 gp_Vec2d aVec2d(aBasePnt, aNextPnt);
358 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
359 Standard_Real aCross = aVec2d.Crossed(aBaseVec);
360 Standard_Real aSquareDist = aCross * aCross
361 / aBaseVec.SquareMagnitude();
363 return (aSquareDist <= aSquareMaxDist);
366 //=========================================================================
367 // function : IsInsideIn3d
368 // purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
369 // In 3d space. Static subfunction in DeleteByTube.
370 //=========================================================================
371 static Standard_Boolean IsInsideIn3d(const gp_Pnt& aBasePnt,
372 const gp_Vec& aBaseVec,
373 const gp_Pnt& aNextPnt,
374 const Standard_Real aSquareMaxDist)
376 gp_Vec aVec(aBasePnt, aNextPnt);
378 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
379 Standard_Real aSquareDist = aVec.CrossSquareMagnitude(aBaseVec)
380 / aBaseVec.SquareMagnitude();
382 return (aSquareDist <= aSquareMaxDist);
385 static const Standard_Integer aMinNbBadDistr = 15;
386 static const Standard_Integer aNbSingleBezier = 30;
388 //=========================================================================
389 // function : DeleteByTube
390 // purpose : Check and delete points using tube criteria.
391 // Static subfunction in ComputePurgedWLine.
392 //=========================================================================
393 static Handle(IntPatch_WLine)
394 DeleteByTube(const Handle(IntPatch_WLine) &theWLine,
395 const Handle(Adaptor3d_HSurface) &theS1,
396 const Handle(Adaptor3d_HSurface) &theS2)
398 // III: Check points for tube criteria:
399 // Workaround to handle case of small amount points after purge.
400 // Test "boolean boptuc_complex B5" and similar.
401 Standard_Integer aNbPnt = 0 , i;
403 if (theWLine->NbPnts() <= 2)
406 NCollection_Array1<Standard_Integer> aNewPointsHash(1, theWLine->NbPnts());
407 FillPointsHash(theWLine, aNewPointsHash);
409 // Initial computations.
410 Standard_Real UonS1[3], VonS1[3], UonS2[3], VonS2[3];
411 theWLine->Point(1).ParametersOnS1(UonS1[0], VonS1[0]);
412 theWLine->Point(2).ParametersOnS1(UonS1[1], VonS1[1]);
413 theWLine->Point(1).ParametersOnS2(UonS2[0], VonS2[0]);
414 theWLine->Point(2).ParametersOnS2(UonS2[1], VonS2[1]);
416 gp_Pnt2d aBase2dPnt1(UonS1[0], VonS1[0]);
417 gp_Pnt2d aBase2dPnt2(UonS2[0], VonS2[0]);
418 gp_Vec2d aBase2dVec1(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
419 gp_Vec2d aBase2dVec2(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
420 gp_Pnt aBase3dPnt = theWLine->Point(1).Value();
421 gp_Vec aBase3dVec(theWLine->Point(1).Value(), theWLine->Point(2).Value());
423 // Choose base tolerance and scale it to pipe algorithm.
424 const Standard_Real aBaseTolerance = Precision::Approximation();
425 Standard_Real aResS1Tol = Min(theS1->UResolution(aBaseTolerance),
426 theS1->VResolution(aBaseTolerance));
427 Standard_Real aResS2Tol = Min(theS2->UResolution(aBaseTolerance),
428 theS2->VResolution(aBaseTolerance));
429 Standard_Real aTol1 = aResS1Tol * aResS1Tol;
430 Standard_Real aTol2 = aResS2Tol * aResS2Tol;
431 Standard_Real aTol3d = aBaseTolerance * aBaseTolerance;
433 const Standard_Real aLimitCoeff = 0.99 * 0.99;
434 for(i = 3; i <= theWLine->NbPnts(); i++)
436 Standard_Boolean isDeleteState = Standard_False;
438 theWLine->Point(i).ParametersOnS1(UonS1[2], VonS1[2]);
439 theWLine->Point(i).ParametersOnS2(UonS2[2], VonS2[2]);
440 gp_Pnt2d aPnt2dOnS1(UonS1[2], VonS1[2]);
441 gp_Pnt2d aPnt2dOnS2(UonS2[2], VonS2[2]);
442 const gp_Pnt& aPnt3d = theWLine->Point(i).Value();
444 if (aNewPointsHash(i - 1) != - 1 &&
445 IsInsideIn2d(aBase2dPnt1, aBase2dVec1, aPnt2dOnS1, aTol1) &&
446 IsInsideIn2d(aBase2dPnt2, aBase2dVec2, aPnt2dOnS2, aTol2) &&
447 IsInsideIn3d(aBase3dPnt, aBase3dVec, aPnt3d, aTol3d) )
449 // Handle possible uneven parametrization on one of 2d subspaces.
450 // Delete point only when expected lengths are close to each other (aLimitCoeff).
454 // c2d2 - geometrically line, but have uneven parametrization -> c2d2 is bspline.
455 gp_XY aPntOnS1[2]= { gp_XY(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0])
456 , gp_XY(UonS1[2] - UonS1[1], VonS1[2] - VonS1[1])};
457 gp_XY aPntOnS2[2]= { gp_XY(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0])
458 , gp_XY(UonS2[2] - UonS2[1], VonS2[2] - VonS2[1])};
460 Standard_Real aStepOnS1 = aPntOnS1[0].SquareModulus() / aPntOnS1[1].SquareModulus();
461 Standard_Real aStepOnS2 = aPntOnS2[0].SquareModulus() / aPntOnS2[1].SquareModulus();
463 // Check very rare case when wline fluctuates nearly one point and some of them may be equal.
464 // Middle point will be deleted when such situation occurs.
465 // bugs moddata_2 bug469.
466 if (Min(aStepOnS1, aStepOnS2) >= aLimitCoeff * Max(aStepOnS1, aStepOnS2))
468 // Set hash flag to "Delete" state.
469 isDeleteState = Standard_True;
470 aNewPointsHash.SetValue(i - 1, 1);
472 // Change middle point.
482 // Compute new pipe parameters.
493 aBase2dPnt1.SetCoord(UonS1[0], VonS1[0]);
494 aBase2dPnt2.SetCoord(UonS2[0], VonS2[0]);
495 aBase2dVec1.SetCoord(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
496 aBase2dVec2.SetCoord(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
497 aBase3dPnt = theWLine->Point(i - 1).Value();
498 aBase3dVec = gp_Vec(theWLine->Point(i - 1).Value(), theWLine->Point(i).Value());
504 // Workaround to handle case of small amount of points after purge.
505 // Test "boolean boptuc_complex B5" and similar.
506 // This is possible since there are at least two points.
507 if (aNewPointsHash(1) == -1 &&
508 aNewPointsHash(2) == -1 &&
512 aNewPointsHash(1) = 1;
514 if (aNewPointsHash(theWLine->NbPnts() - 1) == -1 &&
515 aNewPointsHash(theWLine->NbPnts() ) == -1 &&
519 aNewPointsHash(theWLine->NbPnts()) = 1;
522 // Purgre when too small amount of points left.
525 for(i = aNewPointsHash.Lower(); i <= aNewPointsHash.Upper(); i++)
527 if (aNewPointsHash(i) != -1)
529 aNewPointsHash(i) = 1;
534 // Handle possible bad distribution of points,
535 // which are will converted into one single bezier curve (less than 30 points).
536 // Make distribution more even:
537 // max step will be nearly to 0.1 of param distance.
538 if (aNbPnt + 2 > aMinNbBadDistr &&
539 aNbPnt + 2 < aNbSingleBezier )
541 for(Standard_Integer anIdx = 1; anIdx <= 8; anIdx++)
543 Standard_Integer aHashIdx =
544 Standard_Integer(anIdx * theWLine->NbPnts() / 9);
546 //Vertex must be stored as VERTEX (HASH = -1)
547 if (aNewPointsHash(aHashIdx) != -1)
548 aNewPointsHash(aHashIdx) = 0;
552 return MakeNewWLine(theWLine, aNewPointsHash, Standard_False);
555 //=======================================================================
556 //function : IsSeamOrBound
557 //purpose : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
558 // (if it exist) or surface boundaries and both thePtf and thePtl do
559 // not match "seam-edge" or boundaries.
560 // Point thePtmid lies in this segment (in both 3D and 2D-space).
561 // If thePtmid match "seam-edge" or boundaries strictly
562 // (without any tolerance) then the function will return TRUE.
563 // See comments in function body for detail information.
565 // Arrays theArrPeriods, theFBound and theLBound must be filled
567 // [0] - U-parameter of 1st surface;
568 // [1] - V-parameter of 1st surface;
569 // [2] - U-parameter of 2nd surface;
570 // [3] - V-parameter of 2nd surface.
571 //=======================================================================
572 static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
573 const IntSurf_PntOn2S& thePtl,
574 const IntSurf_PntOn2S& thePtmid,
575 const Standard_Real theArrPeriods[4],
576 const Standard_Real theFBound[4],
577 const Standard_Real theLBound[4])
579 Standard_Real aParF[4] = { 0.0, 0.0, 0.0, 0.0 };
580 Standard_Real aParL[4] = { 0.0, 0.0, 0.0, 0.0 };
581 thePtf.Parameters(aParF[0], aParF[1], aParF[2], aParF[3]);
582 thePtl.Parameters(aParL[0], aParL[1], aParL[2], aParL[3]);
586 for (Standard_Integer i = 0; i < 4; i++)
588 aBndR[i].Add(aParF[i]);
589 aBndR[i].Add(aParL[i]);
591 if (aBndR[i].IsIntersected(theFBound[i], theArrPeriods[i]) == 1)
592 return Standard_True;
594 if (aBndR[i].IsIntersected(theLBound[i], theArrPeriods[i]) == 1)
595 return Standard_True;
598 for (Standard_Integer i = 0; i < 4; i++)
600 if (theArrPeriods[i] == 0.0)
606 const Standard_Real aDelta = Abs(aParL[i] - aParF[i]);
607 if (2.0*aDelta > theArrPeriods[i])
609 //Most likely, seam is intersected.
610 return Standard_True;
613 if (aBndR[i].IsIntersected(0.0, theArrPeriods[i]) == 1)
614 return Standard_True;
617 //The segment [thePtf, thePtl] does not intersect the boundaries and
618 //the seam-edge of the surfaces.
619 //Nevertheless, following situation is possible:
630 //This case must be processed, too.
632 Standard_Real aMPar[4] = { 0.0, 0.0, 0.0, 0.0 };
633 thePtmid.Parameters(aMPar[0], aMPar[1], aMPar[2], aMPar[3]);
635 for (Standard_Integer i = 0; i < 4; i++)
637 const Bnd_Range aBR(aMPar[i], aMPar[i]);
638 if (aBR.IsIntersected(theFBound[i], theArrPeriods[i]))
639 return Standard_True;
641 if (aBR.IsIntersected(theLBound[i], theArrPeriods[i]))
642 return Standard_True;
644 if (aBR.IsIntersected(0.0, theArrPeriods[i]))
645 return Standard_True;
648 return Standard_False;
651 //=======================================================================
652 //function : IsIntersectionPoint
653 //purpose : Returns True if thePmid is intersection point
654 // between theS1 and theS2 with given tolerance.
655 // In this case, parameters of thePmid on every quadric
656 // will be recomputed and returned.
657 //=======================================================================
658 static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid,
659 const Handle(Adaptor3d_HSurface)& theS1,
660 const Handle(Adaptor3d_HSurface)& theS2,
661 const IntSurf_PntOn2S& theRefPt,
662 const Standard_Real theTol,
663 const Standard_Real* const theArrPeriods,
664 IntSurf_PntOn2S& theNewPt)
666 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
668 switch(theS1->GetType())
671 ElSLib::Parameters(theS1->Plane(), thePmid, aU1, aV1);
674 case GeomAbs_Cylinder:
675 ElSLib::Parameters(theS1->Cylinder(), thePmid, aU1, aV1);
679 ElSLib::Parameters(theS1->Sphere(), thePmid, aU1, aV1);
683 ElSLib::Parameters(theS1->Cone(), thePmid, aU1, aV1);
687 ElSLib::Parameters(theS1->Torus(), thePmid, aU1, aV1);
691 return Standard_False;
694 switch(theS2->GetType())
697 ElSLib::Parameters(theS2->Plane(), thePmid, aU2, aV2);
700 case GeomAbs_Cylinder:
701 ElSLib::Parameters(theS2->Cylinder(), thePmid, aU2, aV2);
705 ElSLib::Parameters(theS2->Sphere(), thePmid, aU2, aV2);
709 ElSLib::Parameters(theS2->Cone(), thePmid, aU2, aV2);
713 ElSLib::Parameters(theS2->Torus(), thePmid, aU2, aV2);
717 return Standard_False;
720 theNewPt.SetValue(thePmid, aU1, aV1, aU2, aV2);
722 IntPatch_SpecialPoints::AdjustPointAndVertex(theRefPt, theArrPeriods, theNewPt);
724 const gp_Pnt aP1(theS1->Value(aU1, aV1));
725 const gp_Pnt aP2(theS2->Value(aU2, aV2));
727 return (aP1.SquareDistance(aP2) <= theTol*theTol);
730 //=======================================================================
731 //function : ExtendFirst
732 //purpose : Adds thePOn2S to the begin of theWline
733 //=======================================================================
734 static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
735 const IntSurf_PntOn2S& theAddedPt)
737 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
738 theAddedPt.Parameters(aU1, aV1, aU2, aV2);
740 if(theAddedPt.IsSame(theWline->Point(1), Precision::Confusion()))
742 theWline->Curve()->Value(1, theAddedPt);
743 for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
745 IntPatch_Point &aVert = theWline->ChangeVertex(i);
746 if(aVert.ParameterOnLine() != 1)
749 aVert.SetParameters(aU1, aV1, aU2, aV2);
750 aVert.SetValue(theAddedPt.Value());
756 theWline->Curve()->InsertBefore(1, theAddedPt);
758 for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
760 IntPatch_Point &aVert = theWline->ChangeVertex(i);
762 if(aVert.ParameterOnLine() == 1)
764 aVert.SetParameters(aU1, aV1, aU2, aV2);
765 aVert.SetValue(theAddedPt.Value());
769 aVert.SetParameter(aVert.ParameterOnLine()+1);
774 //=======================================================================
775 //function : ExtendLast
776 //purpose : Adds thePOn2S to the end of theWline
777 //=======================================================================
778 static void ExtendLast(const Handle(IntPatch_WLine)& theWline,
779 const IntSurf_PntOn2S& theAddedPt)
781 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
782 theAddedPt.Parameters(aU1, aV1, aU2, aV2);
784 const Standard_Integer aNbPnts = theWline->NbPnts();
785 if(theAddedPt.IsSame(theWline->Point(aNbPnts), Precision::Confusion()))
787 theWline->Curve()->Value(aNbPnts, theAddedPt);
791 theWline->Curve()->Add(theAddedPt);
794 for(Standard_Integer i = theWline->NbVertex(); i >= 1; i--)
796 IntPatch_Point &aVert = theWline->ChangeVertex(i);
797 if(aVert.ParameterOnLine() != aNbPnts)
800 aVert.SetParameters(aU1, aV1, aU2, aV2);
801 aVert.SetValue(theAddedPt.Value());
802 aVert.SetParameter(theWline->NbPnts());
806 //=========================================================================
807 // function: IsOutOfDomain
808 // purpose : Checks, if 2D-representation of thePOn2S is in surfaces domain,
809 // defined by bounding-boxes theBoxS1 and theBoxS2
810 //=========================================================================
811 static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1,
812 const Bnd_Box2d& theBoxS2,
813 const IntSurf_PntOn2S &thePOn2S,
814 const Standard_Real* const theArrPeriods)
816 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
817 Standard_Real aU1min = 0.0, aU1max = 0.0, aV1min = 0.0, aV1max = 0.0;
818 Standard_Real aU2min = 0.0, aU2max = 0.0, aV2min = 0.0, aV2max = 0.0;
820 thePOn2S.Parameters(aU1, aV1, aU2, aV2);
822 theBoxS1.Get(aU1min, aV1min, aU1max, aV1max);
823 theBoxS2.Get(aU2min, aV2min, aU2max, aV2max);
825 aU1 = ElCLib::InPeriod(aU1, aU1min, aU1min + theArrPeriods[0]);
826 aV1 = ElCLib::InPeriod(aV1, aV1min, aV1min + theArrPeriods[1]);
827 aU2 = ElCLib::InPeriod(aU2, aU2min, aU2min + theArrPeriods[2]);
828 aV2 = ElCLib::InPeriod(aV2, aV2min, aV2min + theArrPeriods[3]);
830 return (theBoxS1.IsOut(gp_Pnt2d(aU1, aV1)) ||
831 theBoxS2.IsOut(gp_Pnt2d(aU2, aV2)));
834 //=======================================================================
835 //function : CheckArgumentsToExtend
836 //purpose : Check if extending is possible
837 // (see IntPatch_WLineTool::ExtendTwoWLines)
838 //=======================================================================
839 static IntPatchWT_WLsConnectionType
840 CheckArgumentsToExtend(const Handle(Adaptor3d_HSurface)& theS1,
841 const Handle(Adaptor3d_HSurface)& theS2,
842 const IntSurf_PntOn2S& thePtWL1,
843 const IntSurf_PntOn2S& thePtWL2,
844 IntSurf_PntOn2S& theNewPoint,
845 const gp_Vec& theVec1,
846 const gp_Vec& theVec2,
847 const gp_Vec& theVec3,
848 const Bnd_Box2d& theBoxS1,
849 const Bnd_Box2d& theBoxS2,
850 const Standard_Real theToler3D,
851 const Standard_Real* const theArrPeriods)
853 const Standard_Real aSqToler = theToler3D*theToler3D;
854 IntPatchWT_WLsConnectionType aRetVal = IntPatchWT_NotConnected;
855 if(theVec3.SquareMagnitude() <= aSqToler)
857 if ((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle))
863 aRetVal = IntPatchWT_Common;
866 else if((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle) ||
867 (theVec1.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle) ||
868 (theVec2.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle))
873 const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ()));
875 Standard_Real aNewPar[4] = {0.0, 0.0, 0.0, 0.0};
878 Standard_Real aParLBC[4] = {0.0, 0.0, 0.0, 0.0};
879 theBoxS1.Get(aParLBC[0], aParLBC[1], aNewPar[0], aNewPar[0]);
880 theBoxS2.Get(aParLBC[2], aParLBC[3], aNewPar[0], aNewPar[0]);
882 if(!IsIntersectionPoint(aPmid, theS1, theS2, thePtWL1, theToler3D,
883 theArrPeriods, theNewPoint))
885 return IntPatchWT_NotConnected;
888 if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint, theArrPeriods))
890 return IntPatchWT_NotConnected;
893 Standard_Real aParWL1[4] = {0.0, 0.0, 0.0, 0.0},
894 aParWL2[4] = {0.0, 0.0, 0.0, 0.0};
896 thePtWL1.Parameters(aParWL1[0], aParWL1[1], aParWL1[2], aParWL1[3]);
897 thePtWL2.Parameters(aParWL2[0], aParWL2[1], aParWL2[2], aParWL2[3]);
898 theNewPoint.Parameters(aNewPar[0], aNewPar[1], aNewPar[2], aNewPar[3]);
902 Standard_Boolean isOnBoundary = Standard_False;
903 for(Standard_Integer i = 0; i < 4; i++)
905 if (theArrPeriods[i] == 0.0)
915 if (aR1.IsIntersected(aParLBC[i],theArrPeriods[i]))
917 //Check, if we intersect surface boundary when we will extend Wline1 or Wline2
919 MinMax(aParWL1[i], aParWL2[i]);
920 if(aNewPar[i] > aParWL2[i])
924 //---*---------------*------------*-----
925 // aParWL1[i] aParWL2[i] aNewPar[i]
927 //After possible adjusting:
929 //---*---------------*------------*-----
930 // aParWL1[i] aNewPar[i] aParWL2[i]
932 //Now we will be able to extend every WLine to
933 //aNewPar[i] to make them close to each other.
934 //However, it is necessary to add check if we
935 //intersect boundary.
936 const Standard_Real aPar = aParWL1[i] +
937 theArrPeriods[i]*Ceiling((aNewPar[i]-aParWL1[i])/theArrPeriods[i]);
938 aParWL1[i] = aParWL2[i];
941 else if(aNewPar[i] < aParWL1[i])
943 //See comments to main "if".
946 //---*---------------*------------*-----
947 // aNewPar[i] aParWL1[i] aParWL2[i]
949 //After possible adjusting:
951 //---*---------------*------------*-----
952 // aParWL1[i] aNewPar[i] aParWL2[i]
954 const Standard_Real aPar = aParWL2[i] -
955 theArrPeriods[i]*Ceiling((aParWL2[i]-aNewPar[i])/theArrPeriods[i]);
956 aParWL2[i] = aParWL1[i];
967 if (aR1.IsIntersected(aParLBC[i], theArrPeriods[i]) ||
968 aR2.IsIntersected(aParLBC[i], theArrPeriods[i]))
970 return IntPatchWT_NotConnected;
974 isOnBoundary = Standard_True;
981 return IntPatchWT_Singular;
984 if (aRetVal == IntPatchWT_Common)
986 return IntPatchWT_Common;
989 return IntPatchWT_ReqExtend;
992 //=======================================================================
993 //function : CheckArgumentsToJoin
994 //purpose : Check if joining is possible
995 // (see IntPatch_WLineTool::JoinWLines(...))
996 //=======================================================================
997 Standard_Boolean CheckArgumentsToJoin(const Handle(Adaptor3d_HSurface)& theS1,
998 const Handle(Adaptor3d_HSurface)& theS2,
999 const IntSurf_PntOn2S& thePnt,
1000 const gp_Pnt& theP1,
1001 const gp_Pnt& theP2,
1002 const gp_Pnt& theP3,
1003 const Standard_Real theMinRad)
1005 const Standard_Real aRad =
1006 IntPatch_PointLine::CurvatureRadiusOfIntersLine(theS1, theS2, thePnt);
1008 if (aRad > theMinRad)
1010 return Standard_True;
1012 else if (aRad > 0.0)
1014 return Standard_False;
1017 // Curvature radius cannot be computed.
1018 // Check smoothness of polygon.
1027 //Joining is enabled if two conditions are satisfied together:
1028 // 1. Angle (theP1, theP2, theP3) is quite big;
1029 // 2. Modulus of perpendicular (O->theP2) to the segment (theP1->theP3)
1030 // is less than 0.01*<modulus of this segment>.
1032 const gp_Vec aV12f(theP1, theP2), aV12l(theP2, theP3);
1034 if (aV12f.Angle(aV12l) > IntPatch_WLineTool::myMaxConcatAngle)
1035 return Standard_False;
1037 const gp_Vec aV13(theP1, theP3);
1038 const Standard_Real aSq13 = aV13.SquareMagnitude();
1040 return (aV12f.CrossSquareMagnitude(aV13) < 1.0e-4*aSq13*aSq13);
1043 //=======================================================================
1044 //function : ExtendTwoWLFirstFirst
1045 //purpose : Performs extending theWLine1 and theWLine2 through their
1046 // respecting start point.
1047 //=======================================================================
1048 static void ExtendTwoWLFirstFirst(const Handle(Adaptor3d_HSurface)& theS1,
1049 const Handle(Adaptor3d_HSurface)& theS2,
1050 const Handle(IntPatch_WLine)& theWLine1,
1051 const Handle(IntPatch_WLine)& theWLine2,
1052 const IntSurf_PntOn2S& thePtWL1,
1053 const IntSurf_PntOn2S& thePtWL2,
1054 const gp_Vec& theVec1,
1055 const gp_Vec& theVec2,
1056 const gp_Vec& theVec3,
1057 const Bnd_Box2d& theBoxS1,
1058 const Bnd_Box2d& theBoxS2,
1059 const Standard_Real theToler3D,
1060 const Standard_Real* const theArrPeriods,
1061 unsigned int &theCheckResult,
1062 Standard_Boolean &theHasBeenJoined)
1064 IntSurf_PntOn2S aPOn2S;
1065 const IntPatchWT_WLsConnectionType aCheckRes =
1066 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1067 theVec1, theVec2, theVec3,
1069 theToler3D, theArrPeriods);
1071 if(aCheckRes != IntPatchWT_NotConnected)
1072 theCheckResult |= (IntPatchWT_DisFirstLast | IntPatchWT_DisLastFirst);
1076 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1077 ExtendFirst(theWLine1, aPOn2S);
1078 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1079 ExtendFirst(theWLine2, aPOn2S);
1081 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
1084 Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
1085 while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
1086 theWLine1->RemoveVertex(1);
1088 aPrm = theWLine2->Vertex(1).ParameterOnLine();
1089 while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
1090 theWLine2->RemoveVertex(1);
1092 const Standard_Integer aNbPts = theWLine2->NbPnts();
1093 for(Standard_Integer aNPt = 2; aNPt <= aNbPts; aNPt++)
1095 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1096 theWLine1->Curve()->InsertBefore(1, aPt);
1099 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
1101 IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
1102 const Standard_Real aCurParam = aVert.ParameterOnLine();
1103 aVert.SetParameter(aNbPts+aCurParam-1);
1106 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
1108 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1109 const Standard_Real aCurParam = aVert.ParameterOnLine();
1110 aVert.SetParameter(aNbPts-aCurParam+1);
1111 theWLine1->AddVertex(aVert, Standard_True);
1114 theHasBeenJoined = Standard_True;
1117 //=======================================================================
1118 //function : ExtendTwoWLFirstLast
1119 //purpose : Performs extending theWLine1 through its start point and theWLine2
1120 // through its end point.
1121 //=======================================================================
1122 static void ExtendTwoWLFirstLast(const Handle(Adaptor3d_HSurface)& theS1,
1123 const Handle(Adaptor3d_HSurface)& theS2,
1124 const Handle(IntPatch_WLine)& theWLine1,
1125 const Handle(IntPatch_WLine)& theWLine2,
1126 const IntSurf_PntOn2S& thePtWL1,
1127 const IntSurf_PntOn2S& thePtWL2,
1128 const gp_Vec& theVec1,
1129 const gp_Vec& theVec2,
1130 const gp_Vec& theVec3,
1131 const Bnd_Box2d& theBoxS1,
1132 const Bnd_Box2d& theBoxS2,
1133 const Standard_Real theToler3D,
1134 const Standard_Real* const theArrPeriods,
1135 unsigned int &theCheckResult,
1136 Standard_Boolean &theHasBeenJoined)
1138 IntSurf_PntOn2S aPOn2S;
1139 const IntPatchWT_WLsConnectionType aCheckRes =
1140 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1141 theVec1, theVec2, theVec3,
1143 theToler3D, theArrPeriods);
1145 if(aCheckRes != IntPatchWT_NotConnected)
1146 theCheckResult |= IntPatchWT_DisLastLast;
1150 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1151 ExtendFirst(theWLine1, aPOn2S);
1152 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1153 ExtendLast (theWLine2, aPOn2S);
1155 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
1158 Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
1159 while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
1160 theWLine1->RemoveVertex(1);
1162 aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
1163 while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
1164 theWLine2->RemoveVertex(theWLine2->NbVertex());
1166 const Standard_Integer aNbPts = theWLine2->NbPnts();
1167 for(Standard_Integer aNPt = aNbPts - 1; aNPt >= 1; aNPt--)
1169 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1170 theWLine1->Curve()->InsertBefore(1, aPt);
1173 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
1175 IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
1176 const Standard_Real aCurParam = aVert.ParameterOnLine();
1177 aVert.SetParameter(aNbPts+aCurParam-1);
1180 for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
1182 const IntPatch_Point &aVert = theWLine2->Vertex(aNVtx);
1183 theWLine1->AddVertex(aVert, Standard_True);
1186 theHasBeenJoined = Standard_True;
1189 //=======================================================================
1190 //function : ExtendTwoWLLastFirst
1191 //purpose : Performs extending theWLine1 through its end point and theWLine2
1192 // through its start point.
1193 //=======================================================================
1194 static void ExtendTwoWLLastFirst(const Handle(Adaptor3d_HSurface)& theS1,
1195 const Handle(Adaptor3d_HSurface)& theS2,
1196 const Handle(IntPatch_WLine)& theWLine1,
1197 const Handle(IntPatch_WLine)& theWLine2,
1198 const IntSurf_PntOn2S& thePtWL1,
1199 const IntSurf_PntOn2S& thePtWL2,
1200 const gp_Vec& theVec1,
1201 const gp_Vec& theVec2,
1202 const gp_Vec& theVec3,
1203 const Bnd_Box2d& theBoxS1,
1204 const Bnd_Box2d& theBoxS2,
1205 const Standard_Real theToler3D,
1206 const Standard_Real* const theArrPeriods,
1207 unsigned int &theCheckResult,
1208 Standard_Boolean &theHasBeenJoined)
1210 IntSurf_PntOn2S aPOn2S;
1211 const IntPatchWT_WLsConnectionType aCheckRes =
1212 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1213 theVec1, theVec2, theVec3,
1215 theToler3D, theArrPeriods);
1217 if(aCheckRes != IntPatchWT_NotConnected)
1218 theCheckResult |= IntPatchWT_DisLastLast;
1222 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1223 ExtendLast (theWLine1, aPOn2S);
1224 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1225 ExtendFirst(theWLine2, aPOn2S);
1227 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
1232 Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
1233 while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
1234 theWLine1->RemoveVertex(theWLine1->NbVertex());
1236 aPrm = theWLine2->Vertex(1).ParameterOnLine();
1237 while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
1238 theWLine2->RemoveVertex(1);
1240 const Standard_Integer aNbPts = theWLine1->NbPnts();
1241 for(Standard_Integer aNPt = 2; aNPt <= theWLine2->NbPnts(); aNPt++)
1243 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1244 theWLine1->Curve()->Add(aPt);
1247 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
1249 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1250 const Standard_Real aCurParam = aVert.ParameterOnLine();
1251 aVert.SetParameter(aNbPts+aCurParam-1);
1252 theWLine1->AddVertex(aVert, Standard_False);
1255 theHasBeenJoined = Standard_True;
1258 //=======================================================================
1259 //function : ExtendTwoWLLastLast
1261 //=======================================================================
1262 static void ExtendTwoWLLastLast(const Handle(Adaptor3d_HSurface)& theS1,
1263 const Handle(Adaptor3d_HSurface)& theS2,
1264 const Handle(IntPatch_WLine)& theWLine1,
1265 const Handle(IntPatch_WLine)& theWLine2,
1266 const IntSurf_PntOn2S& thePtWL1,
1267 const IntSurf_PntOn2S& thePtWL2,
1268 const gp_Vec& theVec1,
1269 const gp_Vec& theVec2,
1270 const gp_Vec& theVec3,
1271 const Bnd_Box2d& theBoxS1,
1272 const Bnd_Box2d& theBoxS2,
1273 const Standard_Real theToler3D,
1274 const Standard_Real* const theArrPeriods,
1275 unsigned int &theCheckResult,
1276 Standard_Boolean &theHasBeenJoined)
1278 IntSurf_PntOn2S aPOn2S;
1279 const IntPatchWT_WLsConnectionType aCheckRes =
1280 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1281 theVec1, theVec2, theVec3,
1283 theToler3D, theArrPeriods);
1285 if(aCheckRes != IntPatchWT_NotConnected)
1286 theCheckResult |= IntPatchWT_DisLastLast;
1290 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1291 ExtendLast(theWLine1, aPOn2S);
1292 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1293 ExtendLast(theWLine2, aPOn2S);
1295 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
1298 Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
1299 while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
1300 theWLine1->RemoveVertex(theWLine1->NbVertex());
1302 aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
1303 while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
1304 theWLine2->RemoveVertex(theWLine2->NbVertex());
1306 const Standard_Integer aNbPts = theWLine1->NbPnts() + theWLine2->NbPnts();
1307 for(Standard_Integer aNPt = theWLine2->NbPnts()-1; aNPt >= 1; aNPt--)
1309 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1310 theWLine1->Curve()->Add(aPt);
1313 for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
1315 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1316 const Standard_Real aCurParam = aVert.ParameterOnLine();
1317 aVert.SetParameter(aNbPts - aCurParam);
1318 theWLine1->AddVertex(aVert, Standard_False);
1321 theHasBeenJoined = Standard_True;
1324 //=========================================================================
1325 // function : ComputePurgedWLine
1327 //=========================================================================
1328 Handle(IntPatch_WLine) IntPatch_WLineTool::
1329 ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
1330 const Handle(Adaptor3d_HSurface) &theS1,
1331 const Handle(Adaptor3d_HSurface) &theS2,
1332 const Handle(Adaptor3d_TopolTool) &theDom1,
1333 const Handle(Adaptor3d_TopolTool) &theDom2)
1335 Standard_Integer i, k, v, nb, nbvtx;
1336 Handle(IntPatch_WLine) aResult;
1337 nbvtx = theWLine->NbVertex();
1338 nb = theWLine->NbPnts();
1341 const IntSurf_PntOn2S& p1 = theWLine->Point(1);
1342 const IntSurf_PntOn2S& p2 = theWLine->Point(2);
1343 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()))
1347 Handle(IntPatch_WLine) aLocalWLine;
1348 Handle(IntPatch_WLine) aTmpWLine = theWLine;
1349 Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
1350 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
1351 aLocalWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
1352 for(i = 1; i <= nb; i++)
1353 aLineOn2S->Add(theWLine->Point(i));
1355 for(v = 1; v <= nbvtx; v++)
1356 aLocalWLine->AddVertex(theWLine->Vertex(v));
1358 // I: Delete equal points
1359 for(i = 1; i <= aLineOn2S->NbPoints(); i++)
1361 Standard_Integer aStartIndex = i + 1;
1362 Standard_Integer anEndIndex = i + 5;
1363 nb = aLineOn2S->NbPoints();
1364 anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
1366 if((aStartIndex > nb) || (anEndIndex <= 1))
1371 while(k <= anEndIndex)
1375 IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
1376 IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
1378 Standard_Real UV[8];
1379 p1.Parameters(UV[0], UV[1], UV[2], UV[3]);
1380 p2.Parameters(UV[4], UV[5], UV[6], UV[7]);
1382 Standard_Real aMax = Abs(UV[0]);
1383 for(Standard_Integer anIdx = 1; anIdx < 8; anIdx++)
1385 if (aMax < Abs(UV[anIdx]))
1386 aMax = Abs(UV[anIdx]);
1389 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()) ||
1390 Abs(UV[0] - UV[4]) + Abs(UV[1] - UV[5]) < 1.0e-16 * aMax ||
1391 Abs(UV[2] - UV[6]) + Abs(UV[3] - UV[7]) < 1.0e-16 * aMax )
1393 aTmpWLine = aLocalWLine;
1394 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
1395 aLocalWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
1397 for(v = 1; v <= aTmpWLine->NbVertex(); v++)
1399 IntPatch_Point aVertex = aTmpWLine->Vertex(v);
1400 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
1402 if(avertexindex >= k)
1404 aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
1406 aLocalWLine->AddVertex(aVertex);
1408 aLineOn2S->RemovePoint(k);
1417 if (aLineOn2S->NbPoints() <= 2)
1419 if (aLineOn2S->NbPoints() == 2)
1425 // Avoid purge in case of C0 continuity:
1426 // Intersection approximator may produce invalid curve after purge, example:
1427 // bugs modalg_5 bug24731.
1428 // Do not run purger when base number of points is too small.
1429 if (theS1->UContinuity() == GeomAbs_C0 ||
1430 theS1->VContinuity() == GeomAbs_C0 ||
1431 theS2->UContinuity() == GeomAbs_C0 ||
1432 theS2->VContinuity() == GeomAbs_C0 ||
1433 nb < aNbSingleBezier)
1438 // II: Delete out of borders points.
1439 aLocalWLine = DeleteOuterPoints(aLocalWLine, theS1, theS2, theDom1, theDom2);
1441 // III: Delete points by tube criteria.
1442 Handle(IntPatch_WLine) aLocalWLineTube =
1443 DeleteByTube(aLocalWLine, theS1, theS2);
1445 if(aLocalWLineTube->NbPnts() > 1)
1447 aResult = aLocalWLineTube;
1452 //=======================================================================
1453 //function : JoinWLines
1455 //=======================================================================
1456 void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
1457 IntPatch_SequenceOfPoint& theSPnt,
1458 Handle(Adaptor3d_HSurface) theS1,
1459 Handle(Adaptor3d_HSurface) theS2,
1460 const Standard_Real theTol3D)
1462 if(theSlin.Length() == 0)
1465 // For two cylindrical surfaces only
1466 const Standard_Real aMinRad = 1.0e-3*Min(theS1->Cylinder().Radius(),
1467 theS2->Cylinder().Radius());
1469 const Standard_Real anArrPeriods[4] = {theS1->IsUPeriodic() ? theS1->UPeriod() : 0.0,
1470 theS1->IsVPeriodic() ? theS1->VPeriod() : 0.0,
1471 theS2->IsUPeriodic() ? theS2->UPeriod() : 0.0,
1472 theS2->IsVPeriodic() ? theS2->VPeriod() : 0.0};
1474 const Standard_Real anArrFBonds[4] = {theS1->FirstUParameter(), theS1->FirstVParameter(),
1475 theS2->FirstUParameter(), theS2->FirstVParameter()};
1476 const Standard_Real anArrLBonds[4] = {theS1->LastUParameter(), theS1->LastVParameter(),
1477 theS2->LastUParameter(), theS2->LastVParameter()};
1479 Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator();
1481 for(Standard_Integer aN1 = 1; aN1 <= theSlin.Length(); aN1++)
1483 Handle(IntPatch_WLine) aWLine1(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aN1)));
1485 if(aWLine1.IsNull())
1486 {//We must have failed to join not-point-lines
1490 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
1491 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1492 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
1494 for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
1496 const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
1498 if( aPntCur.IsSame(aPntFWL1, Precision::Confusion()) ||
1499 aPntCur.IsSame(aPntLWL1, Precision::Confusion()))
1501 theSPnt.Remove(aNPt);
1507 NCollection_List<Standard_Integer> aListFC(anAlloc),
1510 Standard_Boolean isFirstConnected = Standard_False, isLastConnected = Standard_False;
1512 for (Standard_Integer aN2 = 1; aN2 <= theSlin.Length(); aN2++)
1517 Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aN2)));
1519 if (aWLine2.IsNull())
1522 isFirstConnected = isLastConnected = Standard_False;
1524 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1526 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1527 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1529 Standard_Real aSqDistF = aPntFWL1.Value().SquareDistance(aPntFWL2.Value());
1530 Standard_Real aSqDistL = aPntFWL1.Value().SquareDistance(aPntLWL2.Value());
1532 const Standard_Real aSqMinFDist = Min(aSqDistF, aSqDistL);
1533 if (aSqMinFDist < Precision::SquareConfusion())
1535 const Standard_Boolean isFM = (aSqDistF < aSqDistL);
1536 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
1537 const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
1538 aWLine2->Point(aNbPntsWL2 - 1);
1539 if (!IsSeamOrBound(aPt1, aPt2, aPntFWL1,
1540 anArrPeriods, anArrFBonds, anArrLBonds))
1542 isFirstConnected = Standard_True;
1546 aSqDistF = aPntLWL1.Value().SquareDistance(aPntFWL2.Value());
1547 aSqDistL = aPntLWL1.Value().SquareDistance(aPntLWL2.Value());
1549 const Standard_Real aSqMinLDist = Min(aSqDistF, aSqDistL);
1550 if (aSqMinLDist < Precision::SquareConfusion())
1552 const Standard_Boolean isFM = (aSqDistF < aSqDistL);
1553 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1 - 1);
1554 const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
1555 aWLine2->Point(aNbPntsWL2 - 1);
1556 if (!IsSeamOrBound(aPt1, aPt2, aPntLWL1,
1557 anArrPeriods, anArrFBonds, anArrLBonds))
1559 isLastConnected = Standard_True;
1563 if (isFirstConnected && isLastConnected)
1565 if (aSqMinFDist < aSqMinLDist)
1567 aListFC.Append(aN2);
1571 aListLC.Append(aN2);
1574 else if (isFirstConnected)
1576 aListFC.Append(aN2);
1578 else if (isLastConnected)
1580 aListLC.Append(aN2);
1584 isFirstConnected = (aListFC.Extent() == 1);
1585 isLastConnected = (aListLC.Extent() == 1);
1587 if (!(isFirstConnected || isLastConnected))
1592 const Standard_Integer anIndexWL2 = isFirstConnected ? aListFC.First() : aListLC.First();
1593 Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(anIndexWL2)));
1594 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1595 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1596 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1598 if (isFirstConnected)
1600 const Standard_Real aSqDistF = aPntFWL1.Value().SquareDistance(aPntFWL2.Value());
1601 const Standard_Real aSqDistL = aPntFWL1.Value().SquareDistance(aPntLWL2.Value());
1602 const Standard_Boolean isFM = (aSqDistF < aSqDistL);
1604 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
1605 const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
1606 aWLine2->Point(aNbPntsWL2 - 1);
1608 if (!CheckArgumentsToJoin(theS1, theS2, aPntFWL1, aPt1.Value(),
1609 aPntFWL1.Value(), aPt2.Value(), aMinRad))
1614 aWLine1->ClearVertexes();
1618 //First-First-connection
1619 for (Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
1621 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1622 aWLine1->Curve()->InsertBefore(1, aPt);
1627 //First-Last-connection
1628 for (Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
1630 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1631 aWLine1->Curve()->InsertBefore(1, aPt);
1635 else //if (isLastConnected)
1637 const Standard_Real aSqDistF = aPntLWL1.Value().SquareDistance(aPntFWL2.Value());
1638 const Standard_Real aSqDistL = aPntLWL1.Value().SquareDistance(aPntLWL2.Value());
1640 const Standard_Boolean isFM = (aSqDistF < aSqDistL);
1641 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1 - 1);
1642 const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
1643 aWLine2->Point(aNbPntsWL2 - 1);
1645 if (!CheckArgumentsToJoin(theS1, theS2, aPntLWL1, aPt1.Value(),
1646 aPntLWL1.Value(), aPt2.Value(), aMinRad))
1651 aWLine1->ClearVertexes();
1655 //Last-First connection
1656 for (Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
1658 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1659 aWLine1->Curve()->Add(aPt);
1664 //Last-Last connection
1665 for (Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
1667 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1668 aWLine1->Curve()->Add(aPt);
1673 aWLine1->ComputeVertexParameters(theTol3D);
1674 theSlin.Remove(anIndexWL2);
1679 //=======================================================================
1680 //function : ExtendTwoWLines
1681 //purpose : Performs extending theWLine1 and theWLine2 through their
1682 // respecting end point.
1683 //=======================================================================
1684 void IntPatch_WLineTool::
1685 ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin,
1686 const Handle(Adaptor3d_HSurface)& theS1,
1687 const Handle(Adaptor3d_HSurface)& theS2,
1688 const Standard_Real theToler3D,
1689 const Standard_Real* const theArrPeriods,
1690 const Bnd_Box2d& theBoxS1,
1691 const Bnd_Box2d& theBoxS2,
1692 const NCollection_List<gp_Pnt>& theListOfCriticalPoints)
1694 if(theSlin.Length() < 2)
1697 gp_Vec aVec1, aVec2, aVec3;
1699 for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
1701 Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::
1702 DownCast(theSlin.Value(aNumOfLine1)));
1704 if(aWLine1.IsNull())
1705 {//We must have failed to join not-point-lines
1709 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
1711 if(aWLine1->Vertex(1).ParameterOnLine() != 1)
1714 if(aWLine1->Vertex(aWLine1->NbVertex()).ParameterOnLine() != aWLine1->NbPnts())
1717 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1718 const IntSurf_PntOn2S& aPntFp1WL1 = aWLine1->Point(2);
1720 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
1721 const IntSurf_PntOn2S& aPntLm1WL1 = aWLine1->Point(aNbPntsWL1-1);
1723 //Enable/Disable of some ckeck. Bit-mask is used for it.
1724 //E.g. if 1st point of aWLine1 matches with
1725 //1st point of aWLine2 then we do not need in check
1726 //1st point of aWLine1 and last point of aWLine2 etc.
1727 unsigned int aCheckResult = IntPatchWT_EnAll;
1729 //If aWLine1 is already connected with another Wline then
1730 //there is no point in extending.
1731 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
1732 aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1734 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::
1735 DownCast(theSlin.Value(aNumOfLine2)));
1737 if(aWLine2.IsNull())
1740 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1741 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aWLine2->NbPnts());
1743 if( aPntFWL1.IsSame(aPntFWL2, theToler3D) ||
1744 aPntFWL1.IsSame(aPntLWL2, theToler3D) )
1746 aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast;
1749 if( aPntLWL1.IsSame(aPntFWL2, theToler3D) ||
1750 aPntLWL1.IsSame(aPntFWL2, theToler3D))
1752 aCheckResult |= IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast;
1755 if (!theListOfCriticalPoints.IsEmpty())
1757 for (NCollection_List<gp_Pnt>::Iterator anItr(theListOfCriticalPoints);
1758 anItr.More(); anItr.Next())
1760 const gp_Pnt &aPt = anItr.Value();
1761 if (!(aCheckResult & (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast)))
1763 if (aPt.SquareDistance(aPntFWL1.Value()) < Precision::Confusion())
1765 aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast;
1769 if (!(aCheckResult & (IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast)))
1771 if (aPt.SquareDistance(aPntLWL1.Value()) < Precision::Confusion())
1773 aCheckResult |= IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast;
1777 if (!(aCheckResult & (IntPatchWT_DisFirstFirst | IntPatchWT_DisLastFirst)))
1779 if (aPt.SquareDistance(aPntFWL2.Value()) < Precision::Confusion())
1781 aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisLastFirst;
1785 if (!(aCheckResult & (IntPatchWT_DisFirstLast | IntPatchWT_DisLastLast)))
1787 if (aPt.SquareDistance(aPntLWL2.Value()) < Precision::Confusion())
1789 aCheckResult |= IntPatchWT_DisFirstLast | IntPatchWT_DisLastLast;
1796 if(aCheckResult == (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast |
1797 IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast))
1800 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
1801 aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1803 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::
1804 DownCast(theSlin.Value(aNumOfLine2)));
1806 if(aWLine2.IsNull())
1809 if(aWLine2->Vertex(1).ParameterOnLine() != 1)
1812 if(aWLine2->Vertex(aWLine2->NbVertex()).ParameterOnLine() != aWLine2->NbPnts())
1815 Standard_Boolean hasBeenJoined = Standard_False;
1817 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1819 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1820 const IntSurf_PntOn2S& aPntFp1WL2 = aWLine2->Point(2);
1822 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1823 const IntSurf_PntOn2S& aPntLm1WL2 = aWLine2->Point(aNbPntsWL2-1);
1825 //if(!(aCheckResult & IntPatchWT_DisFirstFirst))
1827 aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
1828 aVec2.SetXYZ(aPntFWL2.Value().XYZ() - aPntFp1WL2.Value().XYZ());
1829 aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntFWL2.Value().XYZ());
1831 ExtendTwoWLFirstFirst(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntFWL2,
1832 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1833 theArrPeriods, aCheckResult, hasBeenJoined);
1836 if(!(aCheckResult & IntPatchWT_DisFirstLast))
1838 aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
1839 aVec2.SetXYZ(aPntLWL2.Value().XYZ() - aPntLm1WL2.Value().XYZ());
1840 aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntLWL2.Value().XYZ());
1842 ExtendTwoWLFirstLast(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntLWL2,
1843 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1844 theArrPeriods, aCheckResult, hasBeenJoined);
1847 if(!(aCheckResult & IntPatchWT_DisLastFirst))
1849 aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
1850 aVec2.SetXYZ(aPntFp1WL2.Value().XYZ() - aPntFWL2.Value().XYZ());
1851 aVec3.SetXYZ(aPntFWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
1853 ExtendTwoWLLastFirst(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntFWL2,
1854 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1855 theArrPeriods, aCheckResult, hasBeenJoined);
1858 if(!(aCheckResult & IntPatchWT_DisLastLast))
1860 aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
1861 aVec2.SetXYZ(aPntLm1WL2.Value().XYZ() - aPntLWL2.Value().XYZ());
1862 aVec3.SetXYZ(aPntLWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
1864 ExtendTwoWLLastLast(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntLWL2,
1865 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1866 theArrPeriods, aCheckResult, hasBeenJoined);
1871 theSlin.Remove(aNumOfLine2);