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