0029807: [Regression to 7.0.0] Impossible to cut cone from prism
[occt.git] / src / IntPatch / IntPatch_WLineTool.cxx
CommitLineData
4e14c88f 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
2//
3// This file is part of Open CASCADE Technology software library.
4//
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.
10//
11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
13
14#include <IntPatch_WLineTool.hxx>
15
16#include <Adaptor3d_HSurface.hxx>
17#include <Adaptor3d_TopolTool.hxx>
261b7d9e 18#include <Bnd_Range.hxx>
b8f67cc2 19#include <ElCLib.hxx>
e2e0498b 20#include <ElSLib.hxx>
21#include <IntPatch_SpecialPoints.hxx>
261b7d9e 22#include <NCollection_IncAllocator.hxx>
23#include <TopAbs_State.hxx>
b8f67cc2 24
d30895f5 25// It is pure empirical value.
26const Standard_Real IntPatch_WLineTool::myMaxConcatAngle = M_PI/6;
27
b8f67cc2 28//Bit-mask is used for information about
29//the operation made in
e2e0498b 30//IntPatch_WLineTool::ExtendTwoWLines(...) method.
b8f67cc2 31enum
32{
33 IntPatchWT_EnAll = 0x00,
34 IntPatchWT_DisLastLast = 0x01,
35 IntPatchWT_DisLastFirst = 0x02,
36 IntPatchWT_DisFirstLast = 0x04,
37 IntPatchWT_DisFirstFirst = 0x08
38};
4e14c88f 39
e2e0498b 40enum IntPatchWT_WLsConnectionType
41{
42 IntPatchWT_NotConnected,
43 IntPatchWT_Singular,
3306fdd9 44 IntPatchWT_Common,
45 IntPatchWT_ReqExtend
e2e0498b 46};
47
4e14c88f 48//=======================================================================
49//function : MinMax
50//purpose : Replaces theParMIN = MIN(theParMIN, theParMAX),
51// theParMAX = MAX(theParMIN, theParMAX).
52//
53// Static subfunction in IsSeamOrBound.
54//=======================================================================
55static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
56{
57 if(theParMIN > theParMAX)
58 {
59 const Standard_Real aTmp = theParMAX;
60 theParMAX = theParMIN;
61 theParMIN = aTmp;
62 }
63}
64
65//=========================================================================
66// function : FillPointsHash
67// purpose : Fill points hash by input data.
68// Static subfunction in ComputePurgedWLine.
69//=========================================================================
70static void FillPointsHash(const Handle(IntPatch_WLine) &theWLine,
71 NCollection_Array1<Standard_Integer> &thePointsHash)
72{
73 // 1 - Delete point.
74 // 0 - Store point.
75 // -1 - Vertex point (not delete).
76 Standard_Integer i, v;
77
78 for(i = 1; i <= theWLine->NbPnts(); i++)
79 thePointsHash.SetValue(i, 0);
80
81 for(v = 1; v <= theWLine->NbVertex(); v++)
82 {
83 IntPatch_Point aVertex = theWLine->Vertex(v);
84 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
85 thePointsHash.SetValue(avertexindex, -1);
86 }
87}
88
89//=========================================================================
90// function : MakeNewWLine
91// purpose : Makes new walking line according to the points hash
92// Static subfunction in ComputePurgedWLine and DeleteOuter.
93//=========================================================================
94static Handle(IntPatch_WLine) MakeNewWLine(const Handle(IntPatch_WLine) &theWLine,
faaa95cb 95 NCollection_Array1<Standard_Integer> &thePointsHash,
96 const Standard_Boolean theIsOuter)
4e14c88f 97{
98 Standard_Integer i;
99
100 Handle(IntSurf_LineOn2S) aPurgedLineOn2S = new IntSurf_LineOn2S();
101 Handle(IntPatch_WLine) aLocalWLine = new IntPatch_WLine(aPurgedLineOn2S, Standard_False);
faaa95cb 102 Standard_Integer anOldLineIdx = 1, aVertexIdx = 1, anIndexPrev = -1, anIdxOld = -1;
103 gp_Pnt aPPrev, aPOld;
4e14c88f 104 for(i = 1; i <= thePointsHash.Upper(); i++)
105 {
106 if (thePointsHash(i) == 0)
107 {
faaa95cb 108 // Point has to be added
109
110 const gp_Pnt aP = theWLine->Point(i).Value();
111 const Standard_Real aSqDistPrev = aPPrev.SquareDistance(aPOld);
112 const Standard_Real aSqDist = aPPrev.SquareDistance(aP);
113
114 const Standard_Real aRatio = (aSqDistPrev < gp::Resolution()) ? 0.0 : 9.0*aSqDist / aSqDistPrev;
115
116 if(theIsOuter ||
117 (aRatio < gp::Resolution()) ||
118 ((1.0 < aRatio) && (aRatio < 81.0)) ||
119 (i - anIndexPrev <= 1) ||
120 (i - anIdxOld <= 1))
121 {
122 // difference in distances is satisfactory
123 // (1/9 < aSqDist/aSqDistPrev < 9)
124
125 // Store this point.
126 aPurgedLineOn2S->Add(theWLine->Point(i));
127 anOldLineIdx++;
128 aPOld = aPPrev;
129 aPPrev = aP;
130 anIdxOld = anIndexPrev;
131 anIndexPrev = i;
132 }
133 else if(aSqDist >= aSqDistPrev*9.0)
134 {
135 // current segment is much more longer
136 // (aSqDist/aSqDistPrev >= 9)
137
138 i = (i + anIndexPrev)/2;
139 thePointsHash(i) = 0;
140 i--;
141 }
142 else
143 {
144 //previous segment is much more longer
145 //(aSqDist/aSqDistPrev <= 1/9)
146
147 if(anIndexPrev - anIdxOld > 1)
148 {
149 //Delete aPPrev from WL
150 aPurgedLineOn2S->RemovePoint(aPurgedLineOn2S->NbPoints());
151 anOldLineIdx--;
152
153 // Insert point between aPOld and aPPrev
154 i = (anIdxOld + anIndexPrev) / 2;
155 thePointsHash(i) = 0;
156
157 aPPrev = aPOld;
158 anIndexPrev = anIdxOld;
159 }
160 else
161 {
162 aPOld = aPPrev;
163 anIdxOld = anIndexPrev;
164 }
165
166 //Next iterations will start from this inserted point.
167 i--;
168 }
4e14c88f 169 }
170 else if (thePointsHash(i) == -1)
171 {
172 // Add vertex.
173 IntPatch_Point aVertex = theWLine->Vertex(aVertexIdx++);
174 aVertex.SetParameter(anOldLineIdx++);
175 aLocalWLine->AddVertex(aVertex);
176 aPurgedLineOn2S->Add(theWLine->Point(i));
faaa95cb 177 aPPrev = aPOld = theWLine->Point(i).Value();
178 anIndexPrev = anIdxOld = i;
4e14c88f 179 }
faaa95cb 180
181 //Other points will be rejected by purger.
4e14c88f 182 }
183
184 return aLocalWLine;
185}
186
187//=========================================================================
188// function : MovePoint
189// purpose : Move point into surface param space. No interpolation used
190// because walking algorithm should care for closeness to the param space.
191// Static subfunction in ComputePurgedWLine.
192//=========================================================================
193static void MovePoint(const Handle(Adaptor3d_HSurface) &theS1,
194 Standard_Real &U1, Standard_Real &V1)
195{
196 if (U1 < theS1->FirstUParameter())
197 U1 = theS1->FirstUParameter();
198
199 if (U1 > theS1->LastUParameter())
200 U1 = theS1->LastUParameter();
201
202 if (V1 < theS1->FirstVParameter())
203 V1 = theS1->FirstVParameter();
204
205 if (V1 > theS1->LastVParameter())
206 V1 = theS1->LastVParameter();
207}
208
209//=========================================================================
210// function : DeleteOuterPoints
211// purpose : Check and delete out of bounds points on walking line.
212// Static subfunction in ComputePurgedWLine.
213//=========================================================================
214static Handle(IntPatch_WLine)
215 DeleteOuterPoints(const Handle(IntPatch_WLine) &theWLine,
216 const Handle(Adaptor3d_HSurface) &theS1,
217 const Handle(Adaptor3d_HSurface) &theS2,
218 const Handle(Adaptor3d_TopolTool) &theDom1,
219 const Handle(Adaptor3d_TopolTool) &theDom2)
220{
221 Standard_Integer i;
222
223 NCollection_Array1<Standard_Integer> aDelOuterPointsHash(1, theWLine->NbPnts());
224 FillPointsHash(theWLine, aDelOuterPointsHash);
225
226 if (theS1->IsUPeriodic() || theS1->IsVPeriodic() ||
227 theS2->IsUPeriodic() || theS2->IsVPeriodic() )
228 return theWLine;
229
230 gp_Pnt2d aPntOnF1, aPntOnF2;
231 Standard_Real aX1, aY1, aX2, aY2;
232
233 // Iterate over points in walking line and delete which are out of bounds.
234 // Forward.
235 Standard_Boolean isAllDeleted = Standard_True;
236 Standard_Boolean aChangedFirst = Standard_False;
237 Standard_Integer aFirstGeomIdx = 1;
238 for(i = 1; i <= theWLine->NbPnts(); i++)
239 {
240 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
241 aPntOnF1.SetCoord(aX1, aY1);
242 aPntOnF2.SetCoord(aX2, aY2);
243
244 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
245 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
246
247 if (aState1 == TopAbs_OUT ||
248 aState2 == TopAbs_OUT )
249 {
250 aDelOuterPointsHash(i) = 1;
251 aChangedFirst = Standard_True;
252 }
253 else
254 {
255 isAllDeleted = Standard_False;
256
257 aFirstGeomIdx = Max (i - 1, 1);
258 if (aDelOuterPointsHash(i) == -1)
259 aFirstGeomIdx = i; // Use data what lies in (i) point / vertex.
260
261 aDelOuterPointsHash(i) = -1;
262 break;
263 }
264 }
265
266 if (isAllDeleted)
267 {
268 // ALL points are out of bounds:
269 // case boolean bcut_complex F5 and similar.
270 return theWLine;
271 }
272
273 // Backward.
274 Standard_Boolean aChangedLast = Standard_False;
275 Standard_Integer aLastGeomIdx = theWLine->NbPnts();
276 for(i = theWLine->NbPnts(); i >= 1; i--)
277 {
278 theWLine->Point(i).Parameters(aX1, aY1, aX2, aY2);
279 aPntOnF1.SetCoord(aX1, aY1);
280 aPntOnF2.SetCoord(aX2, aY2);
281
282 TopAbs_State aState1 = theDom1->Classify(aPntOnF1, Precision::Confusion());
283 TopAbs_State aState2 = theDom2->Classify(aPntOnF2, Precision::Confusion());
284
285 if (aState1 == TopAbs_OUT ||
286 aState2 == TopAbs_OUT )
287 {
288 aDelOuterPointsHash(i) = 1;
289 aChangedLast = Standard_True; // Move vertex to first good point
290 }
291 else
292 {
293 aLastGeomIdx = Min (i + 1, theWLine->NbPnts());
294 if (aDelOuterPointsHash(i) == -1)
295 aLastGeomIdx = i; // Use data what lies in (i) point / vertex.
296
297 aDelOuterPointsHash(i) = -1;
298 break;
299 }
300 }
301
302 if (!aChangedFirst && !aChangedLast)
303 {
304 // Nothing is done, return input.
305 return theWLine;
306 }
307
308 // Build new line and modify geometry of necessary vertexes.
faaa95cb 309 Handle(IntPatch_WLine) aLocalWLine = MakeNewWLine(theWLine, aDelOuterPointsHash, Standard_True);
4e14c88f 310
311 if (aChangedFirst)
312 {
313 // Vertex geometry.
314 IntPatch_Point aVertex = aLocalWLine->Vertex(1);
315 aVertex.SetValue(theWLine->Point(aFirstGeomIdx).Value());
316 Standard_Real aU1, aU2, aV1, aV2;
317 theWLine->Point(aFirstGeomIdx).Parameters(aU1, aV1, aU2, aV2);
318 MovePoint(theS1, aU1, aV1);
319 MovePoint(theS2, aU2, aV2);
320 aVertex.SetParameters(aU1, aV1, aU2, aV2);
321 aLocalWLine->Replace(1, aVertex);
322 // Change point in walking line.
323 aLocalWLine->SetPoint(1, aVertex);
324 }
325
326 if (aChangedLast)
327 {
328 // Vertex geometry.
329 IntPatch_Point aVertex = aLocalWLine->Vertex(aLocalWLine->NbVertex());
330 aVertex.SetValue(theWLine->Point(aLastGeomIdx).Value());
331 Standard_Real aU1, aU2, aV1, aV2;
332 theWLine->Point(aLastGeomIdx).Parameters(aU1, aV1, aU2, aV2);
333 MovePoint(theS1, aU1, aV1);
334 MovePoint(theS2, aU2, aV2);
335 aVertex.SetParameters(aU1, aV1, aU2, aV2);
336 aLocalWLine->Replace(aLocalWLine->NbVertex(), aVertex);
337 // Change point in walking line.
338 aLocalWLine->SetPoint(aLocalWLine->NbPnts(), aVertex);
339 }
340
341
342 return aLocalWLine;
343}
344
345//=========================================================================
346// function : IsInsideIn2d
347// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
348// In 2d space. Static subfunction in DeleteByTube.
349//=========================================================================
350static Standard_Boolean IsInsideIn2d(const gp_Pnt2d& aBasePnt,
351 const gp_Vec2d& aBaseVec,
352 const gp_Pnt2d& aNextPnt,
353 const Standard_Real aSquareMaxDist)
354{
355 gp_Vec2d aVec2d(aBasePnt, aNextPnt);
356
357 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
358 Standard_Real aCross = aVec2d.Crossed(aBaseVec);
359 Standard_Real aSquareDist = aCross * aCross
360 / aBaseVec.SquareMagnitude();
361
362 return (aSquareDist <= aSquareMaxDist);
363}
364
365//=========================================================================
366// function : IsInsideIn3d
367// purpose : Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
368// In 3d space. Static subfunction in DeleteByTube.
369//=========================================================================
370static Standard_Boolean IsInsideIn3d(const gp_Pnt& aBasePnt,
371 const gp_Vec& aBaseVec,
372 const gp_Pnt& aNextPnt,
373 const Standard_Real aSquareMaxDist)
374{
375 gp_Vec aVec(aBasePnt, aNextPnt);
376
377 //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
378 Standard_Real aSquareDist = aVec.CrossSquareMagnitude(aBaseVec)
379 / aBaseVec.SquareMagnitude();
380
381 return (aSquareDist <= aSquareMaxDist);
382}
383
384static const Standard_Integer aMinNbBadDistr = 15;
385static const Standard_Integer aNbSingleBezier = 30;
386
387//=========================================================================
388// function : DeleteByTube
389// purpose : Check and delete points using tube criteria.
390// Static subfunction in ComputePurgedWLine.
391//=========================================================================
392static Handle(IntPatch_WLine)
393 DeleteByTube(const Handle(IntPatch_WLine) &theWLine,
394 const Handle(Adaptor3d_HSurface) &theS1,
395 const Handle(Adaptor3d_HSurface) &theS2)
396{
397 // III: Check points for tube criteria:
398 // Workaround to handle case of small amount points after purge.
399 // Test "boolean boptuc_complex B5" and similar.
400 Standard_Integer aNbPnt = 0 , i;
401
402 if (theWLine->NbPnts() <= 2)
403 return theWLine;
404
405 NCollection_Array1<Standard_Integer> aNewPointsHash(1, theWLine->NbPnts());
406 FillPointsHash(theWLine, aNewPointsHash);
407
408 // Inital computations.
409 Standard_Real UonS1[3], VonS1[3], UonS2[3], VonS2[3];
410 theWLine->Point(1).ParametersOnS1(UonS1[0], VonS1[0]);
411 theWLine->Point(2).ParametersOnS1(UonS1[1], VonS1[1]);
412 theWLine->Point(1).ParametersOnS2(UonS2[0], VonS2[0]);
413 theWLine->Point(2).ParametersOnS2(UonS2[1], VonS2[1]);
414
415 gp_Pnt2d aBase2dPnt1(UonS1[0], VonS1[0]);
416 gp_Pnt2d aBase2dPnt2(UonS2[0], VonS2[0]);
417 gp_Vec2d aBase2dVec1(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
418 gp_Vec2d aBase2dVec2(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
419 gp_Pnt aBase3dPnt = theWLine->Point(1).Value();
420 gp_Vec aBase3dVec(theWLine->Point(1).Value(), theWLine->Point(2).Value());
421
422 // Choose base tolerance and scale it to pipe algorithm.
423 const Standard_Real aBaseTolerance = Precision::Approximation();
424 Standard_Real aResS1Tol = Min(theS1->UResolution(aBaseTolerance),
425 theS1->VResolution(aBaseTolerance));
426 Standard_Real aResS2Tol = Min(theS2->UResolution(aBaseTolerance),
427 theS2->VResolution(aBaseTolerance));
428 Standard_Real aTol1 = aResS1Tol * aResS1Tol;
429 Standard_Real aTol2 = aResS2Tol * aResS2Tol;
430 Standard_Real aTol3d = aBaseTolerance * aBaseTolerance;
431
432 const Standard_Real aLimitCoeff = 0.99 * 0.99;
433 for(i = 3; i <= theWLine->NbPnts(); i++)
434 {
435 Standard_Boolean isDeleteState = Standard_False;
436
437 theWLine->Point(i).ParametersOnS1(UonS1[2], VonS1[2]);
438 theWLine->Point(i).ParametersOnS2(UonS2[2], VonS2[2]);
439 gp_Pnt2d aPnt2dOnS1(UonS1[2], VonS1[2]);
440 gp_Pnt2d aPnt2dOnS2(UonS2[2], VonS2[2]);
441 const gp_Pnt& aPnt3d = theWLine->Point(i).Value();
442
443 if (aNewPointsHash(i - 1) != - 1 &&
444 IsInsideIn2d(aBase2dPnt1, aBase2dVec1, aPnt2dOnS1, aTol1) &&
445 IsInsideIn2d(aBase2dPnt2, aBase2dVec2, aPnt2dOnS2, aTol2) &&
446 IsInsideIn3d(aBase3dPnt, aBase3dVec, aPnt3d, aTol3d) )
447 {
448 // Handle possible uneven parametrization on one of 2d subspaces.
449 // Delete point only when expected lengths are close to each other (aLimitCoeff).
450 // Example:
451 // c2d1 - line
452 // c3d - line
453 // c2d2 - geometrically line, but have uneven parametrization -> c2d2 is bspline.
454 gp_XY aPntOnS1[2]= { gp_XY(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0])
455 , gp_XY(UonS1[2] - UonS1[1], VonS1[2] - VonS1[1])};
456 gp_XY aPntOnS2[2]= { gp_XY(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0])
457 , gp_XY(UonS2[2] - UonS2[1], VonS2[2] - VonS2[1])};
458
459 Standard_Real aStepOnS1 = aPntOnS1[0].SquareModulus() / aPntOnS1[1].SquareModulus();
460 Standard_Real aStepOnS2 = aPntOnS2[0].SquareModulus() / aPntOnS2[1].SquareModulus();
461
871776ea 462 // Check very rare case when wline fluctuates nearly one point and some of them may be equal.
463 // Middle point will be deleted when such situation occurs.
464 // bugs moddata_2 bug469.
465 if (Min(aStepOnS1, aStepOnS2) >= aLimitCoeff * Max(aStepOnS1, aStepOnS2))
4e14c88f 466 {
467 // Set hash flag to "Delete" state.
468 isDeleteState = Standard_True;
469 aNewPointsHash.SetValue(i - 1, 1);
470
471 // Change middle point.
472 UonS1[1] = UonS1[2];
473 UonS2[1] = UonS2[2];
474 VonS1[1] = VonS1[2];
475 VonS2[1] = VonS2[2];
476 }
477 }
478
479 if (!isDeleteState)
480 {
481 // Compute new pipe parameters.
482 UonS1[0] = UonS1[1];
483 VonS1[0] = VonS1[1];
484 UonS2[0] = UonS2[1];
485 VonS2[0] = VonS2[1];
486
487 UonS1[1] = UonS1[2];
488 VonS1[1] = VonS1[2];
489 UonS2[1] = UonS2[2];
490 VonS2[1] = VonS2[2];
491
492 aBase2dPnt1.SetCoord(UonS1[0], VonS1[0]);
493 aBase2dPnt2.SetCoord(UonS2[0], VonS2[0]);
494 aBase2dVec1.SetCoord(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
495 aBase2dVec2.SetCoord(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
496 aBase3dPnt = theWLine->Point(i - 1).Value();
497 aBase3dVec = gp_Vec(theWLine->Point(i - 1).Value(), theWLine->Point(i).Value());
498
499 aNbPnt++;
500 }
501 }
502
503 // Workaround to handle case of small amount of points after purge.
504 // Test "boolean boptuc_complex B5" and similar.
505 // This is possible since there are at least two points.
506 if (aNewPointsHash(1) == -1 &&
507 aNewPointsHash(2) == -1 &&
508 aNbPnt <= 3)
509 {
510 // Delete first.
511 aNewPointsHash(1) = 1;
512 }
513 if (aNewPointsHash(theWLine->NbPnts() - 1) == -1 &&
514 aNewPointsHash(theWLine->NbPnts() ) == -1 &&
515 aNbPnt <= 3)
516 {
517 // Delete last.
518 aNewPointsHash(theWLine->NbPnts()) = 1;
519 }
520
521 // Purgre when too small amount of points left.
522 if (aNbPnt <= 2)
523 {
524 for(i = aNewPointsHash.Lower(); i <= aNewPointsHash.Upper(); i++)
525 {
526 if (aNewPointsHash(i) != -1)
527 {
528 aNewPointsHash(i) = 1;
529 }
530 }
531 }
532
533 // Handle possible bad distribution of points,
534 // which are will converted into one single bezier curve (less than 30 points).
535 // Make distribution more even:
536 // max step will be nearly to 0.1 of param distance.
537 if (aNbPnt + 2 > aMinNbBadDistr &&
538 aNbPnt + 2 < aNbSingleBezier )
539 {
540 for(Standard_Integer anIdx = 1; anIdx <= 8; anIdx++)
541 {
542 Standard_Integer aHashIdx =
543 Standard_Integer(anIdx * theWLine->NbPnts() / 9);
544
47e3009d 545 //Vertex must be stored as VERTEX (HASH = -1)
546 if (aNewPointsHash(aHashIdx) != -1)
547 aNewPointsHash(aHashIdx) = 0;
4e14c88f 548 }
549 }
550
faaa95cb 551 return MakeNewWLine(theWLine, aNewPointsHash, Standard_False);
4e14c88f 552}
553
554//=======================================================================
4e14c88f 555//function : IsSeamOrBound
556//purpose : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
557// (if it exist) or surface boundaries and both thePtf and thePtl do
558// not match "seam-edge" or boundaries.
eee615ad 559// Point thePtmid lies in this segment (in both 3D and 2D-space).
560// If thePtmid match "seam-edge" or boundaries strictly
561// (without any tolerance) then the function will return TRUE.
4e14c88f 562// See comments in function body for detail information.
261b7d9e 563//
564// Arrays theArrPeriods, theFBound and theLBound must be filled
565// as follows:
566// [0] - U-parameter of 1st surface;
567// [1] - V-parameter of 1st surface;
568// [2] - U-parameter of 2nd surface;
569// [3] - V-parameter of 2nd surface.
4e14c88f 570//=======================================================================
571static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
572 const IntSurf_PntOn2S& thePtl,
573 const IntSurf_PntOn2S& thePtmid,
261b7d9e 574 const Standard_Real theArrPeriods[4],
575 const Standard_Real theFBound[4],
576 const Standard_Real theLBound[4])
4e14c88f 577{
261b7d9e 578 Standard_Real aParF[4] = { 0.0, 0.0, 0.0, 0.0 };
579 Standard_Real aParL[4] = { 0.0, 0.0, 0.0, 0.0 };
580 thePtf.Parameters(aParF[0], aParF[1], aParF[2], aParF[3]);
581 thePtl.Parameters(aParL[0], aParL[1], aParL[2], aParL[3]);
4e14c88f 582
261b7d9e 583 Bnd_Range aBndR[4];
4e14c88f 584
261b7d9e 585 for (Standard_Integer i = 0; i < 4; i++)
586 {
587 aBndR[i].Add(aParF[i]);
588 aBndR[i].Add(aParL[i]);
4e14c88f 589
261b7d9e 590 if (aBndR[i].IsIntersected(theFBound[i], theArrPeriods[i]) == 1)
591 return Standard_True;
4e14c88f 592
261b7d9e 593 if (aBndR[i].IsIntersected(theLBound[i], theArrPeriods[i]) == 1)
594 return Standard_True;
4e14c88f 595 }
596
261b7d9e 597 for (Standard_Integer i = 0; i < 4; i++)
598 {
599 if (theArrPeriods[i] == 0.0)
600 {
601 //Strictly equal
602 continue;
603 }
4e14c88f 604
261b7d9e 605 const Standard_Real aDelta = Abs(aParL[i] - aParF[i]);
606 if (2.0*aDelta > theArrPeriods[i])
607 {
608 //Most likely, seam is intersected.
609 return Standard_True;
610 }
4e14c88f 611
261b7d9e 612 if (aBndR[i].IsIntersected(0.0, theArrPeriods[i]) == 1)
613 return Standard_True;
4e14c88f 614 }
615
261b7d9e 616 //The segment [thePtf, thePtl] does not intersect the boundaries and
617 //the seam-edge of the surfaces.
618 //Nevertheless, following situation is possible:
4e14c88f 619
261b7d9e 620 // seam or
621 // bound
622 // |
623 // thePtf * |
624 // |
625 // * thePtmid
626 // thePtl * |
627 // |
4e14c88f 628
261b7d9e 629 //This case must be processed, too.
4e14c88f 630
261b7d9e 631 Standard_Real aMPar[4] = { 0.0, 0.0, 0.0, 0.0 };
632 thePtmid.Parameters(aMPar[0], aMPar[1], aMPar[2], aMPar[3]);
4e14c88f 633
261b7d9e 634 for (Standard_Integer i = 0; i < 4; i++)
635 {
636 const Bnd_Range aBR(aMPar[i], aMPar[i]);
637 if (aBR.IsIntersected(theFBound[i], theArrPeriods[i]))
638 return Standard_True;
4e14c88f 639
261b7d9e 640 if (aBR.IsIntersected(theLBound[i], theArrPeriods[i]))
641 return Standard_True;
4e14c88f 642
261b7d9e 643 if (aBR.IsIntersected(0.0, theArrPeriods[i]))
644 return Standard_True;
645 }
4e14c88f 646
647 return Standard_False;
648}
649
eee615ad 650//=======================================================================
eee615ad 651//function : IsIntersectionPoint
652//purpose : Returns True if thePmid is intersection point
653// between theS1 and theS2 with given tolerance.
654// In this case, parameters of thePmid on every quadric
655// will be recomputed and returned.
656//=======================================================================
657static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid,
e2e0498b 658 const Handle(Adaptor3d_HSurface)& theS1,
659 const Handle(Adaptor3d_HSurface)& theS2,
eee615ad 660 const IntSurf_PntOn2S& theRefPt,
661 const Standard_Real theTol,
e2e0498b 662 const Standard_Real* const theArrPeriods,
663 IntSurf_PntOn2S& theNewPt)
eee615ad 664{
e2e0498b 665 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
666
667 switch(theS1->GetType())
668 {
669 case GeomAbs_Plane:
670 ElSLib::Parameters(theS1->Plane(), thePmid, aU1, aV1);
671 break;
672
673 case GeomAbs_Cylinder:
674 ElSLib::Parameters(theS1->Cylinder(), thePmid, aU1, aV1);
675 break;
676
677 case GeomAbs_Sphere:
678 ElSLib::Parameters(theS1->Sphere(), thePmid, aU1, aV1);
679 break;
680
681 case GeomAbs_Cone:
682 ElSLib::Parameters(theS1->Cone(), thePmid, aU1, aV1);
683 break;
684
685 case GeomAbs_Torus:
686 ElSLib::Parameters(theS1->Torus(), thePmid, aU1, aV1);
687 break;
688
689 default:
690 return Standard_False;
691 }
692
693 switch(theS2->GetType())
694 {
695 case GeomAbs_Plane:
696 ElSLib::Parameters(theS2->Plane(), thePmid, aU2, aV2);
697 break;
698
699 case GeomAbs_Cylinder:
700 ElSLib::Parameters(theS2->Cylinder(), thePmid, aU2, aV2);
701 break;
702
703 case GeomAbs_Sphere:
704 ElSLib::Parameters(theS2->Sphere(), thePmid, aU2, aV2);
705 break;
eee615ad 706
e2e0498b 707 case GeomAbs_Cone:
708 ElSLib::Parameters(theS2->Cone(), thePmid, aU2, aV2);
709 break;
eee615ad 710
e2e0498b 711 case GeomAbs_Torus:
712 ElSLib::Parameters(theS2->Torus(), thePmid, aU2, aV2);
713 break;
714
715 default:
716 return Standard_False;
717 }
718
719 theNewPt.SetValue(thePmid, aU1, aV1, aU2, aV2);
720
721 IntPatch_SpecialPoints::AdjustPointAndVertex(theRefPt, theArrPeriods, theNewPt);
722
723 const gp_Pnt aP1(theS1->Value(aU1, aV1));
724 const gp_Pnt aP2(theS2->Value(aU2, aV2));
eee615ad 725
726 return (aP1.SquareDistance(aP2) <= theTol*theTol);
727}
728
729//=======================================================================
730//function : ExtendFirst
731//purpose : Adds thePOn2S to the begin of theWline
732//=======================================================================
733static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
b8f67cc2 734 const IntSurf_PntOn2S& theAddedPt)
eee615ad 735{
b8f67cc2 736 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
737 theAddedPt.Parameters(aU1, aV1, aU2, aV2);
eee615ad 738
b8f67cc2 739 if(theAddedPt.IsSame(theWline->Point(1), Precision::Confusion()))
740 {
741 theWline->Curve()->Value(1, theAddedPt);
742 for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
743 {
744 IntPatch_Point &aVert = theWline->ChangeVertex(i);
745 if(aVert.ParameterOnLine() != 1)
746 break;
eee615ad 747
b8f67cc2 748 aVert.SetParameters(aU1, aV1, aU2, aV2);
749 aVert.SetValue(theAddedPt.Value());
750 }
751
752 return;
753 }
eee615ad 754
b8f67cc2 755 theWline->Curve()->InsertBefore(1, theAddedPt);
eee615ad 756
b8f67cc2 757 for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
eee615ad 758 {
b8f67cc2 759 IntPatch_Point &aVert = theWline->ChangeVertex(i);
760
761 if(aVert.ParameterOnLine() == 1)
762 {
763 aVert.SetParameters(aU1, aV1, aU2, aV2);
764 aVert.SetValue(theAddedPt.Value());
765 }
766 else
767 {
768 aVert.SetParameter(aVert.ParameterOnLine()+1);
769 }
eee615ad 770 }
771}
772
773//=======================================================================
774//function : ExtendLast
775//purpose : Adds thePOn2S to the end of theWline
776//=======================================================================
777static void ExtendLast(const Handle(IntPatch_WLine)& theWline,
b8f67cc2 778 const IntSurf_PntOn2S& theAddedPt)
eee615ad 779{
b8f67cc2 780 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
781 theAddedPt.Parameters(aU1, aV1, aU2, aV2);
782
783 const Standard_Integer aNbPnts = theWline->NbPnts();
784 if(theAddedPt.IsSame(theWline->Point(aNbPnts), Precision::Confusion()))
785 {
786 theWline->Curve()->Value(aNbPnts, theAddedPt);
787 }
788 else
789 {
790 theWline->Curve()->Add(theAddedPt);
791 }
eee615ad 792
b8f67cc2 793 for(Standard_Integer i = theWline->NbVertex(); i >= 1; i--)
794 {
795 IntPatch_Point &aVert = theWline->ChangeVertex(i);
796 if(aVert.ParameterOnLine() != aNbPnts)
797 break;
eee615ad 798
b8f67cc2 799 aVert.SetParameters(aU1, aV1, aU2, aV2);
800 aVert.SetValue(theAddedPt.Value());
801 aVert.SetParameter(theWline->NbPnts());
802 }
803}
804
805//=========================================================================
806// function: IsOutOfDomain
807// purpose : Checks, if 2D-representation of thePOn2S is in surfaces domain,
808// defined by bounding-boxes theBoxS1 and theBoxS2
809//=========================================================================
810static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1,
811 const Bnd_Box2d& theBoxS2,
812 const IntSurf_PntOn2S &thePOn2S,
e2e0498b 813 const Standard_Real* const theArrPeriods)
b8f67cc2 814{
eee615ad 815 Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
b8f67cc2 816 Standard_Real aU1min = 0.0, aU1max = 0.0, aV1min = 0.0, aV1max = 0.0;
817 Standard_Real aU2min = 0.0, aU2max = 0.0, aV2min = 0.0, aV2max = 0.0;
818
eee615ad 819 thePOn2S.Parameters(aU1, aV1, aU2, aV2);
820
b8f67cc2 821 theBoxS1.Get(aU1min, aV1min, aU1max, aV1max);
822 theBoxS2.Get(aU2min, aV2min, aU2max, aV2max);
823
e2e0498b 824 aU1 = ElCLib::InPeriod(aU1, aU1min, aU1min + theArrPeriods[0]);
825 aV1 = ElCLib::InPeriod(aV1, aV1min, aV1min + theArrPeriods[1]);
826 aU2 = ElCLib::InPeriod(aU2, aU2min, aU2min + theArrPeriods[2]);
827 aV2 = ElCLib::InPeriod(aV2, aV2min, aV2min + theArrPeriods[3]);
b8f67cc2 828
829 return (theBoxS1.IsOut(gp_Pnt2d(aU1, aV1)) ||
830 theBoxS2.IsOut(gp_Pnt2d(aU2, aV2)));
831}
832
833//=======================================================================
d30895f5 834//function : CheckArgumentsToExtend
b8f67cc2 835//purpose : Check if extending is possible
e2e0498b 836// (see IntPatch_WLineTool::ExtendTwoWLines)
b8f67cc2 837//=======================================================================
e2e0498b 838static IntPatchWT_WLsConnectionType
839 CheckArgumentsToExtend(const Handle(Adaptor3d_HSurface)& theS1,
840 const Handle(Adaptor3d_HSurface)& theS2,
841 const IntSurf_PntOn2S& thePtWL1,
842 const IntSurf_PntOn2S& thePtWL2,
843 IntSurf_PntOn2S& theNewPoint,
844 const gp_Vec& theVec1,
845 const gp_Vec& theVec2,
846 const gp_Vec& theVec3,
847 const Bnd_Box2d& theBoxS1,
848 const Bnd_Box2d& theBoxS2,
849 const Standard_Real theToler3D,
850 const Standard_Real* const theArrPeriods)
b8f67cc2 851{
b8f67cc2 852 const Standard_Real aSqToler = theToler3D*theToler3D;
3306fdd9 853 IntPatchWT_WLsConnectionType aRetVal = IntPatchWT_NotConnected;
b8f67cc2 854 if(theVec3.SquareMagnitude() <= aSqToler)
855 {
3306fdd9 856 if ((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle))
857 {
858 return aRetVal;
859 }
860 else
861 {
862 aRetVal = IntPatchWT_Common;
863 }
b8f67cc2 864 }
3306fdd9 865 else if((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle) ||
866 (theVec1.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle) ||
867 (theVec2.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle))
b8f67cc2 868 {
3306fdd9 869 return aRetVal;
b8f67cc2 870 }
871
872 const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ()));
873
e2e0498b 874 Standard_Real aNewPar[4] = {0.0, 0.0, 0.0, 0.0};
b8f67cc2 875
e2e0498b 876 //Left-bottom corner
877 Standard_Real aParLBC[4] = {0.0, 0.0, 0.0, 0.0};
878 theBoxS1.Get(aParLBC[0], aParLBC[1], aNewPar[0], aNewPar[0]);
879 theBoxS2.Get(aParLBC[2], aParLBC[3], aNewPar[0], aNewPar[0]);
b8f67cc2 880
881 if(!IsIntersectionPoint(aPmid, theS1, theS2, thePtWL1, theToler3D,
e2e0498b 882 theArrPeriods, theNewPoint))
b8f67cc2 883 {
e2e0498b 884 return IntPatchWT_NotConnected;
b8f67cc2 885 }
886
e2e0498b 887 if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint, theArrPeriods))
b8f67cc2 888 {
e2e0498b 889 return IntPatchWT_NotConnected;
b8f67cc2 890 }
891
e2e0498b 892 Standard_Real aParWL1[4] = {0.0, 0.0, 0.0, 0.0},
893 aParWL2[4] = {0.0, 0.0, 0.0, 0.0};
894
895 thePtWL1.Parameters(aParWL1[0], aParWL1[1], aParWL1[2], aParWL1[3]);
896 thePtWL2.Parameters(aParWL2[0], aParWL2[1], aParWL2[2], aParWL2[3]);
897 theNewPoint.Parameters(aNewPar[0], aNewPar[1], aNewPar[2], aNewPar[3]);
b8f67cc2 898
261b7d9e 899 Bnd_Range aR1, aR2;
900
e2e0498b 901 Standard_Boolean isOnBoundary = Standard_False;
902 for(Standard_Integer i = 0; i < 4; i++)
903 {
261b7d9e 904 if (theArrPeriods[i] == 0.0)
905 {
906 //Strictly equal
907 continue;
908 }
909
910 aR1.SetVoid();
911 aR1.Add(aParWL1[i]);
912 aR1.Add(aParWL2[i]);
913
914 if (aR1.IsIntersected(aParLBC[i],theArrPeriods[i]))
e2e0498b 915 {
916 //Check, if we intersect surface boundary when we will extend Wline1 or Wline2
917 //to theNewPoint
918 MinMax(aParWL1[i], aParWL2[i]);
261b7d9e 919 if(aNewPar[i] > aParWL2[i])
e2e0498b 920 {
261b7d9e 921 //Source situation:
922 //
923 //---*---------------*------------*-----
924 // aParWL1[i] aParWL2[i] aNewPar[i]
925 //
926 //After possible adjusting:
927 //
928 //---*---------------*------------*-----
929 // aParWL1[i] aNewPar[i] aParWL2[i]
930 //
931 //Now we will be able to extend every WLine to
932 //aNewPar[i] to make them close to each other.
933 //However, it is necessary to add check if we
934 //intersect boundary.
935 const Standard_Real aPar = aParWL1[i] +
2967828d 936 theArrPeriods[i]*Ceiling((aNewPar[i]-aParWL1[i])/theArrPeriods[i]);
261b7d9e 937 aParWL1[i] = aParWL2[i];
938 aParWL2[i] = aPar;
939 }
940 else if(aNewPar[i] < aParWL1[i])
941 {
942 //See comments to main "if".
943 //Source situation:
944 //
945 //---*---------------*------------*-----
946 // aNewPar[i] aParWL1[i] aParWL2[i]
947 //
948 //After possible adjusting:
949 //
950 //---*---------------*------------*-----
951 // aParWL1[i] aNewPar[i] aParWL2[i]
e2e0498b 952
261b7d9e 953 const Standard_Real aPar = aParWL2[i] -
2967828d 954 theArrPeriods[i]*Ceiling((aParWL2[i]-aNewPar[i])/theArrPeriods[i]);
261b7d9e 955 aParWL2[i] = aParWL1[i];
956 aParWL1[i] = aPar;
e2e0498b 957 }
958
261b7d9e 959 aR1.SetVoid();
960 aR2.SetVoid();
961 aR1.Add(aParWL1[i]);
962 aR1.Add(aNewPar[i]);
963 aR2.Add(aNewPar[i]);
964 aR2.Add(aParWL2[i]);
965
966 if (aR1.IsIntersected(aParLBC[i], theArrPeriods[i]) ||
967 aR2.IsIntersected(aParLBC[i], theArrPeriods[i]))
e2e0498b 968 {
969 return IntPatchWT_NotConnected;
970 }
971 else
972 {
973 isOnBoundary = Standard_True;
974 }
975 }
976 }
b8f67cc2 977
e2e0498b 978 if(isOnBoundary)
b8f67cc2 979 {
e2e0498b 980 return IntPatchWT_Singular;
b8f67cc2 981 }
982
3306fdd9 983 if (aRetVal == IntPatchWT_Common)
984 {
985 return IntPatchWT_Common;
986 }
987
988 return IntPatchWT_ReqExtend;
b8f67cc2 989}
990
991//=======================================================================
d30895f5 992//function : CheckArgumentsToJoin
993//purpose : Check if joining is possible
e2e0498b 994// (see IntPatch_WLineTool::JoinWLines(...))
d30895f5 995//=======================================================================
261b7d9e 996Standard_Boolean CheckArgumentsToJoin(const Handle(Adaptor3d_HSurface)& theS1,
997 const Handle(Adaptor3d_HSurface)& theS2,
998 const IntSurf_PntOn2S& thePnt,
3306fdd9 999 const gp_Pnt& theP1,
1000 const gp_Pnt& theP2,
1001 const gp_Pnt& theP3,
261b7d9e 1002 const Standard_Real theMinRad)
d30895f5 1003{
3306fdd9 1004 const Standard_Real aRad =
1005 IntPatch_PointLine::CurvatureRadiusOfIntersLine(theS1, theS2, thePnt);
1006
1007 if (aRad > theMinRad)
1008 {
1009 return Standard_True;
1010 }
1011 else if (aRad > 0.0)
1012 {
1013 return Standard_False;
1014 }
d30895f5 1015
3306fdd9 1016 // Curvature radius cannot be computed.
1017 // Check smoothness of polygon.
1018
1019 // theP2
1020 // *
1021 // |
1022 // |
1023 // * o *
1024 // theP1 O theP3
1025
1026 //Joining is enabled if two conditions are satisfied together:
1027 // 1. Angle (theP1, theP2, theP3) is quite big;
1028 // 2. Modulus of perpendicular (O->theP2) to the segment (theP1->theP3)
1029 // is less than 0.01*<modulus of this segment>.
1030
1031 const gp_Vec aV12f(theP1, theP2), aV12l(theP2, theP3);
1032
1033 if (aV12f.Angle(aV12l) > IntPatch_WLineTool::myMaxConcatAngle)
1034 return Standard_False;
1035
1036 const gp_Vec aV13(theP1, theP3);
1037 const Standard_Real aSq13 = aV13.SquareMagnitude();
1038
1039 return (aV12f.CrossSquareMagnitude(aV13) < 1.0e-4*aSq13*aSq13);
d30895f5 1040}
1041
1042//=======================================================================
b8f67cc2 1043//function : ExtendTwoWLFirstFirst
1044//purpose : Performs extending theWLine1 and theWLine2 through their
1045// respecting start point.
1046//=======================================================================
e2e0498b 1047static void ExtendTwoWLFirstFirst(const Handle(Adaptor3d_HSurface)& theS1,
1048 const Handle(Adaptor3d_HSurface)& theS2,
1049 const Handle(IntPatch_WLine)& theWLine1,
1050 const Handle(IntPatch_WLine)& theWLine2,
1051 const IntSurf_PntOn2S& thePtWL1,
1052 const IntSurf_PntOn2S& thePtWL2,
1053 const gp_Vec& theVec1,
1054 const gp_Vec& theVec2,
1055 const gp_Vec& theVec3,
1056 const Bnd_Box2d& theBoxS1,
1057 const Bnd_Box2d& theBoxS2,
1058 const Standard_Real theToler3D,
1059 const Standard_Real* const theArrPeriods,
1060 unsigned int &theCheckResult,
1061 Standard_Boolean &theHasBeenJoined)
b8f67cc2 1062{
1063 IntSurf_PntOn2S aPOn2S;
e2e0498b 1064 const IntPatchWT_WLsConnectionType aCheckRes =
1065 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1066 theVec1, theVec2, theVec3,
1067 theBoxS1, theBoxS2,
1068 theToler3D, theArrPeriods);
1069
1070 if(aCheckRes != IntPatchWT_NotConnected)
1071 theCheckResult |= (IntPatchWT_DisFirstLast | IntPatchWT_DisLastFirst);
1072 else
b8f67cc2 1073 return;
b8f67cc2 1074
e2e0498b 1075 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
b8f67cc2 1076 ExtendFirst(theWLine1, aPOn2S);
e2e0498b 1077 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
b8f67cc2 1078 ExtendFirst(theWLine2, aPOn2S);
1079
e2e0498b 1080 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
b8f67cc2 1081 return;
1082
1083 Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
1084 while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
1085 theWLine1->RemoveVertex(1);
1086
1087 aPrm = theWLine2->Vertex(1).ParameterOnLine();
1088 while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
1089 theWLine2->RemoveVertex(1);
1090
1091 const Standard_Integer aNbPts = theWLine2->NbPnts();
1092 for(Standard_Integer aNPt = 2; aNPt <= aNbPts; aNPt++)
1093 {
1094 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1095 theWLine1->Curve()->InsertBefore(1, aPt);
1096 }
1097
1098 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
1099 {
1100 IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
1101 const Standard_Real aCurParam = aVert.ParameterOnLine();
1102 aVert.SetParameter(aNbPts+aCurParam-1);
1103 }
1104
1105 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
1106 {
1107 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1108 const Standard_Real aCurParam = aVert.ParameterOnLine();
1109 aVert.SetParameter(aNbPts-aCurParam+1);
1110 theWLine1->AddVertex(aVert, Standard_True);
1111 }
1112
1113 theHasBeenJoined = Standard_True;
1114}
1115
1116//=======================================================================
1117//function : ExtendTwoWLFirstLast
1118//purpose : Performs extending theWLine1 through its start point and theWLine2
1119// through its end point.
1120//=======================================================================
e2e0498b 1121static void ExtendTwoWLFirstLast(const Handle(Adaptor3d_HSurface)& theS1,
1122 const Handle(Adaptor3d_HSurface)& theS2,
b8f67cc2 1123 const Handle(IntPatch_WLine)& theWLine1,
1124 const Handle(IntPatch_WLine)& theWLine2,
1125 const IntSurf_PntOn2S& thePtWL1,
1126 const IntSurf_PntOn2S& thePtWL2,
1127 const gp_Vec& theVec1,
1128 const gp_Vec& theVec2,
1129 const gp_Vec& theVec3,
1130 const Bnd_Box2d& theBoxS1,
1131 const Bnd_Box2d& theBoxS2,
1132 const Standard_Real theToler3D,
e2e0498b 1133 const Standard_Real* const theArrPeriods,
b8f67cc2 1134 unsigned int &theCheckResult,
1135 Standard_Boolean &theHasBeenJoined)
1136{
1137 IntSurf_PntOn2S aPOn2S;
e2e0498b 1138 const IntPatchWT_WLsConnectionType aCheckRes =
1139 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1140 theVec1, theVec2, theVec3,
1141 theBoxS1, theBoxS2,
1142 theToler3D, theArrPeriods);
1143
1144 if(aCheckRes != IntPatchWT_NotConnected)
1145 theCheckResult |= IntPatchWT_DisLastLast;
1146 else
b8f67cc2 1147 return;
b8f67cc2 1148
e2e0498b 1149 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
b8f67cc2 1150 ExtendFirst(theWLine1, aPOn2S);
e2e0498b 1151 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
b8f67cc2 1152 ExtendLast (theWLine2, aPOn2S);
1153
e2e0498b 1154 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
b8f67cc2 1155 return;
1156
1157 Standard_Real aPrm = theWLine1->Vertex(1).ParameterOnLine();
1158 while(theWLine1->Vertex(1).ParameterOnLine() == aPrm)
1159 theWLine1->RemoveVertex(1);
1160
1161 aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
1162 while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
1163 theWLine2->RemoveVertex(theWLine2->NbVertex());
1164
1165 const Standard_Integer aNbPts = theWLine2->NbPnts();
1166 for(Standard_Integer aNPt = aNbPts - 1; aNPt >= 1; aNPt--)
1167 {
1168 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1169 theWLine1->Curve()->InsertBefore(1, aPt);
1170 }
1171
1172 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine1->NbVertex(); aNVtx++)
1173 {
1174 IntPatch_Point &aVert = theWLine1->ChangeVertex(aNVtx);
1175 const Standard_Real aCurParam = aVert.ParameterOnLine();
1176 aVert.SetParameter(aNbPts+aCurParam-1);
1177 }
1178
1179 for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
1180 {
1181 const IntPatch_Point &aVert = theWLine2->Vertex(aNVtx);
1182 theWLine1->AddVertex(aVert, Standard_True);
1183 }
1184
1185 theHasBeenJoined = Standard_True;
1186}
1187
1188//=======================================================================
1189//function : ExtendTwoWLLastFirst
1190//purpose : Performs extending theWLine1 through its end point and theWLine2
1191// through its start point.
1192//=======================================================================
e2e0498b 1193static void ExtendTwoWLLastFirst(const Handle(Adaptor3d_HSurface)& theS1,
1194 const Handle(Adaptor3d_HSurface)& theS2,
b8f67cc2 1195 const Handle(IntPatch_WLine)& theWLine1,
1196 const Handle(IntPatch_WLine)& theWLine2,
1197 const IntSurf_PntOn2S& thePtWL1,
1198 const IntSurf_PntOn2S& thePtWL2,
1199 const gp_Vec& theVec1,
1200 const gp_Vec& theVec2,
1201 const gp_Vec& theVec3,
1202 const Bnd_Box2d& theBoxS1,
1203 const Bnd_Box2d& theBoxS2,
1204 const Standard_Real theToler3D,
e2e0498b 1205 const Standard_Real* const theArrPeriods,
b8f67cc2 1206 unsigned int &theCheckResult,
1207 Standard_Boolean &theHasBeenJoined)
1208{
1209 IntSurf_PntOn2S aPOn2S;
e2e0498b 1210 const IntPatchWT_WLsConnectionType aCheckRes =
1211 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1212 theVec1, theVec2, theVec3,
1213 theBoxS1, theBoxS2,
1214 theToler3D, theArrPeriods);
1215
1216 if(aCheckRes != IntPatchWT_NotConnected)
1217 theCheckResult |= IntPatchWT_DisLastLast;
1218 else
b8f67cc2 1219 return;
b8f67cc2 1220
e2e0498b 1221 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
b8f67cc2 1222 ExtendLast (theWLine1, aPOn2S);
e2e0498b 1223 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
b8f67cc2 1224 ExtendFirst(theWLine2, aPOn2S);
1225
e2e0498b 1226 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
b8f67cc2 1227 {
1228 return;
1229 }
1230
1231 Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
1232 while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
1233 theWLine1->RemoveVertex(theWLine1->NbVertex());
1234
1235 aPrm = theWLine2->Vertex(1).ParameterOnLine();
1236 while(theWLine2->Vertex(1).ParameterOnLine() == aPrm)
1237 theWLine2->RemoveVertex(1);
1238
1239 const Standard_Integer aNbPts = theWLine1->NbPnts();
1240 for(Standard_Integer aNPt = 2; aNPt <= theWLine2->NbPnts(); aNPt++)
1241 {
1242 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1243 theWLine1->Curve()->Add(aPt);
1244 }
1245
1246 for(Standard_Integer aNVtx = 1; aNVtx <= theWLine2->NbVertex(); aNVtx++)
1247 {
1248 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1249 const Standard_Real aCurParam = aVert.ParameterOnLine();
1250 aVert.SetParameter(aNbPts+aCurParam-1);
1251 theWLine1->AddVertex(aVert, Standard_False);
1252 }
1253
1254 theHasBeenJoined = Standard_True;
1255}
1256
1257//=======================================================================
1258//function : ExtendTwoWLLastLast
1259//purpose :
1260//=======================================================================
e2e0498b 1261static void ExtendTwoWLLastLast(const Handle(Adaptor3d_HSurface)& theS1,
1262 const Handle(Adaptor3d_HSurface)& theS2,
b8f67cc2 1263 const Handle(IntPatch_WLine)& theWLine1,
1264 const Handle(IntPatch_WLine)& theWLine2,
1265 const IntSurf_PntOn2S& thePtWL1,
1266 const IntSurf_PntOn2S& thePtWL2,
1267 const gp_Vec& theVec1,
1268 const gp_Vec& theVec2,
1269 const gp_Vec& theVec3,
1270 const Bnd_Box2d& theBoxS1,
1271 const Bnd_Box2d& theBoxS2,
1272 const Standard_Real theToler3D,
e2e0498b 1273 const Standard_Real* const theArrPeriods,
1274 unsigned int &theCheckResult,
b8f67cc2 1275 Standard_Boolean &theHasBeenJoined)
1276{
1277 IntSurf_PntOn2S aPOn2S;
e2e0498b 1278 const IntPatchWT_WLsConnectionType aCheckRes =
1279 CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1280 theVec1, theVec2, theVec3,
1281 theBoxS1, theBoxS2,
1282 theToler3D, theArrPeriods);
b8f67cc2 1283
e2e0498b 1284 if(aCheckRes != IntPatchWT_NotConnected)
1285 theCheckResult |= IntPatchWT_DisLastLast;
1286 else
1287 return;
b8f67cc2 1288
e2e0498b 1289 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
b8f67cc2 1290 ExtendLast(theWLine1, aPOn2S);
e2e0498b 1291 IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
b8f67cc2 1292 ExtendLast(theWLine2, aPOn2S);
1293
e2e0498b 1294 if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
b8f67cc2 1295 return;
1296
1297 Standard_Real aPrm = theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine();
1298 while(theWLine1->Vertex(theWLine1->NbVertex()).ParameterOnLine() == aPrm)
1299 theWLine1->RemoveVertex(theWLine1->NbVertex());
1300
1301 aPrm = theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine();
1302 while(theWLine2->Vertex(theWLine2->NbVertex()).ParameterOnLine() == aPrm)
1303 theWLine2->RemoveVertex(theWLine2->NbVertex());
1304
1305 const Standard_Integer aNbPts = theWLine1->NbPnts() + theWLine2->NbPnts();
1306 for(Standard_Integer aNPt = theWLine2->NbPnts()-1; aNPt >= 1; aNPt--)
1307 {
1308 const IntSurf_PntOn2S& aPt = theWLine2->Point(aNPt);
1309 theWLine1->Curve()->Add(aPt);
1310 }
1311
1312 for(Standard_Integer aNVtx = theWLine2->NbVertex(); aNVtx >= 1; aNVtx--)
1313 {
1314 IntPatch_Point &aVert = theWLine2->ChangeVertex(aNVtx);
1315 const Standard_Real aCurParam = aVert.ParameterOnLine();
1316 aVert.SetParameter(aNbPts - aCurParam);
1317 theWLine1->AddVertex(aVert, Standard_False);
1318 }
1319
1320 theHasBeenJoined = Standard_True;
eee615ad 1321}
1322
4e14c88f 1323//=========================================================================
1324// function : ComputePurgedWLine
1325// purpose :
1326//=========================================================================
1327Handle(IntPatch_WLine) IntPatch_WLineTool::
1328 ComputePurgedWLine(const Handle(IntPatch_WLine) &theWLine,
1329 const Handle(Adaptor3d_HSurface) &theS1,
1330 const Handle(Adaptor3d_HSurface) &theS2,
1331 const Handle(Adaptor3d_TopolTool) &theDom1,
7797eb38 1332 const Handle(Adaptor3d_TopolTool) &theDom2)
4e14c88f 1333{
1334 Standard_Integer i, k, v, nb, nbvtx;
1335 Handle(IntPatch_WLine) aResult;
1336 nbvtx = theWLine->NbVertex();
1337 nb = theWLine->NbPnts();
1338 if (nb==2)
1339 {
1340 const IntSurf_PntOn2S& p1 = theWLine->Point(1);
1341 const IntSurf_PntOn2S& p2 = theWLine->Point(2);
1342 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()))
1343 return aResult;
1344 }
1345
1346 Handle(IntPatch_WLine) aLocalWLine;
1347 Handle(IntPatch_WLine) aTmpWLine = theWLine;
1348 Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
1349 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
1350 for(i = 1; i <= nb; i++)
1351 aLineOn2S->Add(theWLine->Point(i));
1352
1353 for(v = 1; v <= nbvtx; v++)
1354 aLocalWLine->AddVertex(theWLine->Vertex(v));
1355
1356 // I: Delete equal points
1357 for(i = 1; i <= aLineOn2S->NbPoints(); i++)
1358 {
1359 Standard_Integer aStartIndex = i + 1;
1360 Standard_Integer anEndIndex = i + 5;
1361 nb = aLineOn2S->NbPoints();
1362 anEndIndex = (anEndIndex > nb) ? nb : anEndIndex;
1363
1364 if((aStartIndex > nb) || (anEndIndex <= 1))
1365 continue;
1366
1367 k = aStartIndex;
1368
1369 while(k <= anEndIndex)
1370 {
1371 if(i != k)
1372 {
1373 IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
1374 IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
1375
1376 Standard_Real UV[8];
1377 p1.Parameters(UV[0], UV[1], UV[2], UV[3]);
1378 p2.Parameters(UV[4], UV[5], UV[6], UV[7]);
1379
1380 Standard_Real aMax = Abs(UV[0]);
1381 for(Standard_Integer anIdx = 1; anIdx < 8; anIdx++)
1382 {
1383 if (aMax < Abs(UV[anIdx]))
1384 aMax = Abs(UV[anIdx]);
1385 }
1386
1387 if(p1.Value().IsEqual(p2.Value(), gp::Resolution()) ||
1388 Abs(UV[0] - UV[4]) + Abs(UV[1] - UV[5]) < 1.0e-16 * aMax ||
1389 Abs(UV[2] - UV[6]) + Abs(UV[3] - UV[7]) < 1.0e-16 * aMax )
1390 {
1391 aTmpWLine = aLocalWLine;
1392 aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
1393
1394 for(v = 1; v <= aTmpWLine->NbVertex(); v++)
1395 {
1396 IntPatch_Point aVertex = aTmpWLine->Vertex(v);
1397 Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
1398
1399 if(avertexindex >= k)
1400 {
1401 aVertex.SetParameter(aVertex.ParameterOnLine() - 1.);
1402 }
1403 aLocalWLine->AddVertex(aVertex);
1404 }
1405 aLineOn2S->RemovePoint(k);
1406 anEndIndex--;
1407 continue;
1408 }
1409 }
1410 k++;
1411 }
1412 }
1413
1414 if (aLineOn2S->NbPoints() <= 2)
1415 {
1416 if (aLineOn2S->NbPoints() == 2)
1417 return aLocalWLine;
1418 else
1419 return aResult;
1420 }
1421
1422 // Avoid purge in case of C0 continuity:
1423 // Intersection approximator may produce invalid curve after purge, example:
1424 // bugs modalg_5 bug24731.
1425 // Do not run purger when base number of points is too small.
1426 if (theS1->UContinuity() == GeomAbs_C0 ||
1427 theS1->VContinuity() == GeomAbs_C0 ||
1428 theS2->UContinuity() == GeomAbs_C0 ||
1429 theS2->VContinuity() == GeomAbs_C0 ||
1430 nb < aNbSingleBezier)
1431 {
1432 return aLocalWLine;
1433 }
1434
7797eb38 1435 // II: Delete out of borders points.
1436 aLocalWLine = DeleteOuterPoints(aLocalWLine, theS1, theS2, theDom1, theDom2);
4e14c88f 1437
1438 // III: Delete points by tube criteria.
1439 Handle(IntPatch_WLine) aLocalWLineTube =
5185b161 1440 DeleteByTube(aLocalWLine, theS1, theS2);
4e14c88f 1441
1442 if(aLocalWLineTube->NbPnts() > 1)
1443 {
1444 aResult = aLocalWLineTube;
1445 }
1446 return aResult;
1447}
1448
4e14c88f 1449//=======================================================================
1450//function : JoinWLines
1451//purpose :
1452//=======================================================================
1453void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
1454 IntPatch_SequenceOfPoint& theSPnt,
261b7d9e 1455 Handle(Adaptor3d_HSurface) theS1,
1456 Handle(Adaptor3d_HSurface) theS2,
1457 const Standard_Real theTol3D)
4e14c88f 1458{
1459 if(theSlin.Length() == 0)
1460 return;
1461
261b7d9e 1462 // For two cylindrical surfaces only
1463 const Standard_Real aMinRad = 1.0e-3*Min(theS1->Cylinder().Radius(),
1464 theS2->Cylinder().Radius());
1465
1466 const Standard_Real anArrPeriods[4] = {theS1->IsUPeriodic() ? theS1->UPeriod() : 0.0,
1467 theS1->IsVPeriodic() ? theS1->VPeriod() : 0.0,
1468 theS2->IsUPeriodic() ? theS2->UPeriod() : 0.0,
1469 theS2->IsVPeriodic() ? theS2->VPeriod() : 0.0};
1470
1471 const Standard_Real anArrFBonds[4] = {theS1->FirstUParameter(), theS1->FirstVParameter(),
1472 theS2->FirstUParameter(), theS2->FirstVParameter()};
1473 const Standard_Real anArrLBonds[4] = {theS1->LastUParameter(), theS1->LastVParameter(),
1474 theS2->LastUParameter(), theS2->LastVParameter()};
1475
1476 Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator();
1477
1478 for(Standard_Integer aN1 = 1; aN1 <= theSlin.Length(); aN1++)
4e14c88f 1479 {
261b7d9e 1480 Handle(IntPatch_WLine) aWLine1(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aN1)));
4e14c88f 1481
1482 if(aWLine1.IsNull())
1483 {//We must have failed to join not-point-lines
1484 continue;
1485 }
1486
1487 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
261b7d9e 1488 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1489 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
4e14c88f 1490
1491 for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
1492 {
1493 const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
1494
261b7d9e 1495 if( aPntCur.IsSame(aPntFWL1, Precision::Confusion()) ||
1496 aPntCur.IsSame(aPntLWL1, Precision::Confusion()))
4e14c88f 1497 {
1498 theSPnt.Remove(aNPt);
1499 aNPt--;
1500 }
1501 }
1502
261b7d9e 1503 anAlloc->Reset();
1504 NCollection_List<Standard_Integer> aListFC(anAlloc),
1505 aListLC(anAlloc);
1506
1507 Standard_Boolean isFirstConnected = Standard_False, isLastConnected = Standard_False;
1508
1509 for (Standard_Integer aN2 = 1; aN2 <= theSlin.Length(); aN2++)
4e14c88f 1510 {
261b7d9e 1511 if (aN2 == aN1)
1512 continue;
4e14c88f 1513
261b7d9e 1514 Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aN2)));
1515
1516 if (aWLine2.IsNull())
4e14c88f 1517 continue;
1518
261b7d9e 1519 isFirstConnected = isLastConnected = Standard_False;
4e14c88f 1520
261b7d9e 1521 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
4e14c88f 1522
1523 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1524 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1525
261b7d9e 1526 Standard_Real aSqDistF = aPntFWL1.Value().SquareDistance(aPntFWL2.Value());
1527 Standard_Real aSqDistL = aPntFWL1.Value().SquareDistance(aPntLWL2.Value());
1528
1529 const Standard_Real aSqMinFDist = Min(aSqDistF, aSqDistL);
1530 if (aSqMinFDist < Precision::SquareConfusion())
4e14c88f 1531 {
3306fdd9 1532 const Standard_Boolean isFM = (aSqDistF < aSqDistL);
1533 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
1534 const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
1535 aWLine2->Point(aNbPntsWL2 - 1);
1536 if (!IsSeamOrBound(aPt1, aPt2, aPntFWL1,
1537 anArrPeriods, anArrFBonds, anArrLBonds))
4e14c88f 1538 {
3306fdd9 1539 isFirstConnected = Standard_True;
4e14c88f 1540 }
1541 }
1542
261b7d9e 1543 aSqDistF = aPntLWL1.Value().SquareDistance(aPntFWL2.Value());
1544 aSqDistL = aPntLWL1.Value().SquareDistance(aPntLWL2.Value());
1545
1546 const Standard_Real aSqMinLDist = Min(aSqDistF, aSqDistL);
1547 if (aSqMinLDist < Precision::SquareConfusion())
4e14c88f 1548 {
3306fdd9 1549 const Standard_Boolean isFM = (aSqDistF < aSqDistL);
1550 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1 - 1);
1551 const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
1552 aWLine2->Point(aNbPntsWL2 - 1);
1553 if (!IsSeamOrBound(aPt1, aPt2, aPntLWL1,
1554 anArrPeriods, anArrFBonds, anArrLBonds))
4e14c88f 1555 {
3306fdd9 1556 isLastConnected = Standard_True;
4e14c88f 1557 }
1558 }
1559
261b7d9e 1560 if (isFirstConnected && isLastConnected)
4e14c88f 1561 {
261b7d9e 1562 if (aSqMinFDist < aSqMinLDist)
4e14c88f 1563 {
261b7d9e 1564 aListFC.Append(aN2);
1565 }
1566 else
1567 {
1568 aListLC.Append(aN2);
1569 }
1570 }
1571 else if (isFirstConnected)
1572 {
1573 aListFC.Append(aN2);
1574 }
1575 else if (isLastConnected)
1576 {
1577 aListLC.Append(aN2);
1578 }
1579 }
4e14c88f 1580
261b7d9e 1581 isFirstConnected = (aListFC.Extent() == 1);
1582 isLastConnected = (aListLC.Extent() == 1);
4e14c88f 1583
261b7d9e 1584 if (!(isFirstConnected || isLastConnected))
1585 {
1586 continue;
1587 }
4e14c88f 1588
261b7d9e 1589 const Standard_Integer anIndexWL2 = isFirstConnected ? aListFC.First() : aListLC.First();
1590 Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(anIndexWL2)));
261b7d9e 1591 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1592 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
3306fdd9 1593 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1594
261b7d9e 1595 if (isFirstConnected)
1596 {
3306fdd9 1597 const Standard_Real aSqDistF = aPntFWL1.Value().SquareDistance(aPntFWL2.Value());
1598 const Standard_Real aSqDistL = aPntFWL1.Value().SquareDistance(aPntLWL2.Value());
1599 const Standard_Boolean isFM = (aSqDistF < aSqDistL);
1600
1601 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
1602 const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
1603 aWLine2->Point(aNbPntsWL2 - 1);
1604
1605 if (!CheckArgumentsToJoin(theS1, theS2, aPntFWL1, aPt1.Value(),
1606 aPntFWL1.Value(), aPt2.Value(), aMinRad))
1607 {
1608 continue;
1609 }
1610
1611 aWLine1->ClearVertexes();
1612
1613 if (isFM)
261b7d9e 1614 {
1615 //First-First-connection
1616 for (Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
1617 {
1618 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1619 aWLine1->Curve()->InsertBefore(1, aPt);
4e14c88f 1620 }
1621 }
261b7d9e 1622 else
4e14c88f 1623 {
261b7d9e 1624 //First-Last-connection
1625 for (Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
4e14c88f 1626 {
261b7d9e 1627 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1628 aWLine1->Curve()->InsertBefore(1, aPt);
1629 }
1630 }
1631 }
1632 else //if (isLastConnected)
1633 {
3306fdd9 1634 const Standard_Real aSqDistF = aPntLWL1.Value().SquareDistance(aPntFWL2.Value());
1635 const Standard_Real aSqDistL = aPntLWL1.Value().SquareDistance(aPntLWL2.Value());
1636
1637 const Standard_Boolean isFM = (aSqDistF < aSqDistL);
1638 const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1 - 1);
1639 const IntSurf_PntOn2S& aPt2 = isFM ? aWLine2->Point(2) :
1640 aWLine2->Point(aNbPntsWL2 - 1);
1641
1642 if (!CheckArgumentsToJoin(theS1, theS2, aPntLWL1, aPt1.Value(),
1643 aPntFWL1.Value(), aPt2.Value(), aMinRad))
1644 {
1645 continue;
1646 }
1647
1648 aWLine1->ClearVertexes();
1649
1650 if (isFM)
261b7d9e 1651 {
1652 //Last-First connection
3306fdd9 1653 for (Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
261b7d9e 1654 {
1655 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1656 aWLine1->Curve()->Add(aPt);
1657 }
1658 }
1659 else
1660 {
1661 //Last-Last connection
1662 for (Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
1663 {
1664 const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1665 aWLine1->Curve()->Add(aPt);
4e14c88f 1666 }
1667 }
1668 }
1669
261b7d9e 1670 aWLine1->ComputeVertexParameters(theTol3D);
1671 theSlin.Remove(anIndexWL2);
1672 aN1--;
4e14c88f 1673 }
eee615ad 1674}
1675
1676//=======================================================================
e2e0498b 1677//function : ExtendTwoWLines
b8f67cc2 1678//purpose : Performs extending theWLine1 and theWLine2 through their
1679// respecting end point.
eee615ad 1680//=======================================================================
3306fdd9 1681void IntPatch_WLineTool::
1682 ExtendTwoWLines(IntPatch_SequenceOfLine& theSlin,
1683 const Handle(Adaptor3d_HSurface)& theS1,
1684 const Handle(Adaptor3d_HSurface)& theS2,
1685 const Standard_Real theToler3D,
1686 const Standard_Real* const theArrPeriods,
1687 const Bnd_Box2d& theBoxS1,
1688 const Bnd_Box2d& theBoxS2,
1689 const NCollection_List<gp_Pnt>& theListOfCriticalPoints)
eee615ad 1690{
1691 if(theSlin.Length() < 2)
1692 return;
1693
eee615ad 1694 gp_Vec aVec1, aVec2, aVec3;
1695
1696 for(Standard_Integer aNumOfLine1 = 1; aNumOfLine1 <= theSlin.Length(); aNumOfLine1++)
1697 {
1698 Handle(IntPatch_WLine) aWLine1 (Handle(IntPatch_WLine)::
1699 DownCast(theSlin.Value(aNumOfLine1)));
1700
1701 if(aWLine1.IsNull())
1702 {//We must have failed to join not-point-lines
1703 continue;
1704 }
1705
1706 const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
1707
b8f67cc2 1708 if(aWLine1->Vertex(1).ParameterOnLine() != 1)
1709 continue;
1710
1711 if(aWLine1->Vertex(aWLine1->NbVertex()).ParameterOnLine() != aWLine1->NbPnts())
1712 continue;
1713
e2e0498b 1714 const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1715 const IntSurf_PntOn2S& aPntFp1WL1 = aWLine1->Point(2);
1716
1717 const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
1718 const IntSurf_PntOn2S& aPntLm1WL1 = aWLine1->Point(aNbPntsWL1-1);
1719
1720 //Enable/Disable of some ckeck. Bit-mask is used for it.
1721 //E.g. if 1st point of aWLine1 matches with
1722 //1st point of aWLine2 then we do not need in check
1723 //1st point of aWLine1 and last point of aWLine2 etc.
1724 unsigned int aCheckResult = IntPatchWT_EnAll;
1725
1726 //If aWLine1 is already connected with another Wline then
1727 //there is no point in extending.
1728 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
1729 aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1730 {
1731 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::
1732 DownCast(theSlin.Value(aNumOfLine2)));
1733
1734 if(aWLine2.IsNull())
1735 continue;
1736
1737 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1738 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aWLine2->NbPnts());
1739
1740 if( aPntFWL1.IsSame(aPntFWL2, theToler3D) ||
1741 aPntFWL1.IsSame(aPntLWL2, theToler3D) )
1742 {
1743 aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast;
1744 }
1745
1746 if( aPntLWL1.IsSame(aPntFWL2, theToler3D) ||
1747 aPntLWL1.IsSame(aPntFWL2, theToler3D))
1748 {
1749 aCheckResult |= IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast;
1750 }
3306fdd9 1751
1752 if (!theListOfCriticalPoints.IsEmpty())
1753 {
1754 for (NCollection_List<gp_Pnt>::Iterator anItr(theListOfCriticalPoints);
1755 anItr.More(); anItr.Next())
1756 {
1757 const gp_Pnt &aPt = anItr.Value();
1758 if (!(aCheckResult & (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast)))
1759 {
1760 if (aPt.SquareDistance(aPntFWL1.Value()) < Precision::Confusion())
1761 {
1762 aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast;
1763 }
1764 }
1765
1766 if (!(aCheckResult & (IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast)))
1767 {
1768 if (aPt.SquareDistance(aPntLWL1.Value()) < Precision::Confusion())
1769 {
1770 aCheckResult |= IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast;
1771 }
1772 }
1773
1774 if (!(aCheckResult & (IntPatchWT_DisFirstFirst | IntPatchWT_DisLastFirst)))
1775 {
1776 if (aPt.SquareDistance(aPntFWL2.Value()) < Precision::Confusion())
1777 {
1778 aCheckResult |= IntPatchWT_DisFirstFirst | IntPatchWT_DisLastFirst;
1779 }
1780 }
1781
1782 if (!(aCheckResult & (IntPatchWT_DisFirstLast | IntPatchWT_DisLastLast)))
1783 {
1784 if (aPt.SquareDistance(aPntLWL2.Value()) < Precision::Confusion())
1785 {
1786 aCheckResult |= IntPatchWT_DisFirstLast | IntPatchWT_DisLastLast;
1787 }
1788 }
1789 }
1790 }
e2e0498b 1791 }
1792
1793 if(aCheckResult == (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast |
1794 IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast))
1795 continue;
1796
eee615ad 1797 for(Standard_Integer aNumOfLine2 = aNumOfLine1 + 1;
1798 aNumOfLine2 <= theSlin.Length(); aNumOfLine2++)
1799 {
1800 Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::
1801 DownCast(theSlin.Value(aNumOfLine2)));
1802
1803 if(aWLine2.IsNull())
1804 continue;
1805
b8f67cc2 1806 if(aWLine2->Vertex(1).ParameterOnLine() != 1)
1807 continue;
1808
1809 if(aWLine2->Vertex(aWLine2->NbVertex()).ParameterOnLine() != aWLine2->NbPnts())
1810 continue;
1811
b8f67cc2 1812 Standard_Boolean hasBeenJoined = Standard_False;
1813
eee615ad 1814 const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1815
eee615ad 1816 const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1817 const IntSurf_PntOn2S& aPntFp1WL2 = aWLine2->Point(2);
1818
1819 const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1820 const IntSurf_PntOn2S& aPntLm1WL2 = aWLine2->Point(aNbPntsWL2-1);
1821
1822 //if(!(aCheckResult & IntPatchWT_DisFirstFirst))
1823 {// First/First
1824 aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
1825 aVec2.SetXYZ(aPntFWL2.Value().XYZ() - aPntFp1WL2.Value().XYZ());
1826 aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntFWL2.Value().XYZ());
1827
b8f67cc2 1828 ExtendTwoWLFirstFirst(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntFWL2,
1829 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
e2e0498b 1830 theArrPeriods, aCheckResult, hasBeenJoined);
b8f67cc2 1831 }
eee615ad 1832
1833 if(!(aCheckResult & IntPatchWT_DisFirstLast))
1834 {// First/Last
1835 aVec1.SetXYZ(aPntFp1WL1.Value().XYZ() - aPntFWL1.Value().XYZ());
1836 aVec2.SetXYZ(aPntLWL2.Value().XYZ() - aPntLm1WL2.Value().XYZ());
1837 aVec3.SetXYZ(aPntFWL1.Value().XYZ() - aPntLWL2.Value().XYZ());
1838
b8f67cc2 1839 ExtendTwoWLFirstLast(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntLWL2,
1840 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
e2e0498b 1841 theArrPeriods, aCheckResult, hasBeenJoined);
b8f67cc2 1842 }
eee615ad 1843
1844 if(!(aCheckResult & IntPatchWT_DisLastFirst))
1845 {// Last/First
1846 aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
1847 aVec2.SetXYZ(aPntFp1WL2.Value().XYZ() - aPntFWL2.Value().XYZ());
1848 aVec3.SetXYZ(aPntFWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
1849
b8f67cc2 1850 ExtendTwoWLLastFirst(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntFWL2,
1851 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
e2e0498b 1852 theArrPeriods, aCheckResult, hasBeenJoined);
b8f67cc2 1853 }
eee615ad 1854
1855 if(!(aCheckResult & IntPatchWT_DisLastLast))
1856 {// Last/Last
1857 aVec1.SetXYZ(aPntLWL1.Value().XYZ() - aPntLm1WL1.Value().XYZ());
1858 aVec2.SetXYZ(aPntLm1WL2.Value().XYZ() - aPntLWL2.Value().XYZ());
1859 aVec3.SetXYZ(aPntLWL2.Value().XYZ() - aPntLWL1.Value().XYZ());
1860
b8f67cc2 1861 ExtendTwoWLLastLast(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntLWL2,
1862 aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
e2e0498b 1863 theArrPeriods, aCheckResult, hasBeenJoined);
b8f67cc2 1864 }
1865
1866 if(hasBeenJoined)
1867 {
1868 theSlin.Remove(aNumOfLine2);
1869 aNumOfLine2--;
1870 }
eee615ad 1871 }
1872 }
1873}