1 // File: IntTools_LineConstructor.cxx
2 // Created: Tue Feb 7 10:12:45 1995
3 // Author: Jacques GOUSSARD
4 // Copyright: OPEN CASCADE 1995
6 #include <IntTools_LineConstructor.ixx>
8 #include <GeomInt_LineTool.hxx>
9 #include <GeomInt_SequenceOfParameterAndOrientation.hxx>
10 #include <GeomInt_ParameterAndOrientation.hxx>
12 #include <IntPatch_Point.hxx>
13 #include <IntPatch_GLine.hxx>
14 #include <IntPatch_WLine.hxx>
15 #include <IntPatch_ALine.hxx>
16 #include <IntSurf_Transition.hxx>
17 #include <TopAbs_Orientation.hxx>
20 #include <Precision.hxx>
22 #include <gp_Pnt2d.hxx>
24 #include <Adaptor2d_HCurve2d.hxx>
26 #include <GeomAdaptor_HSurface.hxx>
27 #include <Standard_ConstructionError.hxx>
28 #include <IntSurf_Quadric.hxx>
29 #include <IntSurf_PntOn2S.hxx>
31 #include <GeomAbs_SurfaceType.hxx>
33 #include <TColStd_IndexedMapOfInteger.hxx>
36 //=======================================================================
39 //=======================================================================
40 static void Recadre(const Handle(GeomAdaptor_HSurface)& myHS1,
41 const Handle(GeomAdaptor_HSurface)& myHS2,
47 Standard_Boolean myHS1IsUPeriodic,myHS1IsVPeriodic;
48 const GeomAbs_SurfaceType typs1 = myHS1->GetType();
51 case GeomAbs_Cylinder:
55 myHS1IsUPeriodic = Standard_True;
56 myHS1IsVPeriodic = Standard_False;
61 myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_True;
66 //-- Case of periodic biparameters is processed upstream
67 myHS1IsUPeriodic = myHS1IsVPeriodic = Standard_False;
71 Standard_Boolean myHS2IsUPeriodic,myHS2IsVPeriodic;
72 const GeomAbs_SurfaceType typs2 = myHS2->GetType();
75 case GeomAbs_Cylinder:
79 myHS2IsUPeriodic = Standard_True;
80 myHS2IsVPeriodic = Standard_False;
85 myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_True;
90 //-- Case of periodic biparameters is processed upstream
91 myHS2IsUPeriodic = myHS2IsVPeriodic = Standard_False;
95 if(myHS1IsUPeriodic) {
96 const Standard_Real lmf = M_PI+M_PI; //-- myHS1->UPeriod();
97 const Standard_Real f = myHS1->FirstUParameter();
98 const Standard_Real l = myHS1->LastUParameter();
99 while(u1 < f) { u1+=lmf; }
100 while(u1 > l) { u1-=lmf; }
102 if(myHS1IsVPeriodic) {
103 const Standard_Real lmf = M_PI+M_PI; //-- myHS1->VPeriod();
104 const Standard_Real f = myHS1->FirstVParameter();
105 const Standard_Real l = myHS1->LastVParameter();
106 while(v1 < f) { v1+=lmf; }
107 while(v1 > l) { v1-=lmf; }
109 if(myHS2IsUPeriodic) {
110 const Standard_Real lmf = M_PI+M_PI; //-- myHS2->UPeriod();
111 const Standard_Real f = myHS2->FirstUParameter();
112 const Standard_Real l = myHS2->LastUParameter();
113 while(u2 < f) { u2+=lmf; }
114 while(u2 > l) { u2-=lmf; }
116 if(myHS2IsVPeriodic) {
117 const Standard_Real lmf = M_PI+M_PI; //-- myHS2->VPeriod();
118 const Standard_Real f = myHS2->FirstVParameter();
119 const Standard_Real l = myHS2->LastVParameter();
120 while(v2 < f) { v2+=lmf; }
121 while(v2 > l) { v2-=lmf; }
126 //=======================================================================
127 //function : Parameters
129 //=======================================================================
130 static void Parameters(const Handle(GeomAdaptor_HSurface)& myHS1,
131 const Handle(GeomAdaptor_HSurface)& myHS2,
138 IntSurf_Quadric quad1,quad2;
139 switch (myHS1->Surface().GetType())
141 case GeomAbs_Plane: quad1.SetValue(myHS1->Surface().Plane()); break;
142 case GeomAbs_Cylinder: quad1.SetValue(myHS1->Surface().Cylinder()); break;
143 case GeomAbs_Cone: quad1.SetValue(myHS1->Surface().Cone()); break;
144 case GeomAbs_Sphere: quad1.SetValue(myHS1->Surface().Sphere()); break;
145 default: Standard_ConstructionError::Raise("IntTools_LineConstructor::Parameters");
147 switch (myHS2->Surface().GetType())
149 case GeomAbs_Plane: quad2.SetValue(myHS2->Surface().Plane()); break;
150 case GeomAbs_Cylinder: quad2.SetValue(myHS2->Surface().Cylinder()); break;
151 case GeomAbs_Cone: quad2.SetValue(myHS2->Surface().Cone()); break;
152 case GeomAbs_Sphere: quad2.SetValue(myHS2->Surface().Sphere()); break;
153 default: Standard_ConstructionError::Raise("IntTools_LineConstructor::Parameters");
155 quad1.Parameters(Ptref,U1,V1);
156 quad2.Parameters(Ptref,U2,V2);
160 //=======================================================================
163 //=======================================================================
164 void IntTools_LineConstructor::Perform(const Handle(IntPatch_Line)& L)
166 Standard_Integer i,nbvtx;
167 Standard_Real firstp,lastp;
168 const Standard_Real Tol = Precision::PConfusion() * 35.0;
170 const IntPatch_IType typl = L->ArcType();
171 if(typl == IntPatch_Analytic)
173 Standard_Real u1,v1,u2,v2;
174 Handle(IntPatch_ALine)& ALine = *((Handle(IntPatch_ALine) *)&L);
176 nbvtx = GeomInt_LineTool::NbVertex(L);
179 firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
180 lastp = GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
183 const Standard_Real pmid = (firstp+lastp)*0.5;
184 const gp_Pnt Pmid = ALine->Value(pmid);
185 Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
186 Recadre(myHS1,myHS2,u1,v1,u2,v2);
187 const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
188 if(in1 != TopAbs_OUT) {
189 const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
190 if(in2 != TopAbs_OUT) {
197 done = Standard_True;
200 else if(typl == IntPatch_Walking)
202 Standard_Real u1,v1,u2,v2;
203 Handle(IntPatch_WLine)& WLine = *((Handle(IntPatch_WLine) *)&L);
205 nbvtx = GeomInt_LineTool::NbVertex(L);
208 firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
209 lastp = GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
212 if(lastp != firstp+1)
214 const Standard_Integer pmid = (Standard_Integer )( (firstp+lastp)/2);
215 const IntSurf_PntOn2S& Pmid = WLine->Point(pmid);
216 Pmid.Parameters(u1,v1,u2,v2);
217 Recadre(myHS1,myHS2,u1,v1,u2,v2);
218 const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
219 if(in1 != TopAbs_OUT) {
220 const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
221 if(in2 != TopAbs_OUT) {
229 const IntSurf_PntOn2S& Pfirst = WLine->Point((Standard_Integer)(firstp));
230 Pfirst.Parameters(u1,v1,u2,v2);
231 Recadre(myHS1,myHS2,u1,v1,u2,v2);
232 TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
233 if(in1 != TopAbs_OUT) { //-- !=ON donne Pb
234 TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
235 if(in2 != TopAbs_OUT) { //-- !=ON
236 const IntSurf_PntOn2S& Plast = WLine->Point((Standard_Integer)(lastp));
237 Plast.Parameters(u1,v1,u2,v2);
238 Recadre(myHS1,myHS2,u1,v1,u2,v2);
239 in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
240 if(in1 != TopAbs_OUT) { //-- !=ON donne Pb
241 in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
242 if(in2 != TopAbs_OUT) {
256 // The One resulting curve consists of 7 segments that are
257 // connected between each other.
258 // The aim of the block is to reject these segments and have
259 // one segment instead of 7.
260 // The other reason to do that is value of TolReached3D=49.
261 // Why -? It is not known yet.
264 const GeomAbs_SurfaceType aST1 = myHS1->Surface().GetType();
265 const GeomAbs_SurfaceType aST2 = myHS2->Surface().GetType();
266 if ((aST1==GeomAbs_Plane && aST2==GeomAbs_SurfaceOfExtrusion) ||
267 (aST2==GeomAbs_Plane && aST1==GeomAbs_SurfaceOfExtrusion))
269 TColStd_IndexedMapOfInteger aMap;
270 TColStd_SequenceOfReal aSeqTmp;
272 Standard_Integer aNb, anIndex, aNbTmp, jx;
275 for(i=1; i<=aNb;++i) {
277 anIndex=(Standard_Integer)lastp;
278 if (!aMap.Contains(anIndex)){
280 aSeqTmp.Append(lastp);
283 aNbTmp=aSeqTmp.Length();
284 aSeqTmp.Remove(aNbTmp);
290 aNb=aSeqTmp.Length()/2;
291 for(i=1; i<=aNb;++i) {
293 firstp=aSeqTmp(jx-1);
300 done = Standard_True;
303 else if (typl != IntPatch_Restriction)
305 Standard_Real u1,v1,u2,v2;
306 Handle(IntPatch_GLine)& GLine = *((Handle(IntPatch_GLine) *)&L);
308 nbvtx = GeomInt_LineTool::NbVertex(L);
309 Standard_Boolean intrvtested = Standard_False;
312 firstp = GeomInt_LineTool::Vertex(L,i).ParameterOnLine();
313 lastp = GeomInt_LineTool::Vertex(L,i+1).ParameterOnLine();
314 if(Abs(firstp-lastp)>Precision::PConfusion())
316 intrvtested = Standard_True;
317 const Standard_Real pmid = (firstp+lastp)*0.5;
321 case IntPatch_Lin: Pmid = ElCLib::Value(pmid,GLine->Line()); break;
322 case IntPatch_Circle: Pmid = ElCLib::Value(pmid,GLine->Circle()); break;
323 case IntPatch_Ellipse: Pmid = ElCLib::Value(pmid,GLine->Ellipse()); break;
324 case IntPatch_Hyperbola: Pmid = ElCLib::Value(pmid,GLine->Hyperbola()); break;
325 case IntPatch_Parabola: Pmid = ElCLib::Value(pmid,GLine->Parabola()); break;
327 Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
328 Recadre(myHS1,myHS2,u1,v1,u2,v2);
329 const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
330 if(in1 != TopAbs_OUT) {
331 const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
332 if(in2 != TopAbs_OUT) {
340 if(typl == IntPatch_Circle || typl == IntPatch_Ellipse)
342 firstp = GeomInt_LineTool::Vertex(L,nbvtx).ParameterOnLine();
343 lastp = M_PI + M_PI + GeomInt_LineTool::Vertex(L,1).ParameterOnLine();
344 const Standard_Real cadrinf = GeomInt_LineTool::FirstParameter(L);
345 const Standard_Real cadrsup = GeomInt_LineTool::LastParameter(L);
346 Standard_Real acadr = (firstp+lastp)*0.5;
347 while(acadr < cadrinf) { acadr+=M_PI+M_PI; }
348 while(acadr > cadrsup) { acadr-=M_PI+M_PI; }
349 if(acadr>=cadrinf && acadr<=cadrsup)
351 if(Abs(firstp-lastp)>Precision::PConfusion())
353 intrvtested = Standard_True;
354 const Standard_Real pmid = (firstp+lastp)*0.5;
356 if (typl == IntPatch_Circle)
357 Pmid = ElCLib::Value(pmid,GLine->Circle());
359 Pmid = ElCLib::Value(pmid,GLine->Ellipse());
360 Parameters(myHS1,myHS2,Pmid,u1,v1,u2,v2);
361 Recadre(myHS1,myHS2,u1,v1,u2,v2);
362 const TopAbs_State in1 = myDom1->Classify(gp_Pnt2d(u1,v1),Tol);
363 if(in1 != TopAbs_OUT) {
364 const TopAbs_State in2 = myDom2->Classify(gp_Pnt2d(u2,v2),Tol);
365 if(in2 != TopAbs_OUT) {
374 // Keep a priori. A point 2d on each
375 // surface is required to make the decision. Will be done in the caller
376 seqp.Append(GeomInt_LineTool::FirstParameter(L));
377 seqp.Append(GeomInt_LineTool::LastParameter(L));
380 //modified by NIZNHY-PKV Mon Jan 21 17:02:12 2002 f
382 // Unite neighbouring intervals if it's possible.
383 // It is valid when 3D intersection curve does not go through
384 // the apex on surface. So for the moment we take into account
385 // Plane and Cylinder - surfaces that do not contain an apex.
386 // by NIZNHY-PKV Tue Jan 22 14:00:51 2002
388 const GeomAbs_SurfaceType aST1 = myHS1->Surface().GetType();
389 const GeomAbs_SurfaceType aST2 = myHS2->Surface().GetType();
390 if ((aST1==GeomAbs_Plane || aST1==GeomAbs_Cylinder) &&
391 (aST2==GeomAbs_Plane || aST2==GeomAbs_Cylinder))
393 if(typl == IntPatch_Circle || typl == IntPatch_Ellipse)
395 Standard_Integer aNbParts = seqp.Length()/2;
399 Standard_Integer j, i2, j2;
400 Standard_Real aFi = seqp(1), aLi, aFj, aLj, aF, aL;
401 TColStd_SequenceOfReal aSeq;
403 for (i=1; i<aNbParts; ++i)
415 if (fabs (aFj-aLi) < Tol)
430 aNbParts=aSeq.Length();
431 for (i=1; i<=aNbParts; ++i)
439 //modified by NIZNHY-PKV Mon Jan 21 17:02:17 2002 t
445 done = Standard_False;
447 nbvtx = GeomInt_LineTool::NbVertex(L);
448 if (nbvtx == 0) { // Keep a priori. Point 2d is required on each
449 // surface to make the decision. Will be done in the caller
450 seqp.Append(GeomInt_LineTool::FirstParameter(L));
451 seqp.Append(GeomInt_LineTool::LastParameter(L));
452 done = Standard_True;
456 GeomInt_SequenceOfParameterAndOrientation seqpss;
457 TopAbs_Orientation or1=TopAbs_FORWARD,or2=TopAbs_FORWARD;
459 for (i=1; i<=nbvtx; i++)
461 const IntPatch_Point& thevtx = GeomInt_LineTool::Vertex(L,i);
462 const Standard_Real prm = thevtx.ParameterOnLine();
463 if (thevtx.IsOnDomS1())
465 switch (thevtx.TransitionLineArc1().TransitionType())
467 case IntSurf_In: or1 = TopAbs_FORWARD; break;
468 case IntSurf_Out: or1 = TopAbs_REVERSED; break;
469 case IntSurf_Touch: or1 = TopAbs_INTERNAL; break;
470 case IntSurf_Undecided: or1 = TopAbs_INTERNAL; break;
474 or1 = TopAbs_INTERNAL;
476 if (thevtx.IsOnDomS2())
478 switch (thevtx.TransitionLineArc2().TransitionType())
480 case IntSurf_In: or2 = TopAbs_FORWARD; break;
481 case IntSurf_Out: or2 = TopAbs_REVERSED; break;
482 case IntSurf_Touch: or2 = TopAbs_INTERNAL; break;
483 case IntSurf_Undecided: or2 = TopAbs_INTERNAL; break;
487 or2 = TopAbs_INTERNAL;
489 const Standard_Integer nbinserted = seqpss.Length();
490 Standard_Boolean inserted = Standard_False;
491 for (Standard_Integer j=1; j<=nbinserted;j++)
493 if (Abs(prm-seqpss(j).Parameter()) <= Tol)
496 GeomInt_ParameterAndOrientation& valj = seqpss.ChangeValue(j);
497 if (or1 != TopAbs_INTERNAL) {
498 if (valj.Orientation1() != TopAbs_INTERNAL) {
499 if (or1 != valj.Orientation1()) {
500 valj.SetOrientation1(TopAbs_INTERNAL);
504 valj.SetOrientation1(or1);
508 if (or2 != TopAbs_INTERNAL) {
509 if (valj.Orientation2() != TopAbs_INTERNAL) {
510 if (or2 != valj.Orientation2()) {
511 valj.SetOrientation2(TopAbs_INTERNAL);
515 valj.SetOrientation2(or2);
518 inserted = Standard_True;
522 if (prm < seqpss(j).Parameter()-Tol ) {
523 // insert before position j
524 seqpss.InsertBefore(j,GeomInt_ParameterAndOrientation(prm,or1,or2));
525 inserted = Standard_True;
531 seqpss.Append(GeomInt_ParameterAndOrientation(prm,or1,or2));
535 // determine the state at the beginning of line
536 Standard_Boolean trim = Standard_False;
537 Standard_Boolean dansS1 = Standard_False;
538 Standard_Boolean dansS2 = Standard_False;
540 nbvtx = seqpss.Length();
541 for (i=1; i<= nbvtx; i++)
543 or1 = seqpss(i).Orientation1();
544 if (or1 != TopAbs_INTERNAL)
546 trim = Standard_True;
547 dansS1 = (or1 != TopAbs_FORWARD);
555 for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ )
557 if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS1() )
559 GeomInt_LineTool::Vertex(L,i).ParametersOnS1(U,V);
561 if (myDom1->Classify(PPCC,Tol) == TopAbs_OUT) {
562 done = Standard_True;
568 dansS1 = Standard_True; // Keep in doubt
571 for (i=1; i<= nbvtx; i++)
573 or2 = seqpss(i).Orientation2();
574 if (or2 != TopAbs_INTERNAL)
576 trim = Standard_True;
577 dansS2 = (or2 != TopAbs_FORWARD);
585 for (i=1; i<=GeomInt_LineTool::NbVertex(L); i++ )
587 if (!GeomInt_LineTool::Vertex(L,i).IsOnDomS2() )
589 GeomInt_LineTool::Vertex(L,i).ParametersOnS2(U,V);
590 if (myDom2->Classify(gp_Pnt2d(U,V),Tol) == TopAbs_OUT) {
591 done = Standard_True;
597 dansS2 = Standard_True; // Keep in doubt
600 if (!trim) { // necessarily dansS1 == dansS2 == Standard_True
601 seqp.Append(GeomInt_LineTool::FirstParameter(L));
602 seqp.Append(GeomInt_LineTool::LastParameter(L));
603 done = Standard_True;
607 // sequence seqpss is peeled to create valid ends
608 // and store them in seqp(2*i+1) and seqp(2*i+2)
610 Standard_Real thefirst = GeomInt_LineTool::FirstParameter(L);
611 Standard_Real thelast = GeomInt_LineTool::LastParameter(L);
614 for (i=1; i<=nbvtx; i++)
616 or1 = seqpss(i).Orientation1();
617 or2 = seqpss(i).Orientation2();
618 if (dansS1 && dansS2)
620 if (or1 == TopAbs_REVERSED)
621 dansS1 = Standard_False;
622 /*else if (or1 == TopAbs_FORWARD) {
624 if (or2 == TopAbs_REVERSED)
625 dansS2 = Standard_False;
626 /*else if (or2 == TopAbs_FORWARD) {
628 if (!dansS1 || !dansS2)
630 lastp = seqpss(i).Parameter();
631 Standard_Real stofirst = Max(firstp, thefirst);
632 Standard_Real stolast = Min(lastp, thelast) ;
634 if (stolast > stofirst) {
635 seqp.Append(stofirst);
636 seqp.Append(stolast);
646 if (or1 == TopAbs_REVERSED)
647 dansS1 = Standard_False;
648 /*else if (or1 == TopAbs_FORWARD) {
653 if (or1 == TopAbs_FORWARD)
654 dansS1 = Standard_True;
655 /*else if (or1 == TopAbs_REVERSED) {
660 if (or2 == TopAbs_REVERSED)
661 dansS2 = Standard_False;
662 /*else if (or2 == TopAbs_FORWARD) {
667 if (or2 == TopAbs_FORWARD)
668 dansS2 = Standard_True;
669 /*else if (or2 == TopAbs_REVERSED) {
672 if (dansS1 && dansS2)
673 firstp = seqpss(i).Parameter();
678 if (dansS1 && dansS2)
681 firstp = Max(firstp,thefirst);
682 if (lastp > firstp) {
687 done = Standard_True;
691 //=======================================================================
692 //function : PeriodicLine
694 //=======================================================================
695 void IntTools_LineConstructor::PeriodicLine (const Handle(IntPatch_Line)& L) const
697 const IntPatch_IType typl = L->ArcType();
698 if (typl != IntPatch_Circle && typl != IntPatch_Ellipse)
701 const Standard_Real Tol = Precision::PConfusion();
702 Handle(IntPatch_GLine) glin = Handle(IntPatch_GLine)::DownCast(L);
703 Standard_Integer i,j,nbvtx = glin->NbVertex();
704 for (i=1; i<=nbvtx; i++)
706 IntPatch_Point thevtx = glin->Vertex(i);
707 const Standard_Real prm = thevtx.ParameterOnLine();
708 Standard_Boolean changevtx = Standard_False;
709 if (thevtx.IsOnDomS1() || thevtx.IsOnDomS2())
711 for (j=1; j<=nbvtx; j++)
715 const IntPatch_Point& thevtxbis = glin->Vertex(j);
716 const Standard_Real prmbis = thevtxbis.ParameterOnLine();
717 if (Abs(prm-prmbis) <= Tol)
721 if (thevtx.IsOnDomS1() && thevtxbis.IsOnDomS1() &&
722 thevtxbis.TransitionLineArc1().TransitionType()==IntSurf_In)
724 p2d = thevtx.ArcOnS1()->Value(thevtx.ParameterOnArc1());
725 u = p2d.X(); v = p2d.Y();
726 p2d = thevtxbis.ArcOnS1()->Value(thevtxbis.ParameterOnArc1());
727 if (Abs(u-p2d.X()) > Tol || Abs(v-p2d.Y()) > Tol)
729 changevtx = Standard_True;
733 if (thevtx.IsOnDomS2() && thevtxbis.IsOnDomS2() &&
734 thevtxbis.TransitionLineArc2().TransitionType()==IntSurf_In)
736 p2d = thevtx.ArcOnS2()->Value(thevtx.ParameterOnArc2());
737 u = p2d.X(); v = p2d.Y();
738 p2d = thevtxbis.ArcOnS2()->Value(thevtxbis.ParameterOnArc2());
739 if (Abs(u-p2d.X()) > Tol || Abs(v-p2d.Y()) > Tol)
741 changevtx = Standard_True;
750 thevtx.SetParameter(prm + 2.*M_PI);
751 glin->Replace(i,thevtx);