b5e9532aa97820f5c2c343700602cbcbc0be3c88
[occt.git] / src / IntPatch / IntPatch_WLineTool.cxx
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>
18 #include <Bnd_Range.hxx>
19 #include <ElCLib.hxx>
20 #include <ElSLib.hxx>
21 #include <IntPatch_SpecialPoints.hxx>
22 #include <NCollection_IncAllocator.hxx>
23 #include <TopAbs_State.hxx>
24
25 // It is pure empirical value.
26 const Standard_Real IntPatch_WLineTool::myMaxConcatAngle = M_PI/6;
27
28 //Bit-mask is used for information about 
29 //the operation made in
30 //IntPatch_WLineTool::ExtendTwoWLines(...) method.
31 enum
32 {
33   IntPatchWT_EnAll = 0x00,
34   IntPatchWT_DisLastLast = 0x01,
35   IntPatchWT_DisLastFirst = 0x02,
36   IntPatchWT_DisFirstLast = 0x04,
37   IntPatchWT_DisFirstFirst = 0x08
38 };
39
40 enum IntPatchWT_WLsConnectionType
41 {
42   IntPatchWT_NotConnected,
43   IntPatchWT_Singular,
44   IntPatchWT_Common,
45   IntPatchWT_ReqExtend
46 };
47
48 //=======================================================================
49 //function : MinMax
50 //purpose  : Replaces theParMIN = MIN(theParMIN, theParMAX),
51 //                    theParMAX = MAX(theParMIN, theParMAX).
52 //
53 //           Static subfunction in IsSeamOrBound.
54 //=======================================================================
55 static 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 //=========================================================================
70 static 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 //=========================================================================
94 static Handle(IntPatch_WLine) MakeNewWLine(const Handle(IntPatch_WLine)         &theWLine,
95                                            NCollection_Array1<Standard_Integer> &thePointsHash,
96                                            const Standard_Boolean theIsOuter)
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);
102   Standard_Integer anOldLineIdx = 1, aVertexIdx = 1, anIndexPrev = -1, anIdxOld = -1;
103   gp_Pnt aPPrev, aPOld;
104   for(i = 1; i <= thePointsHash.Upper(); i++)
105   {
106     if (thePointsHash(i) == 0)
107     {
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       }
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));
177       aPPrev = aPOld = theWLine->Point(i).Value();
178       anIndexPrev = anIdxOld = i;
179     }
180
181     //Other points will be rejected by purger.
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 //=========================================================================
193 static 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 //=========================================================================
214 static 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.
309   Handle(IntPatch_WLine) aLocalWLine = MakeNewWLine(theWLine, aDelOuterPointsHash, Standard_True);
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 //=========================================================================
350 static 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 //=========================================================================
370 static 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
384 static const Standard_Integer aMinNbBadDistr = 15;
385 static 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 //=========================================================================
392 static 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
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))
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
545       //Vertex must be stored as VERTEX (HASH = -1)
546       if (aNewPointsHash(aHashIdx) != -1)
547         aNewPointsHash(aHashIdx) = 0;
548     }
549   }
550
551   return MakeNewWLine(theWLine, aNewPointsHash, Standard_False);
552 }
553
554 //=======================================================================
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.
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.
562 //            See comments in function body for detail information.
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.
570 //=======================================================================
571 static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
572                                       const IntSurf_PntOn2S& thePtl,
573                                       const IntSurf_PntOn2S& thePtmid,
574                                       const Standard_Real theArrPeriods[4],
575                                       const Standard_Real theFBound[4],
576                                       const Standard_Real theLBound[4])
577 {
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]);
582
583   Bnd_Range aBndR[4];
584
585   for (Standard_Integer i = 0; i < 4; i++)
586   {
587     aBndR[i].Add(aParF[i]);
588     aBndR[i].Add(aParL[i]);
589
590     if (aBndR[i].IsIntersected(theFBound[i], theArrPeriods[i]) == 1)
591       return Standard_True;
592
593     if (aBndR[i].IsIntersected(theLBound[i], theArrPeriods[i]) == 1)
594       return Standard_True;
595   }
596
597   for (Standard_Integer i = 0; i < 4; i++)
598   {
599     if (theArrPeriods[i] == 0.0)
600     {
601       //Strictly equal
602       continue;
603     }
604
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     }
611
612     if (aBndR[i].IsIntersected(0.0, theArrPeriods[i]) == 1)
613       return Standard_True;
614   }
615
616   //The segment [thePtf, thePtl] does not intersect the boundaries and
617   //the seam-edge of the surfaces.
618   //Nevertheless, following situation is possible:
619
620   //              seam or
621   //               bound
622   //                 |
623   //    thePtf  *    |
624   //                 |
625   //                 * thePtmid
626   //      thePtl  *  |
627   //                 |
628
629   //This case must be processed, too.
630
631   Standard_Real aMPar[4] = { 0.0, 0.0, 0.0, 0.0 };
632   thePtmid.Parameters(aMPar[0], aMPar[1], aMPar[2], aMPar[3]);
633
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;
639
640     if (aBR.IsIntersected(theLBound[i], theArrPeriods[i]))
641       return Standard_True;
642
643     if (aBR.IsIntersected(0.0, theArrPeriods[i]))
644       return Standard_True;
645   }
646
647   return Standard_False;
648 }
649
650 //=======================================================================
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 //=======================================================================
657 static Standard_Boolean IsIntersectionPoint(const gp_Pnt& thePmid,
658                                             const Handle(Adaptor3d_HSurface)& theS1,
659                                             const Handle(Adaptor3d_HSurface)& theS2,
660                                             const IntSurf_PntOn2S& theRefPt,
661                                             const Standard_Real theTol,
662                                             const Standard_Real* const theArrPeriods,
663                                             IntSurf_PntOn2S& theNewPt)
664 {
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;
706
707   case GeomAbs_Cone:
708     ElSLib::Parameters(theS2->Cone(), thePmid, aU2, aV2);
709     break;
710
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));
725
726   return (aP1.SquareDistance(aP2) <= theTol*theTol);
727 }
728
729 //=======================================================================
730 //function : ExtendFirst
731 //purpose  : Adds thePOn2S to the begin of theWline
732 //=======================================================================
733 static void ExtendFirst(const Handle(IntPatch_WLine)& theWline,
734                         const IntSurf_PntOn2S& theAddedPt)
735 {
736   Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
737   theAddedPt.Parameters(aU1, aV1, aU2, aV2);
738
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;
747
748       aVert.SetParameters(aU1, aV1, aU2, aV2);
749       aVert.SetValue(theAddedPt.Value());
750     }
751
752     return;
753   }
754
755   theWline->Curve()->InsertBefore(1, theAddedPt);
756
757   for(Standard_Integer i = 1; i <= theWline->NbVertex(); i++)
758   {
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     }
770   }
771 }
772
773 //=======================================================================
774 //function : ExtendLast
775 //purpose  : Adds thePOn2S to the end of theWline
776 //=======================================================================
777 static void ExtendLast(const Handle(IntPatch_WLine)& theWline,
778                         const IntSurf_PntOn2S& theAddedPt)
779 {
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   }
792
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;
798
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 //=========================================================================
810 static Standard_Boolean IsOutOfDomain(const Bnd_Box2d& theBoxS1,
811                                       const Bnd_Box2d& theBoxS2,
812                                       const IntSurf_PntOn2S &thePOn2S,
813                                       const Standard_Real* const theArrPeriods)
814 {
815   Standard_Real aU1 = 0.0, aV1 = 0.0, aU2 = 0.0, aV2 = 0.0;
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
819   thePOn2S.Parameters(aU1, aV1, aU2, aV2);
820
821   theBoxS1.Get(aU1min, aV1min, aU1max, aV1max);
822   theBoxS2.Get(aU2min, aV2min, aU2max, aV2max);
823
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]);
828
829   return (theBoxS1.IsOut(gp_Pnt2d(aU1, aV1)) ||
830           theBoxS2.IsOut(gp_Pnt2d(aU2, aV2)));
831 }
832
833 //=======================================================================
834 //function : CheckArgumentsToExtend
835 //purpose  : Check if extending is possible
836 //            (see IntPatch_WLineTool::ExtendTwoWLines)
837 //=======================================================================
838 static 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)
851 {
852   const Standard_Real aSqToler = theToler3D*theToler3D;
853   IntPatchWT_WLsConnectionType aRetVal = IntPatchWT_NotConnected;
854   if(theVec3.SquareMagnitude() <= aSqToler)
855   {
856     if ((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle))
857     {
858       return aRetVal;
859     }
860     else
861     {
862       aRetVal = IntPatchWT_Common;
863     }
864   }
865   else if((theVec1.Angle(theVec2) > IntPatch_WLineTool::myMaxConcatAngle) ||
866           (theVec1.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle) ||
867           (theVec2.Angle(theVec3) > IntPatch_WLineTool::myMaxConcatAngle))
868   {
869     return aRetVal;
870   }
871
872   const gp_Pnt aPmid(0.5*(thePtWL1.Value().XYZ()+thePtWL2.Value().XYZ()));
873
874   Standard_Real aNewPar[4] = {0.0, 0.0, 0.0, 0.0};
875
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]);
880
881   if(!IsIntersectionPoint(aPmid, theS1, theS2, thePtWL1, theToler3D,
882                           theArrPeriods, theNewPoint))
883   {
884     return IntPatchWT_NotConnected;
885   }
886
887   if(IsOutOfDomain(theBoxS1, theBoxS2, theNewPoint, theArrPeriods))
888   {
889     return IntPatchWT_NotConnected;
890   }
891
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]);
898
899   Bnd_Range aR1, aR2;
900
901   Standard_Boolean isOnBoundary = Standard_False;
902   for(Standard_Integer i = 0; i < 4; i++)
903   {
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]))
915     {
916       //Check, if we intersect surface boundary when we will extend Wline1 or Wline2
917       //to theNewPoint
918       MinMax(aParWL1[i], aParWL2[i]);
919       if(aNewPar[i] > aParWL2[i])
920       {
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] +
936                 theArrPeriods[i]*Ceiling((aNewPar[i]-aParWL1[i])/theArrPeriods[i]);
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]
952           
953         const Standard_Real aPar = aParWL2[i] - 
954                 theArrPeriods[i]*Ceiling((aParWL2[i]-aNewPar[i])/theArrPeriods[i]);
955         aParWL2[i] = aParWL1[i];
956         aParWL1[i] = aPar;
957       }
958
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]))
968       {
969         return IntPatchWT_NotConnected;
970       }
971       else
972       {
973         isOnBoundary = Standard_True;
974       }
975     }
976   }
977
978   if(isOnBoundary)
979   {
980     return IntPatchWT_Singular;
981   }
982
983   if (aRetVal == IntPatchWT_Common)
984   {
985     return IntPatchWT_Common;
986   }
987
988   return IntPatchWT_ReqExtend;
989 }
990
991 //=======================================================================
992 //function : CheckArgumentsToJoin
993 //purpose  : Check if joining is possible
994 //            (see IntPatch_WLineTool::JoinWLines(...))
995 //=======================================================================
996 Standard_Boolean CheckArgumentsToJoin(const Handle(Adaptor3d_HSurface)& theS1,
997                                       const Handle(Adaptor3d_HSurface)& theS2,
998                                       const IntSurf_PntOn2S& thePnt,
999                                       const gp_Pnt& theP1,
1000                                       const gp_Pnt& theP2,
1001                                       const gp_Pnt& theP3,
1002                                       const Standard_Real theMinRad)
1003 {
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   }
1015
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);
1040 }
1041
1042 //=======================================================================
1043 //function : ExtendTwoWLFirstFirst
1044 //purpose  : Performs extending theWLine1 and theWLine2 through their
1045 //            respecting start point.
1046 //=======================================================================
1047 static 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)
1062 {
1063   IntSurf_PntOn2S aPOn2S;
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
1073     return;
1074
1075   IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1076   ExtendFirst(theWLine1, aPOn2S);
1077   IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1078   ExtendFirst(theWLine2, aPOn2S);
1079
1080   if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
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 //=======================================================================
1121 static void ExtendTwoWLFirstLast(const Handle(Adaptor3d_HSurface)& theS1,
1122                                  const Handle(Adaptor3d_HSurface)& theS2,
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,
1133                                  const Standard_Real* const theArrPeriods,
1134                                  unsigned int &theCheckResult,
1135                                  Standard_Boolean &theHasBeenJoined)
1136 {
1137   IntSurf_PntOn2S aPOn2S;
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
1147     return;
1148
1149   IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1150   ExtendFirst(theWLine1, aPOn2S);
1151   IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1152   ExtendLast (theWLine2, aPOn2S);
1153
1154   if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
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 //=======================================================================
1193 static void ExtendTwoWLLastFirst(const Handle(Adaptor3d_HSurface)& theS1,
1194                                  const Handle(Adaptor3d_HSurface)& theS2,
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,
1205                                  const Standard_Real* const theArrPeriods,
1206                                  unsigned int &theCheckResult,
1207                                  Standard_Boolean &theHasBeenJoined)
1208 {
1209   IntSurf_PntOn2S aPOn2S;
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
1219     return;
1220
1221   IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1222   ExtendLast (theWLine1, aPOn2S);
1223   IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1224   ExtendFirst(theWLine2, aPOn2S);
1225
1226   if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
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 //=======================================================================
1261 static void ExtendTwoWLLastLast(const Handle(Adaptor3d_HSurface)& theS1,
1262                                 const Handle(Adaptor3d_HSurface)& theS2,
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,
1273                                 const Standard_Real* const theArrPeriods,
1274                                 unsigned int &theCheckResult,
1275                                 Standard_Boolean &theHasBeenJoined)
1276 {
1277   IntSurf_PntOn2S aPOn2S;
1278   const IntPatchWT_WLsConnectionType aCheckRes = 
1279                       CheckArgumentsToExtend(theS1, theS2, thePtWL1, thePtWL2, aPOn2S,
1280                                              theVec1, theVec2, theVec3,
1281                                              theBoxS1, theBoxS2,
1282                                              theToler3D, theArrPeriods);
1283   
1284   if(aCheckRes != IntPatchWT_NotConnected)
1285     theCheckResult |= IntPatchWT_DisLastLast;
1286   else
1287     return;
1288
1289   IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL1, theArrPeriods, aPOn2S);
1290   ExtendLast(theWLine1, aPOn2S);
1291   IntPatch_SpecialPoints::AdjustPointAndVertex(thePtWL2, theArrPeriods, aPOn2S);
1292   ExtendLast(theWLine2, aPOn2S);
1293
1294   if(theHasBeenJoined || (aCheckRes == IntPatchWT_Singular))
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;
1321 }
1322
1323 //=========================================================================
1324 // function : ComputePurgedWLine
1325 // purpose  :
1326 //=========================================================================
1327 Handle(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,
1332                      const Handle(Adaptor3d_TopolTool)  &theDom2)
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
1435   // II: Delete out of borders points.
1436   aLocalWLine = DeleteOuterPoints(aLocalWLine, theS1, theS2, theDom1, theDom2);
1437
1438   // III: Delete points by tube criteria.
1439   Handle(IntPatch_WLine) aLocalWLineTube = 
1440     DeleteByTube(aLocalWLine, theS1, theS2);
1441
1442   if(aLocalWLineTube->NbPnts() > 1)
1443   {
1444     aResult = aLocalWLineTube;
1445   }
1446   return aResult;
1447 }
1448
1449 //=======================================================================
1450 //function : JoinWLines
1451 //purpose  :
1452 //=======================================================================
1453 void IntPatch_WLineTool::JoinWLines(IntPatch_SequenceOfLine& theSlin,
1454                                     IntPatch_SequenceOfPoint& theSPnt,
1455                                     Handle(Adaptor3d_HSurface) theS1,
1456                                     Handle(Adaptor3d_HSurface) theS2,
1457                                     const Standard_Real theTol3D)
1458 {
1459   if(theSlin.Length() == 0)
1460     return;
1461
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++)
1479   {
1480     Handle(IntPatch_WLine) aWLine1(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aN1)));
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();
1488     const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
1489     const IntSurf_PntOn2S& aPntLWL1 = aWLine1->Point(aNbPntsWL1);
1490
1491     for(Standard_Integer aNPt = 1; aNPt <= theSPnt.Length(); aNPt++)
1492     {
1493       const IntSurf_PntOn2S aPntCur = theSPnt.Value(aNPt).PntOn2S();
1494
1495       if( aPntCur.IsSame(aPntFWL1, Precision::Confusion()) ||
1496         aPntCur.IsSame(aPntLWL1, Precision::Confusion()))
1497       {
1498         theSPnt.Remove(aNPt);
1499         aNPt--;
1500       }
1501     }
1502
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++)
1510     {
1511       if (aN2 == aN1)
1512         continue;
1513
1514       Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(aN2)));
1515
1516       if (aWLine2.IsNull())
1517         continue;
1518
1519       isFirstConnected = isLastConnected = Standard_False;
1520
1521       const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1522
1523       const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1524       const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1525
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())
1531       {
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))
1538         {
1539           isFirstConnected = Standard_True;
1540         }
1541       }
1542
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())
1548       {
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))
1555         {
1556           isLastConnected = Standard_True;
1557         }
1558       }
1559
1560       if (isFirstConnected && isLastConnected)
1561       {
1562         if (aSqMinFDist < aSqMinLDist)
1563         {
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     }
1580
1581     isFirstConnected = (aListFC.Extent() == 1);
1582     isLastConnected = (aListLC.Extent() == 1);
1583
1584     if (!(isFirstConnected || isLastConnected))
1585     {
1586       continue;
1587     }
1588
1589     const Standard_Integer anIndexWL2 = isFirstConnected ? aListFC.First() : aListLC.First();
1590     Handle(IntPatch_WLine) aWLine2(Handle(IntPatch_WLine)::DownCast(theSlin.Value(anIndexWL2)));
1591     const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1592     const IntSurf_PntOn2S& aPntFWL2 = aWLine2->Point(1);
1593     const IntSurf_PntOn2S& aPntLWL2 = aWLine2->Point(aNbPntsWL2);
1594     
1595     if (isFirstConnected)
1596     {
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)
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);
1620         }
1621       }
1622       else
1623       {
1624         //First-Last-connection
1625         for (Standard_Integer aNPt = aNbPntsWL2; aNPt >= 1; aNPt--)
1626         {
1627           const IntSurf_PntOn2S& aPt = aWLine2->Point(aNPt);
1628           aWLine1->Curve()->InsertBefore(1, aPt);
1629         }
1630       }
1631     }
1632     else //if (isLastConnected)
1633     {
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)
1651       {
1652         //Last-First connection
1653         for (Standard_Integer aNPt = 1; aNPt <= aNbPntsWL2; aNPt++)
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);
1666         }
1667       }
1668     }
1669
1670     aWLine1->ComputeVertexParameters(theTol3D);
1671     theSlin.Remove(anIndexWL2);
1672     aN1--;
1673   }
1674 }
1675
1676 //=======================================================================
1677 //function : ExtendTwoWLines
1678 //purpose  : Performs extending theWLine1 and theWLine2 through their
1679 //            respecting end point.
1680 //=======================================================================
1681 void 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)
1690 {
1691   if(theSlin.Length() < 2)
1692     return;
1693
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
1708     if(aWLine1->Vertex(1).ParameterOnLine() != 1)
1709       continue;
1710
1711     if(aWLine1->Vertex(aWLine1->NbVertex()).ParameterOnLine() != aWLine1->NbPnts())
1712       continue;
1713
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       }
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       }
1791     }
1792
1793     if(aCheckResult == (IntPatchWT_DisFirstFirst | IntPatchWT_DisFirstLast |
1794                         IntPatchWT_DisLastFirst | IntPatchWT_DisLastLast))
1795       continue;
1796
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
1806       if(aWLine2->Vertex(1).ParameterOnLine() != 1)
1807         continue;
1808
1809       if(aWLine2->Vertex(aWLine2->NbVertex()).ParameterOnLine() != aWLine2->NbPnts())
1810         continue;
1811
1812       Standard_Boolean hasBeenJoined = Standard_False;
1813
1814       const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
1815
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
1828         ExtendTwoWLFirstFirst(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntFWL2,
1829                               aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1830                               theArrPeriods, aCheckResult, hasBeenJoined);
1831       }
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
1839         ExtendTwoWLFirstLast(theS1, theS2, aWLine1, aWLine2, aPntFWL1, aPntLWL2,
1840                              aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1841                              theArrPeriods, aCheckResult, hasBeenJoined);
1842       }
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
1850         ExtendTwoWLLastFirst(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntFWL2,
1851                              aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1852                              theArrPeriods, aCheckResult, hasBeenJoined);
1853       }
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
1861         ExtendTwoWLLastLast(theS1, theS2, aWLine1, aWLine2, aPntLWL1, aPntLWL2,
1862                             aVec1, aVec2, aVec3, theBoxS1, theBoxS2, theToler3D,
1863                             theArrPeriods, aCheckResult, hasBeenJoined);
1864       }
1865
1866       if(hasBeenJoined)
1867       {
1868         theSlin.Remove(aNumOfLine2);
1869         aNumOfLine2--;
1870       }
1871     }
1872   }
1873 }