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>
20 #include <IntPatch_SpecialPoints.hxx>
22 // It is pure empirical value.
23 const Standard_Real IntPatch_WLineTool::myMaxConcatAngle = M_PI/6;
25 //Bit-mask is used for information about
26 //the operation made in
27 //IntPatch_WLineTool::ExtendTwoWLines(...) method.
30 IntPatchWT_EnAll = 0x00,
31 IntPatchWT_DisLastLast = 0x01,
32 IntPatchWT_DisLastFirst = 0x02,
33 IntPatchWT_DisFirstLast = 0x04,
34 IntPatchWT_DisFirstFirst = 0x08
37 enum IntPatchWT_WLsConnectionType
39 IntPatchWT_NotConnected,
44 //=======================================================================
46 //purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
47 // theParMAX = MAX(theParMIN, theParMAX).
49 // Static subfunction in IsSeamOrBound.
50 //=======================================================================
51 static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
53 if(theParMIN > theParMAX)
55 const Standard_Real aTmp = theParMAX;
56 theParMAX = theParMIN;
61 //=========================================================================
62 // function : FillPointsHash
63 // purpose : Fill points hash by input data.
64 // Static subfunction in ComputePurgedWLine.
65 //=========================================================================
66 static void FillPointsHash(const Handle(IntPatch_WLine) &theWLine,
67 NCollection_Array1<Standard_Integer> &thePointsHash)
71 // -1 - Vertex point (not delete).
72 Standard_Integer i, v;
74 for(i = 1; i <= theWLine->NbPnts(); i++)
75 thePointsHash.SetValue(i, 0);
77 for(v = 1; v <= theWLine->NbVertex(); v++)
79 IntPatch_Point aVertex = theWLine->Vertex(v);
80 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
81 thePointsHash.SetValue(avertexindex, -1);
85 //=========================================================================
86 // function : MakeNewWLine
87 // purpose : Makes new walking line according to the points hash
88 // Static subfunction in ComputePurgedWLine and DeleteOuter.
89 //=========================================================================
90 static Handle(IntPatch_WLine) MakeNewWLine(const Handle(IntPatch_WLine) &theWLine,
91 const NCollection_Array1<Standard_Integer> &thePointsHash)
95 Handle(IntSurf_LineOn2S) aPurgedLineOn2S = new IntSurf_LineOn2S();
96 Handle(IntPatch_WLine) aLocalWLine = new IntPatch_WLine(aPurgedLineOn2S, Standard_False);
97 Standard_Integer anOldLineIdx = 1, aVertexIdx = 1;
98 for(i = 1; i <= thePointsHash.Upper(); i++)
100 if (thePointsHash(i) == 0)
103 aPurgedLineOn2S->Add(theWLine->Point(i));
106 else if (thePointsHash(i) == -1)
109 IntPatch_Point aVertex = theWLine->Vertex(aVertexIdx++);
110 aVertex.SetParameter(anOldLineIdx++);
111 aLocalWLine->AddVertex(aVertex);
112 aPurgedLineOn2S->Add(theWLine->Point(i));
119 //=========================================================================
120 // function : MovePoint
121 // purpose : Move point into surface param space. No interpolation used
122 // because walking algorithm should care for closeness to the param space.
123 // Static subfunction in ComputePurgedWLine.
124 //=========================================================================
125 static void MovePoint(const Handle(Adaptor3d_HSurface) &theS1,
126 Standard_Real &U1, Standard_Real &V1)
128 if (U1 < theS1->FirstUParameter())
129 U1 = theS1->FirstUParameter();
131 if (U1 > theS1->LastUParameter())
132 U1 = theS1->LastUParameter();
134 if (V1 < theS1->FirstVParameter())
135 V1 = theS1->FirstVParameter();
137 if (V1 > theS1->LastVParameter())
138 V1 = theS1->LastVParameter();
141 //=========================================================================
142 // function : DeleteOuterPoints
143 // purpose : Check and delete out of bounds points on walking line.
144 // Static subfunction in ComputePurgedWLine.
145 //=========================================================================
146 static Handle(IntPatch_WLine)
147 DeleteOuterPoints(const Handle(IntPatch_WLine) &theWLine,
148 const Handle(Adaptor3d_HSurface) &theS1,
149 const Handle(Adaptor3d_HSurface) &theS2,
150 const Handle(Adaptor3d_TopolTool) &theDom1,
151 const Handle(Adaptor3d_TopolTool) &theDom2)
155 NCollection_Array1<Standard_Integer> aDelOuterPointsHash(1, theWLine->NbPnts());
156 FillPointsHash(theWLine, aDelOuterPointsHash);
158 if (theS1->IsUPeriodic() || theS1->IsVPeriodic() ||
159 theS2->IsUPeriodic() || theS2->IsVPeriodic() )
162 gp_Pnt2d aPntOnF1, aPntOnF2;
163 Standard_Real aX1, aY1, aX2, aY2;
165 // Iterate over points in walking line and delete which are out of bounds.
167 Standard_Boolean isAllDeleted = Standard_True;
168 Standard_Boolean aChangedFirst = Standard_False;
169 Standard_Integer aFirstGeomIdx = 1;
170 for(i = 1; i <= theWLine->NbPnts(); i++)
172 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
173 aPntOnF1.SetCoord(aX1, aY1);
174 aPntOnF2.SetCoord(aX2, aY2);
176 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
177 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
179 if (aState1 == TopAbs_OUT ||
180 aState2 == TopAbs_OUT )
182 aDelOuterPointsHash(i) = 1;
183 aChangedFirst = Standard_True;
187 isAllDeleted = Standard_False;
189 aFirstGeomIdx = Max (i - 1, 1);
190 if (aDelOuterPointsHash(i) == -1)
191 aFirstGeomIdx = i; // Use data what lies in (i) point / vertex.
193 aDelOuterPointsHash(i) = -1;
200 // ALL points are out of bounds:
201 // case boolean bcut_complex F5 and similar.
206 Standard_Boolean aChangedLast = Standard_False;
207 Standard_Integer aLastGeomIdx = theWLine->NbPnts();
208 for(i = theWLine->NbPnts(); i >= 1; i--)
210 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
211 aPntOnF1.SetCoord(aX1, aY1);
212 aPntOnF2.SetCoord(aX2, aY2);
214 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
215 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
217 if (aState1 == TopAbs_OUT ||
218 aState2 == TopAbs_OUT )
220 aDelOuterPointsHash(i) = 1;
221 aChangedLast = Standard_True; // Move vertex to first good point
225 aLastGeomIdx = Min (i + 1, theWLine->NbPnts());
226 if (aDelOuterPointsHash(i) == -1)
227 aLastGeomIdx = i; // Use data what lies in (i) point / vertex.
229 aDelOuterPointsHash(i) = -1;
234 if (!aChangedFirst && !aChangedLast)
236 // Nothing is done, return input.
240 // Build new line and modify geometry of necessary vertexes.
241 Handle(IntPatch_WLine) aLocalWLine = MakeNewWLine(theWLine, aDelOuterPointsHash);
246 IntPatch_Point aVertex = aLocalWLine->Vertex(1);
247 aVertex.SetValue(theWLine->Point(aFirstGeomIdx).Value());
248 Standard_Real aU1, aU2, aV1, aV2;
249 theWLine->Point(aFirstGeomIdx).Parameters(aU1, aV1, aU2, aV2);
250 MovePoint(theS1, aU1, aV1);
251 MovePoint(theS2, aU2, aV2);
252 aVertex.SetParameters(aU1, aV1, aU2, aV2);
253 aLocalWLine->Replace(1, aVertex);
254 // Change point in walking line.
255 aLocalWLine->SetPoint(1, aVertex);
261 IntPatch_Point aVertex = aLocalWLine->Vertex(aLocalWLine->NbVertex());
262 aVertex.SetValue(theWLine->Point(aLastGeomIdx).Value());
263 Standard_Real aU1, aU2, aV1, aV2;
264 theWLine->Point(aLastGeomIdx).Parameters(aU1, aV1, aU2, aV2);
265 MovePoint(theS1, aU1, aV1);
266 MovePoint(theS2, aU2, aV2);
267 aVertex.SetParameters(aU1, aV1, aU2, aV2);
268 aLocalWLine->Replace(aLocalWLine->NbVertex(), aVertex);
269 // Change point in walking line.
270 aLocalWLine->SetPoint(aLocalWLine->NbPnts(), aVertex);
277 //=========================================================================
278 // function : IsInsideIn2d
279 // purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
280 // In 2d space. Static subfunction in DeleteByTube.
281 //=========================================================================
282 static Standard_Boolean IsInsideIn2d(const gp_Pnt2d& aBasePnt,
283 const gp_Vec2d& aBaseVec,
284 const gp_Pnt2d& aNextPnt,
285 const Standard_Real aSquareMaxDist)
287 gp_Vec2d aVec2d(aBasePnt, aNextPnt);
289 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
290 Standard_Real aCross = aVec2d.Crossed(aBaseVec);
291 Standard_Real aSquareDist = aCross * aCross
292 / aBaseVec.SquareMagnitude();
294 return (aSquareDist <= aSquareMaxDist);
297 //=========================================================================
298 // function : IsInsideIn3d
299 // purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
300 // In 3d space. Static subfunction in DeleteByTube.
301 //=========================================================================
302 static Standard_Boolean IsInsideIn3d(const gp_Pnt& aBasePnt,
303 const gp_Vec& aBaseVec,
304 const gp_Pnt& aNextPnt,
305 const Standard_Real aSquareMaxDist)
307 gp_Vec aVec(aBasePnt, aNextPnt);
309 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
310 Standard_Real aSquareDist = aVec.CrossSquareMagnitude(aBaseVec)
311 / aBaseVec.SquareMagnitude();
313 return (aSquareDist <= aSquareMaxDist);
316 static const Standard_Integer aMinNbBadDistr = 15;
317 static const Standard_Integer aNbSingleBezier = 30;
319 //=========================================================================
320 // function : DeleteByTube
321 // purpose : Check and delete points using tube criteria.
322 // Static subfunction in ComputePurgedWLine.
323 //=========================================================================
324 static Handle(IntPatch_WLine)
325 DeleteByTube(const Handle(IntPatch_WLine) &theWLine,
326 const Handle(Adaptor3d_HSurface) &theS1,
327 const Handle(Adaptor3d_HSurface) &theS2)
329 // III: Check points for tube criteria:
330 // Workaround to handle case of small amount points after purge.
331 // Test "boolean boptuc_complex B5" and similar.
332 Standard_Integer aNbPnt = 0 , i;
334 if (theWLine->NbPnts() <= 2)
337 NCollection_Array1<Standard_Integer> aNewPointsHash(1, theWLine->NbPnts());
338 FillPointsHash(theWLine, aNewPointsHash);
340 // Inital computations.
341 Standard_Real UonS1[3], VonS1[3], UonS2[3], VonS2[3];
342 theWLine->Point(1).ParametersOnS1(UonS1[0], VonS1[0]);
343 theWLine->Point(2).ParametersOnS1(UonS1[1], VonS1[1]);
344 theWLine->Point(1).ParametersOnS2(UonS2[0], VonS2[0]);
345 theWLine->Point(2).ParametersOnS2(UonS2[1], VonS2[1]);
347 gp_Pnt2d aBase2dPnt1(UonS1[0], VonS1[0]);
348 gp_Pnt2d aBase2dPnt2(UonS2[0], VonS2[0]);
349 gp_Vec2d aBase2dVec1(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
350 gp_Vec2d aBase2dVec2(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
351 gp_Pnt aBase3dPnt = theWLine->Point(1).Value();
352 gp_Vec aBase3dVec(theWLine->Point(1).Value(), theWLine->Point(2).Value());
354 // Choose base tolerance and scale it to pipe algorithm.
355 const Standard_Real aBaseTolerance = Precision::Approximation();
356 Standard_Real aResS1Tol = Min(theS1->UResolution(aBaseTolerance),
357 theS1->VResolution(aBaseTolerance));
358 Standard_Real aResS2Tol = Min(theS2->UResolution(aBaseTolerance),
359 theS2->VResolution(aBaseTolerance));
360 Standard_Real aTol1 = aResS1Tol * aResS1Tol;
361 Standard_Real aTol2 = aResS2Tol * aResS2Tol;
362 Standard_Real aTol3d = aBaseTolerance * aBaseTolerance;
364 const Standard_Real aLimitCoeff = 0.99 * 0.99;
365 for(i = 3; i <= theWLine->NbPnts(); i++)
367 Standard_Boolean isDeleteState = Standard_False;
369 theWLine->Point(i).ParametersOnS1(UonS1[2], VonS1[2]);
370 theWLine->Point(i).ParametersOnS2(UonS2[2], VonS2[2]);
371 gp_Pnt2d aPnt2dOnS1(UonS1[2], VonS1[2]);
372 gp_Pnt2d aPnt2dOnS2(UonS2[2], VonS2[2]);
373 const gp_Pnt& aPnt3d = theWLine->Point(i).Value();
375 if (aNewPointsHash(i - 1) != - 1 &&
376 IsInsideIn2d(aBase2dPnt1, aBase2dVec1, aPnt2dOnS1, aTol1) &&
377 IsInsideIn2d(aBase2dPnt2, aBase2dVec2, aPnt2dOnS2, aTol2) &&
378 IsInsideIn3d(aBase3dPnt, aBase3dVec, aPnt3d, aTol3d) )
380 // Handle possible uneven parametrization on one of 2d subspaces.
381 // Delete point only when expected lengths are close to each other (aLimitCoeff).
385 // c2d2 - geometrically line, but have uneven parametrization -> c2d2 is bspline.
386 gp_XY aPntOnS1[2]= { gp_XY(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0])
387 , gp_XY(UonS1[2] - UonS1[1], VonS1[2] - VonS1[1])};
388 gp_XY aPntOnS2[2]= { gp_XY(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0])
389 , gp_XY(UonS2[2] - UonS2[1], VonS2[2] - VonS2[1])};
391 Standard_Real aStepOnS1 = aPntOnS1[0].SquareModulus() / aPntOnS1[1].SquareModulus();
392 Standard_Real aStepOnS2 = aPntOnS2[0].SquareModulus() / aPntOnS2[1].SquareModulus();
394 // Check very rare case when wline fluctuates nearly one point and some of them may be equal.
395 // Middle point will be deleted when such situation occurs.
396 // bugs moddata_2 bug469.
397 if (Min(aStepOnS1, aStepOnS2) >= aLimitCoeff * Max(aStepOnS1, aStepOnS2))
399 // Set hash flag to "Delete" state.
400 isDeleteState = Standard_True;
401 aNewPointsHash.SetValue(i - 1, 1);
403 // Change middle point.
413 // Compute new pipe parameters.
424 aBase2dPnt1.SetCoord(UonS1[0], VonS1[0]);
425 aBase2dPnt2.SetCoord(UonS2[0], VonS2[0]);
426 aBase2dVec1.SetCoord(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
427 aBase2dVec2.SetCoord(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
428 aBase3dPnt = theWLine->Point(i - 1).Value();
429 aBase3dVec = gp_Vec(theWLine->Point(i - 1).Value(), theWLine->Point(i).Value());
435 // Workaround to handle case of small amount of points after purge.
436 // Test "boolean boptuc_complex B5" and similar.
437 // This is possible since there are at least two points.
438 if (aNewPointsHash(1) == -1 &&
439 aNewPointsHash(2) == -1 &&
443 aNewPointsHash(1) = 1;
445 if (aNewPointsHash(theWLine->NbPnts() - 1) == -1 &&
446 aNewPointsHash(theWLine->NbPnts() ) == -1 &&
450 aNewPointsHash(theWLine->NbPnts()) = 1;
453 // Purgre when too small amount of points left.
456 for(i = aNewPointsHash.Lower(); i <= aNewPointsHash.Upper(); i++)
458 if (aNewPointsHash(i) != -1)
460 aNewPointsHash(i) = 1;
465 // Handle possible bad distribution of points,
466 // which are will converted into one single bezier curve (less than 30 points).
467 // Make distribution more even:
468 // max step will be nearly to 0.1 of param distance.
469 if (aNbPnt + 2 > aMinNbBadDistr &&
470 aNbPnt + 2 < aNbSingleBezier )
472 for(Standard_Integer anIdx = 1; anIdx <= 8; anIdx++)
474 Standard_Integer aHashIdx =
475 Standard_Integer(anIdx * theWLine->NbPnts() / 9);
477 //Vertex must be stored as VERTEX (HASH = -1)
478 if (aNewPointsHash(aHashIdx) != -1)
479 aNewPointsHash(aHashIdx) = 0;
483 return MakeNewWLine(theWLine, aNewPointsHash);
486 //=======================================================================
487 //function : IsOnPeriod
488 //purpose : Checks, if [theU1, theU2] intersects the period-value
489 // (k*thePeriod, where k is an integer number (k = 0, +/-1, +/-2, ...).
492 // 0 - if interval [theU1, theU2] does not intersect the "period-value"
493 // or if thePeriod == 0.0;
494 // 1 - if interval (theU1, theU2) intersect the "period-value".
495 // 2 - if theU1 or/and theU2 lie ON the "period-value"
498 // If (theU1 == theU2) then this function will return only both 0 or 2.
499 //=======================================================================
500 static Standard_Integer IsOnPeriod(const Standard_Real theU1,
501 const Standard_Real theU2,
502 const Standard_Real thePeriod)
504 if(thePeriod < RealSmall())
507 //If interval [theU1, theU2] intersect seam-edge then there exists an integer
509 // (theU1 <= T*N <= theU2) <=> (theU1/T <= N <= theU2/T),
510 //where T is the period.
511 //I.e. the inerval [theU1/T, theU2/T] must contain at least one
512 //integer number. In this case, Floor(theU1/T) and Floor(theU2/T)
513 //return different values or theU1/T is strictly integer number.
515 // 1. theU1/T==2.8, theU2/T==3.5 => Floor(theU1/T) == 2, Floor(theU2/T) == 3.
516 // 2. theU1/T==2.0, theU2/T==2.6 => Floor(theU1/T) == Floor(theU2/T) == 2.
518 const Standard_Real aVal1 = theU1/thePeriod,
519 aVal2 = theU2/thePeriod;
520 const Standard_Integer aPar1 = static_cast<Standard_Integer>(Floor(aVal1));
521 const Standard_Integer aPar2 = static_cast<Standard_Integer>(Floor(aVal2));
523 {//Interval (theU1, theU2] intersects seam-edge
524 if(IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
525 {//aVal2 is an integer number => theU2 lies ON the "seam-edge"
532 //Here, aPar1 == aPar2.
534 if(IsEqual(aVal1, static_cast<Standard_Real>(aPar1)))
535 {//aVal1 is an integer number => theU1 lies ON the "seam-edge"
539 //If aVal2 is a true integer number then always (aPar1 != aPar2).
544 //=======================================================================
545 //function : IsSeamOrBound
546 //purpose : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
547 // (if it exist) or surface boundaries and both thePtf and thePtl do
548 // not match "seam-edge" or boundaries.
549 // Point thePtmid lies in this segment (in both 3D and 2D-space).
550 // If thePtmid match "seam-edge" or boundaries strictly
551 // (without any tolerance) then the function will return TRUE.
552 // See comments in function body for detail information.
553 //=======================================================================
554 static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
555 const IntSurf_PntOn2S& thePtl,
556 const IntSurf_PntOn2S& thePtmid,
557 const Standard_Real theU1Period,
558 const Standard_Real theU2Period,
559 const Standard_Real theV1Period,
560 const Standard_Real theV2Period,
561 const Standard_Real theUfSurf1,
562 const Standard_Real theUlSurf1,
563 const Standard_Real theVfSurf1,
564 const Standard_Real theVlSurf1,
565 const Standard_Real theUfSurf2,
566 const Standard_Real theUlSurf2,
567 const Standard_Real theVfSurf2,
568 const Standard_Real theVlSurf2)
570 Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
571 Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
572 thePtf.Parameters(aU11, aV11, aU12, aV12);
573 thePtl.Parameters(aU21, aV21, aU22, aV22);
580 if((aU11 - theUfSurf1)*(aU21 - theUfSurf1) < 0.0)
581 {//Interval [aU11, aU21] intersects theUfSurf1
582 return Standard_True;
585 if((aU11 - theUlSurf1)*(aU21 - theUlSurf1) < 0.0)
586 {//Interval [aU11, aU21] intersects theUlSurf1
587 return Standard_True;
590 if((aV11 - theVfSurf1)*(aV21 - theVfSurf1) < 0.0)
591 {//Interval [aV11, aV21] intersects theVfSurf1
592 return Standard_True;
595 if((aV11 - theVlSurf1)*(aV21 - theVlSurf1) < 0.0)
596 {//Interval [aV11, aV21] intersects theVlSurf1
597 return Standard_True;
600 if((aU12 - theUfSurf2)*(aU22 - theUfSurf2) < 0.0)
601 {//Interval [aU12, aU22] intersects theUfSurf2
602 return Standard_True;
605 if((aU12 - theUlSurf2)*(aU22 - theUlSurf2) < 0.0)
606 {//Interval [aU12, aU22] intersects theUlSurf2
607 return Standard_True;
610 if((aV12 - theVfSurf2)*(aV22 - theVfSurf2) < 0.0)
611 {//Interval [aV12, aV22] intersects theVfSurf2
612 return Standard_True;
615 if((aV12 - theVlSurf2)*(aV22 - theVlSurf2) < 0.0)
616 {//Interval [aV12, aV22] intersects theVlSurf2
617 return Standard_True;
620 if(IsOnPeriod(aU11, aU21, theU1Period))
621 return Standard_True;
623 if(IsOnPeriod(aV11, aV21, theV1Period))
624 return Standard_True;
626 if(IsOnPeriod(aU12, aU22, theU2Period))
627 return Standard_True;
629 if(IsOnPeriod(aV12, aV22, theV2Period))
630 return Standard_True;
633 The segment [thePtf, thePtl] does not intersect the boundaries and
634 the seam-edge of the surfaces.
635 Nevertheless, following situation is possible:
646 This case must be processed, too.
649 Standard_Real aU1 = 0.0, aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
650 thePtmid.Parameters(aU1, aV1, aU2, aV2);
652 if(IsEqual(aU1, theUfSurf1) || IsEqual(aU1, theUlSurf1))
653 return Standard_True;
655 if(IsEqual(aU2, theUfSurf2) || IsEqual(aU2, theUlSurf2))
656 return Standard_True;
658 if(IsEqual(aV1, theVfSurf1) || IsEqual(aV1, theVlSurf1))
659 return Standard_True;
661 if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2))
662 return Standard_True;
664 if(IsOnPeriod(aU1, aU1, theU1Period))
665 return Standard_True;
667 if(IsOnPeriod(aU2, aU2, theU2Period))
668 return Standard_True;
670 if(IsOnPeriod(aV1, aV1, theV1Period))
671 return Standard_True;
673 if(IsOnPeriod(aV2, aV2, theV2Period))
674 return Standard_True;
676 return Standard_False;
679 //=======================================================================
680 //function : IsIntersectionPoint
681 //purpose : Returns True if thePmid is intersection point
682 // between theS1 and theS2 with given tolerance.
683 // In this case, parameters of thePmid on every quadric
684 // will be recomputed and returned.
685 //=======================================================================
686 static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid,
687 const Handle(Adaptor3d_HSurface)& theS1,
688 const Handle(Adaptor3d_HSurface)& theS2,
689 const IntSurf_PntOn2S& theRefPt,
690 const Standard_Real theTol,
691 const Standard_Real* const theArrPeriods,
692 IntSurf_PntOn2S& theNewPt)
694 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
696 switch(theS1->GetType())
699 ElSLib::Parameters(theS1->Plane(), thePmid, aU1, aV1);
702 case GeomAbs_Cylinder:
703 ElSLib::Parameters(theS1->Cylinder(), thePmid, aU1, aV1);
707 ElSLib::Parameters(theS1->Sphere(), thePmid, aU1, aV1);
711 ElSLib::Parameters(theS1->Cone(), thePmid, aU1, aV1);
715 ElSLib::Parameters(theS1->Torus(), thePmid, aU1, aV1);
719 return Standard_False;
722 switch(theS2->GetType())
725 ElSLib::Parameters(theS2->Plane(), thePmid, aU2, aV2);
728 case GeomAbs_Cylinder:
729 ElSLib::Parameters(theS2->Cylinder(), thePmid, aU2, aV2);
733 ElSLib::Parameters(theS2->Sphere(), thePmid, aU2, aV2);
737 ElSLib::Parameters(theS2->Cone(), thePmid, aU2, aV2);
741 ElSLib::Parameters(theS2->Torus(), thePmid, aU2, aV2);
745 return Standard_False;
748 theNewPt.SetValue(thePmid, aU1, aV1, aU2, aV2);
750 IntPatch_SpecialPoints::AdjustPointAndVertex(theRefPt, theArrPeriods, theNewPt);
752 const gp_Pnt aP1(theS1->Value(aU1, aV1));
753 const gp_Pnt aP2(theS2->Value(aU2, aV2));
755 return (aP1.SquareDistance(aP2) <= theTol*theTol);
758 //=======================================================================
759 //function : ExtendFirst
760 //purpose : Adds thePOn2S to the begin of theWline
761 //=======================================================================
762 static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
763 const IntSurf_PntOn2S& theAddedPt)
765 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
766 theAddedPt.Parameters(aU1, aV1, aU2, aV2);
768 if(theAddedPt.IsSame(theWline->Point(1), Precision::Confusion()))
770 theWline->Curve()->Value(1, theAddedPt);
771 for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
773 IntPatch_Point &aVert = theWline->ChangeVertex(i);
774 if(aVert.ParameterOnLine() != 1)
777 aVert.SetParameters(aU1, aV1, aU2, aV2);
778 aVert.SetValue(theAddedPt.Value());
784 theWline->Curve()->InsertBefore(1, theAddedPt);
786 for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
788 IntPatch_Point &aVert = theWline->ChangeVertex(i);
790 if(aVert.ParameterOnLine() == 1)
792 aVert.SetParameters(aU1, aV1, aU2, aV2);
793 aVert.SetValue(theAddedPt.Value());
797 aVert.SetParameter(aVert.ParameterOnLine()+1);
802 //=======================================================================
803 //function : ExtendLast
804 //purpose : Adds thePOn2S to the end of theWline
805 //=======================================================================
806 static void ExtendLast(const Handle(IntPatch_WLine)& theWline,
807 const IntSurf_PntOn2S& theAddedPt)
809 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
810 theAddedPt.Parameters(aU1, aV1, aU2, aV2);
812 const Standard_Integer aNbPnts = theWline->NbPnts();
813 if(theAddedPt.IsSame(theWline->Point(aNbPnts), Precision::Confusion()))
815 theWline->Curve()->Value(aNbPnts, theAddedPt);
819 theWline->Curve()->Add(theAddedPt);
822 for(Standard_Integer i = theWline->NbVertex(); i >= 1; i--)
824 IntPatch_Point &aVert = theWline->ChangeVertex(i);
825 if(aVert.ParameterOnLine() != aNbPnts)
828 aVert.SetParameters(aU1, aV1, aU2, aV2);
829 aVert.SetValue(theAddedPt.Value());
830 aVert.SetParameter(theWline->NbPnts());
834 //=========================================================================
835 // function: IsOutOfDomain
836 // purpose : Checks, if 2D-representation of thePOn2S is in surfaces domain,
837 // defined by bounding-boxes theBoxS1 and theBoxS2
838 //=========================================================================
839 static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1,
840 const Bnd_Box2d& theBoxS2,
841 const IntSurf_PntOn2S &thePOn2S,
842 const Standard_Real* const theArrPeriods)
844 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
845 Standard_Real aU1min = 0.0, aU1max = 0.0, aV1min = 0.0, aV1max = 0.0;
846 Standard_Real aU2min = 0.0, aU2max = 0.0, aV2min = 0.0, aV2max = 0.0;
848 thePOn2S.Parameters(aU1, aV1, aU2, aV2);
850 theBoxS1.Get(aU1min, aV1min, aU1max, aV1max);
851 theBoxS2.Get(aU2min, aV2min, aU2max, aV2max);
853 aU1 = ElCLib::InPeriod(aU1, aU1min, aU1min + theArrPeriods[0]);
854 aV1 = ElCLib::InPeriod(aV1, aV1min, aV1min + theArrPeriods[1]);
855 aU2 = ElCLib::InPeriod(aU2, aU2min, aU2min + theArrPeriods[2]);
856 aV2 = ElCLib::InPeriod(aV2, aV2min, aV2min + theArrPeriods[3]);
858 return (theBoxS1.IsOut(gp_Pnt2d(aU1, aV1)) ||
859 theBoxS2.IsOut(gp_Pnt2d(aU2, aV2)));
862 //=======================================================================
863 //function : CheckArgumentsToExtend
864 //purpose : Check if extending is possible
865 // (see IntPatch_WLineTool::ExtendTwoWLines)
866 //=======================================================================
867 static IntPatchWT_WLsConnectionType
868 CheckArgumentsToExtend(const Handle(Adaptor3d_HSurface)& theS1,
869 const Handle(Adaptor3d_HSurface)& theS2,
870 const IntSurf_PntOn2S& thePtWL1,
871 const IntSurf_PntOn2S& thePtWL2,
872 IntSurf_PntOn2S& theNewPoint,
873 const gp_Vec& theVec1,
874 const gp_Vec& theVec2,
875 const gp_Vec& theVec3,
876 const Bnd_Box2d& theBoxS1,
877 const Bnd_Box2d& theBoxS2,
878 const Standard_Real theToler3D,
879 const Standard_Real* const theArrPeriods)
881 const Standard_Real aSqToler = theToler3D*theToler3D;
883 if(theVec3.SquareMagnitude() <= aSqToler)
885 return IntPatchWT_NotConnected;
888 if((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle) ||
889 (theVec1.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle) ||
890 (theVec2.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle))
892 return IntPatchWT_NotConnected;
895 const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ()));
897 Standard_Real aNewPar[4] = {0.0, 0.0, 0.0, 0.0};
900 Standard_Real aParLBC[4] = {0.0, 0.0, 0.0, 0.0};
901 theBoxS1.Get(aParLBC[0], aParLBC[1], aNewPar[0], aNewPar[0]);
902 theBoxS2.Get(aParLBC[2], aParLBC[3], aNewPar[0], aNewPar[0]);
904 if(!IsIntersectionPoint(aPmid, theS1, theS2, thePtWL1, theToler3D,
905 theArrPeriods, theNewPoint))
907 return IntPatchWT_NotConnected;
910 if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint, theArrPeriods))
912 return IntPatchWT_NotConnected;
915 Standard_Real aParWL1[4] = {0.0, 0.0, 0.0, 0.0},
916 aParWL2[4] = {0.0, 0.0, 0.0, 0.0};
918 thePtWL1.Parameters(aParWL1[0], aParWL1[1], aParWL1[2], aParWL1[3]);
919 thePtWL2.Parameters(aParWL2[0], aParWL2[1], aParWL2[2], aParWL2[3]);
920 theNewPoint.Parameters(aNewPar[0], aNewPar[1], aNewPar[2], aNewPar[3]);
922 Standard_Boolean isOnBoundary = Standard_False;
923 for(Standard_Integer i = 0; i < 4; i++)
925 if(IsOnPeriod(aParWL1[i] - aParLBC[i], aParWL2[i] - aParLBC[i], theArrPeriods[i]))
927 //Check, if we intersect surface boundary when we will extend Wline1 or Wline2
929 MinMax(aParWL1[i], aParWL2[i]);
930 if(theArrPeriods[i] > 0.0)
932 if(aNewPar[i] > aParWL2[i])
936 //---*---------------*------------*-----
937 // aParWL1[i] aParWL2[i] aNewPar[i]
939 //After possible adjusting:
941 //---*---------------*------------*-----
942 // aParWL1[i] aNewPar[i] aParWL2[i]
944 //Now we will be able to extend every WLine to
945 //aNewPar[i] to make them close to each other.
946 //However, it is necessary to add check if we
947 //intersect boundary.
948 const Standard_Real aPar = aParWL1[i] +
949 theArrPeriods[0]*Ceiling((aNewPar[i]-aParWL1[i])/theArrPeriods[0]);
950 aParWL1[i] = aParWL2[i];
953 else if(aNewPar[i] < aParWL1[i])
955 //See comments to main "if".
958 //---*---------------*------------*-----
959 // aNewPar[i] aParWL1[i] aParWL2[i]
961 //After possible adjusting:
963 //---*---------------*------------*-----
964 // aParWL1[i] aNewPar[i] aParWL2[i]
966 const Standard_Real aPar = aParWL2[i] -
967 theArrPeriods[0]*Ceiling((aParWL2[i]-aNewPar[i])/theArrPeriods[0]);
968 aParWL2[i] = aParWL1[i];
973 if( IsOnPeriod(aParWL1[i] - aParLBC[i], aNewPar[i] - aParLBC[i], theArrPeriods[0]) ||
974 IsOnPeriod(aNewPar[i] - aParLBC[i], aParWL2[i] - aParLBC[i], theArrPeriods[0]))
976 return IntPatchWT_NotConnected;
980 isOnBoundary = Standard_True;
987 return IntPatchWT_Singular;
990 return IntPatchWT_EachOther;
993 //=======================================================================
994 //function : CheckArgumentsToJoin
995 //purpose : Check if joining is possible
996 // (see IntPatch_WLineTool::JoinWLines(...))
997 //=======================================================================
998 Standard_Boolean CheckArgumentsToJoin(const gp_Vec& theVec1,
999 const gp_Vec& theVec2)
1002 const Standard_Real anAngle = theVec1.Angle(theVec2);
1004 return (anAngle < IntPatch_WLineTool::myMaxConcatAngle);
1007 //=======================================================================
1008 //function : ExtendTwoWLFirstFirst
1009 //purpose : Performs extending theWLine1 and theWLine2 through their
1010 // respecting start point.
1011 //=======================================================================
1012 static void ExtendTwoWLFirstFirst(const Handle(Adaptor3d_HSurface)& theS1,
1013 const Handle(Adaptor3d_HSurface)& theS2,
1014 const Handle(IntPatch_WLine)& theWLine1,
1015 const Handle(IntPatch_WLine)& theWLine2,
1016 const IntSurf_PntOn2S& thePtWL1,
1017 const IntSurf_PntOn2S& thePtWL2,
1018 const gp_Vec& theVec1,
1019 const gp_Vec& theVec2,
1020 const gp_Vec& theVec3,
1021 const Bnd_Box2d& theBoxS1,
1022 const Bnd_Box2d& theBoxS2,
1023 const Standard_Real theToler3D,
1024 const Standard_Real* const theArrPeriods,
1025 unsigned int &theCheckResult,
1026 Standard_Boolean &theHasBeenJoined)
1028 IntSurf_PntOn2S aPOn2S;
1029 const IntPatchWT_WLsConnectionType aCheckRes =
1030 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1031 theVec1, theVec2, theVec3,
1033 theToler3D, theArrPeriods);
1035 if(aCheckRes != IntPatchWT_NotConnected)
1036 theCheckResult |= (IntPatchWT_DisFirstLast | IntPatchWT_DisLastFirst);
1040 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1041 ExtendFirst(theWLine1, aPOn2S);
1042 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1043 ExtendFirst(theWLine2, aPOn2S);
1045 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
1048 Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
1049 while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
1050 theWLine1->RemoveVertex(1);
1052 aPrm = theWLine2->Vertex(1).ParameterOnLine();
1053 while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
1054 theWLine2->RemoveVertex(1);
1056 const Standard_Integer aNbPts = theWLine2->NbPnts();
1057 for(Standard_Integer aNPt = 2; aNPt <= aNbPts; aNPt++)
1059 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1060 theWLine1->Curve()->InsertBefore(1, aPt);
1063 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
1065 IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
1066 const Standard_Real aCurParam = aVert.ParameterOnLine();
1067 aVert.SetParameter(aNbPts+aCurParam-1);
1070 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
1072 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1073 const Standard_Real aCurParam = aVert.ParameterOnLine();
1074 aVert.SetParameter(aNbPts-aCurParam+1);
1075 theWLine1->AddVertex(aVert, Standard_True);
1078 theHasBeenJoined = Standard_True;
1081 //=======================================================================
1082 //function : ExtendTwoWLFirstLast
1083 //purpose : Performs extending theWLine1 through its start point and theWLine2
1084 // through its end point.
1085 //=======================================================================
1086 static void ExtendTwoWLFirstLast(const Handle(Adaptor3d_HSurface)& theS1,
1087 const Handle(Adaptor3d_HSurface)& theS2,
1088 const Handle(IntPatch_WLine)& theWLine1,
1089 const Handle(IntPatch_WLine)& theWLine2,
1090 const IntSurf_PntOn2S& thePtWL1,
1091 const IntSurf_PntOn2S& thePtWL2,
1092 const gp_Vec& theVec1,
1093 const gp_Vec& theVec2,
1094 const gp_Vec& theVec3,
1095 const Bnd_Box2d& theBoxS1,
1096 const Bnd_Box2d& theBoxS2,
1097 const Standard_Real theToler3D,
1098 const Standard_Real* const theArrPeriods,
1099 unsigned int &theCheckResult,
1100 Standard_Boolean &theHasBeenJoined)
1102 IntSurf_PntOn2S aPOn2S;
1103 const IntPatchWT_WLsConnectionType aCheckRes =
1104 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1105 theVec1, theVec2, theVec3,
1107 theToler3D, theArrPeriods);
1109 if(aCheckRes != IntPatchWT_NotConnected)
1110 theCheckResult |= IntPatchWT_DisLastLast;
1114 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1115 ExtendFirst(theWLine1, aPOn2S);
1116 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1117 ExtendLast (theWLine2, aPOn2S);
1119 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
1122 Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
1123 while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
1124 theWLine1->RemoveVertex(1);
1126 aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
1127 while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
1128 theWLine2->RemoveVertex(theWLine2->NbVertex());
1130 const Standard_Integer aNbPts = theWLine2->NbPnts();
1131 for(Standard_Integer aNPt = aNbPts - 1; aNPt >= 1; aNPt--)
1133 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1134 theWLine1->Curve()->InsertBefore(1, aPt);
1137 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
1139 IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
1140 const Standard_Real aCurParam = aVert.ParameterOnLine();
1141 aVert.SetParameter(aNbPts+aCurParam-1);
1144 for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
1146 const IntPatch_Point &aVert = theWLine2->Vertex(aNVtx);
1147 theWLine1->AddVertex(aVert, Standard_True);
1150 theHasBeenJoined = Standard_True;
1153 //=======================================================================
1154 //function : ExtendTwoWLLastFirst
1155 //purpose : Performs extending theWLine1 through its end point and theWLine2
1156 // through its start point.
1157 //=======================================================================
1158 static void ExtendTwoWLLastFirst(const Handle(Adaptor3d_HSurface)& theS1,
1159 const Handle(Adaptor3d_HSurface)& theS2,
1160 const Handle(IntPatch_WLine)& theWLine1,
1161 const Handle(IntPatch_WLine)& theWLine2,
1162 const IntSurf_PntOn2S& thePtWL1,
1163 const IntSurf_PntOn2S& thePtWL2,
1164 const gp_Vec& theVec1,
1165 const gp_Vec& theVec2,
1166 const gp_Vec& theVec3,
1167 const Bnd_Box2d& theBoxS1,
1168 const Bnd_Box2d& theBoxS2,
1169 const Standard_Real theToler3D,
1170 const Standard_Real* const theArrPeriods,
1171 unsigned int &theCheckResult,
1172 Standard_Boolean &theHasBeenJoined)
1174 IntSurf_PntOn2S aPOn2S;
1175 const IntPatchWT_WLsConnectionType aCheckRes =
1176 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1177 theVec1, theVec2, theVec3,
1179 theToler3D, theArrPeriods);
1181 if(aCheckRes != IntPatchWT_NotConnected)
1182 theCheckResult |= IntPatchWT_DisLastLast;
1186 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1187 ExtendLast (theWLine1, aPOn2S);
1188 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1189 ExtendFirst(theWLine2, aPOn2S);
1191 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
1196 Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
1197 while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
1198 theWLine1->RemoveVertex(theWLine1->NbVertex());
1200 aPrm = theWLine2->Vertex(1).ParameterOnLine();
1201 while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
1202 theWLine2->RemoveVertex(1);
1204 const Standard_Integer aNbPts = theWLine1->NbPnts();
1205 for(Standard_Integer aNPt = 2; aNPt <= theWLine2->NbPnts(); aNPt++)
1207 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1208 theWLine1->Curve()->Add(aPt);
1211 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
1213 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1214 const Standard_Real aCurParam = aVert.ParameterOnLine();
1215 aVert.SetParameter(aNbPts+aCurParam-1);
1216 theWLine1->AddVertex(aVert, Standard_False);
1219 theHasBeenJoined = Standard_True;
1222 //=======================================================================
1223 //function : ExtendTwoWLLastLast
1225 //=======================================================================
1226 static void ExtendTwoWLLastLast(const Handle(Adaptor3d_HSurface)& theS1,
1227 const Handle(Adaptor3d_HSurface)& theS2,
1228 const Handle(IntPatch_WLine)& theWLine1,
1229 const Handle(IntPatch_WLine)& theWLine2,
1230 const IntSurf_PntOn2S& thePtWL1,
1231 const IntSurf_PntOn2S& thePtWL2,
1232 const gp_Vec& theVec1,
1233 const gp_Vec& theVec2,
1234 const gp_Vec& theVec3,
1235 const Bnd_Box2d& theBoxS1,
1236 const Bnd_Box2d& theBoxS2,
1237 const Standard_Real theToler3D,
1238 const Standard_Real* const theArrPeriods,
1239 unsigned int &theCheckResult,
1240 Standard_Boolean &theHasBeenJoined)
1242 IntSurf_PntOn2S aPOn2S;
1243 const IntPatchWT_WLsConnectionType aCheckRes =
1244 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1245 theVec1, theVec2, theVec3,
1247 theToler3D, theArrPeriods);
1249 if(aCheckRes != IntPatchWT_NotConnected)
1250 theCheckResult |= IntPatchWT_DisLastLast;
1254 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1255 ExtendLast(theWLine1, aPOn2S);
1256 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1257 ExtendLast(theWLine2, aPOn2S);
1259 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
1262 Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
1263 while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
1264 theWLine1->RemoveVertex(theWLine1->NbVertex());
1266 aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
1267 while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
1268 theWLine2->RemoveVertex(theWLine2->NbVertex());
1270 const Standard_Integer aNbPts = theWLine1->NbPnts() + theWLine2->NbPnts();
1271 for(Standard_Integer aNPt = theWLine2->NbPnts()-1; aNPt >= 1; aNPt--)
1273 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1274 theWLine1->Curve()->Add(aPt);
1277 for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
1279 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1280 const Standard_Real aCurParam = aVert.ParameterOnLine();
1281 aVert.SetParameter(aNbPts - aCurParam);
1282 theWLine1->AddVertex(aVert, Standard_False);
1285 theHasBeenJoined = Standard_True;
1288 //=========================================================================
1289 // function : ComputePurgedWLine
1291 //=========================================================================
1292 Handle(IntPatch_WLine) IntPatch_WLineTool::
1293 ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
1294 const Handle(Adaptor3d_HSurface) &theS1,
1295 const Handle(Adaptor3d_HSurface) &theS2,
1296 const Handle(Adaptor3d_TopolTool) &theDom1,
1297 const Handle(Adaptor3d_TopolTool) &theDom2,
1298 const Standard_Boolean theRestrictLine)
1300 Standard_Integer i, k, v, nb, nbvtx;
1301 Handle(IntPatch_WLine) aResult;
1302 nbvtx = theWLine->NbVertex();
1303 nb = theWLine->NbPnts();
1306 const IntSurf_PntOn2S& p1 = theWLine->Point(1);
1307 const IntSurf_PntOn2S& p2 = theWLine->Point(2);
1308 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()))
1312 Handle(IntPatch_WLine) aLocalWLine;
1313 Handle(IntPatch_WLine) aTmpWLine = theWLine;
1314 Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
1315 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
1316 for(i = 1; i <= nb; i++)
1317 aLineOn2S->Add(theWLine->Point(i));
1319 for(v = 1; v <= nbvtx; v++)
1320 aLocalWLine->AddVertex(theWLine->Vertex(v));
1322 // I: Delete equal points
1323 for(i = 1; i <= aLineOn2S->NbPoints(); i++)
1325 Standard_Integer aStartIndex = i + 1;
1326 Standard_Integer anEndIndex = i + 5;
1327 nb = aLineOn2S->NbPoints();
1328 anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
1330 if((aStartIndex > nb) || (anEndIndex <= 1))
1335 while(k <= anEndIndex)
1339 IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
1340 IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
1342 Standard_Real UV[8];
1343 p1.Parameters(UV[0], UV[1], UV[2], UV[3]);
1344 p2.Parameters(UV[4], UV[5], UV[6], UV[7]);
1346 Standard_Real aMax = Abs(UV[0]);
1347 for(Standard_Integer anIdx = 1; anIdx < 8; anIdx++)
1349 if (aMax < Abs(UV[anIdx]))
1350 aMax = Abs(UV[anIdx]);
1353 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()) ||
1354 Abs(UV[0] - UV[4]) + Abs(UV[1] - UV[5]) < 1.0e-16 * aMax ||
1355 Abs(UV[2] - UV[6]) + Abs(UV[3] - UV[7]) < 1.0e-16 * aMax )
1357 aTmpWLine = aLocalWLine;
1358 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
1360 for(v = 1; v <= aTmpWLine->NbVertex(); v++)
1362 IntPatch_Point aVertex = aTmpWLine->Vertex(v);
1363 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
1365 if(avertexindex >= k)
1367 aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
1369 aLocalWLine->AddVertex(aVertex);
1371 aLineOn2S->RemovePoint(k);
1380 if (aLineOn2S->NbPoints() <= 2)
1382 if (aLineOn2S->NbPoints() == 2)
1388 // Avoid purge in case of C0 continuity:
1389 // Intersection approximator may produce invalid curve after purge, example:
1390 // bugs modalg_5 bug24731.
1391 // Do not run purger when base number of points is too small.
1392 if (theS1->UContinuity() == GeomAbs_C0 ||
1393 theS1->VContinuity() == GeomAbs_C0 ||
1394 theS2->UContinuity() == GeomAbs_C0 ||
1395 theS2->VContinuity() == GeomAbs_C0 ||
1396 nb < aNbSingleBezier)
1401 if (theRestrictLine)
1403 // II: Delete out of borders points.
1404 aLocalWLine = DeleteOuterPoints(aLocalWLine, theS1, theS2, theDom1, theDom2);
1407 // III: Delete points by tube criteria.
1408 Handle(IntPatch_WLine) aLocalWLineTube =
1409 DeleteByTube(aLocalWLine, theS1, theS2);
1411 if(aLocalWLineTube->NbPnts() > 1)
1413 aResult = aLocalWLineTube;
1419 //=======================================================================
1420 //function : JoinWLines
1422 //=======================================================================
1423 void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
1424 IntPatch_SequenceOfPoint& theSPnt,
1425 const Standard_Real theTol3D,
1426 const Standard_Real theU1Period,
1427 const Standard_Real theU2Period,
1428 const Standard_Real theV1Period,
1429 const Standard_Real theV2Period,
1430 const Standard_Real theUfSurf1,
1431 const Standard_Real theUlSurf1,
1432 const Standard_Real theVfSurf1,
1433 const Standard_Real theVlSurf1,
1434 const Standard_Real theUfSurf2,
1435 const Standard_Real theUlSurf2,
1436 const Standard_Real theVfSurf2,
1437 const Standard_Real theVlSurf2)
1439 if(theSlin.Length() == 0)
1442 for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
1444 Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine1)));
1446 if(aWLine1.IsNull())
1447 {//We must have failed to join not-point-lines
1451 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
1452 const IntSurf_PntOn2S& aPntFW1 = aWLine1->Point(1);
1453 const IntSurf_PntOn2S& aPntLW1 = aWLine1->Point(aNbPntsWL1);
1455 for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
1457 const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
1459 if( aPntCur.IsSame(aPntFW1, Precision::Confusion()) ||
1460 aPntCur.IsSame(aPntLW1, Precision::Confusion()))
1462 theSPnt.Remove(aNPt);
1467 Standard_Boolean hasBeenRemoved = Standard_False;
1468 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1; aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1470 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine2)));
1472 if(aWLine2.IsNull())
1475 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1477 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1478 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
1480 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1481 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1483 if(aPntFWL1.IsSame(aPntFWL2, Precision::Confusion()))
1485 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
1486 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
1488 Standard_Boolean aCond =
1489 CheckArgumentsToJoin(gp_Vec(aPntFWL1.Value(), aPt1.Value()),
1490 gp_Vec(aPt2.Value(), aPntFWL2.Value()));
1492 aCond = aCond && !IsSeamOrBound(aPt1, aPt2, aPntFWL1,
1493 theU1Period, theU2Period,
1494 theV1Period, theV2Period,
1495 theUfSurf1, theUlSurf1,
1496 theVfSurf1, theVlSurf1,
1497 theUfSurf2, theUlSurf2,
1498 theVfSurf2, theVlSurf2);
1502 aWLine1->ClearVertexes();
1503 for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
1505 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1506 aWLine1->Curve()->InsertBefore(1, aPt);
1509 aWLine1->ComputeVertexParameters(theTol3D);
1511 theSlin.Remove(aNumOfLine2);
1513 hasBeenRemoved = Standard_True;
1519 if(aPntFWL1.IsSame(aPntLWL2, Precision::Confusion()))
1521 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
1522 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
1524 Standard_Boolean aCond =
1525 CheckArgumentsToJoin(gp_Vec(aPntFWL1.Value(), aPt1.Value()),
1526 gp_Vec(aPt2.Value(), aPntLWL2.Value()));
1528 aCond = aCond && !IsSeamOrBound(aPt1, aPt2, aPntFWL1,
1529 theU1Period, theU2Period,
1530 theV1Period, theV2Period,
1531 theUfSurf1, theUlSurf1,
1532 theVfSurf1, theVlSurf1,
1533 theUfSurf2, theUlSurf2,
1534 theVfSurf2, theVlSurf2);
1538 aWLine1->ClearVertexes();
1539 for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
1541 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1542 aWLine1->Curve()->InsertBefore(1, aPt);
1545 aWLine1->ComputeVertexParameters(theTol3D);
1547 theSlin.Remove(aNumOfLine2);
1549 hasBeenRemoved = Standard_True;
1555 if(aPntLWL1.IsSame(aPntFWL2, Precision::Confusion()))
1557 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
1558 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
1560 Standard_Boolean aCond =
1561 CheckArgumentsToJoin(gp_Vec(aPt1.Value(), aPntLWL1.Value()),
1562 gp_Vec(aPntFWL2.Value(), aPt2.Value()));
1564 aCond = aCond && !IsSeamOrBound(aPt1, aPt2, aPntLWL1,
1565 theU1Period, theU2Period,
1566 theV1Period, theV2Period,
1567 theUfSurf1, theUlSurf1,
1568 theVfSurf1, theVlSurf1,
1569 theUfSurf2, theUlSurf2,
1570 theVfSurf2, theVlSurf2);
1574 aWLine1->ClearVertexes();
1575 for(Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
1577 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1578 aWLine1->Curve()->Add(aPt);
1581 aWLine1->ComputeVertexParameters(theTol3D);
1583 theSlin.Remove(aNumOfLine2);
1585 hasBeenRemoved = Standard_True;
1591 if(aPntLWL1.IsSame(aPntLWL2, Precision::Confusion()))
1593 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
1594 const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
1596 Standard_Boolean aCond =
1597 CheckArgumentsToJoin(gp_Vec(aPt1.Value(), aPntLWL1.Value()),
1598 gp_Vec(aPntLWL2.Value(), aPt2.Value()));
1600 aCond = aCond && !IsSeamOrBound(aPt1, aPt2, aPntLWL1,
1601 theU1Period, theU2Period,
1602 theV1Period, theV2Period,
1603 theUfSurf1, theUlSurf1,
1604 theVfSurf1, theVlSurf1,
1605 theUfSurf2, theUlSurf2,
1606 theVfSurf2, theVlSurf2);
1610 aWLine1->ClearVertexes();
1611 for(Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
1613 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1614 aWLine1->Curve()->Add(aPt);
1617 aWLine1->ComputeVertexParameters(theTol3D);
1619 theSlin.Remove(aNumOfLine2);
1621 hasBeenRemoved = Standard_True;
1633 //=======================================================================
1634 //function : ExtendTwoWLines
1635 //purpose : Performs extending theWLine1 and theWLine2 through their
1636 // respecting end point.
1637 //=======================================================================
1638 void IntPatch_WLineTool::ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin,
1639 const Handle(Adaptor3d_HSurface)& theS1,
1640 const Handle(Adaptor3d_HSurface)& theS2,
1641 const Standard_Real theToler3D,
1642 const Standard_Real* const theArrPeriods,
1643 const Bnd_Box2d& theBoxS1,
1644 const Bnd_Box2d& theBoxS2)
1646 if(theSlin.Length() < 2)
1649 gp_Vec aVec1, aVec2, aVec3;
1651 for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
1653 Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::
1654 DownCast(theSlin.Value(aNumOfLine1)));
1656 if(aWLine1.IsNull())
1657 {//We must have failed to join not-point-lines
1661 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
1663 if(aWLine1->Vertex(1).ParameterOnLine() != 1)
1666 if(aWLine1->Vertex(aWLine1->NbVertex()).ParameterOnLine() != aWLine1->NbPnts())
1669 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1670 const IntSurf_PntOn2S& aPntFp1WL1 = aWLine1->Point(2);
1672 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
1673 const IntSurf_PntOn2S& aPntLm1WL1 = aWLine1->Point(aNbPntsWL1-1);
1675 //Enable/Disable of some ckeck. Bit-mask is used for it.
1676 //E.g. if 1st point of aWLine1 matches with
1677 //1st point of aWLine2 then we do not need in check
1678 //1st point of aWLine1 and last point of aWLine2 etc.
1679 unsigned int aCheckResult = IntPatchWT_EnAll;
1681 //If aWLine1 is already connected with another Wline then
1682 //there is no point in extending.
1683 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
1684 aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1686 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::
1687 DownCast(theSlin.Value(aNumOfLine2)));
1689 if(aWLine2.IsNull())
1692 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1693 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aWLine2->NbPnts());
1695 if( aPntFWL1.IsSame(aPntFWL2, theToler3D) ||
1696 aPntFWL1.IsSame(aPntLWL2, theToler3D) )
1698 aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast;
1701 if( aPntLWL1.IsSame(aPntFWL2, theToler3D) ||
1702 aPntLWL1.IsSame(aPntFWL2, theToler3D))
1704 aCheckResult |= IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast;
1708 if(aCheckResult == (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast |
1709 IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast))
1712 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
1713 aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1715 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::
1716 DownCast(theSlin.Value(aNumOfLine2)));
1718 if(aWLine2.IsNull())
1721 if(aWLine2->Vertex(1).ParameterOnLine() != 1)
1724 if(aWLine2->Vertex(aWLine2->NbVertex()).ParameterOnLine() != aWLine2->NbPnts())
1727 Standard_Boolean hasBeenJoined = Standard_False;
1729 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1731 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1732 const IntSurf_PntOn2S& aPntFp1WL2 = aWLine2->Point(2);
1734 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1735 const IntSurf_PntOn2S& aPntLm1WL2 = aWLine2->Point(aNbPntsWL2-1);
1737 //if(!(aCheckResult & IntPatchWT_DisFirstFirst))
1739 aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
1740 aVec2.SetXYZ(aPntFWL2.Value().XYZ() - aPntFp1WL2.Value().XYZ());
1741 aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntFWL2.Value().XYZ());
1743 ExtendTwoWLFirstFirst(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntFWL2,
1744 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1745 theArrPeriods, aCheckResult, hasBeenJoined);
1748 if(!(aCheckResult & IntPatchWT_DisFirstLast))
1750 aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
1751 aVec2.SetXYZ(aPntLWL2.Value().XYZ() - aPntLm1WL2.Value().XYZ());
1752 aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntLWL2.Value().XYZ());
1754 ExtendTwoWLFirstLast(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntLWL2,
1755 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1756 theArrPeriods, aCheckResult, hasBeenJoined);
1759 if(!(aCheckResult & IntPatchWT_DisLastFirst))
1761 aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
1762 aVec2.SetXYZ(aPntFp1WL2.Value().XYZ() - aPntFWL2.Value().XYZ());
1763 aVec3.SetXYZ(aPntFWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
1765 ExtendTwoWLLastFirst(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntFWL2,
1766 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1767 theArrPeriods, aCheckResult, hasBeenJoined);
1770 if(!(aCheckResult & IntPatchWT_DisLastLast))
1772 aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
1773 aVec2.SetXYZ(aPntLm1WL2.Value().XYZ() - aPntLWL2.Value().XYZ());
1774 aVec3.SetXYZ(aPntLWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
1776 ExtendTwoWLLastLast(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntLWL2,
1777 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1778 theArrPeriods, aCheckResult, hasBeenJoined);
1783 theSlin.Remove(aNumOfLine2);