7a73a38c0a7f56ff08dd5b307198726391d087eb
[occt.git] / src / Adaptor3d / Adaptor3d_TopolTool.cxx
1
2 #include <Standard_NotImplemented.hxx>
3 #include <Adaptor3d_TopolTool.ixx>
4 #include <Precision.hxx>
5
6 #include <gp_Cone.hxx>
7 #include <gp_Pnt.hxx>
8 #include <gp_Trsf.hxx>
9
10 #define myInfinite 1.e15
11
12 static void GetConeApexParam(const gp_Cone& C, Standard_Real& U, Standard_Real& V)
13 {
14   const gp_Ax3& Pos = C.Position();
15   Standard_Real Radius = C.RefRadius();
16   Standard_Real SAngle = C.SemiAngle();
17   const gp_Pnt& P = C.Apex();
18  
19   gp_Trsf T;
20   T.SetTransformation (Pos);
21   gp_Pnt Ploc = P.Transformed (T);
22
23   if(Ploc.X() ==0.0  &&  Ploc.Y()==0.0 ) {
24     U = 0.0;
25   }
26   else if ( -Radius > Ploc.Z()* Tan(SAngle) ) {
27     // the point is at the `wrong` side of the apex
28     U = atan2(-Ploc.Y(), -Ploc.X());
29   }
30   else {
31     U = atan2(Ploc.Y(),Ploc.X());
32   }
33   if      (U < -1.e-16)  U += (PI+PI);
34   else if (U < 0)        U = 0;
35
36   V =  sin(SAngle) * ( Ploc.X() * cos(U) + Ploc.Y() * sin(U) - Radius)
37     + cos(SAngle) * Ploc.Z();
38 }
39
40
41 Adaptor3d_TopolTool::Adaptor3d_TopolTool () : nbRestr(0),idRestr(0),myNbSamplesU(-1)
42                                               
43 {
44 }
45
46 Adaptor3d_TopolTool::Adaptor3d_TopolTool (const Handle(Adaptor3d_HSurface)& S)
47 {
48   Initialize(S);
49 }
50
51
52 void Adaptor3d_TopolTool::Initialize ()
53 {
54  Standard_NotImplemented::Raise("Adaptor3d_TopolTool::Initialize ()");
55 }
56
57 void Adaptor3d_TopolTool::Initialize (const Handle(Adaptor3d_HSurface)& S)
58 {
59   Standard_Real pinf,psup,deltap;
60   //Adaptor2d_Line2d  * Line2dPtr ;
61
62   myNbSamplesU=-1;
63   Uinf = S->FirstUParameter(); // where UIntervalFirst ??
64   Vinf = S->FirstVParameter();
65   Usup = S->LastUParameter();
66   Vsup = S->LastVParameter();
67   nbRestr = 0;
68   idRestr = 0;
69
70   Standard_Boolean Uinfinfinite = Precision::IsNegativeInfinite(Uinf);
71   Standard_Boolean Usupinfinite = Precision::IsPositiveInfinite(Usup);
72   Standard_Boolean Vinfinfinite = Precision::IsNegativeInfinite(Vinf);
73   Standard_Boolean Vsupinfinite = Precision::IsPositiveInfinite(Vsup);
74
75   if (! Vinfinfinite) {
76     deltap = Min(Usup-Uinf,2.*myInfinite);
77     if (Uinf >= -myInfinite){
78       pinf = Uinf;
79       psup = pinf + deltap;
80     }
81     else if (Usup <= myInfinite) {
82       psup = Usup;
83       pinf = psup - deltap;
84     }
85     else {
86       pinf = -myInfinite;
87       psup = myInfinite;
88     }
89
90     // Line2dPtr = new Adaptor2d_Line2d(gp_Pnt2d(0.,Vinf),gp_Dir2d(1.,0.),pinf,psup);
91     //myRestr[nbRestr] = new Adaptor2d_HLine2d(*Line2dPtr);
92     myRestr[nbRestr] = new Adaptor2d_HLine2d(Adaptor2d_Line2d(gp_Pnt2d(0.,Vinf),gp_Dir2d(1.,0.),pinf,psup));
93     nbRestr++;
94   }
95
96   if (!Usupinfinite) {
97     deltap = Min(Vsup-Vinf,2.*myInfinite);
98     if (Vinf >= -myInfinite){
99       pinf = Vinf;
100       psup = pinf + deltap;
101     }
102     else if (Vsup <= myInfinite) {
103       psup = Vsup;
104       pinf = psup - deltap;
105     }
106     else {
107       pinf = -myInfinite;
108       psup = myInfinite;
109     }
110
111
112     
113     //Line2dPtr = new Adaptor2d_Line2d(gp_Pnt2d(Usup,0.),gp_Dir2d(0.,1.),pinf,psup);
114     //myRestr[nbRestr] = new Adaptor2d_HLine2d(*Line2dPtr);
115     myRestr[nbRestr] = new Adaptor2d_HLine2d(Adaptor2d_Line2d(gp_Pnt2d(Usup,0.),gp_Dir2d(0.,1.),pinf,psup));
116     nbRestr++;
117   }
118
119   if (!Vsupinfinite) {
120     deltap = Min(Usup-Uinf,2.*myInfinite);
121     if (-Usup >= -myInfinite){
122       pinf = -Usup;
123       psup = pinf + deltap;
124     }
125     else if (-Uinf <= myInfinite) {
126       psup = -Uinf;
127       pinf = psup - deltap;
128     }
129     else {
130       pinf = -myInfinite;
131       psup = myInfinite;
132     }
133
134     
135     //Line2dPtr = new Adaptor2d_Line2d(gp_Pnt2d(0.,Vsup),gp_Dir2d(-1.,0.),pinf,psup);
136     //myRestr[nbRestr] = new Adaptor2d_HLine2d(*Line2dPtr);
137     myRestr[nbRestr] = new Adaptor2d_HLine2d(Adaptor2d_Line2d(gp_Pnt2d(0.,Vsup),gp_Dir2d(-1.,0.),pinf,psup));
138     nbRestr++;
139   }
140
141   if (!Uinfinfinite) {
142     deltap = Min(Vsup-Vinf,2.*myInfinite);
143     if (-Vsup >= -myInfinite){
144       pinf = -Vsup;
145       psup = pinf + deltap;
146     }
147     else if (-Vinf <= myInfinite) {
148       psup = -Vinf;
149       pinf = psup - deltap;
150     }
151     else {
152       pinf = -myInfinite;
153       psup = myInfinite;
154     }
155
156     //Line2dPtr = new Adaptor2d_Line2d(gp_Pnt2d(Uinf,0.),gp_Dir2d(0.,-1),pinf,psup);
157     //myRestr[nbRestr] = new Adaptor2d_HLine2d(*Line2dPtr);
158     myRestr[nbRestr] = new Adaptor2d_HLine2d(Adaptor2d_Line2d(gp_Pnt2d(Uinf,0.),gp_Dir2d(0.,-1),pinf,psup));
159     nbRestr++;
160   }
161
162   myS = S;
163
164   if(nbRestr == 2 && S->GetType() == GeomAbs_Cone ) {
165     Standard_Real U = 0., V = 0.;
166     GetConeApexParam(S->Cone(),U,V);
167
168     deltap = Min(Usup-Uinf,2.*myInfinite);
169     if (Uinf >= -myInfinite){
170       pinf = Uinf;
171       psup = pinf + deltap;
172     }
173     else if (Usup <= myInfinite) {
174       psup = Usup;
175       pinf = psup - deltap;
176     }
177     else {
178       pinf = -myInfinite;
179       psup = myInfinite;
180     }
181
182     //Line2dPtr = new Adaptor2d_Line2d(gp_Pnt2d(U,V),gp_Dir2d(1.,0.),pinf,psup);
183     //myRestr[nbRestr] = new Adaptor2d_HLine2d(*Line2dPtr);
184     myRestr[nbRestr] = new Adaptor2d_HLine2d(Adaptor2d_Line2d(gp_Pnt2d(U,V),gp_Dir2d(1.,0.),pinf,psup));
185     nbRestr++;
186   }
187 }
188
189
190 void Adaptor3d_TopolTool::Init ()
191 {
192   idRestr = 0;
193 }
194
195
196 Standard_Boolean Adaptor3d_TopolTool::More ()
197 {
198   return (idRestr < nbRestr);
199 }
200
201 Handle(Adaptor2d_HCurve2d) Adaptor3d_TopolTool::Value ()
202 {
203   if (idRestr >= nbRestr) {Standard_DomainError::Raise();}
204   return myRestr[idRestr];
205 }
206
207 void Adaptor3d_TopolTool::Next ()
208 {
209   idRestr++;
210 }
211
212
213 void Adaptor3d_TopolTool::Initialize(const Handle(Adaptor2d_HCurve2d)& C)
214 {
215   nbVtx = 0;
216   idVtx = 0;
217   Standard_Real theUinf,theUsup;
218   theUinf = C->FirstParameter();
219   theUsup = C->LastParameter();
220 //  if (!Precision::IsNegativeInfinite(theUinf)) {
221   if (theUinf > -myInfinite) {
222     myVtx[nbVtx] = new Adaptor3d_HVertex(C->Value(theUinf),TopAbs_FORWARD,1.e-8);
223     nbVtx++;
224   }
225 //  if (!Precision::IsPositiveInfinite(theUsup)) {
226   if (theUsup < myInfinite) {
227     myVtx[nbVtx] = new Adaptor3d_HVertex(C->Value(theUsup),TopAbs_REVERSED,1.e-8);
228     nbVtx++;
229   }
230 }
231
232
233 void Adaptor3d_TopolTool::InitVertexIterator ()
234 {
235   idVtx =  0;
236 }
237
238
239 Standard_Boolean Adaptor3d_TopolTool::MoreVertex ()
240 {
241   return (idVtx < nbVtx);
242 }
243
244
245 Handle(Adaptor3d_HVertex) Adaptor3d_TopolTool::Vertex ()
246 {
247   if (idVtx >= nbVtx) {Standard_DomainError::Raise();}
248   return myVtx[idVtx];
249 }
250
251 void Adaptor3d_TopolTool::NextVertex ()
252 {
253   idVtx++;
254 }
255
256
257 TopAbs_State Adaptor3d_TopolTool::Classify(const gp_Pnt2d& P,
258                                          const Standard_Real Tol,
259                                          const Standard_Boolean )
260 //                                       const Standard_Boolean RecadreOnPeriodic)
261 {
262
263   Standard_Real U = P.X();
264   Standard_Real V = P.Y();
265
266   if (nbRestr == 4) {
267     if ((U < Uinf - Tol) || (U > Usup + Tol) ||
268         (V < Vinf - Tol) || (V > Vsup + Tol)) {
269       return TopAbs_OUT;
270     }
271     if ((Abs(U - Uinf) <= Tol) || (Abs(U - Usup) <= Tol) ||
272         (Abs(V - Vinf) <= Tol) || (Abs(V - Vsup) <= Tol)) {
273       return TopAbs_ON;
274     }
275     return TopAbs_IN;
276   }
277   else if (nbRestr == 0) {
278     return TopAbs_IN;
279   }
280   else {
281     Standard_Boolean dansu,dansv,surumin,surumax,survmin,survmax;
282     if (Precision::IsNegativeInfinite(Uinf) && 
283         Precision::IsPositiveInfinite(Usup)) {
284       dansu = Standard_True;
285       surumin = surumax = Standard_False;
286     }
287     else if (Precision::IsNegativeInfinite(Uinf)) {
288       surumin = Standard_False;
289       if (U >= Usup+Tol) {
290         dansu = Standard_False;
291         surumax = Standard_False;
292       }
293       else {
294         dansu = Standard_True;
295         surumax = Standard_False;
296         if (Abs(U-Usup)<=Tol) {
297           surumax = Standard_True;
298         }
299       }
300     }
301     else if (Precision::IsPositiveInfinite(Usup)) {
302       surumax = Standard_False;
303       if (U < Uinf-Tol) {
304         dansu = Standard_False;
305         surumin = Standard_False;
306       }
307       else {
308         dansu = Standard_True;
309         surumin = Standard_False;
310         if (Abs(U-Uinf)<=Tol) {
311           surumin = Standard_True;
312         }
313       }
314     }
315     else {
316       if ((U < Uinf - Tol) || (U > Usup + Tol)) {
317         surumin = surumax = dansu = Standard_False;
318       }
319       else {
320         dansu = Standard_True;
321         surumin = surumax = Standard_False;
322         if (Abs(U-Uinf)<=Tol) {
323           surumin = Standard_True;
324         }
325         else if (Abs(U-Usup)<=Tol) {
326           surumax = Standard_True;
327         }
328       }
329     }
330
331     if (Precision::IsNegativeInfinite(Vinf) &&
332         Precision::IsPositiveInfinite(Vsup)) {
333       dansv = Standard_True;
334       survmin = survmax = Standard_False;
335     }
336     else if (Precision::IsNegativeInfinite(Vinf)) {
337       survmin = Standard_False;
338       if (V > Vsup+Tol) {
339         dansv = Standard_False;
340         survmax = Standard_False;
341       }
342       else {
343         dansv = Standard_True;
344         survmax = Standard_False;
345         if (Abs(V-Vsup)<=Tol) {
346           survmax = Standard_True;
347         }
348       }
349     }
350     else if (Precision::IsPositiveInfinite(Vsup)) {
351       survmax = Standard_False;
352       if (V < Vinf-Tol) {
353         dansv = Standard_False;
354         survmin = Standard_False;
355       }
356       else {
357         dansv = Standard_True;
358         survmin = Standard_False;
359         if (Abs(V-Vinf)<=Tol) {
360           survmin = Standard_True;
361         }
362       }
363     }
364     else {
365       if ((V < Vinf - Tol) || (V > Vsup + Tol)) {
366         survmin = survmax = dansv = Standard_False;
367       }
368       else {
369         dansv = Standard_True;
370         survmin = survmax = Standard_False;
371         if (Abs(V-Vinf)<=Tol) {
372           survmin = Standard_True;
373         }
374         else if (Abs(V-Vsup)<=Tol) {
375           survmax = Standard_True;
376         }
377       }
378     }
379
380     if (!dansu || !dansv) {
381       return TopAbs_OUT;
382     }
383     if (surumin || survmin || surumax || survmax) {
384       return TopAbs_ON;
385     }
386     return TopAbs_IN;
387   }
388 }
389
390
391
392 Standard_Boolean  Adaptor3d_TopolTool::IsThePointOn(const gp_Pnt2d& P,
393                                              const Standard_Real Tol,
394                                              const Standard_Boolean )
395 //                                           const Standard_Boolean RecadreOnPeriodic)
396 {
397
398   Standard_Real U = P.X();
399   Standard_Real V = P.Y();
400
401   if (nbRestr == 4) {
402     if ((U < Uinf - Tol) || (U > Usup + Tol) ||
403         (V < Vinf - Tol) || (V > Vsup + Tol)) {
404       return(Standard_False);
405     }
406     if ((Abs(U - Uinf) <= Tol) || (Abs(U - Usup) <= Tol) ||
407         (Abs(V - Vinf) <= Tol) || (Abs(V - Vsup) <= Tol)) {
408       return(Standard_True);
409     }
410     return(Standard_False);
411   }
412   else if (nbRestr == 0) {
413     return(Standard_False);
414   }
415   else {
416     Standard_Boolean dansu,dansv,surumin,surumax,survmin,survmax;
417     if (Precision::IsNegativeInfinite(Uinf) && 
418         Precision::IsPositiveInfinite(Usup)) {
419       dansu = Standard_True;
420       surumin = surumax = Standard_False;
421     }
422     else if (Precision::IsNegativeInfinite(Uinf)) {
423       surumin = Standard_False;
424       if (U >= Usup+Tol) {
425         dansu = Standard_False;
426         surumax = Standard_False;
427       }
428       else {
429         dansu = Standard_True;
430         surumax = Standard_False;
431         if (Abs(U-Usup)<=Tol) {
432           surumax = Standard_True;
433         }
434       }
435     }
436     else if (Precision::IsPositiveInfinite(Usup)) {
437       surumax = Standard_False;
438       if (U < Uinf-Tol) {
439         dansu = Standard_False;
440         surumin = Standard_False;
441       }
442       else {
443         dansu = Standard_True;
444         surumin = Standard_False;
445         if (Abs(U-Uinf)<=Tol) {
446           surumin = Standard_True;
447         }
448       }
449     }
450     else {
451       if ((U < Uinf - Tol) || (U > Usup + Tol)) {
452         surumin = surumax = dansu = Standard_False;
453       }
454       else {
455         dansu = Standard_True;
456         surumin = surumax = Standard_False;
457         if (Abs(U-Uinf)<=Tol) {
458           surumin = Standard_True;
459         }
460         else if (Abs(U-Usup)<=Tol) {
461           surumax = Standard_True;
462         }
463       }
464     }
465
466     if (Precision::IsNegativeInfinite(Vinf) &&
467         Precision::IsPositiveInfinite(Vsup)) {
468       dansv = Standard_True;
469       survmin = survmax = Standard_False;
470     }
471     else if (Precision::IsNegativeInfinite(Vinf)) {
472       survmin = Standard_False;
473       if (V > Vsup+Tol) {
474         dansv = Standard_False;
475         survmax = Standard_False;
476       }
477       else {
478         dansv = Standard_True;
479         survmax = Standard_False;
480         if (Abs(V-Vsup)<=Tol) {
481           survmax = Standard_True;
482         }
483       }
484     }
485     else if (Precision::IsPositiveInfinite(Vsup)) {
486       survmax = Standard_False;
487       if (V < Vinf-Tol) {
488         dansv = Standard_False;
489         survmin = Standard_False;
490       }
491       else {
492         dansv = Standard_True;
493         survmin = Standard_False;
494         if (Abs(V-Vinf)<=Tol) {
495           survmin = Standard_True;
496         }
497       }
498     }
499     else {
500       if ((V < Vinf - Tol) || (V > Vsup + Tol)) {
501         survmin = survmax = dansv = Standard_False;
502       }
503       else {
504         dansv = Standard_True;
505         survmin = survmax = Standard_False;
506         if (Abs(V-Vinf)<=Tol) {
507           survmin = Standard_True;
508         }
509         else if (Abs(V-Vsup)<=Tol) {
510           survmax = Standard_True;
511         }
512       }
513     }
514
515     if (!dansu || !dansv) {
516       return(Standard_False);
517     }
518     if (surumin || survmin || surumax || survmax) {
519       return(Standard_True);
520     }
521     return(Standard_False);;
522   }
523 }
524
525
526 TopAbs_Orientation Adaptor3d_TopolTool::Orientation
527   (const Handle(Adaptor2d_HCurve2d)&)
528 {
529   return TopAbs_FORWARD;
530 }
531
532 TopAbs_Orientation Adaptor3d_TopolTool::Orientation
533   (const Handle(Adaptor3d_HVertex)& V)
534 {
535   return V->Orientation();
536 }
537
538 Standard_Boolean Adaptor3d_TopolTool::Identical
539   (const Handle(Adaptor3d_HVertex)& V1,
540    const Handle(Adaptor3d_HVertex)& V2)
541 {
542   return V1->IsSame(V2);
543 }
544
545
546 //-- ============================================================
547 //-- m e t h o d e s   u t i l i s e e s   p o u r   l e s  
548 //--  s a m p l e s
549 //-- ============================================================ 
550 #include <TColgp_Array2OfPnt.hxx>
551 #include <Geom_BezierSurface.hxx>
552 #include <Geom_BSplineSurface.hxx>
553 #include <TColStd_Array1OfReal.hxx>
554 #include <TColStd_Array1OfBoolean.hxx>
555 //#include <gce_MakeLin.hxx>
556 #include <gp_Lin.hxx>
557 #include <gp_Dir.hxx>
558 #include <gp_Vec.hxx>
559
560 #define myMinPnts 4 //Absolut possible minimum of sample points
561                     //Restriction of IntPolyh
562
563
564 static void Analyse(const TColgp_Array2OfPnt& array2,
565                     const Standard_Integer nbup,
566                     const Standard_Integer nbvp,
567                     Standard_Integer& myNbSamplesU,
568                     Standard_Integer& myNbSamplesV) { 
569   gp_Vec Vi,Vip1;
570   Standard_Integer sh,nbch,i,j;
571   
572   sh = 1;
573   nbch = 0;
574   if(nbvp>2) { 
575     for(i=2;i<nbup;i++) { 
576       const gp_Pnt& A=array2.Value(i,1);
577       const gp_Pnt& B=array2.Value(i,2);
578       const gp_Pnt& C=array2.Value(i,3);
579       Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
580                   C.Y()-B.Y()-B.Y()+A.Y(),
581                   C.Z()-B.Z()-B.Z()+A.Z());
582       Standard_Integer locnbch=0;
583       for(j=3; j<nbvp;j++) {  //-- try
584         const gp_Pnt& A1=array2.Value(i,j-1);
585         const gp_Pnt& B1=array2.Value(i,j);
586         const gp_Pnt& C1=array2.Value(i,j+1);
587         Vip1.SetCoord(C1.X()-B1.X()-B1.X()+A1.X(),
588                       C1.Y()-B1.Y()-B1.Y()+A1.Y(),
589                       C1.Z()-B1.Z()-B1.Z()+A1.Z());
590         Standard_Real pd = Vi.Dot(Vip1);
591         Vi=Vip1;
592         if(pd>1.0e-7 || pd<-1.0e-7) { 
593           if(pd>0) {  if(sh==-1) {   sh=1; locnbch++;   }  }
594           else {        if(sh==1) {  sh=-1; locnbch++;  }  }
595         }
596       }
597       if(locnbch>nbch) { 
598         nbch=locnbch; 
599       }
600     }
601   }
602   myNbSamplesV = nbch+5;
603   
604   nbch=0;
605   if(nbup>2) { 
606     for(j=2;j<nbvp;j++) { 
607       const gp_Pnt& A=array2.Value(1,j);
608       const gp_Pnt& B=array2.Value(2,j);
609       const gp_Pnt& C=array2.Value(3,j);
610       Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
611                   C.Y()-B.Y()-B.Y()+A.Y(),
612                   C.Z()-B.Z()-B.Z()+A.Z());
613       Standard_Integer locnbch=0;
614       for(i=3; i<nbup;i++) {  //-- try
615         const gp_Pnt& A1=array2.Value(i-1,j);
616         const gp_Pnt& B1=array2.Value(i,j);
617         const gp_Pnt& C1=array2.Value(i+1,j);
618         Vip1.SetCoord(C1.X()-B1.X()-B1.X()+A1.X(),
619                       C1.Y()-B1.Y()-B1.Y()+A1.Y(),
620                       C1.Z()-B1.Z()-B1.Z()+A1.Z());
621         Standard_Real pd = Vi.Dot(Vip1);
622         Vi=Vip1;
623         if(pd>1.0e-7 || pd<-1.0e-7) { 
624           if(pd>0) {  if(sh==-1) {   sh=1; locnbch++;   }  }
625           else {        if(sh==1) {  sh=-1; locnbch++;  }  }
626         }
627       }
628       if(locnbch>nbch) nbch=locnbch;
629     }  
630   }
631   myNbSamplesU = nbch+5;
632 }  
633
634
635 void Adaptor3d_TopolTool::ComputeSamplePoints() { 
636   Standard_Real uinf,usup,vinf,vsup;
637   uinf = myS->FirstUParameter();  usup = myS->LastUParameter();
638   vinf = myS->FirstVParameter();  vsup = myS->LastVParameter();
639   if (usup < uinf) { Standard_Real temp=uinf; uinf=usup; usup=temp; }
640   if (vsup < vinf) { Standard_Real temp=vinf; vinf=vsup; vsup=temp; }
641   if (uinf == RealFirst() && usup == RealLast()) { uinf=-1.e5; usup=1.e5; }
642   else if (uinf == RealFirst()) { uinf=usup-2.e5; }
643   else if (usup == RealLast()) {  usup=uinf+2.e5; }
644   
645   if (vinf == RealFirst() && vsup == RealLast()) { vinf=-1.e5; vsup=1.e5; }
646   else if (vinf == RealFirst()) { vinf=vsup-2.e5;  }
647   else if (vsup == RealLast()) {  vsup=vinf+2.e5;  }
648   
649   Standard_Integer nbsu,nbsv;
650   GeomAbs_SurfaceType typS = myS->GetType();
651   switch(typS) { 
652   case GeomAbs_Plane:          { nbsv=2; nbsu=2; } break;
653   case GeomAbs_BezierSurface:  { nbsv=3+myS->NbVPoles(); nbsu=3+myS->NbUPoles();  } break;
654   case GeomAbs_BSplineSurface: {
655     nbsv = myS->NbVKnots();     nbsv*= myS->VDegree();     if(nbsv < 4) nbsv=4;    
656     nbsu = myS->NbUKnots();     nbsu*= myS->UDegree();     if(nbsu < 4) nbsu=4;
657   }
658     break;
659   case GeomAbs_Cylinder:
660   case GeomAbs_Cone:
661   case GeomAbs_Sphere:
662   case GeomAbs_Torus:
663   case GeomAbs_SurfaceOfRevolution:
664   case GeomAbs_SurfaceOfExtrusion:    { nbsv = 15; nbsu=15; }     break;
665   default:                            { nbsu = 10; nbsv=10; }    break;
666   }
667   
668   //-- If the number of points is too great... analyze 
669   //-- 
670   //-- 
671   
672   if(nbsu<6) nbsu=6;
673   if(nbsv<6) nbsv=6;
674   
675   myNbSamplesU = nbsu;
676   myNbSamplesV = nbsv;
677
678   if(nbsu>8 || nbsv>8) {
679     if(typS == GeomAbs_BSplineSurface) { 
680       const Handle(Geom_BSplineSurface)& Bspl = myS->BSpline();
681       Standard_Integer nbup = Bspl->NbUPoles();
682       Standard_Integer nbvp = Bspl->NbVPoles();
683       TColgp_Array2OfPnt array2(1,nbup,1,nbvp);
684       Bspl->Poles(array2);
685       Analyse(array2,nbup,nbvp,myNbSamplesU,myNbSamplesV);
686     }
687     else if(typS == GeomAbs_BezierSurface) { 
688       const Handle(Geom_BezierSurface)& Bez = myS->Bezier();
689       Standard_Integer nbup = Bez->NbUPoles();
690       Standard_Integer nbvp = Bez->NbVPoles();
691       TColgp_Array2OfPnt array2(1,nbup,1,nbvp);
692       Bez->Poles(array2);
693       Analyse(array2,nbup,nbvp,myNbSamplesU,myNbSamplesV);
694     }
695   }
696 }
697
698 Standard_Integer Adaptor3d_TopolTool::NbSamplesU()
699
700   if(myNbSamplesU <0) {
701     ComputeSamplePoints();
702   }
703   return(myNbSamplesU);
704 }
705
706 Standard_Integer Adaptor3d_TopolTool::NbSamplesV()
707
708   if(myNbSamplesU <0) { 
709     ComputeSamplePoints();    
710   }
711   return(myNbSamplesV);
712 }
713
714 Standard_Integer Adaptor3d_TopolTool::NbSamples()
715
716   if(myNbSamplesU <0) { 
717     ComputeSamplePoints();    
718   }
719   return(myNbSamplesU*myNbSamplesV);
720 }
721
722 void Adaptor3d_TopolTool::UParameters(TColStd_Array1OfReal& theArray) const
723 {
724   theArray = myUPars->Array1();
725 }
726
727 void Adaptor3d_TopolTool::VParameters(TColStd_Array1OfReal& theArray) const
728 {
729   theArray = myVPars->Array1();
730 }
731
732 void Adaptor3d_TopolTool::SamplePoint(const Standard_Integer i,
733                                       gp_Pnt2d& P2d,
734                                       gp_Pnt& P3d)
735 {
736   Standard_Integer iu, iv;
737   Standard_Real u, v;
738   if (myUPars.IsNull())
739     {
740       Standard_Real myDU=(Usup-Uinf)/(myNbSamplesU+1);
741       Standard_Real myDV=(Vsup-Vinf)/(myNbSamplesV+1);
742       iv = 1 + i/myNbSamplesU;
743       iu = 1+ i-(iv-1)*myNbSamplesU;
744       u=Uinf+iu*myDU;
745       v=Vinf+iv*myDV;
746     }
747   else
748     {
749       iv = (i-1)/myNbSamplesU + 1;
750       iu = (i-1)%myNbSamplesU + 1;
751       u = myUPars->Value(iu);
752       v = myVPars->Value(iv);
753     }
754
755   P2d.SetCoord(u,v);
756   P3d = myS->Value(u,v);
757 }
758
759
760
761 Standard_Boolean Adaptor3d_TopolTool::DomainIsInfinite() { 
762   if(Precision::IsNegativeInfinite(Uinf)) return(Standard_True);
763   if(Precision::IsPositiveInfinite(Usup)) return(Standard_True);
764   if(Precision::IsNegativeInfinite(Vinf)) return(Standard_True);
765   if(Precision::IsPositiveInfinite(Vsup)) return(Standard_True);
766   return(Standard_False);
767 }
768 //modified by NIZNHY-PKV Mon Apr 23 16:00:31 2001 f
769 //=======================================================================
770 //function : Edge
771 //purpose  : 
772 //=======================================================================
773   Standard_Address Adaptor3d_TopolTool::Edge() const 
774 {
775   return NULL;
776
777 //modified by NIZNHY-PKV Mon Apr 23 16:00:35 2001 t
778
779 //=======================================================================
780 //function : Has3d
781 //purpose  : 
782 //=======================================================================
783
784 Standard_Boolean Adaptor3d_TopolTool::Has3d() const
785 {
786   return Standard_False;
787 }
788
789 //=======================================================================
790 //function : Tol3d
791 //purpose  : 
792 //=======================================================================
793
794 Standard_Real Adaptor3d_TopolTool::Tol3d(const Handle(Adaptor2d_HCurve2d)&) const
795 {
796   Standard_DomainError::Raise("Adaptor3d_TopolTool: has no 3d representation");
797   return 0.;
798 }
799
800 //=======================================================================
801 //function : Tol3d
802 //purpose  : 
803 //=======================================================================
804
805 Standard_Real Adaptor3d_TopolTool::Tol3d(const Handle(Adaptor3d_HVertex)&) const
806 {
807   Standard_DomainError::Raise("Adaptor3d_TopolTool: has no 3d representation");
808   return 0.;
809 }
810
811 //=======================================================================
812 //function : Pnt
813 //purpose  : 
814 //=======================================================================
815
816 gp_Pnt Adaptor3d_TopolTool::Pnt(const Handle(Adaptor3d_HVertex)&) const
817 {
818   Standard_DomainError::Raise("Adaptor3d_TopolTool: has no 3d representation");
819   return gp::Origin();
820 }
821
822
823 //=======================================================================
824 //function : SamplePnts
825 //purpose  : 
826 //=======================================================================
827
828 void Adaptor3d_TopolTool::SamplePnts(const Standard_Real theDefl, 
829                                      const Standard_Integer theNUmin,
830                                      const Standard_Integer theNVmin)
831
832   Standard_Real uinf,usup,vinf,vsup;
833   uinf = myS->FirstUParameter();  usup = myS->LastUParameter();
834   vinf = myS->FirstVParameter();  vsup = myS->LastVParameter();
835   if (usup < uinf) { Standard_Real temp=uinf; uinf=usup; usup=temp; }
836   if (vsup < vinf) { Standard_Real temp=vinf; vinf=vsup; vsup=temp; }
837   if (uinf == RealFirst() && usup == RealLast()) { uinf=-1.e5; usup=1.e5; }
838   else if (uinf == RealFirst()) { uinf=usup-2.e5; }
839   else if (usup == RealLast()) {  usup=uinf+2.e5; }
840   
841   if (vinf == RealFirst() && vsup == RealLast()) { vinf=-1.e5; vsup=1.e5; }
842   else if (vinf == RealFirst()) { vinf=vsup-2.e5;  }
843   else if (vsup == RealLast()) {  vsup=vinf+2.e5;  }
844   
845 //   Standard_Integer nbsu,nbsv;
846   GeomAbs_SurfaceType typS = myS->GetType();
847 //   switch(typS) { 
848 //   case GeomAbs_Plane:          { nbsv=2; nbsu=2; } break;
849 //   case GeomAbs_BezierSurface:  { 
850 //     nbsv=myS->NbVPoles(); 
851 //     nbsu=myS->NbUPoles();
852 //     nbsu = Max(nbsu, theNUmin);
853 //     nbsv = Max(nbsv, theNVmin);
854 //     if(nbsu>8 || nbsv>8) {
855 //       const Handle(Geom_BezierSurface)& Bez = myS->Bezier();
856 //       Standard_Integer nbup = Bez->NbUPoles();
857 //       Standard_Integer nbvp = Bez->NbVPoles();
858 //       TColgp_Array2OfPnt array2(1,nbup,1,nbvp);
859 //       Bez->Poles(array2);
860 //       Analyse(array2,nbup,nbvp,myNbSamplesU,myNbSamplesV);
861 //     }  
862 //   } 
863 //     break;
864 //   case GeomAbs_BSplineSurface: {
865   if(typS == GeomAbs_BSplineSurface) {
866     // Processing BSpline surface 
867     BSplSamplePnts(theDefl, theNUmin, theNVmin);
868     return;
869   }
870   else {
871     ComputeSamplePoints();
872   }
873 //   case GeomAbs_Cylinder:
874 //   case GeomAbs_Cone:
875 //   case GeomAbs_Sphere:
876 //   case GeomAbs_Torus:
877 //   case GeomAbs_SurfaceOfRevolution:
878 //   case GeomAbs_SurfaceOfExtrusion:    { nbsv = Max(15,theNVmin); nbsu=Max(15,theNUmin); } break;
879 //   default:                            { nbsu = Max(10,theNUmin); nbsv=Max(10,theNVmin); } break;
880 //   }
881   
882   
883 //   if(nbsu<6) nbsu=6;
884 //   if(nbsv<6) nbsv=6;
885   
886 //   myNbSamplesU = nbsu;
887 //   myNbSamplesV = nbsv;
888
889
890   myUPars = new TColStd_HArray1OfReal(1, myNbSamplesU);
891   myVPars = new TColStd_HArray1OfReal(1, myNbSamplesV);
892   Standard_Integer i;
893   Standard_Real t, dt = (usup - uinf)/(myNbSamplesU - 1);
894   myUPars->SetValue(1, uinf);
895   myUPars->SetValue(myNbSamplesU, usup);
896   for(i = 2, t = uinf+dt; i < myNbSamplesU; ++i, t += dt) {
897     myUPars->SetValue(i, t);
898   }
899
900   dt = (vsup - vinf)/(myNbSamplesV - 1);
901   myVPars->SetValue(1, vinf);
902   myVPars->SetValue(myNbSamplesV, vsup);
903   for(i = 2, t = vinf+dt; i < myNbSamplesV; ++i, t += dt) {
904     myVPars->SetValue(i, t);
905   }
906
907   return;
908
909 }
910
911 //=======================================================================
912 //function : BSplSamplePnts
913 //purpose  : 
914 //=======================================================================
915
916 void Adaptor3d_TopolTool::BSplSamplePnts(const Standard_Real theDefl, 
917                                          const Standard_Integer theNUmin,
918                                          const Standard_Integer theNVmin)
919
920   const Handle(Geom_BSplineSurface)& aBS = myS->BSpline();
921   Standard_Real uinf,usup,vinf,vsup;
922   uinf = myS->FirstUParameter();  usup = myS->LastUParameter();
923   vinf = myS->FirstVParameter();  vsup = myS->LastVParameter();
924
925   Standard_Integer i, j, k, nbi;
926   Standard_Real t1, t2, dt;
927   Standard_Integer ui1 = aBS->FirstUKnotIndex();
928   Standard_Integer ui2 = aBS->LastUKnotIndex();
929   Standard_Integer vi1 = aBS->FirstVKnotIndex();
930   Standard_Integer vi2 = aBS->LastVKnotIndex();
931
932   for(i = ui1; i < ui2; ++i) {
933     if(uinf >= aBS->UKnot(i) && uinf < aBS->UKnot(i+1)) {
934       ui1 = i;
935       break;
936     }
937   }
938
939   for(i = ui2; i > ui1; --i) {
940     if(usup <= aBS->UKnot(i) && usup > aBS->UKnot(i-1)) {
941       ui2 = i;
942       break;
943     }
944   }
945
946   for(i = vi1; i < vi2; ++i) {
947     if(vinf >= aBS->VKnot(i) && vinf < aBS->VKnot(i+1)) {
948       vi1 = i;
949       break;
950     }
951   }
952
953   for(i = vi2; i > vi1; --i) {
954     if(vsup <= aBS->VKnot(i) && vsup > aBS->VKnot(i-1)) {
955       vi2 = i;
956       break;
957     }
958   }
959
960   Standard_Integer nbsu = ui2-ui1+1; nbsu += (nbsu - 1) * (aBS->UDegree()-1);
961   Standard_Integer nbsv = vi2-vi1+1; nbsv += (nbsv - 1) * (aBS->VDegree()-1);
962   Standard_Boolean bUuniform = Standard_False;
963   Standard_Boolean bVuniform = Standard_False;
964
965   if(nbsu < theNUmin) {
966     nbsu = theNUmin;
967     bUuniform = Standard_True;
968   }
969
970   if(nbsv < theNVmin) {
971     nbsv = theNVmin;
972     bVuniform = Standard_True;
973   }
974
975   TColStd_Array1OfReal anUPars(1, nbsu);
976   TColStd_Array1OfBoolean anUFlg(1, nbsu);
977   TColStd_Array1OfReal aVPars(1, nbsv);
978   TColStd_Array1OfBoolean aVFlg(1, nbsv);
979
980   //Filling of sample parameters
981   if(bUuniform) {
982     t1 = uinf;
983     t2 = usup;
984     dt = (t2 - t1)/(nbsu - 1);
985     anUPars(1) = t1;
986     anUFlg(1) = Standard_False;
987     anUPars(nbsu) = t2;
988     anUFlg(nbsu) = Standard_False;
989     for(i = 2, t1 += dt; i < nbsu; ++i, t1 += dt) {
990       anUPars(i) = t1;
991       anUFlg(i) = Standard_False;
992     }
993   }
994   else {  
995     nbi = aBS->UDegree();
996     k = 0;
997     t1 = uinf;
998     for(i = ui1+1; i <= ui2; ++i) {
999       if(i == ui2) t2 = usup;
1000       else t2 = aBS->UKnot(i);
1001       dt = (t2 - t1)/nbi;
1002       j = 1;
1003       do { 
1004         ++k;
1005         anUPars(k) = t1;
1006         anUFlg(k) = Standard_False;
1007         t1 += dt;       
1008       }
1009       while (++j <= nbi);
1010       t1 = t2;
1011     }
1012     ++k;
1013     anUPars(k) = t1;
1014   }
1015
1016   if(bVuniform) {
1017     t1 = vinf;
1018     t2 = vsup;
1019     dt = (t2 - t1)/(nbsv - 1);
1020     aVPars(1) = t1;
1021     aVFlg(1) = Standard_False;
1022     aVPars(nbsv) = t2;
1023     aVFlg(nbsv) = Standard_False;
1024     for(i = 2, t1 += dt; i < nbsv; ++i, t1 += dt) {
1025       aVPars(i) = t1;
1026       aVFlg(i) = Standard_False;
1027     }
1028   }
1029   else {  
1030     nbi = aBS->VDegree();
1031     k = 0;
1032     t1 = vinf;
1033     for(i = vi1+1; i <= vi2; ++i) {
1034       if(i == vi2) t2 = vsup;
1035       else t2 = aBS->VKnot(i);
1036       dt = (t2 - t1)/nbi;
1037       j = 1;
1038       do { 
1039         ++k;
1040         aVPars(k) = t1;
1041         aVFlg(k) = Standard_False;
1042         t1 += dt;       
1043       }
1044       while (++j <= nbi);
1045       t1 = t2;
1046     }
1047     ++k;
1048     aVPars(k) = t1;
1049   }
1050  
1051   //Analysis of deflection
1052
1053   Standard_Real aDefl2 = Max(theDefl*theDefl, 1.e-9);
1054   Standard_Real tol = Max(0.01*aDefl2, 1.e-9);
1055   Standard_Integer l;
1056
1057   anUFlg(1) = Standard_True;
1058   anUFlg(nbsu) = Standard_True;
1059   myNbSamplesU = 2; 
1060   for(i = 1; i <= nbsv; ++i) {
1061     t1 = aVPars(i);
1062     j = 1;
1063     Standard_Boolean bCont = Standard_True;
1064     while (j < nbsu-1 && bCont) {
1065
1066       if(anUFlg(j+1)) {
1067         ++j;
1068         continue;
1069       }
1070
1071       t2 = anUPars(j);
1072       gp_Pnt p1 = aBS->Value(t2, t1);
1073       for(k = j+2; k <= nbsu; ++k) {
1074         t2 = anUPars(k);
1075         gp_Pnt p2 = aBS->Value(t2, t1);
1076         //gce_MakeLin MkLin(p1, p2);
1077         //const gp_Lin& lin = MkLin.Value();
1078
1079         if(p1.SquareDistance(p2) <= tol) continue;
1080
1081         gp_Lin lin(p1, gp_Dir(gp_Vec(p1, p2)));
1082         Standard_Boolean ok = Standard_True;
1083         for(l = j+1; l < k; ++l) {
1084
1085           if(anUFlg(l)) {
1086             ok = Standard_False;
1087             break;
1088           }
1089
1090           gp_Pnt pp =  aBS->Value(anUPars(l), t1);
1091           Standard_Real d = lin.SquareDistance(pp);
1092           
1093           if(d <= aDefl2) continue;
1094
1095           ok = Standard_False;
1096           break;
1097         }
1098
1099         if(!ok) {
1100           j = k - 1;
1101           anUFlg(j) = Standard_True;
1102           ++myNbSamplesU;
1103           break;
1104         }
1105         
1106         if(anUFlg(k)) {
1107           j = k;
1108           break;
1109         }
1110         
1111
1112       }
1113
1114       if(k >= nbsu) bCont = Standard_False;
1115
1116     }
1117   }
1118   if(myNbSamplesU < myMinPnts) {
1119     if(myNbSamplesU == 2) {
1120       //"uniform" distribution;
1121       Standard_Integer nn = nbsu/myMinPnts;
1122       anUFlg(1+nn) = Standard_True;
1123       anUFlg(nbsu-nn) = Standard_True;
1124     }
1125     else { //myNbSamplesU == 3
1126       //insert in bigger segment
1127       i = 2;
1128       while(!anUFlg(i++));
1129       if(i < nbsu/2) j = Min(i+(nbsu-i)/2, nbsu-1);
1130       else j = Max(i/2, 2);
1131     }
1132     anUFlg(j) = Standard_True;
1133     myNbSamplesU = myMinPnts;
1134   }
1135       
1136   aVFlg(1) = Standard_True;
1137   aVFlg(nbsv) = Standard_True;
1138   myNbSamplesV = 2;
1139   for(i = 1; i <= nbsu; ++i) {
1140     t1 = anUPars(i);
1141     j = 1;
1142     Standard_Boolean bCont = Standard_True;
1143     while (j < nbsv-1 && bCont) {
1144
1145       if(aVFlg(j+1)) {
1146         ++j;
1147         continue;
1148       }
1149
1150       t2 = aVPars(j);
1151       gp_Pnt p1 = aBS->Value(t1, t2);
1152       for(k = j+2; k <= nbsv; ++k) {
1153         t2 = aVPars(k);
1154         gp_Pnt p2 = aBS->Value(t1, t2);
1155
1156         if(p1.SquareDistance(p2) <= tol) continue;
1157         //gce_MakeLin MkLin(p1, p2);
1158         //const gp_Lin& lin = MkLin.Value();
1159         gp_Lin lin(p1, gp_Dir(gp_Vec(p1, p2)));
1160         Standard_Boolean ok = Standard_True;
1161         for(l = j+1; l < k; ++l) {
1162
1163           if(aVFlg(l)) {
1164             ok = Standard_False;
1165             break;
1166           }
1167
1168           gp_Pnt pp =  aBS->Value(t1, aVPars(l));
1169           Standard_Real d = lin.SquareDistance(pp);
1170           
1171           if(d <= aDefl2) continue;
1172
1173           ok = Standard_False;
1174           break;
1175         }
1176
1177         if(!ok) {
1178           j = k - 1;
1179           aVFlg(j) = Standard_True;
1180           ++myNbSamplesV;
1181           break;
1182         }
1183         
1184         if(aVFlg(k)) {
1185           j = k;
1186           break;
1187         }
1188         
1189
1190       }
1191
1192       if(k >= nbsv) bCont = Standard_False;
1193
1194     }
1195   }
1196   if(myNbSamplesV < myMinPnts) {
1197     if(myNbSamplesV == 2) {
1198       //"uniform" distribution;
1199       Standard_Integer nn = nbsv/myMinPnts;
1200       aVFlg(1+nn) = Standard_True;
1201       aVFlg(nbsv-nn) = Standard_True;
1202       myNbSamplesV = myMinPnts;
1203     }
1204     else { //myNbSamplesU == 3
1205       //insert in bigger segment
1206       i = 2;
1207       while(!aVFlg(i++));
1208       if(i < nbsv/2) j = Min(i+(nbsv-i)/2, nbsv-1);
1209       else j = Max(i/2, 2);
1210     }
1211     myNbSamplesV = myMinPnts;
1212     aVFlg(j) = Standard_True;
1213   }
1214
1215  
1216   myUPars = new TColStd_HArray1OfReal(1, myNbSamplesU);
1217   myVPars = new TColStd_HArray1OfReal(1, myNbSamplesV);
1218
1219   j = 0;
1220   for(i = 1; i <= nbsu; ++i) {
1221     if(anUFlg(i)) {
1222       ++j;
1223       myUPars->SetValue(j,anUPars(i));
1224     }
1225   }
1226
1227   j = 0;
1228   for(i = 1; i <= nbsv; ++i) {
1229     if(aVFlg(i)) {
1230       ++j;
1231       myVPars->SetValue(j,aVPars(i));
1232     }
1233   }
1234  
1235
1236 }
1237
1238 Standard_Boolean Adaptor3d_TopolTool::IsUniformSampling() const
1239 {
1240   GeomAbs_SurfaceType typS = myS->GetType();
1241
1242   if(typS == GeomAbs_BSplineSurface)
1243     return Standard_False;
1244   return Standard_True;
1245 }