aed91a52e6ec58ff36d51e9fce5145858de4274f
[occt.git] / src / GeomInt / GeomInt_LineTool.cxx
1 // Created on: 1995-02-08
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <vector>
18 #include <GeomInt_LineTool.hxx>
19
20 #include <Extrema_ExtPS.hxx>
21 #include <GeomAdaptor_HSurface.hxx>
22 #include <GeomAdaptor_Surface.hxx>
23 #include <Geom_Surface.hxx>
24 #include <IntPatch_ALine.hxx>
25 #include <IntPatch_GLine.hxx>
26 #include <IntPatch_RLine.hxx>
27 #include <IntPatch_WLine.hxx>
28 #include <NCollection_IncAllocator.hxx>
29 #include <NCollection_List.hxx>
30 #include <NCollection_LocalArray.hxx>
31 #include <NCollection_StdAllocator.hxx>
32 #include <TColStd_Array1OfListOfInteger.hxx>
33
34 class ProjectPointOnSurf
35 {
36  public:
37   ProjectPointOnSurf() : myIsDone (Standard_False),myIndex(0) {}
38   void Init(const Handle(Geom_Surface)& Surface,
39             const Standard_Real Umin,
40             const Standard_Real Usup,
41             const Standard_Real Vmin,
42             const Standard_Real Vsup);
43   void Init ();
44   void Perform(const gp_Pnt& P);
45   Standard_Boolean IsDone () const { return myIsDone; }
46   void LowerDistanceParameters(Standard_Real& U, Standard_Real& V ) const;
47   Standard_Real LowerDistance() const;
48  protected:
49   Standard_Boolean myIsDone;
50   Standard_Integer myIndex;
51   Extrema_ExtPS myExtPS;
52   GeomAdaptor_Surface myGeomAdaptor;
53 };
54
55 //=======================================================================
56 //function : Init
57 //purpose  : 
58 //=======================================================================
59 void ProjectPointOnSurf::Init ( const Handle(Geom_Surface)& Surface,
60                                 const Standard_Real Umin,
61                                 const Standard_Real Usup,
62                                 const Standard_Real Vmin,
63                                 const Standard_Real Vsup )
64 {
65   const Standard_Real Tolerance = Precision::PConfusion();
66   //
67   myGeomAdaptor.Load(Surface, Umin,Usup,Vmin,Vsup);
68   myExtPS.Initialize(myGeomAdaptor, Umin, Usup, Vmin, Vsup, Tolerance, Tolerance);
69   myIsDone = Standard_False;
70 }
71
72 //=======================================================================
73 //function : Init
74 //purpose  : 
75 //=======================================================================
76 void ProjectPointOnSurf::Init ()
77 {
78   myIsDone = myExtPS.IsDone() && (myExtPS.NbExt() > 0);
79   if (myIsDone) {
80     // evaluate the lower distance and its index;
81     Standard_Real Dist2Min = myExtPS.SquareDistance(1);
82     myIndex = 1;
83     for (Standard_Integer i = 2; i <= myExtPS.NbExt(); i++)
84     {
85       const Standard_Real Dist2 = myExtPS.SquareDistance(i);
86       if (Dist2 < Dist2Min) {
87         Dist2Min = Dist2;
88         myIndex = i;
89       }
90     }
91   }
92 }
93
94 //=======================================================================
95 //function : Perform
96 //purpose  : 
97 //=======================================================================
98 void ProjectPointOnSurf::Perform(const gp_Pnt& P)
99 {
100   myExtPS.Perform(P);
101   Init ();
102 }
103
104 //=======================================================================
105 //function : LowerDistanceParameters
106 //purpose  : 
107 //=======================================================================
108 void ProjectPointOnSurf::LowerDistanceParameters (Standard_Real& U,
109                                                   Standard_Real& V ) const
110 {
111   StdFail_NotDone_Raise_if(!myIsDone, "GeomInt_IntSS::ProjectPointOnSurf::LowerDistanceParameters");
112   (myExtPS.Point(myIndex)).Parameter(U,V);
113 }
114
115 //=======================================================================
116 //function : LowerDistance
117 //purpose  : 
118 //=======================================================================
119 Standard_Real ProjectPointOnSurf::LowerDistance() const
120 {
121   StdFail_NotDone_Raise_if(!myIsDone, "GeomInt_IntSS::ProjectPointOnSurf::LowerDistance");
122   return sqrt(myExtPS.SquareDistance(myIndex));
123 }
124
125 //=======================================================================
126 //function : AdjustPeriodic
127 //purpose  : 
128 //=======================================================================
129 static Standard_Real AdjustPeriodic(const Standard_Real theParameter,
130                                     const Standard_Real parmin,
131                                     const Standard_Real parmax,
132                                     const Standard_Real thePeriod,
133                                     Standard_Real&      theOffset)
134 {
135   Standard_Real aresult = theParameter;
136   theOffset = 0.;
137   while(aresult < parmin) {
138     aresult += thePeriod;
139     theOffset += thePeriod;
140   }
141   while(aresult > parmax) {
142     aresult -= thePeriod;
143     theOffset -= thePeriod;
144   }
145   return aresult;
146 }
147
148 //=======================================================================
149 //function : IsPointOnBoundary
150 //purpose  : 
151 //=======================================================================
152 static Standard_Boolean IsPointOnBoundary(const Standard_Real theParameter,
153                                           const Standard_Real theFirstBoundary,
154                                           const Standard_Real theSecondBoundary,
155                                           const Standard_Real theResolution,
156                                           Standard_Boolean&   IsOnFirstBoundary)
157 {
158   IsOnFirstBoundary = Standard_True;
159   if(fabs(theParameter - theFirstBoundary) < theResolution)
160     return Standard_True;
161   if(fabs(theParameter - theSecondBoundary) < theResolution)
162   {
163     IsOnFirstBoundary = Standard_False;
164     return Standard_True;
165   }
166   return Standard_False;
167 }
168
169 //=======================================================================
170 //function : FindPoint
171 //purpose  : 
172 //=======================================================================
173 static Standard_Boolean FindPoint(const gp_Pnt2d&     theFirstPoint,
174                                   const gp_Pnt2d&     theLastPoint,
175                                   const Standard_Real theUmin,
176                                   const Standard_Real theUmax,
177                                   const Standard_Real theVmin,
178                                   const Standard_Real theVmax,
179                                   gp_Pnt2d&           theNewPoint)
180 {
181   gp_Vec2d aVec(theFirstPoint, theLastPoint);
182   Standard_Integer i = 0, j = 0;
183
184   for(i = 0; i < 4; i++) {
185     gp_Vec2d anOtherVec;
186     gp_Vec2d anOtherVecNormal;
187     gp_Pnt2d aprojpoint = theLastPoint;    
188
189     if((i % 2) == 0) {
190       anOtherVec.SetX(0.);
191       anOtherVec.SetY(1.);
192       anOtherVecNormal.SetX(1.);
193       anOtherVecNormal.SetY(0.);
194
195       if(i < 2)
196         aprojpoint.SetX(theUmin);
197       else
198         aprojpoint.SetX(theUmax);
199     }
200     else {
201       anOtherVec.SetX(1.);
202       anOtherVec.SetY(0.);
203       anOtherVecNormal.SetX(0.);
204       anOtherVecNormal.SetY(1.);
205
206       if(i < 2)
207         aprojpoint.SetY(theVmin);
208       else
209         aprojpoint.SetY(theVmax);
210     }
211     gp_Vec2d anormvec = aVec;
212     anormvec.Normalize();
213     Standard_Real adot1 = anormvec.Dot(anOtherVecNormal);
214
215     if(fabs(adot1) < Precision::Angular())
216       continue;
217     Standard_Real adist = 0.;
218
219     if((i % 2) == 0) {
220       adist = (i < 2) ? fabs(theLastPoint.X() - theUmin) : fabs(theLastPoint.X() - theUmax);
221     }
222     else {
223       adist = (i < 2) ? fabs(theLastPoint.Y() - theVmin) : fabs(theLastPoint.Y() - theVmax);
224     }
225     Standard_Real anoffset = adist * anOtherVec.Dot(anormvec) / adot1;
226
227     for(j = 0; j < 2; j++) {
228       anoffset = (j == 0) ? anoffset : -anoffset;
229       gp_Pnt2d acurpoint(aprojpoint.XY() + (anOtherVec.XY()*anoffset));
230       gp_Vec2d acurvec(theLastPoint, acurpoint);
231
232       //
233       Standard_Real aDotX, anAngleX, aPC;
234       //
235       aDotX=aVec.Dot(acurvec);
236       anAngleX=aVec.Angle(acurvec);
237       aPC=Precision::PConfusion();
238       //
239       if(aDotX > 0. && fabs(anAngleX) < aPC) {
240       //
241         if((i % 2) == 0) {
242           if((acurpoint.Y() >= theVmin) &&
243              (acurpoint.Y() <= theVmax)) {
244             theNewPoint = acurpoint;
245             return Standard_True;
246           }
247         }
248         else {
249           if((acurpoint.X() >= theUmin) &&
250              (acurpoint.X() <= theUmax)) {
251             theNewPoint = acurpoint;
252             return Standard_True;
253           }
254         }
255       }
256     }
257   }
258   return Standard_False;
259 }
260
261
262 //=======================================================================
263 //function : NbVertex
264 //purpose  : 
265 //=======================================================================
266 Standard_Integer GeomInt_LineTool::NbVertex(const Handle(IntPatch_Line)& L)
267 {
268   switch (L->ArcType())
269   {
270     case IntPatch_Analytic:    return Handle(IntPatch_ALine)::DownCast(L)->NbVertex();
271     case IntPatch_Restriction: return Handle(IntPatch_RLine)::DownCast(L)->NbVertex();
272     case IntPatch_Walking:     return Handle(IntPatch_WLine)::DownCast(L)->NbVertex();
273     default: break;
274   }
275   return Handle(IntPatch_GLine)::DownCast(L)->NbVertex();
276 }
277
278
279 //=======================================================================
280 //function : Vertex
281 //purpose  : 
282 //=======================================================================
283 const IntPatch_Point & GeomInt_LineTool::Vertex(const Handle(IntPatch_Line)& L,
284                                                 const Standard_Integer I)
285 {
286   switch (L->ArcType())
287   {
288     case IntPatch_Analytic: return Handle(IntPatch_ALine)::DownCast(L)->Vertex(I);
289     case IntPatch_Restriction: return Handle(IntPatch_RLine)::DownCast(L)->Vertex(I);
290     case IntPatch_Walking: return Handle(IntPatch_WLine)::DownCast(L)->Vertex(I);
291     default: break;
292   }
293   return Handle(IntPatch_GLine)::DownCast(L)->Vertex(I);
294 }
295
296
297 //=======================================================================
298 //function : FirstParameter
299 //purpose  : 
300 //=======================================================================
301 Standard_Real GeomInt_LineTool::FirstParameter (const Handle(IntPatch_Line)& L)
302 {
303   const IntPatch_IType typl = L->ArcType();
304   switch (typl)
305   {
306     case IntPatch_Analytic:
307     {
308       Handle(IntPatch_ALine) alin = Handle(IntPatch_ALine)::DownCast(L);
309       if (alin->HasFirstPoint())
310         return alin->FirstPoint().ParameterOnLine();
311       Standard_Boolean included;
312       Standard_Real firstp = alin->FirstParameter(included);
313       if (!included)
314         firstp += Epsilon(firstp);
315       return firstp;
316     }
317
318     case IntPatch_Restriction:
319     {
320       Handle(IntPatch_RLine) rlin = Handle(IntPatch_RLine)::DownCast(L);
321           return (rlin->HasFirstPoint()? rlin->FirstPoint().ParameterOnLine() : -Precision::Infinite()); // a voir selon le type de la ligne 2d
322     }
323
324     case IntPatch_Walking:
325     {
326       Handle(IntPatch_WLine) wlin = Handle(IntPatch_WLine)::DownCast(L);
327           return (wlin->HasFirstPoint()? wlin->FirstPoint().ParameterOnLine() : 1.);
328     }
329
330     default:
331     {
332       Handle(IntPatch_GLine) glin = Handle(IntPatch_GLine)::DownCast(L);
333       if (glin->HasFirstPoint())
334         return glin->FirstPoint().ParameterOnLine();
335       switch (typl)
336       {
337         case IntPatch_Lin:
338         case IntPatch_Parabola:
339         case IntPatch_Hyperbola:
340           return -Precision::Infinite();
341         default: break;
342       }
343     }
344   }
345   return 0.0;
346 }
347
348
349 //=======================================================================
350 //function : LastParameter
351 //purpose  : 
352 //=======================================================================
353 Standard_Real GeomInt_LineTool::LastParameter (const Handle(IntPatch_Line)& L)
354 {
355   const IntPatch_IType typl = L->ArcType();
356   switch (typl)
357   {
358     case IntPatch_Analytic:
359     {
360       Handle(IntPatch_ALine) alin = Handle(IntPatch_ALine)::DownCast(L);
361       if (alin->HasLastPoint())
362         return alin->LastPoint().ParameterOnLine();
363       Standard_Boolean included;
364       Standard_Real lastp = alin->LastParameter(included);
365       if (!included)
366         lastp -=Epsilon(lastp);
367       return lastp;
368     }
369
370     case IntPatch_Restriction:
371     {
372       Handle(IntPatch_RLine) rlin = Handle(IntPatch_RLine)::DownCast(L);
373           return (rlin->HasLastPoint()? rlin->LastPoint().ParameterOnLine() : Precision::Infinite()); // a voir selon le type de la ligne 2d
374     }
375
376     case IntPatch_Walking:
377     {
378       Handle(IntPatch_WLine) wlin = Handle(IntPatch_WLine)::DownCast(L);
379           return (wlin->HasLastPoint()? wlin->LastPoint().ParameterOnLine() : wlin->NbPnts());
380     }
381
382     default:
383     {
384       Handle(IntPatch_GLine) glin = Handle(IntPatch_GLine)::DownCast(L);
385       if (glin->HasLastPoint())
386         return glin->LastPoint().ParameterOnLine();
387       switch (typl)
388       {
389         case IntPatch_Lin:
390         case IntPatch_Parabola:
391         case IntPatch_Hyperbola:
392           return Precision::Infinite();
393         case IntPatch_Circle:
394         case IntPatch_Ellipse:
395           return 2.*M_PI;
396         default: break;
397       }
398     }
399   }
400   return 0.0;
401 }
402
403 //=======================================================================
404 //function : DecompositionOfWLine
405 //purpose  : 
406 //=======================================================================
407 Standard_Boolean GeomInt_LineTool::
408             DecompositionOfWLine( const Handle(IntPatch_WLine)& theWLine,
409                                   const Handle(GeomAdaptor_HSurface)& theSurface1,
410                                   const Handle(GeomAdaptor_HSurface)& theSurface2,
411                                   const Standard_Real aTolSum,
412                                   const GeomInt_LineConstructor& theLConstructor,
413                                   IntPatch_SequenceOfLine& theNewLines)
414 {
415   typedef NCollection_List<Standard_Integer> ListOfInteger;
416   //have to use std::vector, not NCollection_Vector in order to use copy constructor of
417   //ListOfInteger which will be created with specific allocator instance
418   typedef std::vector<ListOfInteger, NCollection_StdAllocator<
419       ListOfInteger> > ArrayOfListOfInteger;
420
421   Standard_Boolean bIsPrevPointOnBoundary, bIsCurrentPointOnBoundary;
422   Standard_Integer nblines, aNbPnts, aNbParts, pit, i, j, aNbListOfPointIndex;
423   Standard_Real aTol, umin, umax, vmin, vmax;
424
425   //an inc allocator, it will contain wasted space (upon list's Clear()) but it should
426   //still be faster than the standard allocator, and wasted memory should not be
427   //significant and will be limited by time span of this function;
428   //this is a separate allocator from the anIncAlloc below what provides better data
429   //locality in the latter (by avoiding wastes which will only be in anIdxAlloc)
430   Handle(NCollection_IncAllocator) anIdxAlloc = new NCollection_IncAllocator();
431   ListOfInteger aListOfPointIndex (anIdxAlloc);
432
433   //GeomAPI_ProjectPointOnSurf aPrj1, aPrj2;
434   ProjectPointOnSurf aPrj1, aPrj2;
435   Handle(Geom_Surface) aSurf1,  aSurf2;
436   //
437   aNbParts=theLConstructor.NbParts();
438   aNbPnts=theWLine->NbPnts();
439   //
440   if((!aNbPnts) || (!aNbParts)){
441     return Standard_False;
442   }
443   //
444   Handle(NCollection_IncAllocator) anIncAlloc = new NCollection_IncAllocator();
445   NCollection_StdAllocator<ListOfInteger> anAlloc (anIncAlloc);
446   const ListOfInteger aDummy (anIncAlloc); //empty list to be copy constructed from
447   ArrayOfListOfInteger anArrayOfLines (aNbPnts + 1, aDummy, anAlloc);
448
449   NCollection_LocalArray<Standard_Integer> anArrayOfLineTypeArr (aNbPnts + 1);
450   Standard_Integer* anArrayOfLineType = anArrayOfLineTypeArr;
451   //
452   nblines = 0;
453   aTol = Precision::Confusion();
454   //
455   aSurf1 = theSurface1->ChangeSurface().Surface();
456   aSurf1->Bounds(umin, umax, vmin, vmax);
457   aPrj1.Init(aSurf1, umin, umax, vmin, vmax);
458   //
459   aSurf2 = theSurface2->ChangeSurface().Surface();
460   aSurf2->Bounds(umin, umax, vmin, vmax);
461   aPrj2.Init(aSurf2, umin, umax, vmin, vmax);
462   //
463   //
464   bIsPrevPointOnBoundary=Standard_False;
465   for(pit=1; pit<=aNbPnts; pit++) {
466     const IntSurf_PntOn2S& aPoint = theWLine->Point(pit);
467     bIsCurrentPointOnBoundary=Standard_False;
468     //
469     // whether aPoint is on boundary or not
470     //
471     for(i=0; i<2; i++) {// exploration Surface 1,2 
472       Handle(GeomAdaptor_HSurface) aGASurface = (!i) ? theSurface1 : theSurface2;
473       aGASurface->ChangeSurface().Surface()->Bounds(umin, umax, vmin, vmax);
474       //
475       for(j=0; j<2; j++) {// exploration of coordinate U,V
476         Standard_Boolean isperiodic;
477         //
478         isperiodic = (!j) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
479         if(!isperiodic) {
480           continue;
481         }
482         //
483         Standard_Real aResolution, aPeriod, alowerboundary, aupperboundary, U, V;
484         Standard_Real aParameter, anoffset, anAdjustPar;
485         Standard_Boolean bIsOnFirstBoundary, bIsPointOnBoundary;
486         //
487         aResolution = (!j) ? aGASurface->UResolution(aTol) : aGASurface->VResolution(aTol);
488         aPeriod     = (!j) ? aGASurface->UPeriod() : aGASurface->VPeriod();
489         alowerboundary = (!j) ? umin : vmin;
490         aupperboundary = (!j) ? umax : vmax;
491         U=0.;V=0.;//?
492         //
493         if(!i){
494           aPoint.ParametersOnS1(U, V);
495         }
496         else{
497           aPoint.ParametersOnS2(U, V);
498         }
499         //
500         aParameter = (!j) ? U : V;
501         anoffset=0.;
502         anAdjustPar=AdjustPeriodic(aParameter, alowerboundary, aupperboundary, aPeriod, anoffset);
503         //
504         bIsOnFirstBoundary=Standard_True;
505         //
506         bIsPointOnBoundary=
507           IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
508         
509         if(bIsPointOnBoundary) {
510           bIsCurrentPointOnBoundary = Standard_True;
511           break;
512         }
513       }// for(j=0; j<2; j++)
514       
515       if(bIsCurrentPointOnBoundary){
516         break;
517       }
518     }// for(i=0; i<2; i++) 
519     //
520     if((bIsCurrentPointOnBoundary != bIsPrevPointOnBoundary)) {
521
522       if(!aListOfPointIndex.IsEmpty()) {
523         nblines++;
524         anArrayOfLines[nblines] = aListOfPointIndex;
525         anArrayOfLineType[nblines] = bIsPrevPointOnBoundary;
526         aListOfPointIndex.Clear();
527       }
528       bIsPrevPointOnBoundary = bIsCurrentPointOnBoundary;
529     }
530     aListOfPointIndex.Append(pit);
531   } // for(pit=1; pit<=aNbPnts; pit++)
532   //
533   aNbListOfPointIndex=aListOfPointIndex.Extent();
534   if(aNbListOfPointIndex) {
535     nblines++;
536     anArrayOfLines[nblines].Assign (aListOfPointIndex);
537     anArrayOfLineType[nblines] = bIsPrevPointOnBoundary;
538     aListOfPointIndex.Clear();
539   }
540   //
541   if(nblines <= 1){
542     return Standard_False;
543   }
544   //
545   // Correct wlines.begin
546   Standard_Integer aLineType;
547   TColStd_Array1OfListOfInteger anArrayOfLineEnds(1, nblines);
548   Handle(IntSurf_LineOn2S) aSeqOfPntOn2S = new IntSurf_LineOn2S (new NCollection_IncAllocator());
549   //
550   for(i = 1; i <= nblines; i++) {
551     aLineType=anArrayOfLineType[i];
552     if(aLineType) {
553       continue;
554     }
555     //
556     const ListOfInteger& aListOfIndex = anArrayOfLines[i];
557     if(aListOfIndex.Extent() < 2) {
558       continue;
559     }
560     //
561     TColStd_ListOfInteger aListOfFLIndex;
562     Standard_Integer aneighbourindex, aLineTypeNeib;
563     //
564     for(j = 0; j < 2; j++) {// neighbour line choice 
565       aneighbourindex = (!j) ? (i-1) : (i+1);
566       if((aneighbourindex < 1) || (aneighbourindex > nblines)){
567         continue;
568       }
569       //
570       aLineTypeNeib=anArrayOfLineType[aneighbourindex];
571       if(!aLineTypeNeib){
572         continue;
573       }
574       //
575       const ListOfInteger& aNeighbour = anArrayOfLines[aneighbourindex];
576       Standard_Integer anIndex = (!j) ? aNeighbour.Last() : aNeighbour.First();
577       const IntSurf_PntOn2S& aPoint = theWLine->Point(anIndex);
578       // check if need use derivative.begin .end [absence]
579       //
580       IntSurf_PntOn2S aNewP = aPoint;
581       Standard_Integer surfit, parit;
582       //
583       for(surfit = 0; surfit < 2; ++surfit) {
584
585         Handle(GeomAdaptor_HSurface) aGASurface = (!surfit) ? theSurface1 : theSurface2;
586         
587         umin = aGASurface->FirstUParameter();
588         umax = aGASurface->LastUParameter();
589         vmin = aGASurface->FirstVParameter();
590         vmax = aGASurface->LastVParameter();
591         Standard_Real U=0., V=0.;
592
593         if(!surfit) {
594           aNewP.ParametersOnS1(U, V);
595         }
596         else {
597           aNewP.ParametersOnS2(U, V);
598         }
599         //
600         Standard_Integer nbboundaries = 0;
601         Standard_Integer bIsUBoundary = Standard_False; // use if nbboundaries == 1
602         Standard_Integer bIsFirstBoundary = Standard_False; // use if nbboundaries == 1
603         //
604         for(parit = 0; parit < 2; parit++) {
605           Standard_Boolean isperiodic = (!parit) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
606
607           Standard_Real aResolution = (!parit) ? aGASurface->UResolution(aTol) : aGASurface->VResolution(aTol);
608           Standard_Real alowerboundary = (!parit) ? umin : vmin;
609           Standard_Real aupperboundary = (!parit) ? umax : vmax;
610
611           Standard_Real aParameter = (!parit) ? U : V;
612           Standard_Boolean bIsOnFirstBoundary = Standard_True;
613   
614           if(!isperiodic) {
615             if(IsPointOnBoundary(aParameter, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary)) {
616               bIsUBoundary = (!parit);
617               bIsFirstBoundary = bIsOnFirstBoundary;
618               nbboundaries++;
619             }
620           }
621           else {
622             Standard_Real aPeriod     = (!parit) ? aGASurface->UPeriod() : aGASurface->VPeriod();
623             Standard_Real anoffset = 0.;
624             Standard_Real anAdjustPar = AdjustPeriodic(aParameter, alowerboundary, aupperboundary, aPeriod, anoffset);
625
626             if(IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary)) {
627               bIsUBoundary = (parit == 0);
628               bIsFirstBoundary = bIsOnFirstBoundary;
629               nbboundaries++;
630             }
631           }
632         }
633         //
634         Standard_Boolean bComputeLineEnd = Standard_False;
635         
636         if(nbboundaries == 2) {
637           bComputeLineEnd = Standard_True;
638         }
639         else if(nbboundaries == 1) {
640           Standard_Boolean isperiodic = (bIsUBoundary) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
641
642           if(isperiodic) {
643             Standard_Real alowerboundary = (bIsUBoundary) ? umin : vmin;
644             Standard_Real aupperboundary = (bIsUBoundary) ? umax : vmax;
645             Standard_Real aPeriod     = (bIsUBoundary) ? aGASurface->UPeriod() : aGASurface->VPeriod();
646             Standard_Real aParameter = (bIsUBoundary) ? U : V;
647             Standard_Real anoffset = 0.;
648             Standard_Real anAdjustPar = AdjustPeriodic(aParameter, alowerboundary, aupperboundary, aPeriod, anoffset);
649
650             Standard_Real adist = (bIsFirstBoundary) ? fabs(anAdjustPar - alowerboundary) : fabs(anAdjustPar - aupperboundary);
651             Standard_Real anotherPar = (bIsFirstBoundary) ? (aupperboundary - adist) : (alowerboundary + adist);
652             anotherPar += anoffset;
653             Standard_Integer aneighbourpointindex = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
654             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex);
655             Standard_Real nU1, nV1;
656
657             if(surfit == 0)
658               aNeighbourPoint.ParametersOnS1(nU1, nV1);
659             else
660               aNeighbourPoint.ParametersOnS2(nU1, nV1);
661             
662             Standard_Real adist1 = (bIsUBoundary) ? fabs(nU1 - U) : fabs(nV1 - V);
663             Standard_Real adist2 = (bIsUBoundary) ? fabs(nU1 - anotherPar) : fabs(nV1 - anotherPar);
664             bComputeLineEnd = Standard_True;
665             Standard_Boolean bCheckAngle1 = Standard_False;
666             Standard_Boolean bCheckAngle2 = Standard_False;
667             gp_Vec2d aNewVec;
668             Standard_Real anewU = (bIsUBoundary) ? anotherPar : U;
669             Standard_Real anewV = (bIsUBoundary) ? V : anotherPar;
670             //
671             if(((adist1 - adist2) > Precision::PConfusion()) && 
672                (adist2 < (aPeriod / 4.))) {
673               bCheckAngle1 = Standard_True;
674               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(anewU, anewV));
675
676               if(aNewVec.SquareMagnitude() < (gp::Resolution() * gp::Resolution())) {
677                 aNewP.SetValue((surfit == 0), anewU, anewV);
678                 bCheckAngle1 = Standard_False;
679               }
680             }
681             else if(adist1 < (aPeriod / 4.)) {
682               bCheckAngle2 = Standard_True;
683               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(U, V));
684
685               if(aNewVec.SquareMagnitude() < (gp::Resolution() * gp::Resolution())) {
686                 bCheckAngle2 = Standard_False;
687               }
688             }
689             //
690             if(bCheckAngle1 || bCheckAngle2) {
691               // assume there are at least two points in line (see "if" above)
692               Standard_Integer anindexother = aneighbourpointindex;
693               
694               while((anindexother <= aListOfIndex.Last()) && (anindexother >= aListOfIndex.First())) {
695                 anindexother = (j == 0) ? (anindexother + 1) : (anindexother - 1);
696                 const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(anindexother);
697                 Standard_Real nU2, nV2;
698                 
699                 if(surfit == 0)
700                   aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
701                 else
702                   aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
703                 gp_Vec2d aVecOld(gp_Pnt2d(nU2, nV2), gp_Pnt2d(nU1, nV1));
704
705                 if(aVecOld.SquareMagnitude() <= (gp::Resolution() * gp::Resolution())) {
706                   continue;
707                 }
708                 else {
709                   Standard_Real anAngle = aNewVec.Angle(aVecOld);
710
711                   if((fabs(anAngle) < (M_PI * 0.25)) && (aNewVec.Dot(aVecOld) > 0.)) {
712
713                     if(bCheckAngle1) {
714                       Standard_Real U1, U2, V1, V2;
715                       IntSurf_PntOn2S atmppoint = aNewP;
716                       atmppoint.SetValue((surfit == 0), anewU, anewV);
717                       atmppoint.Parameters(U1, V1, U2, V2);
718                       gp_Pnt P1 = theSurface1->Value(U1, V1);
719                       gp_Pnt P2 = theSurface2->Value(U2, V2);
720                       gp_Pnt P0 = aPoint.Value();
721
722                       if(P0.IsEqual(P1, aTol) &&
723                          P0.IsEqual(P2, aTol) &&
724                          P1.IsEqual(P2, aTol)) {
725                         bComputeLineEnd = Standard_False;
726                         aNewP.SetValue((surfit == 0), anewU, anewV);
727                       }
728                     }
729                     
730                     if(bCheckAngle2) {
731                       bComputeLineEnd = Standard_False;
732                     }
733                   }
734                   break;
735                 }
736               } // end while(anindexother...)
737             }
738           }
739         }
740         //
741         if(bComputeLineEnd) {
742           Standard_Integer aneighbourpointindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
743           const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
744           Standard_Real nU1, nV1;
745
746           if(surfit == 0)
747             aNeighbourPoint.ParametersOnS1(nU1, nV1);
748           else
749             aNeighbourPoint.ParametersOnS2(nU1, nV1);
750           gp_Pnt2d ap1(nU1, nV1);
751           gp_Pnt2d ap2(nU1, nV1);
752           Standard_Integer aneighbourpointindex2 = aneighbourpointindex1;
753
754           while((aneighbourpointindex2 <= aListOfIndex.Last()) && (aneighbourpointindex2 >= aListOfIndex.First())) {
755             aneighbourpointindex2 = (j == 0) ? (aneighbourpointindex2 + 1) : (aneighbourpointindex2 - 1);
756             const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(aneighbourpointindex2);
757             Standard_Real nU2, nV2;
758
759             if(surfit == 0)
760               aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
761             else
762               aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
763             ap2.SetX(nU2);
764             ap2.SetY(nV2);
765
766             if(ap1.SquareDistance(ap2) > (gp::Resolution() * gp::Resolution())) {
767               break;
768             }
769           }       
770           gp_Pnt2d anewpoint;
771           Standard_Boolean found = FindPoint(ap2, ap1, umin, umax, vmin, vmax, anewpoint);
772
773           if(found) {
774             // check point
775             Standard_Real aCriteria =aTolSum;// BRep_Tool::Tolerance(theFace1) + BRep_Tool::Tolerance(theFace2);
776             //GeomAPI_ProjectPointOnSurf& aProjector = (surfit == 0) ? aPrj2 : aPrj1;
777             ProjectPointOnSurf& aProjector = (surfit == 0) ? aPrj2 : aPrj1;
778             Handle(GeomAdaptor_HSurface) aSurface = (surfit == 0) ? theSurface1 : theSurface2;
779
780             gp_Pnt aP3d = aSurface->Value(anewpoint.X(), anewpoint.Y());
781             aProjector.Perform(aP3d);
782
783             if(aProjector.IsDone()) {
784               if(aProjector.LowerDistance() < aCriteria) {
785                 Standard_Real foundU = U, foundV = V;
786                 aProjector.LowerDistanceParameters(foundU, foundV);
787
788                 if(surfit == 0)
789                   aNewP.SetValue(aP3d, anewpoint.X(), anewpoint.Y(), foundU, foundV);
790                 else
791                   aNewP.SetValue(aP3d, foundU, foundV, anewpoint.X(), anewpoint.Y());
792               }
793             }
794           }
795         }
796       }
797       aSeqOfPntOn2S->Add(aNewP);
798       aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
799     }
800     anArrayOfLineEnds.SetValue(i, aListOfFLIndex);
801   }
802   // Correct wlines.end
803
804   // Split wlines.begin
805   for(j = 1; j <= theLConstructor.NbParts(); j++) {
806     Standard_Real fprm = 0., lprm = 0.;
807     theLConstructor.Part(j, fprm, lprm);
808     Standard_Integer ifprm = (Standard_Integer)fprm;
809     Standard_Integer ilprm = (Standard_Integer)lprm;
810     //
811     Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
812     //
813     for(i = 1; i <= nblines; i++) {
814       if(anArrayOfLineType[i] != 0) {
815         continue;
816       }
817       const ListOfInteger& aListOfIndex = anArrayOfLines[i];
818
819       if(aListOfIndex.Extent() < 2) {
820         continue;
821       }
822       const TColStd_ListOfInteger& aListOfFLIndex = anArrayOfLineEnds.Value(i);
823       Standard_Boolean bhasfirstpoint = (aListOfFLIndex.Extent() == 2);
824       Standard_Boolean bhaslastpoint = (aListOfFLIndex.Extent() == 2);
825
826       if(!bhasfirstpoint && !aListOfFLIndex.IsEmpty()) {
827         bhasfirstpoint = (i != 1);
828       }
829
830       if(!bhaslastpoint && !aListOfFLIndex.IsEmpty()) {
831         bhaslastpoint = (i != nblines);
832       }
833       Standard_Boolean bIsFirstInside = ((ifprm >= aListOfIndex.First()) && (ifprm <= aListOfIndex.Last()));
834       Standard_Boolean bIsLastInside =  ((ilprm >= aListOfIndex.First()) && (ilprm <= aListOfIndex.Last()));
835
836       if(!bIsFirstInside && !bIsLastInside) {
837         if((ifprm < aListOfIndex.First()) && (ilprm > aListOfIndex.Last())) {
838           // append whole line, and boundaries if neccesary
839           if(bhasfirstpoint) {
840             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.First());
841             aLineOn2S->Add(aP);
842           }
843           ListOfInteger::Iterator anIt(aListOfIndex);
844
845           for(; anIt.More(); anIt.Next()) {
846             const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
847             aLineOn2S->Add(aP);
848           }
849
850           if(bhaslastpoint) {
851             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.Last());
852             aLineOn2S->Add(aP);
853           }
854
855           // check end of split line (end is almost always)
856           Standard_Integer aneighbour = i + 1;
857           Standard_Boolean bIsEndOfLine = Standard_True;
858
859           if(aneighbour <= nblines) {
860             const ListOfInteger& aListOfNeighbourIndex = anArrayOfLines[aneighbour];
861
862             if((anArrayOfLineType[aneighbour] != 0) &&
863                (aListOfNeighbourIndex.IsEmpty())) {
864               bIsEndOfLine = Standard_False;
865             }
866           }
867
868           if(bIsEndOfLine) {
869             if(aLineOn2S->NbPoints() > 1) {
870               Handle(IntPatch_WLine) aNewWLine = 
871                 new IntPatch_WLine(aLineOn2S, Standard_False);
872               aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
873               theNewLines.Append(aNewWLine);
874             }
875             aLineOn2S = new IntSurf_LineOn2S();
876           }
877         }
878         continue;
879       }
880       // end if(!bIsFirstInside && !bIsLastInside)
881
882       if(bIsFirstInside && bIsLastInside) {
883         // append inside points between ifprm and ilprm
884         ListOfInteger::Iterator anIt(aListOfIndex);
885
886         for(; anIt.More(); anIt.Next()) {
887           if((anIt.Value() < ifprm) || (anIt.Value() > ilprm))
888             continue;
889           const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
890           aLineOn2S->Add(aP);
891         }
892       }
893       else {
894
895         if(bIsFirstInside) {
896           // append points from ifprm to last point + boundary point
897           ListOfInteger::Iterator anIt(aListOfIndex);
898
899           for(; anIt.More(); anIt.Next()) {
900             if(anIt.Value() < ifprm)
901               continue;
902             const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
903             aLineOn2S->Add(aP);
904           }
905
906           if(bhaslastpoint) {
907             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.Last());
908             aLineOn2S->Add(aP);
909           }
910           // check end of split line (end is almost always)
911           Standard_Integer aneighbour = i + 1;
912           Standard_Boolean bIsEndOfLine = Standard_True;
913
914           if(aneighbour <= nblines) {
915             const ListOfInteger& aListOfNeighbourIndex = anArrayOfLines[aneighbour];
916
917             if((anArrayOfLineType[aneighbour] != 0) &&
918                (aListOfNeighbourIndex.IsEmpty())) {
919               bIsEndOfLine = Standard_False;
920             }
921           }
922
923           if(bIsEndOfLine) {
924             if(aLineOn2S->NbPoints() > 1) {
925               Handle(IntPatch_WLine) aNewWLine = 
926                 new IntPatch_WLine(aLineOn2S, Standard_False);
927               aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
928               theNewLines.Append(aNewWLine);
929             }
930             aLineOn2S = new IntSurf_LineOn2S();
931           }
932         }
933         // end if(bIsFirstInside)
934
935         if(bIsLastInside) {
936           // append points from first boundary point to ilprm
937           if(bhasfirstpoint) {
938             const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.First());
939             aLineOn2S->Add(aP);
940           }
941           ListOfInteger::Iterator anIt(aListOfIndex);
942
943           for(; anIt.More(); anIt.Next()) {
944             if(anIt.Value() > ilprm)
945               continue;
946             const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
947             aLineOn2S->Add(aP);
948           }
949         }
950         //end if(bIsLastInside)
951       }
952     }
953
954     if(aLineOn2S->NbPoints() > 1) {
955       Handle(IntPatch_WLine) aNewWLine = 
956         new IntPatch_WLine(aLineOn2S, Standard_False);
957       aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
958       theNewLines.Append(aNewWLine);
959     }
960   }
961   // Split wlines.end
962   //
963   // cda002/I3
964   Standard_Real fprm, lprm;
965   Standard_Integer ifprm, ilprm, aNbPoints, aIndex;
966   //
967   aNbParts=theLConstructor.NbParts();
968   //
969   for(j = 1; j <= aNbParts; j++) {
970     theLConstructor.Part(j, fprm, lprm);
971     ifprm=(Standard_Integer)fprm;
972     ilprm=(Standard_Integer)lprm;
973     //
974     if ((ilprm-ifprm)==1) {
975       for(i = 1; i <= nblines; i++) {
976         aLineType=anArrayOfLineType[i];
977         if(aLineType) {
978           continue;
979         }
980         //
981         const ListOfInteger& aListOfIndex = anArrayOfLines[i];
982         aNbPoints=aListOfIndex.Extent();
983         if(aNbPoints==1) {
984           aIndex=aListOfIndex.First();
985           if (aIndex==ifprm || aIndex==ilprm) {
986             Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
987             const IntSurf_PntOn2S& aP1 = theWLine->Point(ifprm);
988             const IntSurf_PntOn2S& aP2 = theWLine->Point(ilprm);
989             aLineOn2S->Add(aP1);
990             aLineOn2S->Add(aP2);
991             Handle(IntPatch_WLine) aNewWLine = 
992               new IntPatch_WLine(aLineOn2S, Standard_False);
993             aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
994             theNewLines.Append(aNewWLine);
995           }
996         }
997       }
998     }
999   }
1000   //
1001   return Standard_True;
1002 }