0026431: Can't cut a sphere from a cylinder
[occt.git] / src / ApproxInt / ApproxInt_MultiLine.gxx
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
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 <TColStd_Array1OfReal.hxx>
18 #include <gp_Pnt2d.hxx>
19 #include <gp_Pnt.hxx>
20 #include <gp_Vec2d.hxx>
21 #include <gp_Vec.hxx>
22 #include <IntSurf_LineOn2S.hxx>
23
24 //=======================================================================
25 //function : Constructor
26 //purpose  : 
27 //=======================================================================
28 ApproxInt_MultiLine::
29   ApproxInt_MultiLine(const Handle_TheLine& line,
30                       const Standard_Address svsurf,
31                       const Standard_Integer NbP3d,
32                       const Standard_Integer NbP2d,
33                       const Standard_Real xo,
34                       const Standard_Real yo,
35                       const Standard_Real zo,
36                       const Standard_Real u1o,
37                       const Standard_Real v1o,
38                       const Standard_Real u2o,
39                       const Standard_Real v2o,
40                       const Standard_Boolean P2DOnFirst,
41                       const Standard_Integer IndMin,
42                       const Standard_Integer IndMax): PtrOnmySvSurfaces(svsurf),
43                                                       myLine(line),
44                                                       indicemin(Min(IndMin, IndMax)),
45                                                       indicemax(Max(IndMin, IndMax)),
46                                                       nbp3d(NbP3d), nbp2d(NbP2d),
47                                                       p2donfirst(P2DOnFirst),
48                                                       Xo(xo), Yo(yo), Zo(zo),
49                                                       U1o(u1o), V1o(v1o),
50                                                       U2o(u2o), V2o(v2o)
51
52 {
53 #if OCCT_DEBUG 
54   //if(indicemin == indicemax)
55   //{
56   //  cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
57   //}
58 #endif
59 }
60
61 //=======================================================================
62 //function : Constructor
63 //purpose  : 
64 //=======================================================================
65 ApproxInt_MultiLine::
66   ApproxInt_MultiLine(const Handle_TheLine& line,
67                       const Standard_Integer NbP3d,
68                       const Standard_Integer NbP2d,
69                       const Standard_Real xo,
70                       const Standard_Real yo,
71                       const Standard_Real zo,
72                       const Standard_Real u1o,
73                       const Standard_Real v1o,
74                       const Standard_Real u2o,
75                       const Standard_Real v2o,
76                       const Standard_Boolean P2DOnFirst,
77                       const Standard_Integer IndMin,
78                       const Standard_Integer IndMax): PtrOnmySvSurfaces(0),
79                                                       myLine(line),
80                                                       indicemin(Min(IndMin, IndMax)),
81                                                       indicemax(Max(IndMin, IndMax)),
82                                                       nbp3d(NbP3d), nbp2d(NbP2d),
83                                                       p2donfirst(P2DOnFirst),
84                                                       Xo(xo), Yo(yo), Zo(zo),
85                                                       U1o(u1o), V1o(v1o),
86                                                       U2o(u2o), V2o(v2o)
87 {
88 #if OCCT_DEBUG
89   //if(indicemin == indicemax)
90   //{
91   //  cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
92   //}
93 #endif
94 }
95
96 //--------------------------------------------------------------------------------
97 Standard_Integer ApproxInt_MultiLine::FirstPoint() const { 
98   return(indicemin);
99 }
100 //--------------------------------------------------------------------------------
101 Standard_Integer ApproxInt_MultiLine::LastPoint() const { 
102   return(indicemax);
103 }
104 //--------------------------------------------------------------------------------
105 Approx_Status ApproxInt_MultiLine::WhatStatus() const { 
106   if(PtrOnmySvSurfaces)
107     return(Approx_PointsAdded);
108   else 
109     return(Approx_NoPointsAdded);
110 }
111 //--------------------------------------------------------------------------------
112 Standard_Integer ApproxInt_MultiLine::NbP3d() const { 
113   return(nbp3d);
114 }
115 //--------------------------------------------------------------------------------
116 Standard_Integer ApproxInt_MultiLine::NbP2d() const { 
117   return(nbp2d);
118 }
119 //================================================================================
120 void ApproxInt_MultiLine::Value(const Standard_Integer  Index,
121                                 TColgp_Array1OfPnt&     TabPnt)  const 
122
123   const gp_Pnt& aP = myLine->Point(Index).Value();
124   TabPnt(1).SetCoord(aP.X()+Xo, aP.Y()+Yo, aP.Z()+Zo);
125 }
126
127 //=======================================================================
128 //function : Value
129 //purpose  : 
130 //=======================================================================
131 void ApproxInt_MultiLine::Value(const Standard_Integer Index,
132                                 TColgp_Array1OfPnt2d&  TabPnt2d) const 
133 {
134   IntSurf_PntOn2S POn2S(myLine->Point(Index));
135   Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
136   POn2S.Parameters(u1, v1, u2, v2);
137   if(nbp2d==1)
138   { 
139     if(p2donfirst)
140     { 
141       TabPnt2d(1).SetCoord(u1+U1o, v1+V1o);
142     }
143     else
144     {
145       TabPnt2d(1).SetCoord(u2+U2o, v2+V2o);
146     }
147   }
148   else
149   {
150     TabPnt2d(1).SetCoord(u1+U1o, v1+V1o);
151     if(TabPnt2d.Length() >= 2)
152     { 
153       TabPnt2d(2).SetCoord(u2+U2o, v2+V2o);
154     } 
155   }
156 }
157
158 //=======================================================================
159 //function : Value
160 //purpose  : 
161 //=======================================================================
162 void ApproxInt_MultiLine::Value(const Standard_Integer Index,
163                                 TColgp_Array1OfPnt&    TabPnt,
164                                 TColgp_Array1OfPnt2d&  TabPnt2d)  const 
165
166     Value(Index, TabPnt);
167     Value(Index, TabPnt2d);
168 }
169
170 //=======================================================================
171 //function : Tangency
172 //purpose  : 
173 //=======================================================================
174 Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
175                                                 TColgp_Array1OfVec&    TabVec) const 
176 {
177   if(PtrOnmySvSurfaces==NULL) 
178     return Standard_False;
179
180   const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
181   Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
182   POn2S.Parameters(u1,v1,u2,v2);
183
184   Standard_Boolean ret=
185             ((TheSvSurfaces *)PtrOnmySvSurfaces)->Tangency(u1, v1, u2, v2, TabVec(1));
186   if(!ret)
187   {
188     TabVec(1).SetCoord(0.0, 0.0, 0.0);
189   }
190
191   return ret;
192 }
193
194 //=======================================================================
195 //function : Tangency
196 //purpose  : 
197 //=======================================================================
198 Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
199                                                 TColgp_Array1OfVec2d&  TabVec2d) const 
200 {
201   if(PtrOnmySvSurfaces==NULL) 
202     return Standard_False;
203
204   const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
205   Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
206   POn2S.Parameters(u1,v1,u2,v2);
207
208   Standard_Boolean ret = Standard_False;
209   if(nbp2d==1)
210   { 
211     if(p2donfirst)
212     {
213       ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1));
214     }
215     else
216     { 
217       ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(1));
218     }
219   }
220   else
221   {
222     ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf1(u1, v1, u2, v2, TabVec2d(1));
223     if(ret)
224     { 
225       if(TabVec2d.Length()>=2)
226       {
227         ret = 
228               (ret && 
229               ((TheSvSurfaces *)PtrOnmySvSurfaces)->
230                                           TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(2)));
231       }
232     }
233   }
234
235   if(!ret)
236   {
237     TabVec2d(1) = gp_Vec2d(0.0, 0.0);
238     if(TabVec2d.Length() >= 2)
239     {
240       TabVec2d(2) = gp_Vec2d(0.0,0.0);
241     }
242   }
243
244   return ret;
245 }
246
247 //=======================================================================
248 //function : Tangency
249 //purpose  : 
250 //=======================================================================
251 Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
252                                                 TColgp_Array1OfVec& TabVec,
253                                                 TColgp_Array1OfVec2d& TabVec2d) const
254
255   return (Tangency(Index, TabVec) && Tangency(Index, TabVec2d));
256 }
257
258 //=======================================================================
259 //function : MakeMLBetween
260 //purpose  : 
261 //=======================================================================
262 ApproxInt_MultiLine
263   ApproxInt_MultiLine::MakeMLBetween( const Standard_Integer Low,
264                                       const Standard_Integer High,
265                                       const Standard_Integer aNbPntsToInsert) const
266
267   if(PtrOnmySvSurfaces==NULL) {
268     //-- cout<<"\n Erreur dans : ApproxInt_MultiLine  ApproxInt_MultiLine::MakeMLBetween "<<endl;
269     Handle(IntSurf_LineOn2S) vide1 = new IntSurf_LineOn2S();
270     Handle(TheLine) vide = new TheLine(vide1,Standard_False);
271     return(ApproxInt_MultiLine(vide,
272                                NULL,
273                                nbp3d,
274                                nbp2d,
275                                Xo,Yo,Zo,U1o,V1o,U2o,V2o,
276                                p2donfirst,
277                                1,1));
278     //-- return(*this);
279   }
280
281   Standard_Integer NbPntsToInsert=aNbPntsToInsert;
282   if(NbPntsToInsert<(High-Low)) NbPntsToInsert=(High-Low);
283   Standard_Integer NbPnts = NbPntsToInsert + High - Low + 1;
284   Standard_Integer NbPntsmin = High-Low;
285   NbPntsmin+=NbPntsmin;
286   
287   if(NbPnts<NbPntsmin) NbPnts=NbPntsmin;
288
289
290   gp_Vec T;
291   gp_Vec2d TS1,TS2;
292   gp_Pnt P;
293   
294   //-----------------------l-------------------------------------------
295   //--  Indice     :   Low       Low+1     I    I+1         High    --
296   //--                                                              --
297   //--  Abs.Curv.  :  S(Low)              S(I)  S(I+1)      S(High) --
298   //--                                                              --
299   //--                On echantillonne a abcisse curviligne         --
300   //--                constante.                                    --
301   //--                L abcisse est calculee sur les params U1,V1   --
302   //------------------------------------------------------------------
303   TColStd_Array1OfReal U1(Low,High);
304   TColStd_Array1OfReal V1(Low,High);
305   TColStd_Array1OfReal U2(Low,High);
306   TColStd_Array1OfReal V2(Low,High);
307   TColStd_Array1OfReal AC(Low,High);
308   Standard_Real s,ds;
309   
310   //------------------------------------------------------------
311   //-- Creation des Tableaux U1 .. V2 et AC
312   //-- 
313   Standard_Real u1,v1,u2,v2;
314   Standard_Integer i ;
315   myLine->Point(Low).Parameters(u1,v1,u2,v2);
316   U1(Low) = u1;
317   V1(Low) = v1;
318   U2(Low) = u2;
319   V2(Low) = v2;
320   AC(Low) =0.0;
321   
322 #if 0 
323   for( i=Low+1; i<=High; i++) { 
324     myLine->Point(i).Parameters(u1,v1,u2,v2);
325     U1(i) = u1;
326     V1(i) = v1;
327     U2(i) = u2;
328     V2(i) = v2;
329     
330     Standard_Real du1=u1-U1(i-1);
331     Standard_Real dv1=v1-V1(i-1);
332     
333     AC(i) = AC(i-1) + sqrt((du1*du1)+(dv1*dv1));
334   }
335 #else 
336   //-- Essai du 19 juin 96 (parametrage selon abs curv en XYZ)
337   for( i=Low+1; i<=High; i++) { 
338     myLine->Point(i).Parameters(u1,v1,u2,v2);
339     U1(i) = u1;
340     V1(i) = v1;
341     U2(i) = u2;
342     V2(i) = v2;    
343     AC(i) = AC(i-1) + (myLine->Point(i-1).Value()).Distance(myLine->Point(i).Value());
344   }
345
346 #endif
347   //-------------------------------------------------------------
348   //-- Creation des structures contenant les resultats
349   
350   Handle(IntSurf_LineOn2S) ResultPntOn2SLine = new IntSurf_LineOn2S();
351   
352   IntSurf_PntOn2S StartPOn2S;  
353   TColStd_Array1OfReal StartParams(1,4);  
354   
355   ds = AC(High) / (NbPnts-1);
356   Standard_Integer Indice = Low;
357   Standard_Boolean HasBeenInserted = Standard_False;
358   Standard_Real dsmin = ds*0.3;
359   Standard_Real smax  = AC(High);
360   
361   for(i=2,s=ds; (s < smax && Indice <= High-1); i++,s+=ds) { 
362     //----------------------------------------------------------
363     //-- Recherche des indices des points                     --
364     //-- Point           :    2       i       NbPnts-1        --
365     //-- s                            s                       --
366     //-- Current Indice tel que AC(Indice)<= s < AC(Indice+1) --
367     //----------------------------------------------------------
368     while(AC(Indice+1) <= s)
369     { 
370       if(!HasBeenInserted)
371         ResultPntOn2SLine->Add(myLine->Point(Indice));
372
373       HasBeenInserted = Standard_False;
374       Indice++;
375       if (Indice == High)
376         break;
377     }
378     
379     if (Indice == High)
380       break;
381     
382     if(!HasBeenInserted  && AC(Indice) <= s)
383     { 
384       ResultPntOn2SLine->Add(myLine->Point(Indice));
385       HasBeenInserted = Standard_True;
386     }
387     
388     Standard_Real a = s - AC(Indice);
389     Standard_Real b = AC(Indice+1) - s;
390     Standard_Real nab = 1.0/(a+b);
391     
392     //----------------------------------------------------------
393     //-- Verification :  Si Dist au prochain  point < dsmin   --
394     //--                 Si Dist au precedent point < dsmin   --
395     //--                                                      --
396     //----------------------------------------------------------
397     if((a>dsmin) && (b>dsmin))
398     {
399       u1 = (U1(Indice) * b   +  U1(Indice+1) * a) * nab;
400       v1 = (V1(Indice) * b   +  V1(Indice+1) * a) * nab;
401       u2 = (U2(Indice) * b   +  U2(Indice+1) * a) * nab;
402       v2 = (V2(Indice) * b   +  V2(Indice+1) * a) * nab;
403             
404       if(((TheSvSurfaces *)PtrOnmySvSurfaces)->Compute(u1,v1,u2,v2,P,T,TS1,TS2))
405       {
406         StartPOn2S.SetValue(P,u1,v1,u2,v2);
407         //-- cout<<" Insertion du point calcule : "<<u1<<","<<v1<<","<<u2<<","<<v2<<",";
408         //-- cout<<P.X()<<","<<P.Y()<<","<<P.Z()<<endl;
409         ResultPntOn2SLine->Add(StartPOn2S);
410       }
411       else
412       {
413         //-- cout<<" Probleme Non Traite ds ApproxInt_ApproxIntIntersection "<<endl;
414       }
415     }
416     else
417     {
418       //-- Point non situe a distance suffisante de 2 pts existants
419       //-- avec le point p[indice] deja insere
420       
421       if(b<0.0)
422       {
423         while(AC(Indice+1) <= s)
424         {
425           if(!HasBeenInserted)
426             ResultPntOn2SLine->Add(myLine->Point(Indice));
427
428           //-- cout<<" Insertion du point :"<<Indice<<endl;
429           HasBeenInserted = Standard_False;
430           Indice++;
431
432           if (Indice == High)
433             break;
434         }
435
436         if(Indice == High)
437           break;
438
439         if(!HasBeenInserted  && AC(Indice) <= s)
440         {
441           ResultPntOn2SLine->Add(myLine->Point(Indice));
442           HasBeenInserted = Standard_True;
443         }
444       }
445       else
446       {
447         s+= (dsmin - ds);
448       }
449     }
450   }
451   
452   ResultPntOn2SLine->Add(myLine->Point(High));     //--  Point NbPnts
453   Handle(TheLine) temp = new TheLine(ResultPntOn2SLine,Standard_False);
454   
455   //-- Verification   a posteriori 
456   //-- On verifie qu il n y a pas de virage trop important en 2d et en 3d
457   
458   temp->Point(1).Parameters(u1,v1,u2,v2);
459   gp_Pnt2d P1A(u1,v1);
460   gp_Pnt2d P2A(u2,v2);
461
462   temp->Point(2).Parameters(u1,v1,u2,v2);
463   gp_Pnt2d P1B(u1,v1);
464   gp_Pnt2d P2B(u2,v2);
465
466   gp_Pnt2d P1C,P2C;
467
468   Standard_Integer CodeErreur=0; 
469   
470   for(i=3,NbPnts=temp->NbPnts();CodeErreur==0 &&  i<=NbPnts; i++)
471   {
472     Standard_Real d,du,dv,duv2;
473     temp->Point(i).Parameters(u1,v1,u2,v2);
474     //-- Virage P1A P1B P1C
475     P1C.SetCoord(u1,v1);
476     du  = P1B.X()-P1A.X();
477     dv  = P1B.Y()-P1A.Y();
478     duv2= 0.25*(du*du+dv*dv);
479     u1 = P1B.X() + du;
480     v1 = P1B.Y() + dv;
481     du = P1C.X() - u1;
482     dv = P1C.Y() - v1;
483     d = du*du+dv*dv;
484     if(d>duv2)
485     { 
486       CodeErreur = 1;
487       CodeErreur = 1;
488       break;
489     }
490     
491     //-- Virage P2A P2B P2C
492     P2C.SetCoord(u2,v2);
493     du  = P2B.X()-P2A.X();
494     dv  = P2B.Y()-P2A.Y();
495     duv2= 0.25*(du*du+dv*dv);
496     u2 = P2B.X() + du;
497     v2 = P2B.Y() + dv;
498     du = P2C.X() - u2;
499     dv = P2C.Y() - v2;
500     d = du*du+dv*dv;
501     if(d>duv2)
502     {
503       CodeErreur = 2;
504       break;
505     }
506     
507     P1A=P1B;
508     P2A=P2B;
509     P1B=P1C;
510     P2B=P2C;
511   }
512
513 #if OCCT_DEBUG
514   //if (temp->NbPnts() < NbPntsToInsert + High - Low + 1)
515   //{ 
516   //  cout<<" *** Pas assez de points entre :"<<
517   //            Low<<" et "<<High<<" -> "<<temp->NbPnts()<<endl;
518   //}
519
520   //if(CodeErreur)
521   //{ 
522   //  cout<<" *** CodeErreur : "<<CodeErreur<<endl;
523   //}
524 #endif
525
526   if((temp->NbPnts() >= NbPntsToInsert + High - Low + 1) && (CodeErreur==0))
527   {
528     return(ApproxInt_MultiLine( temp, 
529                                 (High-Low>10)? PtrOnmySvSurfaces : NULL,
530                                 nbp3d,
531                                 nbp2d,
532                                 Xo,Yo,Zo,
533                                 U1o,V1o,
534                                 U2o,V2o,
535                                 p2donfirst,
536                                 1,ResultPntOn2SLine->NbPoints()));
537   }
538   else
539   {
540     //-- cout<<" ApproxInt_MultiLine "<<endl;
541     //-- cout<<" Pas de Rajout de points ds1min =  "<<minds1<<" ds2min = "<<minds2<<endl;
542     Handle(IntSurf_LineOn2S) vide1 = new IntSurf_LineOn2S();
543     Handle(TheLine) vide = new TheLine(vide1,Standard_False);
544     return(ApproxInt_MultiLine( vide,
545                                 NULL,
546                                 nbp3d,
547                                 nbp2d,
548                                 Xo,Yo,Zo,
549                                 U1o,V1o,
550                                 U2o,V2o,
551                                 p2donfirst,
552                                 1,1));
553   }
554 }
555
556 //=======================================================================
557 //function : Dump
558 //purpose  : 
559 //=======================================================================
560 void ApproxInt_MultiLine::Dump() const
561 {
562   TColgp_Array1OfPnt anArr1(1, 1);
563   TColgp_Array1OfPnt2d anArr2(1, 2);
564         
565   const Standard_Integer  anIndF = FirstPoint(),
566                           anIndL = LastPoint();
567         
568   for(Standard_Integer ind = anIndF; ind <= anIndL; ind++)
569   {
570     Value(ind, anArr1, anArr2);
571     printf("%4d  [%+10.20f %+10.20f %+10.20f]  "
572             "[%+10.20f %+10.20f]  [%+10.20f %+10.20f]\n",
573       ind, anArr1(1).X(), anArr1(1).Y(), anArr1(1).Z(), anArr2(1).X(),
574       anArr2(1).Y(),anArr2(2).X(),anArr2(2).Y());
575   }
576 }
577