0026431: Can't cut a sphere from a cylinder
[occt.git] / src / ApproxInt / ApproxInt_MultiLine.gxx
CommitLineData
b311480e 1// Created on: 1993-03-22
2// Created by: Laurent BUCHARD
3// Copyright (c) 1993-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
7fd59977 17#include <TColStd_Array1OfReal.hxx>
7fd59977 18#include <gp_Pnt2d.hxx>
19#include <gp_Pnt.hxx>
20#include <gp_Vec2d.hxx>
21#include <gp_Vec.hxx>
4e14c88f 22#include <IntSurf_LineOn2S.hxx>
7fd59977 23
4e14c88f 24//=======================================================================
25//function : Constructor
26//purpose :
27//=======================================================================
28ApproxInt_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)
7fd59977 51
4e14c88f 52{
53#if OCCT_DEBUG
54 //if(indicemin == indicemax)
55 //{
56 // cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
57 //}
7fd59977 58#endif
59}
4e14c88f 60
61//=======================================================================
62//function : Constructor
63//purpose :
64//=======================================================================
65ApproxInt_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)
7fd59977 87{
4e14c88f 88#if OCCT_DEBUG
89 //if(indicemin == indicemax)
90 //{
91 // cout<<"ApproxInt_MultiLine: indicemin = indicemax = " << indicemin << endl;
92 //}
7fd59977 93#endif
7fd59977 94}
4e14c88f 95
7fd59977 96//--------------------------------------------------------------------------------
97Standard_Integer ApproxInt_MultiLine::FirstPoint() const {
98 return(indicemin);
99}
100//--------------------------------------------------------------------------------
101Standard_Integer ApproxInt_MultiLine::LastPoint() const {
102 return(indicemax);
103}
104//--------------------------------------------------------------------------------
105Approx_Status ApproxInt_MultiLine::WhatStatus() const {
106 if(PtrOnmySvSurfaces)
107 return(Approx_PointsAdded);
108 else
109 return(Approx_NoPointsAdded);
110}
111//--------------------------------------------------------------------------------
112Standard_Integer ApproxInt_MultiLine::NbP3d() const {
113 return(nbp3d);
114}
115//--------------------------------------------------------------------------------
116Standard_Integer ApproxInt_MultiLine::NbP2d() const {
117 return(nbp2d);
118}
119//================================================================================
120void ApproxInt_MultiLine::Value(const Standard_Integer Index,
4e14c88f 121 TColgp_Array1OfPnt& TabPnt) const
7fd59977 122{
4e14c88f 123 const gp_Pnt& aP = myLine->Point(Index).Value();
124 TabPnt(1).SetCoord(aP.X()+Xo, aP.Y()+Yo, aP.Z()+Zo);
7fd59977 125}
4e14c88f 126
127//=======================================================================
128//function : Value
129//purpose :
130//=======================================================================
131void ApproxInt_MultiLine::Value(const Standard_Integer Index,
132 TColgp_Array1OfPnt2d& TabPnt2d) const
7fd59977 133{
134 IntSurf_PntOn2S POn2S(myLine->Point(Index));
4e14c88f 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);
7fd59977 142 }
4e14c88f 143 else
144 {
145 TabPnt2d(1).SetCoord(u2+U2o, v2+V2o);
7fd59977 146 }
147 }
4e14c88f 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);
7fd59977 154 }
155 }
156}
4e14c88f 157
158//=======================================================================
159//function : Value
160//purpose :
161//=======================================================================
162void ApproxInt_MultiLine::Value(const Standard_Integer Index,
163 TColgp_Array1OfPnt& TabPnt,
164 TColgp_Array1OfPnt2d& TabPnt2d) const
7fd59977 165{
4e14c88f 166 Value(Index, TabPnt);
167 Value(Index, TabPnt2d);
7fd59977 168}
4e14c88f 169
170//=======================================================================
171//function : Tangency
172//purpose :
173//=======================================================================
174Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
175 TColgp_Array1OfVec& TabVec) const
176{
7fd59977 177 if(PtrOnmySvSurfaces==NULL)
4e14c88f 178 return Standard_False;
7fd59977 179
4e14c88f 180 const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
181 Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
7fd59977 182 POn2S.Parameters(u1,v1,u2,v2);
4e14c88f 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);
7fd59977 189 }
4e14c88f 190
191 return ret;
7fd59977 192}
4e14c88f 193
194//=======================================================================
195//function : Tangency
196//purpose :
197//=======================================================================
198Standard_Boolean ApproxInt_MultiLine::Tangency( const Standard_Integer Index,
199 TColgp_Array1OfVec2d& TabVec2d) const
200{
7fd59977 201 if(PtrOnmySvSurfaces==NULL)
4e14c88f 202 return Standard_False;
7fd59977 203
4e14c88f 204 const IntSurf_PntOn2S& POn2S = myLine->Point(Index);
205 Standard_Real u1 = 0.0, u2 = 0.0, v1 = 0.0, v2 = 0.0;
7fd59977 206 POn2S.Parameters(u1,v1,u2,v2);
4e14c88f 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));
7fd59977 214 }
4e14c88f 215 else
216 {
217 ret=((TheSvSurfaces *)PtrOnmySvSurfaces)->TangencyOnSurf2(u1, v1, u2, v2, TabVec2d(1));
7fd59977 218 }
7fd59977 219 }
4e14c88f 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)));
7fd59977 231 }
232 }
233 }
7fd59977 234
4e14c88f 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);
7fd59977 241 }
242 }
7fd59977 243
4e14c88f 244 return ret;
245}
7fd59977 246
4e14c88f 247//=======================================================================
248//function : Tangency
249//purpose :
250//=======================================================================
251Standard_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}
7fd59977 257
4e14c88f 258//=======================================================================
259//function : MakeMLBetween
260//purpose :
261//=======================================================================
262ApproxInt_MultiLine
263 ApproxInt_MultiLine::MakeMLBetween( const Standard_Integer Low,
264 const Standard_Integer High,
265 const Standard_Integer aNbPntsToInsert) const
266{
7fd59977 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,
4e14c88f 275 Xo,Yo,Zo,U1o,V1o,U2o,V2o,
7fd59977 276 p2donfirst,
277 1,1));
278 //-- return(*this);
279 }
4e14c88f 280
7fd59977 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
7fd59977 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;
4e14c88f 343 AC(i) = AC(i-1) + (myLine->Point(i-1).Value()).Distance(myLine->Point(i).Value());
7fd59977 344 }
345
346#endif
347 //-------------------------------------------------------------
348 //-- Creation des structures contenant les resultats
349
4e14c88f 350 Handle(IntSurf_LineOn2S) ResultPntOn2SLine = new IntSurf_LineOn2S();
7fd59977 351
352 IntSurf_PntOn2S StartPOn2S;
4e14c88f 353 TColStd_Array1OfReal StartParams(1,4);
7fd59977 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
39408dc0 361 for(i=2,s=ds; (s < smax && Indice <= High-1); i++,s+=ds) {
7fd59977 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 //----------------------------------------------------------
4e14c88f 368 while(AC(Indice+1) <= s)
369 {
370 if(!HasBeenInserted)
371 ResultPntOn2SLine->Add(myLine->Point(Indice));
372
7fd59977 373 HasBeenInserted = Standard_False;
374 Indice++;
39408dc0
J
375 if (Indice == High)
376 break;
7fd59977 377 }
39408dc0
J
378
379 if (Indice == High)
380 break;
381
4e14c88f 382 if(!HasBeenInserted && AC(Indice) <= s)
383 {
7fd59977 384 ResultPntOn2SLine->Add(myLine->Point(Indice));
385 HasBeenInserted = Standard_True;
386 }
4e14c88f 387
7fd59977 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 //----------------------------------------------------------
4e14c88f 397 if((a>dsmin) && (b>dsmin))
398 {
7fd59977 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;
4e14c88f 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);
7fd59977 410 }
4e14c88f 411 else
412 {
413 //-- cout<<" Probleme Non Traite ds ApproxInt_ApproxIntIntersection "<<endl;
7fd59977 414 }
415 }
4e14c88f 416 else
417 {
7fd59977 418 //-- Point non situe a distance suffisante de 2 pts existants
419 //-- avec le point p[indice] deja insere
420
4e14c88f 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
39408dc0
J
432 if (Indice == High)
433 break;
4e14c88f 434 }
435
436 if(Indice == High)
39408dc0 437 break;
4e14c88f 438
439 if(!HasBeenInserted && AC(Indice) <= s)
440 {
441 ResultPntOn2SLine->Add(myLine->Point(Indice));
442 HasBeenInserted = Standard_True;
443 }
7fd59977 444 }
4e14c88f 445 else
446 {
447 s+= (dsmin - ds);
7fd59977 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
4e14c88f 470 for(i=3,NbPnts=temp->NbPnts();CodeErreur==0 && i<=NbPnts; i++)
471 {
7fd59977 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;
4e14c88f 484 if(d>duv2)
485 {
7fd59977 486 CodeErreur = 1;
487 CodeErreur = 1;
488 break;
489 }
4e14c88f 490
7fd59977 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;
4e14c88f 501 if(d>duv2)
502 {
7fd59977 503 CodeErreur = 2;
504 break;
505 }
4e14c88f 506
7fd59977 507 P1A=P1B;
508 P2A=P2B;
509 P1B=P1C;
510 P2B=P2C;
511 }
4e14c88f 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 //}
7fd59977 524#endif
4e14c88f 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()));
7fd59977 537 }
4e14c88f 538 else
539 {
7fd59977 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);
4e14c88f 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));
7fd59977 553 }
554}
7fd59977 555
4e14c88f 556//=======================================================================
557//function : Dump
558//purpose :
559//=======================================================================
7c32c7c4 560void ApproxInt_MultiLine::Dump() const
561{
562 TColgp_Array1OfPnt anArr1(1, 1);
563 TColgp_Array1OfPnt2d anArr2(1, 2);
564
4e14c88f 565 const Standard_Integer anIndF = FirstPoint(),
566 anIndL = LastPoint();
567
568 for(Standard_Integer ind = anIndF; ind <= anIndL; ind++)
7c32c7c4 569 {
570 Value(ind, anArr1, anArr2);
4e14c88f 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());
7c32c7c4 575 }
576}
577