Test for 0022778: Bug in BRepMesh
[occt.git] / src / Contap / Contap_ContourGen_3.gxx
1 // Created on: 1993-02-05
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #define Tolpetit 1.e-10  // pour dist au carre
23 #include <ElSLib.hxx>
24
25
26 #include <TColStd_SequenceOfInteger.hxx>
27
28 static Standard_Boolean FindLine(Contap_TheLine& Line,
29                                  const TheSurface& Surf,
30                                  const gp_Pnt2d& Pt2d,
31                                  gp_Pnt& Ptref,
32                                  Standard_Real& Paramin,
33                                  gp_Vec& Tgmin,
34                                  gp_Vec& Norm)
35 {
36 //  Standard_Integer i;
37   gp_Pnt pt,ptmin;
38   gp_Vec tg;
39   Standard_Real para,dist;
40   Standard_Real dismin = RealLast();
41
42   Contap_TheSurfProps::Normale(Surf,Pt2d.X(),Pt2d.Y(),Ptref,Norm);
43
44   if (Line.TypeContour() == Contap_Lin) {
45     gp_Lin lin(Line.Line());
46     para = ElCLib::Parameter(lin,Ptref);
47     ElCLib::D1(para,lin,pt,tg);
48     dist = pt.Distance(Ptref) + Abs(Norm.Dot(lin.Direction()));
49   }
50   else { // Contap__Circle
51     gp_Circ cir(Line.Circle());
52     para = ElCLib::Parameter(cir,Ptref);
53     ElCLib::D1(para,cir,pt,tg);
54     dist = pt.Distance(Ptref)+Abs(Norm.Dot(tg/cir.Radius()));
55   }
56   if (dist < dismin) {
57     dismin = dist;
58     Paramin = para;
59     ptmin = pt;
60     Tgmin = tg;
61   }
62   if (ptmin.SquareDistance(Ptref) <= Tolpetit) {
63     return Standard_True;
64   }
65   else {
66     return Standard_False;
67   }
68 }
69
70
71 static void PutPointsOnLine (const Contap_TheSearch& solrst,
72                              const TheSurface& Surf,
73                              Contap_TheSequenceOfLine& slin)
74
75 {
76   Standard_Integer i,l;//,index; 
77   Standard_Integer NbPoints = solrst.NbPoints();
78
79   Standard_Real theparam;
80
81   IntSurf_Transition TLine,TArc;
82   Standard_Boolean goon;
83   
84   gp_Pnt2d pt2d;
85   gp_Vec2d d2d;
86
87   gp_Pnt ptonsurf;
88   gp_Vec vectg,normale,tgtrst;
89   Standard_Real paramlin;
90
91   
92   Standard_Integer nbLin = slin.Length();
93   for(l=1;l<=nbLin;l++) { 
94     Contap_TheLine& Line=slin.ChangeValue(l);
95     for (i=1; i<= NbPoints; i++) {
96       
97       const Contap_ThePathPointOfTheSearch& PStart = solrst.Point(i);
98       const TheArc& thearc = PStart.Arc();
99       theparam = PStart.Parameter();
100       
101       TheArcTool::D1(thearc,theparam,pt2d,d2d);
102       goon = FindLine(Line,Surf,pt2d,ptonsurf,paramlin,vectg,normale);
103       
104       Contap_ThePoint PPoint;
105
106       if (goon) {
107         gp_Vec d1u,d1v;
108         gp_Pnt bidpt;
109         TheSurfaceTool::D1(Surf,pt2d.X(),pt2d.Y(),bidpt,d1u,d1v);
110         PPoint.SetValue(ptonsurf,pt2d.X(),pt2d.Y());
111         if (normale.Magnitude() < RealEpsilon()) {
112           TLine.SetValue();
113           TArc.SetValue();
114         }
115         else {
116           // Petit test qui devrait permettre de bien traiter les pointes
117           // des cones, et les sommets d`une sphere. Il faudrait peut-etre
118           // rajouter une methode dans SurfProps
119           
120           if (Abs(d2d.Y()) <= Precision::Confusion()) {
121             tgtrst = d1v.Crossed(normale);
122             if(d2d.X() < 0.0) 
123               tgtrst.Reverse();
124           }
125           else {
126             tgtrst.SetLinearForm(d2d.X(),d1u,d2d.Y(),d1v);
127           }
128           IntSurf::MakeTransition(vectg,tgtrst,normale,TLine,TArc);
129         }
130         
131         PPoint.SetArc(thearc,theparam, TLine, TArc);
132         PPoint.SetParameter(paramlin);
133         if (!PStart.IsNew()) {
134           PPoint.SetVertex(PStart.Vertex());
135         }
136         Line.Add(PPoint);
137       }
138     }
139   }
140 }
141
142
143 //----------------------------------------------------------------------------------
144 //-- Orientation des contours Apparents quand ceux-ci sont des lignes ou des cercles
145 //-- On prend un point de la ligne ou du cercle ---> P 
146 //-- On projete ce point sur la surface P ---> u,v
147 //-- et on evalue la transition au point u,v
148 //----------------------------------------------------------------------------------
149
150 IntSurf_TypeTrans ComputeTransitionOngpLine
151   (Contap_TheSurfFunction& SFunc,
152    const gp_Lin& L)
153
154   const TheSurface& Surf=SFunc.Surface();
155   GeomAbs_SurfaceType typS = TheSurfaceTool::GetType(Surf);
156   gp_Pnt P;
157   gp_Vec T;
158   ElCLib::D1(0.0,L,P,T);
159   Standard_Real u,v;
160   switch (typS) {
161   case GeomAbs_Cylinder: {
162     ElSLib::Parameters(TheSurfaceTool::Cylinder(Surf),P,u,v);
163       break;
164     }
165   case GeomAbs_Cone: {
166     ElSLib::Parameters(TheSurfaceTool::Cone(Surf),P,u,v);
167       break;
168     }
169   case GeomAbs_Sphere: { 
170     ElSLib::Parameters(TheSurfaceTool::Sphere(Surf),P,u,v);
171       break;
172     }
173   default:
174     break;
175   }
176   return(ComputeTransitionOnLine(SFunc,u,v,T));
177 }
178
179
180 IntSurf_TypeTrans ComputeTransitionOngpCircle
181   (Contap_TheSurfFunction& SFunc,
182    const gp_Circ& C)
183
184   const TheSurface& Surf=SFunc.Surface();
185   GeomAbs_SurfaceType typS = TheSurfaceTool::GetType(Surf);
186   gp_Pnt P;
187   gp_Vec T;
188   ElCLib::D1(0.0,C,P,T);
189   Standard_Real u,v;
190   switch (typS) {
191   case GeomAbs_Cylinder: {
192     ElSLib::Parameters(TheSurfaceTool::Cylinder(Surf),P,u,v);
193       break;
194     }
195   case GeomAbs_Cone: {
196     ElSLib::Parameters(TheSurfaceTool::Cone(Surf),P,u,v);
197       break;
198     }
199   case GeomAbs_Sphere: { 
200     ElSLib::Parameters(TheSurfaceTool::Sphere(Surf),P,u,v);
201       break;
202     }
203   default:
204     break;
205   }
206   return(ComputeTransitionOnLine(SFunc,u,v,T));
207 }
208
209
210 void Contap_ContourGen::PerformAna(const Handle(TheTopolTool)& Domain)
211 {
212
213   done = Standard_False;
214   slin.Clear();
215
216   Standard_Real TolArc = 1.e-5;
217
218   Standard_Integer nbCont, nbPointRst, i;
219   //gp_Circ cirsol;
220   //gp_Lin linsol;
221   Contap_ContAna contana;
222   Contap_TheLine theline;
223   const TheSurface& Surf = mySFunc.Surface();
224   Contap_TFunction TypeFunc(mySFunc.FunctionType());
225   Standard_Boolean PerformSolRst = Standard_True;
226
227   GeomAbs_SurfaceType typS = TheSurfaceTool::GetType(Surf);
228
229   switch (typS) {
230   case GeomAbs_Plane: 
231     {
232       gp_Pln pl(TheSurfaceTool::Plane(Surf));
233       switch (TypeFunc) {
234       case Contap_ContourStd:
235         {
236           gp_Dir Dirpln(pl.Axis().Direction());
237           if (Abs(mySFunc.Direction().Dot(Dirpln)) > Precision::Angular()) {
238             // Aucun point du plan n`est solution, en particulier aucun point
239             // sur restriction.
240             PerformSolRst = Standard_False;
241           }
242         }
243         break;
244       case Contap_ContourPrs:
245         {
246           gp_Pnt Eye(mySFunc.Eye());
247           if (pl.Distance(Eye) > Precision::Confusion()) {
248             // Aucun point du plan n`est solution, en particulier aucun point
249             // sur restriction.
250             PerformSolRst = Standard_False;
251           }         
252         }
253         break;
254       case Contap_DraftStd:
255         {
256           gp_Dir Dirpln(pl.Axis().Direction());
257           Standard_Real Sina = Sin(mySFunc.Angle());
258           if (Abs(mySFunc.Direction().Dot(Dirpln)+ Sina) > //voir SurfFunction
259               Precision::Angular()) {
260           
261             PerformSolRst = Standard_False;
262           }
263         }
264         break;
265       case Contap_DraftPrs:
266       default:
267         {
268         }
269       }
270     }
271     break;
272
273   case GeomAbs_Sphere:
274     {
275       switch (TypeFunc) {
276       case Contap_ContourStd:
277         {
278           contana.Perform(TheSurfaceTool::Sphere(Surf),mySFunc.Direction());
279         }
280         break;
281       case Contap_ContourPrs:
282         {
283           contana.Perform(TheSurfaceTool::Sphere(Surf),mySFunc.Eye());
284         }
285         break;
286       case Contap_DraftStd:
287         {
288           contana.Perform(TheSurfaceTool::Sphere(Surf),
289                           mySFunc.Direction(),mySFunc.Angle());
290         }
291         break;
292       case Contap_DraftPrs:
293       default:
294         {
295         }
296       }
297     }
298     break;
299
300   case GeomAbs_Cylinder:
301     {
302       switch (TypeFunc) {
303       case Contap_ContourStd:
304         {
305           contana.Perform(TheSurfaceTool::Cylinder(Surf),mySFunc.Direction());
306         }
307         break;
308       case Contap_ContourPrs:
309         {
310           contana.Perform(TheSurfaceTool::Cylinder(Surf),mySFunc.Eye());
311         }
312         break;
313       case Contap_DraftStd:
314         {
315           contana.Perform(TheSurfaceTool::Cylinder(Surf),
316                           mySFunc.Direction(),mySFunc.Angle());
317         }
318         break;
319       case Contap_DraftPrs:
320       default:
321         {
322         }
323       }
324     }
325     break;
326
327   case GeomAbs_Cone:
328     {
329       switch (TypeFunc) {
330       case Contap_ContourStd:
331         {
332           contana.Perform(TheSurfaceTool::Cone(Surf),mySFunc.Direction());
333         }
334         break;
335       case Contap_ContourPrs:
336         {
337           contana.Perform(TheSurfaceTool::Cone(Surf),mySFunc.Eye());
338         }
339         break;
340       case Contap_DraftStd:
341         {
342           contana.Perform(TheSurfaceTool::Cone(Surf),
343                           mySFunc.Direction(),mySFunc.Angle());
344         }
345         break;
346       case Contap_DraftPrs:
347       default:
348         {
349         }
350       }
351     default:
352       break;
353     }
354     break;
355   }
356   
357   if (typS != GeomAbs_Plane) {
358
359     if (!contana.IsDone()) {
360       return;
361     }
362
363     nbCont = contana.NbContours();
364
365     if (contana.NbContours() == 0) {
366       done = Standard_True;
367       return;
368     }
369
370     GeomAbs_CurveType typL = contana.TypeContour();
371     if (typL == GeomAbs_Circle) {
372       theline.SetValue(contana.Circle());
373       IntSurf_TypeTrans TransCircle;
374       TransCircle = ComputeTransitionOngpCircle(mySFunc,contana.Circle());
375       theline.SetTransitionOnS(TransCircle);
376       slin.Append(theline);
377     }
378     else if (typL == GeomAbs_Line) {
379       for (i=1; i<=nbCont; i++) {
380         theline.SetValue(contana.Line(i));
381         IntSurf_TypeTrans TransLine;
382         TransLine = ComputeTransitionOngpLine(mySFunc,contana.Line(i));
383         theline.SetTransitionOnS(TransLine);
384         slin.Append(theline);
385         theline.Clear();
386       }
387       
388 /*
389       if (typS == GeomAbs_Cone) {
390         Standard_Real u,v;
391         gp_Cone thecone(TheSurfaceTool::Cone(Surf));
392         ElSLib::Parameters(thecone,thecone.Apex(),u,v);
393         Contap_ThePoint vtxapex(thecone.Apex(),u,v);
394         vtxapex.SetInternal();
395         vtxapex.SetMultiple();
396         for (i=1; i<=nbCont i++) {
397           slin.ChangeValue(i).Add(vtxapex);
398         }
399       }
400 */
401     }
402   }
403
404   if(PerformSolRst) { 
405     
406     solrst.Perform(myAFunc,Domain,TolArc,TolArc);
407     if (!solrst.IsDone()) {
408       return;
409     }
410     nbPointRst = solrst.NbPoints();
411     
412     if (nbPointRst != 0) {
413       PutPointsOnLine(solrst,Surf,slin);
414     }
415     
416     if (solrst.NbSegments() !=0) {
417       ProcessSegments(solrst,slin,TolArc,mySFunc,Domain);
418     }
419     
420     
421     //-- lbr 
422     //Standard_Boolean oneremov;
423     Standard_Integer nblinto = slin.Length();
424     TColStd_SequenceOfInteger SeqToDestroy;
425     
426     //-- cout<<" Construct Contour_3   nblin = "<<nblinto<<endl;
427     for(i=1; i<= nblinto ; i++) { 
428       //-- cout<<" nbvtx : "<<slin.Value(i).NbVertex()<<endl;
429       //--if(slin.Value(i).NbVertex() > 1) { 
430       if(slin.Value(i).TypeContour() != Contap_Restriction) { 
431         LineConstructor(slin,Domain,slin.ChangeValue(i),Surf);
432         SeqToDestroy.Append(i);
433       }
434       //-- }
435     }
436     for(i=SeqToDestroy.Length(); i>=1; i--) { 
437       slin.Remove(SeqToDestroy.Value(i));
438     } 
439   }
440
441   done = Standard_True;
442 }
443
444
445
446
447