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