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