1 // Created on: 1993-03-22
2 // Created by: Laurent BUCHARD
3 // Copyright (c) 1993-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.
17 #include <TColStd_Array1OfReal.hxx>
18 #include <gp_Pnt2d.hxx>
20 #include <gp_Vec2d.hxx>
22 #include <IntSurf_LineOn2S.hxx>
23 #include <Precision.hxx>
24 #include <math_Vector.hxx>
27 #include <DrawTrSurf.hxx>
30 //=======================================================================
31 //function : Constructor
33 //=======================================================================
34 ApproxInt_MultiLine::ApproxInt_MultiLine()
36 PtrOnmySvSurfaces = NULL;
42 myApproxU1V1 = Standard_False;
43 myApproxU2V2 = Standard_False;
44 p2donfirst = Standard_True;
54 //=======================================================================
55 //function : Constructor
57 //=======================================================================
59 ApproxInt_MultiLine(const Handle_TheLine& line,
60 const Standard_Address svsurf,
61 const Standard_Integer NbP3d,
62 const Standard_Integer NbP2d,
63 const Standard_Boolean ApproxU1V1,
64 const Standard_Boolean ApproxU2V2,
65 const Standard_Real xo,
66 const Standard_Real yo,
67 const Standard_Real zo,
68 const Standard_Real u1o,
69 const Standard_Real v1o,
70 const Standard_Real u2o,
71 const Standard_Real v2o,
72 const Standard_Boolean P2DOnFirst,
73 const Standard_Integer IndMin,
74 const Standard_Integer IndMax): PtrOnmySvSurfaces(svsurf),
76 indicemin(Min(IndMin, IndMax)),
77 indicemax(Max(IndMin, IndMax)),
78 nbp3d(NbP3d), nbp2d(NbP2d),
79 myApproxU1V1(ApproxU1V1),
80 myApproxU2V2(ApproxU2V2),
81 p2donfirst(P2DOnFirst),
82 Xo(xo), Yo(yo), Zo(zo),
88 //if(indicemin == indicemax)
90 // cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
95 //=======================================================================
96 //function : Constructor
98 //=======================================================================
100 ApproxInt_MultiLine(const Handle_TheLine& line,
101 const Standard_Integer NbP3d,
102 const Standard_Integer NbP2d,
103 const Standard_Boolean ApproxU1V1,
104 const Standard_Boolean ApproxU2V2,
105 const Standard_Real xo,
106 const Standard_Real yo,
107 const Standard_Real zo,
108 const Standard_Real u1o,
109 const Standard_Real v1o,
110 const Standard_Real u2o,
111 const Standard_Real v2o,
112 const Standard_Boolean P2DOnFirst,
113 const Standard_Integer IndMin,
114 const Standard_Integer IndMax): PtrOnmySvSurfaces(0),
116 indicemin(Min(IndMin, IndMax)),
117 indicemax(Max(IndMin, IndMax)),
118 nbp3d(NbP3d), nbp2d(NbP2d),
119 myApproxU1V1(ApproxU1V1),
120 myApproxU2V2(ApproxU2V2),
121 p2donfirst(P2DOnFirst),
122 Xo(xo), Yo(yo), Zo(zo),
127 //if(indicemin == indicemax)
129 // cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
134 //--------------------------------------------------------------------------------
135 Standard_Integer ApproxInt_MultiLine::FirstPoint() const {
138 //--------------------------------------------------------------------------------
139 Standard_Integer ApproxInt_MultiLine::LastPoint() const {
142 //--------------------------------------------------------------------------------
143 Approx_Status ApproxInt_MultiLine::WhatStatus() const {
144 if(PtrOnmySvSurfaces)
145 return Approx_PointsAdded;
147 return Approx_NoPointsAdded;
149 //--------------------------------------------------------------------------------
150 Standard_Integer ApproxInt_MultiLine::NbP3d() const {
153 //--------------------------------------------------------------------------------
154 Standard_Integer ApproxInt_MultiLine::NbP2d() const {
157 //================================================================================
158 void ApproxInt_MultiLine::Value(const Standard_Integer Index,
159 TColgp_Array1OfPnt& TabPnt) const
161 const gp_Pnt aP = myLine->Point(Index).Value();
162 TabPnt(1).SetCoord(aP.X()+Xo, aP.Y()+Yo, aP.Z()+Zo);
165 //=======================================================================
168 //=======================================================================
169 void ApproxInt_MultiLine::Value(const Standard_Integer Index,
170 TColgp_Array1OfPnt2d& TabPnt2d) const
172 IntSurf_PntOn2S POn2S(myLine->Point(Index));
173 Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
174 POn2S.Parameters(u1, v1, u2, v2);
179 TabPnt2d(1).SetCoord(u1+U1o, v1+V1o);
183 TabPnt2d(1).SetCoord(u2+U2o, v2+V2o);
188 TabPnt2d(1).SetCoord(u1+U1o, v1+V1o);
189 if(TabPnt2d.Length() >= 2)
191 TabPnt2d(2).SetCoord(u2+U2o, v2+V2o);
196 //=======================================================================
199 //=======================================================================
200 void ApproxInt_MultiLine::Value(const Standard_Integer Index,
201 TColgp_Array1OfPnt& TabPnt,
202 TColgp_Array1OfPnt2d& TabPnt2d) const
204 Value(Index, TabPnt);
205 Value(Index, TabPnt2d);
208 //=======================================================================
209 //function : Tangency
211 //=======================================================================
212 Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
213 TColgp_Array1OfVec& TabVec) const
215 if(PtrOnmySvSurfaces==NULL)
216 return Standard_False;
218 const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
219 Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
220 POn2S.Parameters(u1,v1,u2,v2);
222 Standard_Boolean ret=
223 ((TheSvSurfaces *)PtrOnmySvSurfaces)->Tangency(u1, v1, u2, v2, TabVec(1));
226 TabVec(1).SetCoord(0.0, 0.0, 0.0);
232 //=======================================================================
233 //function : Tangency
235 //=======================================================================
236 Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
237 TColgp_Array1OfVec2d& TabVec2d) const
239 if(PtrOnmySvSurfaces==NULL)
240 return Standard_False;
242 const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
243 Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
244 POn2S.Parameters(u1,v1,u2,v2);
246 Standard_Boolean ret = Standard_False;
251 ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1));
255 ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(1));
260 ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1));
263 if(TabVec2d.Length()>=2)
267 ((TheSvSurfaces *)PtrOnmySvSurfaces)->
268 TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(2)));
275 TabVec2d(1) = gp_Vec2d(0.0, 0.0);
276 if(TabVec2d.Length() >= 2)
278 TabVec2d(2) = gp_Vec2d(0.0,0.0);
285 //=======================================================================
286 //function : Tangency
288 //=======================================================================
289 Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
290 TColgp_Array1OfVec& TabVec,
291 TColgp_Array1OfVec2d& TabVec2d) const
293 return (Tangency(Index, TabVec) && Tangency(Index, TabVec2d));
296 //=======================================================================
297 //function : MakeMLBetween
299 //=======================================================================
301 ApproxInt_MultiLine::MakeMLBetween( const Standard_Integer Low,
302 const Standard_Integer High,
303 const Standard_Integer aNbPntsToInsert) const
305 if(PtrOnmySvSurfaces==NULL) {
306 //-- cout<<"\n Erreur dans : ApproxInt_MultiLine ApproxInt_MultiLine::MakeMLBetween "<<endl;
307 Handle(IntSurf_LineOn2S) vide1 = new IntSurf_LineOn2S();
308 Handle(TheLine) vide = new TheLine(vide1,Standard_False);
309 return (ApproxInt_MultiLine(vide,
313 myApproxU1V1, myApproxU2V2,
314 Xo,Yo,Zo,U1o,V1o,U2o,V2o,
320 Standard_Boolean aSaveUseSolver = ((TheSvSurfaces *)PtrOnmySvSurfaces)->GetUseSolver();
323 ((TheSvSurfaces *)PtrOnmySvSurfaces)->SetUseSolver(Standard_True);
325 Standard_Integer NbPntsToInsert=aNbPntsToInsert;
326 if(NbPntsToInsert<(High-Low)) NbPntsToInsert=(High-Low);
327 Standard_Integer NbPnts = NbPntsToInsert + High - Low + 1;
328 Standard_Integer NbPntsmin = High-Low;
329 NbPntsmin+=NbPntsmin;
331 if(NbPnts<NbPntsmin) NbPnts=NbPntsmin;
338 //-----------------------l-------------------------------------------
339 //-- Indice : Low Low+1 I I+1 High --
341 //-- Abs.Curv. : S(Low) S(I) S(I+1) S(High) --
343 //-- On echantillonne a abcisse curviligne --
345 //-- L abcisse est calculee sur les params U1,V1 --
346 //------------------------------------------------------------------
347 TColStd_Array1OfReal U1(Low,High);
348 TColStd_Array1OfReal V1(Low,High);
349 TColStd_Array1OfReal U2(Low,High);
350 TColStd_Array1OfReal V2(Low,High);
351 TColStd_Array1OfReal AC(Low,High);
354 //------------------------------------------------------------
355 //-- Creation des Tableaux U1 .. V2 et AC
357 Standard_Real u1,v1,u2,v2;
359 myLine->Point(Low).Parameters(u1,v1,u2,v2);
367 for( i=Low+1; i<=High; i++) {
368 myLine->Point(i).Parameters(u1,v1,u2,v2);
374 Standard_Real du1=u1-U1(i-1);
375 Standard_Real dv1=v1-V1(i-1);
377 AC(i) = AC(i-1) + sqrt((du1*du1)+(dv1*dv1));
380 //-- Essai du 19 juin 96 (parametrage selon abs curv en XYZ)
381 for( i=Low+1; i<=High; i++) {
382 myLine->Point(i).Parameters(u1,v1,u2,v2);
387 AC(i) = AC(i-1) + (myLine->Point(i-1).Value()).Distance(myLine->Point(i).Value());
391 //-------------------------------------------------------------
392 //-- Creation des structures contenant les resultats
394 Handle(IntSurf_LineOn2S) ResultPntOn2SLine = new IntSurf_LineOn2S();
396 IntSurf_PntOn2S StartPOn2S;
397 TColStd_Array1OfReal StartParams(1,4);
399 ds = AC(High) / (NbPnts-1);
400 Standard_Integer Indice = Low;
401 Standard_Boolean HasBeenInserted = Standard_False;
402 Standard_Real dsmin = ds*0.3;
403 Standard_Real smax = AC(High);
405 for(i=2,s=ds; (s < smax && Indice <= High-1); i++,s+=ds) {
406 //----------------------------------------------------------
407 //-- Recherche des indices des points --
408 //-- Point : 2 i NbPnts-1 --
410 //-- Current Indice tel que AC(Indice)<= s < AC(Indice+1) --
411 //----------------------------------------------------------
412 while(AC(Indice+1) <= s)
415 ResultPntOn2SLine->Add(myLine->Point(Indice));
417 HasBeenInserted = Standard_False;
426 if(!HasBeenInserted && AC(Indice) <= s)
428 ResultPntOn2SLine->Add(myLine->Point(Indice));
429 HasBeenInserted = Standard_True;
432 Standard_Real a = s - AC(Indice);
433 Standard_Real b = AC(Indice+1) - s;
434 Standard_Real nab = 1.0/(a+b);
436 //----------------------------------------------------------
437 //-- Verification : Si Dist au prochain point < dsmin --
438 //-- Si Dist au precedent point < dsmin --
440 //----------------------------------------------------------
441 if((a>dsmin) && (b>dsmin))
443 u1 = (U1(Indice) * b + U1(Indice+1) * a) * nab;
444 v1 = (V1(Indice) * b + V1(Indice+1) * a) * nab;
445 u2 = (U2(Indice) * b + U2(Indice+1) * a) * nab;
446 v2 = (V2(Indice) * b + V2(Indice+1) * a) * nab;
448 if(((TheSvSurfaces *)PtrOnmySvSurfaces)->Compute(u1,v1,u2,v2,P,T,TS1,TS2))
450 StartPOn2S.SetValue(P,u1,v1,u2,v2);
451 //-- cout<<" Insertion du point calcule : "<<u1<<","<<v1<<","<<u2<<","<<v2<<",";
452 //-- cout<<P.X()<<","<<P.Y()<<","<<P.Z()<<endl;
453 ResultPntOn2SLine->Add(StartPOn2S);
457 //-- cout<<" Probleme Non Traite ds ApproxInt_ApproxIntIntersection "<<endl;
462 //-- Point non situe a distance suffisante de 2 pts existants
463 //-- avec le point p[indice] deja insere
467 while(AC(Indice+1) <= s)
470 ResultPntOn2SLine->Add(myLine->Point(Indice));
472 //-- cout<<" Insertion du point :"<<Indice<<endl;
473 HasBeenInserted = Standard_False;
483 if(!HasBeenInserted && AC(Indice) <= s)
485 ResultPntOn2SLine->Add(myLine->Point(Indice));
486 HasBeenInserted = Standard_True;
496 ResultPntOn2SLine->Add(myLine->Point(High)); //-- Point NbPnts
497 Handle(TheLine) temp = new TheLine(ResultPntOn2SLine,Standard_False);
499 //-- Verification a posteriori
500 //-- On verifie qu il n y a pas de virage trop important en 2d et en 3d
502 temp->Point(1).Parameters(u1,v1,u2,v2);
506 temp->Point(2).Parameters(u1,v1,u2,v2);
512 Standard_Integer CodeErreur=0;
514 for(i=3,NbPnts=temp->NbPnts();CodeErreur==0 && i<=NbPnts; i++)
516 Standard_Real d,du,dv,duv2;
517 temp->Point(i).Parameters(u1,v1,u2,v2);
518 //-- Virage P1A P1B P1C
520 du = P1B.X()-P1A.X();
521 dv = P1B.Y()-P1A.Y();
522 duv2= 0.25*(du*du+dv*dv);
535 //-- Virage P2A P2B P2C
537 du = P2B.X()-P2A.X();
538 dv = P2B.Y()-P2A.Y();
539 duv2= 0.25*(du*du+dv*dv);
558 //if (temp->NbPnts() < NbPntsToInsert + High - Low + 1)
560 // cout<<" *** Pas assez de points entre :"<<
561 // Low<<" et "<<High<<" -> "<<temp->NbPnts()<<endl;
566 // cout<<" *** CodeErreur : "<<CodeErreur<<endl;
570 if((temp->NbPnts() >= NbPntsToInsert + High - Low + 1) && (CodeErreur==0))
572 ((TheSvSurfaces *)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver);
573 return (ApproxInt_MultiLine( temp,
574 (High-Low>10)? PtrOnmySvSurfaces : NULL,
577 myApproxU1V1, myApproxU2V2,
582 1,ResultPntOn2SLine->NbPoints()));
586 //-- cout<<" ApproxInt_MultiLine "<<endl;
587 //-- cout<<" Pas de Rajout de points ds1min = "<<minds1<<" ds2min = "<<minds2<<endl;
588 ((TheSvSurfaces *)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver);
589 Handle(IntSurf_LineOn2S) vide1 = new IntSurf_LineOn2S();
590 Handle(TheLine) vide = new TheLine(vide1,Standard_False);
591 return (ApproxInt_MultiLine( vide,
595 myApproxU1V1, myApproxU2V2,
604 //=======================================================================
605 //function : MakeMLOneMorePoint
607 //=======================================================================
609 ApproxInt_MultiLine::MakeMLOneMorePoint(const Standard_Integer theLow,
610 const Standard_Integer theHigh,
611 const Standard_Integer theIndbad,
612 ApproxInt_MultiLine& theNewMultiLine) const
614 Standard_Boolean OtherLineMade = Standard_False;
615 if(PtrOnmySvSurfaces==NULL)
616 return Standard_False;
618 Standard_Boolean aSaveUseSolver = ((TheSvSurfaces *)PtrOnmySvSurfaces)->GetUseSolver();
621 ((TheSvSurfaces *)PtrOnmySvSurfaces)->SetUseSolver(Standard_True);
624 const Standard_Real SqTol3d = Precision::SquareConfusion();
625 math_Vector tolerance(1,2);
626 tolerance(1) = tolerance(2) = 1.e-8;
628 Handle(IntSurf_LineOn2S) ResultPntOn2SLine = new IntSurf_LineOn2S();
629 for (Standard_Integer Indice = theLow; Indice <= theHigh; Indice++)
630 ResultPntOn2SLine->Add(myLine->Point(Indice));
632 //Insert new point between (theIndbad-1) and theIndbad
633 //Using <thePtrSVSurf> for Rsnld: it may be ImpPrm or PrmPrm
634 gp_Pnt PrevPnt = myLine->Point(theIndbad-1).Value();
635 gp_Pnt CurPnt = myLine->Point(theIndbad).Value();
636 Standard_Real uprev1, vprev1, uprev2, vprev2, ucur1, vcur1, ucur2, vcur2;
637 myLine->Point(theIndbad-1).Parameters(uprev1, vprev1, uprev2, vprev2);
638 myLine->Point(theIndbad).Parameters(ucur1, vcur1, ucur2, vcur2);
639 Standard_Real umid1, vmid1, umid2, vmid2;
640 umid1 = (uprev1 + ucur1)/2;
641 vmid1 = (vprev1 + vcur1)/2;
642 umid2 = (uprev2 + ucur2)/2;
643 vmid2 = (vprev2 + vcur2)/2;
644 IntSurf_PntOn2S MidPoint;
645 Standard_Boolean IsNewPointInvalid = Standard_False;
648 Abs(ucur1 - umid1) <= tolerance(1) &&
649 Abs(vcur1 - vmid1) <= tolerance(2);
650 if (!IsNewPointInvalid)
654 Abs(ucur2 - umid2) <= tolerance(1) &&
655 Abs(vcur2 - vmid2) <= tolerance(2);
656 if (!IsNewPointInvalid &&
657 ((TheSvSurfaces *)PtrOnmySvSurfaces)->SeekPoint(umid1, vmid1, umid2, vmid2,
660 const gp_Pnt& NewPnt = MidPoint.Value();
661 Standard_Real SqDistNewPrev = NewPnt.SquareDistance(PrevPnt);
662 Standard_Real SqDistNewCur = NewPnt.SquareDistance(CurPnt);
663 IsNewPointInvalid = (SqDistNewPrev <= SqTol3d ||
664 SqDistNewCur <= SqTol3d);
665 if (!IsNewPointInvalid)
667 Standard_Real unew1, vnew1, unew2, vnew2;
668 MidPoint.Parameters(unew1, vnew1, unew2, vnew2);
671 Standard_Real SqDistCurMid1 =
672 (ucur1 - umid1)*(ucur1 - umid1)+(vcur1 - vmid1)*(vcur1 - vmid1);
673 Standard_Real SqDistMidNew1 =
674 (umid1 - unew1)*(umid1 - unew1)+(vmid1 - vnew1)*(vmid1 - vnew1);
675 IsNewPointInvalid = (SqDistMidNew1 > SqDistCurMid1);
677 if (!IsNewPointInvalid)
681 Standard_Real SqDistCurMid2 =
682 (ucur2 - umid2)*(ucur2 - umid2)+(vcur2 - vmid2)*(vcur2 - vmid2);
683 Standard_Real SqDistMidNew2 =
684 (umid2 - unew2)*(umid2 - unew2)+(vmid2 - vnew2)*(vmid2 - vnew2);
685 IsNewPointInvalid = (SqDistMidNew2 > SqDistCurMid2);
687 if (!IsNewPointInvalid)
689 ResultPntOn2SLine->InsertBefore(theIndbad-theLow+1, MidPoint);
690 OtherLineMade = Standard_True;
699 ((TheSvSurfaces *)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver);
700 return Standard_False;
704 char* name = new char[100];
705 Standard_Integer indc = 1;
706 Standard_Boolean onfirst = Standard_True;
707 for (Standard_Integer i = 1; i <= ResultPntOn2SLine->NbPoints(); i++)
709 const IntSurf_PntOn2S& thePoint = ResultPntOn2SLine->Value(i);
710 gp_Pnt curPnt = thePoint.Value();
711 sprintf(name, "p%d_%d", indc, i);
712 DrawTrSurf::Set(name, curPnt);
713 gp_Pnt2d curPnt2d = thePoint.ValueOnSurface(onfirst);
714 sprintf(name, "pp%d_%d", indc, i);
715 DrawTrSurf::Set(name, curPnt2d);
718 Handle(TheLine) temp = new TheLine(ResultPntOn2SLine,Standard_False);
719 ((TheSvSurfaces *)PtrOnmySvSurfaces)->SetUseSolver(aSaveUseSolver);
720 theNewMultiLine = ApproxInt_MultiLine( temp,
730 1,ResultPntOn2SLine->NbPoints());
731 return Standard_True;
734 //=======================================================================
737 //=======================================================================
738 void ApproxInt_MultiLine::Dump() const
740 TColgp_Array1OfPnt anArr1(1, 1);
741 TColgp_Array1OfPnt2d anArr2(1, 2);
743 const Standard_Integer anIndF = FirstPoint(),
744 anIndL = LastPoint();
746 for(Standard_Integer ind = anIndF; ind <= anIndL; ind++)
748 Value(ind, anArr1, anArr2);
749 printf("%4d [%+10.20f %+10.20f %+10.20f] "
750 "[%+10.20f %+10.20f] [%+10.20f %+10.20f]\n",
751 ind, anArr1(1).X(), anArr1(1).Y(), anArr1(1).Z(), anArr2(1).X(),
752 anArr2(1).Y(),anArr2(2).X(),anArr2(2).Y());