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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <GeomInt_LineTool.hxx>
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>
34 class ProjectPointOnSurf
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);
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;
49 Standard_Boolean myIsDone;
50 Standard_Integer myIndex;
51 Extrema_ExtPS myExtPS;
52 GeomAdaptor_Surface myGeomAdaptor;
55 //=======================================================================
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 )
65 const Standard_Real Tolerance = Precision::PConfusion();
67 myGeomAdaptor.Load(Surface, Umin,Usup,Vmin,Vsup);
68 myExtPS.Initialize(myGeomAdaptor, Umin, Usup, Vmin, Vsup, Tolerance, Tolerance);
69 myIsDone = Standard_False;
72 //=======================================================================
75 //=======================================================================
76 void ProjectPointOnSurf::Init ()
78 myIsDone = myExtPS.IsDone() && (myExtPS.NbExt() > 0);
80 // evaluate the lower distance and its index;
81 Standard_Real Dist2Min = myExtPS.SquareDistance(1);
83 for (Standard_Integer i = 2; i <= myExtPS.NbExt(); i++)
85 const Standard_Real Dist2 = myExtPS.SquareDistance(i);
86 if (Dist2 < Dist2Min) {
94 //=======================================================================
97 //=======================================================================
98 void ProjectPointOnSurf::Perform(const gp_Pnt& P)
104 //=======================================================================
105 //function : LowerDistanceParameters
107 //=======================================================================
108 void ProjectPointOnSurf::LowerDistanceParameters (Standard_Real& U,
109 Standard_Real& V ) const
111 StdFail_NotDone_Raise_if(!myIsDone, "GeomInt_IntSS::ProjectPointOnSurf::LowerDistanceParameters");
112 (myExtPS.Point(myIndex)).Parameter(U,V);
115 //=======================================================================
116 //function : LowerDistance
118 //=======================================================================
119 Standard_Real ProjectPointOnSurf::LowerDistance() const
121 StdFail_NotDone_Raise_if(!myIsDone, "GeomInt_IntSS::ProjectPointOnSurf::LowerDistance");
122 return sqrt(myExtPS.SquareDistance(myIndex));
125 //=======================================================================
126 //function : AdjustPeriodic
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)
135 Standard_Real aresult = theParameter;
137 while(aresult < parmin) {
138 aresult += thePeriod;
139 theOffset += thePeriod;
141 while(aresult > parmax) {
142 aresult -= thePeriod;
143 theOffset -= thePeriod;
148 //=======================================================================
149 //function : IsPointOnBoundary
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)
158 IsOnFirstBoundary = Standard_True;
159 if(fabs(theParameter - theFirstBoundary) < theResolution)
160 return Standard_True;
161 if(fabs(theParameter - theSecondBoundary) < theResolution)
163 IsOnFirstBoundary = Standard_False;
164 return Standard_True;
166 return Standard_False;
169 //=======================================================================
170 //function : FindPoint
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)
181 gp_Vec2d aVec(theFirstPoint, theLastPoint);
182 Standard_Integer i = 0, j = 0;
184 for(i = 0; i < 4; i++) {
186 gp_Vec2d anOtherVecNormal;
187 gp_Pnt2d aprojpoint = theLastPoint;
192 anOtherVecNormal.SetX(1.);
193 anOtherVecNormal.SetY(0.);
196 aprojpoint.SetX(theUmin);
198 aprojpoint.SetX(theUmax);
203 anOtherVecNormal.SetX(0.);
204 anOtherVecNormal.SetY(1.);
207 aprojpoint.SetY(theVmin);
209 aprojpoint.SetY(theVmax);
211 gp_Vec2d anormvec = aVec;
212 anormvec.Normalize();
213 Standard_Real adot1 = anormvec.Dot(anOtherVecNormal);
215 if(fabs(adot1) < Precision::Angular())
217 Standard_Real adist = 0.;
220 adist = (i < 2) ? fabs(theLastPoint.X() - theUmin) : fabs(theLastPoint.X() - theUmax);
223 adist = (i < 2) ? fabs(theLastPoint.Y() - theVmin) : fabs(theLastPoint.Y() - theVmax);
225 Standard_Real anoffset = adist * anOtherVec.Dot(anormvec) / adot1;
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);
233 Standard_Real aDotX, anAngleX, aPC;
235 aDotX=aVec.Dot(acurvec);
236 anAngleX=aVec.Angle(acurvec);
237 aPC=Precision::PConfusion();
239 if(aDotX > 0. && fabs(anAngleX) < aPC) {
242 if((acurpoint.Y() >= theVmin) &&
243 (acurpoint.Y() <= theVmax)) {
244 theNewPoint = acurpoint;
245 return Standard_True;
249 if((acurpoint.X() >= theUmin) &&
250 (acurpoint.X() <= theUmax)) {
251 theNewPoint = acurpoint;
252 return Standard_True;
258 return Standard_False;
262 //=======================================================================
263 //function : NbVertex
265 //=======================================================================
266 Standard_Integer GeomInt_LineTool::NbVertex(const Handle(IntPatch_Line)& L)
268 switch (L->ArcType())
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();
275 return Handle(IntPatch_GLine)::DownCast(L)->NbVertex();
279 //=======================================================================
282 //=======================================================================
283 const IntPatch_Point & GeomInt_LineTool::Vertex(const Handle(IntPatch_Line)& L,
284 const Standard_Integer I)
286 switch (L->ArcType())
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);
293 return Handle(IntPatch_GLine)::DownCast(L)->Vertex(I);
297 //=======================================================================
298 //function : FirstParameter
300 //=======================================================================
301 Standard_Real GeomInt_LineTool::FirstParameter (const Handle(IntPatch_Line)& L)
303 const IntPatch_IType typl = L->ArcType();
306 case IntPatch_Analytic:
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);
314 firstp += Epsilon(firstp);
318 case IntPatch_Restriction:
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
324 case IntPatch_Walking:
326 Handle(IntPatch_WLine) wlin = Handle(IntPatch_WLine)::DownCast(L);
327 return (wlin->HasFirstPoint()? wlin->FirstPoint().ParameterOnLine() : 1.);
332 Handle(IntPatch_GLine) glin = Handle(IntPatch_GLine)::DownCast(L);
333 if (glin->HasFirstPoint())
334 return glin->FirstPoint().ParameterOnLine();
338 case IntPatch_Parabola:
339 case IntPatch_Hyperbola:
340 return -Precision::Infinite();
349 //=======================================================================
350 //function : LastParameter
352 //=======================================================================
353 Standard_Real GeomInt_LineTool::LastParameter (const Handle(IntPatch_Line)& L)
355 const IntPatch_IType typl = L->ArcType();
358 case IntPatch_Analytic:
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);
366 lastp -=Epsilon(lastp);
370 case IntPatch_Restriction:
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
376 case IntPatch_Walking:
378 Handle(IntPatch_WLine) wlin = Handle(IntPatch_WLine)::DownCast(L);
379 return (wlin->HasLastPoint()? wlin->LastPoint().ParameterOnLine() : wlin->NbPnts());
384 Handle(IntPatch_GLine) glin = Handle(IntPatch_GLine)::DownCast(L);
385 if (glin->HasLastPoint())
386 return glin->LastPoint().ParameterOnLine();
390 case IntPatch_Parabola:
391 case IntPatch_Hyperbola:
392 return Precision::Infinite();
393 case IntPatch_Circle:
394 case IntPatch_Ellipse:
403 //=======================================================================
404 //function : DecompositionOfWLine
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)
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;
421 Standard_Boolean bIsPrevPointOnBoundary, bIsCurrentPointOnBoundary;
422 Standard_Integer nblines, aNbPnts, aNbParts, pit, i, j, aNbListOfPointIndex;
423 Standard_Real aTol, umin, umax, vmin, vmax;
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);
433 //GeomAPI_ProjectPointOnSurf aPrj1, aPrj2;
434 ProjectPointOnSurf aPrj1, aPrj2;
435 Handle(Geom_Surface) aSurf1, aSurf2;
437 aNbParts=theLConstructor.NbParts();
438 aNbPnts=theWLine->NbPnts();
440 if((!aNbPnts) || (!aNbParts)){
441 return Standard_False;
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);
449 NCollection_LocalArray<Standard_Integer> anArrayOfLineTypeArr (aNbPnts + 1);
450 Standard_Integer* anArrayOfLineType = anArrayOfLineTypeArr;
453 aTol = Precision::Confusion();
455 aSurf1 = theSurface1->ChangeSurface().Surface();
456 aSurf1->Bounds(umin, umax, vmin, vmax);
457 aPrj1.Init(aSurf1, umin, umax, vmin, vmax);
459 aSurf2 = theSurface2->ChangeSurface().Surface();
460 aSurf2->Bounds(umin, umax, vmin, vmax);
461 aPrj2.Init(aSurf2, umin, umax, vmin, vmax);
464 bIsPrevPointOnBoundary=Standard_False;
465 for(pit=1; pit<=aNbPnts; pit++) {
466 const IntSurf_PntOn2S& aPoint = theWLine->Point(pit);
467 bIsCurrentPointOnBoundary=Standard_False;
469 // whether aPoint is on boundary or not
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);
475 for(j=0; j<2; j++) {// exploration of coordinate U,V
476 Standard_Boolean isperiodic;
478 isperiodic = (!j) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
483 Standard_Real aResolution, aPeriod, alowerboundary, aupperboundary, U, V;
484 Standard_Real aParameter, anoffset, anAdjustPar;
485 Standard_Boolean bIsOnFirstBoundary, bIsPointOnBoundary;
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;
494 aPoint.ParametersOnS1(U, V);
497 aPoint.ParametersOnS2(U, V);
500 aParameter = (!j) ? U : V;
502 anAdjustPar=AdjustPeriodic(aParameter, alowerboundary, aupperboundary, aPeriod, anoffset);
504 bIsOnFirstBoundary=Standard_True;
507 IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary);
509 if(bIsPointOnBoundary) {
510 bIsCurrentPointOnBoundary = Standard_True;
513 }// for(j=0; j<2; j++)
515 if(bIsCurrentPointOnBoundary){
518 }// for(i=0; i<2; i++)
520 if((bIsCurrentPointOnBoundary != bIsPrevPointOnBoundary)) {
522 if(!aListOfPointIndex.IsEmpty()) {
524 anArrayOfLines[nblines] = aListOfPointIndex;
525 anArrayOfLineType[nblines] = bIsPrevPointOnBoundary;
526 aListOfPointIndex.Clear();
528 bIsPrevPointOnBoundary = bIsCurrentPointOnBoundary;
530 aListOfPointIndex.Append(pit);
531 } // for(pit=1; pit<=aNbPnts; pit++)
533 aNbListOfPointIndex=aListOfPointIndex.Extent();
534 if(aNbListOfPointIndex) {
536 anArrayOfLines[nblines].Assign (aListOfPointIndex);
537 anArrayOfLineType[nblines] = bIsPrevPointOnBoundary;
538 aListOfPointIndex.Clear();
542 return Standard_False;
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());
550 for(i = 1; i <= nblines; i++) {
551 aLineType=anArrayOfLineType[i];
556 const ListOfInteger& aListOfIndex = anArrayOfLines[i];
557 if(aListOfIndex.Extent() < 2) {
561 TColStd_ListOfInteger aListOfFLIndex;
562 Standard_Integer aneighbourindex, aLineTypeNeib;
564 for(j = 0; j < 2; j++) {// neighbour line choice
565 aneighbourindex = (!j) ? (i-1) : (i+1);
566 if((aneighbourindex < 1) || (aneighbourindex > nblines)){
570 aLineTypeNeib=anArrayOfLineType[aneighbourindex];
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]
580 IntSurf_PntOn2S aNewP = aPoint;
581 Standard_Integer surfit, parit;
583 for(surfit = 0; surfit < 2; ++surfit) {
585 Handle(GeomAdaptor_HSurface) aGASurface = (!surfit) ? theSurface1 : theSurface2;
587 umin = aGASurface->FirstUParameter();
588 umax = aGASurface->LastUParameter();
589 vmin = aGASurface->FirstVParameter();
590 vmax = aGASurface->LastVParameter();
591 Standard_Real U=0., V=0.;
594 aNewP.ParametersOnS1(U, V);
597 aNewP.ParametersOnS2(U, V);
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
604 for(parit = 0; parit < 2; parit++) {
605 Standard_Boolean isperiodic = (!parit) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
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;
611 Standard_Real aParameter = (!parit) ? U : V;
612 Standard_Boolean bIsOnFirstBoundary = Standard_True;
615 if(IsPointOnBoundary(aParameter, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary)) {
616 bIsUBoundary = (!parit);
617 bIsFirstBoundary = bIsOnFirstBoundary;
622 Standard_Real aPeriod = (!parit) ? aGASurface->UPeriod() : aGASurface->VPeriod();
623 Standard_Real anoffset = 0.;
624 Standard_Real anAdjustPar = AdjustPeriodic(aParameter, alowerboundary, aupperboundary, aPeriod, anoffset);
626 if(IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, aResolution, bIsOnFirstBoundary)) {
627 bIsUBoundary = (parit == 0);
628 bIsFirstBoundary = bIsOnFirstBoundary;
634 Standard_Boolean bComputeLineEnd = Standard_False;
636 if(nbboundaries == 2) {
637 bComputeLineEnd = Standard_True;
639 else if(nbboundaries == 1) {
640 Standard_Boolean isperiodic = (bIsUBoundary) ? aGASurface->IsUPeriodic() : aGASurface->IsVPeriodic();
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);
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;
658 aNeighbourPoint.ParametersOnS1(nU1, nV1);
660 aNeighbourPoint.ParametersOnS2(nU1, nV1);
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;
668 Standard_Real anewU = (bIsUBoundary) ? anotherPar : U;
669 Standard_Real anewV = (bIsUBoundary) ? V : anotherPar;
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));
676 if(aNewVec.SquareMagnitude() < (gp::Resolution() * gp::Resolution())) {
677 aNewP.SetValue((surfit == 0), anewU, anewV);
678 bCheckAngle1 = Standard_False;
681 else if(adist1 < (aPeriod / 4.)) {
682 bCheckAngle2 = Standard_True;
683 aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(U, V));
685 if(aNewVec.SquareMagnitude() < (gp::Resolution() * gp::Resolution())) {
686 bCheckAngle2 = Standard_False;
690 if(bCheckAngle1 || bCheckAngle2) {
691 // assume there are at least two points in line (see "if" above)
692 Standard_Integer anindexother = aneighbourpointindex;
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;
700 aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
702 aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
703 gp_Vec2d aVecOld(gp_Pnt2d(nU2, nV2), gp_Pnt2d(nU1, nV1));
705 if(aVecOld.SquareMagnitude() <= (gp::Resolution() * gp::Resolution())) {
709 Standard_Real anAngle = aNewVec.Angle(aVecOld);
711 if((fabs(anAngle) < (M_PI * 0.25)) && (aNewVec.Dot(aVecOld) > 0.)) {
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();
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);
731 bComputeLineEnd = Standard_False;
736 } // end while(anindexother...)
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;
747 aNeighbourPoint.ParametersOnS1(nU1, nV1);
749 aNeighbourPoint.ParametersOnS2(nU1, nV1);
750 gp_Pnt2d ap1(nU1, nV1);
751 gp_Pnt2d ap2(nU1, nV1);
752 Standard_Integer aneighbourpointindex2 = aneighbourpointindex1;
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;
760 aPrevNeighbourPoint.ParametersOnS1(nU2, nV2);
762 aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
766 if(ap1.SquareDistance(ap2) > (gp::Resolution() * gp::Resolution())) {
771 Standard_Boolean found = FindPoint(ap2, ap1, umin, umax, vmin, vmax, anewpoint);
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;
780 gp_Pnt aP3d = aSurface->Value(anewpoint.X(), anewpoint.Y());
781 aProjector.Perform(aP3d);
783 if(aProjector.IsDone()) {
784 if(aProjector.LowerDistance() < aCriteria) {
785 Standard_Real foundU = U, foundV = V;
786 aProjector.LowerDistanceParameters(foundU, foundV);
789 aNewP.SetValue(aP3d, anewpoint.X(), anewpoint.Y(), foundU, foundV);
791 aNewP.SetValue(aP3d, foundU, foundV, anewpoint.X(), anewpoint.Y());
797 aSeqOfPntOn2S->Add(aNewP);
798 aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
800 anArrayOfLineEnds.SetValue(i, aListOfFLIndex);
802 // Correct wlines.end
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;
811 Handle(IntSurf_LineOn2S) aLineOn2S = new IntSurf_LineOn2S();
813 for(i = 1; i <= nblines; i++) {
814 if(anArrayOfLineType[i] != 0) {
817 const ListOfInteger& aListOfIndex = anArrayOfLines[i];
819 if(aListOfIndex.Extent() < 2) {
822 const TColStd_ListOfInteger& aListOfFLIndex = anArrayOfLineEnds.Value(i);
823 Standard_Boolean bhasfirstpoint = (aListOfFLIndex.Extent() == 2);
824 Standard_Boolean bhaslastpoint = (aListOfFLIndex.Extent() == 2);
826 if(!bhasfirstpoint && !aListOfFLIndex.IsEmpty()) {
827 bhasfirstpoint = (i != 1);
830 if(!bhaslastpoint && !aListOfFLIndex.IsEmpty()) {
831 bhaslastpoint = (i != nblines);
833 Standard_Boolean bIsFirstInside = ((ifprm >= aListOfIndex.First()) && (ifprm <= aListOfIndex.Last()));
834 Standard_Boolean bIsLastInside = ((ilprm >= aListOfIndex.First()) && (ilprm <= aListOfIndex.Last()));
836 if(!bIsFirstInside && !bIsLastInside) {
837 if((ifprm < aListOfIndex.First()) && (ilprm > aListOfIndex.Last())) {
838 // append whole line, and boundaries if neccesary
840 const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.First());
843 ListOfInteger::Iterator anIt(aListOfIndex);
845 for(; anIt.More(); anIt.Next()) {
846 const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
851 const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.Last());
855 // check end of split line (end is almost always)
856 Standard_Integer aneighbour = i + 1;
857 Standard_Boolean bIsEndOfLine = Standard_True;
859 if(aneighbour <= nblines) {
860 const ListOfInteger& aListOfNeighbourIndex = anArrayOfLines[aneighbour];
862 if((anArrayOfLineType[aneighbour] != 0) &&
863 (aListOfNeighbourIndex.IsEmpty())) {
864 bIsEndOfLine = Standard_False;
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);
875 aLineOn2S = new IntSurf_LineOn2S();
880 // end if(!bIsFirstInside && !bIsLastInside)
882 if(bIsFirstInside && bIsLastInside) {
883 // append inside points between ifprm and ilprm
884 ListOfInteger::Iterator anIt(aListOfIndex);
886 for(; anIt.More(); anIt.Next()) {
887 if((anIt.Value() < ifprm) || (anIt.Value() > ilprm))
889 const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
896 // append points from ifprm to last point + boundary point
897 ListOfInteger::Iterator anIt(aListOfIndex);
899 for(; anIt.More(); anIt.Next()) {
900 if(anIt.Value() < ifprm)
902 const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
907 const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.Last());
910 // check end of split line (end is almost always)
911 Standard_Integer aneighbour = i + 1;
912 Standard_Boolean bIsEndOfLine = Standard_True;
914 if(aneighbour <= nblines) {
915 const ListOfInteger& aListOfNeighbourIndex = anArrayOfLines[aneighbour];
917 if((anArrayOfLineType[aneighbour] != 0) &&
918 (aListOfNeighbourIndex.IsEmpty())) {
919 bIsEndOfLine = Standard_False;
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);
930 aLineOn2S = new IntSurf_LineOn2S();
933 // end if(bIsFirstInside)
936 // append points from first boundary point to ilprm
938 const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.First());
941 ListOfInteger::Iterator anIt(aListOfIndex);
943 for(; anIt.More(); anIt.Next()) {
944 if(anIt.Value() > ilprm)
946 const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
950 //end if(bIsLastInside)
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);
964 Standard_Real fprm, lprm;
965 Standard_Integer ifprm, ilprm, aNbPoints, aIndex;
967 aNbParts=theLConstructor.NbParts();
969 for(j = 1; j <= aNbParts; j++) {
970 theLConstructor.Part(j, fprm, lprm);
971 ifprm=(Standard_Integer)fprm;
972 ilprm=(Standard_Integer)lprm;
974 if ((ilprm-ifprm)==1) {
975 for(i = 1; i <= nblines; i++) {
976 aLineType=anArrayOfLineType[i];
981 const ListOfInteger& aListOfIndex = anArrayOfLines[i];
982 aNbPoints=aListOfIndex.Extent();
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);
991 Handle(IntPatch_WLine) aNewWLine =
992 new IntPatch_WLine(aLineOn2S, Standard_False);
993 aNewWLine->SetCreatingWayInfo(theWLine->GetCreatingWay());
994 theNewLines.Append(aNewWLine);
1001 return Standard_True;