0027620: Test perf bop boxholes crashes DRAW
[occt.git] / src / BRepAlgo / BRepAlgo_NormalProjection.cxx
1 // Created on: 1997-10-13
2 // Created by: Roman BORISOV
3 // Copyright (c) 1997-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
18 #include <Adaptor3d_Curve.hxx>
19 #include <Approx_CurveOnSurface.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepAdaptor_HCurve.hxx>
23 #include <BRepAdaptor_HSurface.hxx>
24 #include <BRepAdaptor_Surface.hxx>
25 #include <BRepAlgo_NormalProjection.hxx>
26 #include <BRepAlgoAPI_Section.hxx>
27 #include <BRepLib_MakeEdge.hxx>
28 #include <BRepLib_MakeVertex.hxx>
29 #include <BRepLib_MakeWire.hxx>
30 #include <BRepTools.hxx>
31 #include <BRepTopAdaptor_FClass2d.hxx>
32 #include <Geom2d_BSplineCurve.hxx>
33 #include <Geom2d_Curve.hxx>
34 #include <Geom2d_TrimmedCurve.hxx>
35 #include <Geom2dAdaptor_HCurve.hxx>
36 #include <Geom_BSplineCurve.hxx>
37 #include <GeomAdaptor.hxx>
38 #include <Precision.hxx>
39 #include <ProjLib_CompProjectedCurve.hxx>
40 #include <ProjLib_HCompProjectedCurve.hxx>
41 #include <Standard_ConstructionError.hxx>
42 #include <Standard_NoSuchObject.hxx>
43 #include <StdFail_NotDone.hxx>
44 #include <TColgp_Array1OfPnt2d.hxx>
45 #include <TColStd_Array1OfInteger.hxx>
46 #include <TColStd_Array1OfReal.hxx>
47 #include <TopAbs.hxx>
48 #include <TopExp.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopoDS.hxx>
51 #include <TopoDS_Edge.hxx>
52 #include <TopoDS_Shape.hxx>
53 #include <TopTools_HSequenceOfShape.hxx>
54 #include <TopTools_ListIteratorOfListOfShape.hxx>
55
56 #ifdef OCCT_DEBUG_CHRONO
57 #include <OSD_Timer.hxx>
58
59 OSD_Chronometer chr_total, chr_init, chr_approx, chr_booltool;
60
61 Standard_Real t_total, t_init, t_approx, t_booltool;
62 Standard_IMPORT Standard_Real t_init_point, t_dicho_bound;
63 Standard_IMPORT Standard_Integer init_point_count, dicho_bound_count;
64
65 void InitChron(OSD_Chronometer& ch)
66
67     ch.Reset();
68     ch.Start();
69 }
70
71 void ResultChron( OSD_Chronometer & ch, Standard_Real & time) 
72 {
73     Standard_Real tch ;
74     ch.Stop();
75     ch.Show(tch);
76     time=time +tch;
77 }
78
79 #endif
80 //=======================================================================
81 //function : BRepAlgo_NormalProjection
82 //purpose  : 
83 //=======================================================================
84
85  BRepAlgo_NormalProjection::BRepAlgo_NormalProjection() 
86    : myIsDone(Standard_False), myMaxDist(-1.),
87      myWith3d(Standard_True), myFaceBounds(Standard_True)
88 {
89   BRep_Builder BB;
90   BB.MakeCompound(TopoDS::Compound(myToProj));
91   SetDefaultParams();
92 }
93
94 //=======================================================================
95 //function : BRepAlgo_NormalProjection
96 //purpose  : 
97 //=======================================================================
98
99  BRepAlgo_NormalProjection::BRepAlgo_NormalProjection(const TopoDS_Shape& S) 
100    : myIsDone(Standard_False), myMaxDist(-1.),
101      myWith3d(Standard_True), myFaceBounds(Standard_True)
102 {
103   BRep_Builder BB;
104   BB.MakeCompound(TopoDS::Compound(myToProj));
105   SetDefaultParams();
106   Init(S);
107 }
108
109 //=======================================================================
110 //function : Init
111 //purpose  : 
112 //=======================================================================
113
114  void BRepAlgo_NormalProjection::Init(const TopoDS_Shape& S) 
115 {
116   myShape = S;
117 }
118
119 //=======================================================================
120 //function : Add
121 //purpose  : 
122 //=======================================================================
123
124  void BRepAlgo_NormalProjection::Add(const TopoDS_Shape& ToProj) 
125 {
126   BRep_Builder BB;
127   BB.Add(myToProj, ToProj);
128 }
129
130 //=======================================================================
131 //function : SetParams
132 //purpose  : 
133 //=======================================================================
134
135 void BRepAlgo_NormalProjection::SetParams(const Standard_Real Tol3D,
136                                            const Standard_Real Tol2D,
137                                            const GeomAbs_Shape InternalContinuity,
138                                            const Standard_Integer MaxDegree,
139                                            const Standard_Integer MaxSeg) 
140 {
141   myTol3d = Tol3D;
142   myTol2d = Tol2D;
143   myContinuity = InternalContinuity;
144   myMaxDegree = MaxDegree;
145   myMaxSeg = MaxSeg;
146 }
147
148 //=======================================================================
149 //function : SetDefaultParams
150 //purpose  : 
151 //=======================================================================
152
153 void BRepAlgo_NormalProjection::SetDefaultParams()
154 {
155   myTol3d = 1.e-4;
156   myTol2d = Pow(myTol3d, 2./3);
157   myContinuity = GeomAbs_C2;
158   myMaxDegree = 14;
159   myMaxSeg    = 16;
160 }
161
162 //=======================================================================
163 //function : SetLimits
164 //purpose  : 
165 //=======================================================================
166
167  void BRepAlgo_NormalProjection::SetLimit(const Standard_Boolean FaceBounds)
168 {
169   myFaceBounds = FaceBounds;
170 }
171
172 //=======================================================================
173 //function : SetMaxDistance
174 //purpose  : 
175 //=======================================================================
176
177  void BRepAlgo_NormalProjection::SetMaxDistance(const Standard_Real MaxDist)
178 {
179   myMaxDist = MaxDist;
180 }
181
182 //=======================================================================
183 //function : Compute3d
184 //purpose  : 
185 //=======================================================================
186
187  void BRepAlgo_NormalProjection::Compute3d(const Standard_Boolean With3d)
188 {
189   myWith3d = With3d;
190 }
191
192 //=======================================================================
193 //function : Build
194 //purpose  : 
195 //=======================================================================
196
197  void BRepAlgo_NormalProjection::Build() 
198 {
199 #ifdef OCCT_DEBUG_CHRONO
200   Standard_Integer init_count = 0, approx_count = 0, booltool_count = 0;
201   t_total = 0;
202   t_init = 0;
203   t_approx = 0;
204   t_booltool = 0;
205   
206   t_init_point = 0;
207   init_point_count = 0;
208   
209   t_dicho_bound = 0;
210   dicho_bound_count = 0;
211   
212   InitChron(chr_total);
213 #endif
214   myIsDone = Standard_False;
215   ProjLib_CompProjectedCurve Projector;
216   Handle(TopTools_HSequenceOfShape) Edges = new TopTools_HSequenceOfShape();
217   Handle(TopTools_HSequenceOfShape) Faces = new TopTools_HSequenceOfShape();
218   TopTools_ListOfShape DescenList;
219   Standard_Integer NbEdges = 0, NbFaces = 0, i, j, k;
220   TopExp_Explorer ExpOfWire, ExpOfShape;
221   Standard_Real Udeb, Ufin;
222   TopoDS_Shape VertexRes;
223   Standard_Boolean Only3d, Only2d, Elementary;
224   
225   // for isoparametric cases
226   TColgp_Array1OfPnt2d Poles(1, 2);
227   TColStd_Array1OfReal Knots(1, 2);
228   TColStd_Array1OfInteger Mults(1,2);
229   Standard_Integer Deg;
230   Deg = 1;
231   Mults(1) = Deg + 1;
232   Mults(2) = Deg + 1;
233   //
234   
235   for(ExpOfWire.Init(myToProj, TopAbs_EDGE); 
236       ExpOfWire.More(); 
237       ExpOfWire.Next(), NbEdges++) {
238     Edges->Append(ExpOfWire.Current());
239   }
240   
241   for(ExpOfShape.Init(myShape, TopAbs_FACE); 
242       ExpOfShape.More(); 
243       ExpOfShape.Next(), NbFaces++) {
244     Faces->Append(ExpOfShape.Current());
245   }
246   
247   BRep_Builder BB;
248   BB.MakeCompound(TopoDS::Compound(myRes));
249   BB.MakeCompound(TopoDS::Compound(VertexRes));
250   Standard_Boolean YaVertexRes = Standard_False;
251   
252   for(i = 1; i <= NbEdges; i++){
253     DescenList.Clear();
254     BRepAdaptor_Curve cur(TopoDS::Edge(Edges->Value(i)));
255     Handle(BRepAdaptor_HCurve) hcur = new BRepAdaptor_HCurve();
256     hcur->Set(cur);
257     Elementary = IsElementary(cur);
258     for(j = 1; j <= NbFaces; j++){
259       BRepAdaptor_Surface sur(TopoDS::Face(Faces->Value(j)));
260       Handle(BRepAdaptor_HSurface) hsur = new BRepAdaptor_HSurface();
261       hsur->Set(sur);
262       
263       // computation of  TolU and TolV
264       
265       Standard_Real  TolU, TolV;
266       
267       TolU = hsur->UResolution(myTol3d)/20;
268       TolV = hsur->VResolution(myTol3d)/20;
269       // Projection
270 #ifdef OCCT_DEBUG_CHRONO
271       InitChron(chr_init);
272 #endif
273       Projector = 
274         ProjLib_CompProjectedCurve(hsur, hcur, TolU, TolV, myMaxDist);
275 #ifdef OCCT_DEBUG_CHRONO
276       ResultChron(chr_init,t_init);
277       init_count++;
278 #endif
279       //
280       Handle(ProjLib_HCompProjectedCurve) HProjector = 
281         new ProjLib_HCompProjectedCurve();
282       HProjector->Set(Projector);
283       TopoDS_Shape prj;
284       Standard_Boolean Degenerated = Standard_False;
285       gp_Pnt2d P2d, Pdeb, Pfin;
286       gp_Pnt P;
287       Standard_Real UIso, VIso;
288       
289       Handle(Adaptor2d_HCurve2d) HPCur;
290       Handle(Geom2d_Curve) PCur2d; // Only for isoparametric projection
291       
292       for(k = 1; k <= Projector.NbCurves(); k++){
293         if(Projector.IsSinglePnt(k, P2d)){
294 #ifdef OCCT_DEBUG
295           cout << "Projection of edge "<<i<<" on face "<<j;
296           cout << " is punctual"<<endl<<endl;
297 #endif
298           Projector.GetSurface()->D0(P2d.X(), P2d.Y(), P);
299           prj = BRepLib_MakeVertex(P).Shape();
300           DescenList.Append(prj);
301           BB.Add(VertexRes, prj);
302           YaVertexRes = Standard_True;
303           
304           myAncestorMap.Bind(prj, Edges->Value(i));
305         }
306         else {
307           Only2d = Only3d = Standard_False;
308           Projector.Bounds(k, Udeb, Ufin);
309           
310           /**************************************************************/
311           if (Projector.IsUIso(k, UIso)) {
312 #ifdef OCCT_DEBUG
313             cout << "Projection of edge "<<i<<" on face "<<j;
314             cout << " is U-isoparametric"<<endl<<endl;
315 #endif
316             Projector.D0(Udeb, Pdeb);
317             Projector.D0(Ufin, Pfin);
318             Poles(1) = Pdeb;
319             Poles(2) = Pfin;
320             Knots(1) = Udeb;
321             Knots(2) = Ufin;
322             Handle(Geom2d_BSplineCurve) BS2d = 
323               new Geom2d_BSplineCurve(Poles, Knots, Mults, Deg);
324             PCur2d = new Geom2d_TrimmedCurve( BS2d, Udeb, Ufin);
325             HPCur = new Geom2dAdaptor_HCurve(PCur2d);
326             Only3d = Standard_True;
327           }
328           else if (Projector.IsVIso(k, VIso)) {
329 #ifdef OCCT_DEBUG
330             cout << "Projection of edge "<<i<<" on face "<<j;
331             cout << " is V-isoparametric"<<endl<<endl;
332 #endif
333             Projector.D0(Udeb, Pdeb);
334             Projector.D0(Ufin, Pfin);
335             Poles(1) = Pdeb;
336             Poles(2) = Pfin;
337             Knots(1) = Udeb;
338             Knots(2) = Ufin;
339             Handle(Geom2d_BSplineCurve) BS2d = 
340               new Geom2d_BSplineCurve(Poles, Knots, Mults, Deg);
341             PCur2d = new Geom2d_TrimmedCurve(BS2d, Udeb, Ufin);
342             HPCur = new Geom2dAdaptor_HCurve(PCur2d);
343             Only3d = Standard_True;
344           }
345           else HPCur = HProjector;
346           
347           if((myWith3d == Standard_False || Elementary) && 
348              (Projector.MaxDistance(k) <= myTol3d)        )
349             Only2d = Standard_True;
350           
351           if(Only2d && Only3d) {
352             BRepLib_MakeEdge MKed(GeomAdaptor::MakeCurve(hcur->Curve()), 
353                                   Ufin, Udeb);
354             prj = MKed.Edge();
355             BB.UpdateEdge(TopoDS::Edge(prj), 
356                           PCur2d, 
357                           TopoDS::Face(Faces->Value(j)),
358                           myTol3d);
359             BB.UpdateVertex(TopExp::FirstVertex(TopoDS::Edge(prj)),myTol3d);
360             BB.UpdateVertex(TopExp::LastVertex(TopoDS::Edge(prj)),myTol3d);
361           }
362           else {
363 #ifdef OCCT_DEBUG_CHRONO
364             InitChron(chr_approx);
365 #endif
366             Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d, 
367                                        myContinuity, myMaxDegree, myMaxSeg, 
368                                        Only3d, Only2d);
369 #ifdef OCCT_DEBUG_CHRONO
370             ResultChron(chr_approx,t_approx);
371             approx_count++;
372             
373             cout<<"Approximation.IsDone = "<<appr.IsDone()<<endl;
374             if(!Only2d)
375               cout<<"MaxError3d = "<<appr.MaxError3d()<<endl<<endl;
376             if(!Only3d) {
377               cout<<"MaxError2dU = "<<appr.MaxError2dU()<<endl;
378               cout<<"MaxError2dV = "<<appr.MaxError2dV()<<endl<<endl;
379             }
380 #endif
381
382             
383             if(!Only3d) PCur2d = appr.Curve2d();
384             if(Only2d) {
385               BRepLib_MakeEdge MKed(GeomAdaptor::MakeCurve(hcur->Curve()), 
386                                     Udeb, Ufin);
387               prj = MKed.Edge();
388             }
389             else  {
390             // It is tested if the solution is not degenerated to set the
391             // flag on edge, one takes several points, checks if the cloud of 
392             // points has less diameter than the tolerance 3D
393               Degenerated = Standard_True;
394               Standard_Real Dist;
395               Handle(Geom_BSplineCurve) BS3d = appr.Curve3d();
396               gp_Pnt P1(0.,0.,0.),PP; // skl : I change "P" to "PP"
397               Standard_Integer NbPoint,ii ; // skl : I change "i" to "ii"
398               Standard_Real Par,DPar;
399               // start from 3 points to reject non degenerated edges 
400               // very fast
401               NbPoint =3;
402               DPar = (BS3d->LastParameter()-BS3d->FirstParameter())/(NbPoint-1);
403               for (ii=0;ii<NbPoint;ii++)
404               {
405                  Par=BS3d->FirstParameter()+ii*DPar;
406                  PP=BS3d->Value(Par);
407                  P1.SetXYZ(P1.XYZ() + PP.XYZ()/NbPoint);
408               }
409               for (ii=0;ii<NbPoint && Degenerated ;ii++)   
410               {
411                  Par=BS3d->FirstParameter()+ii*DPar;
412                  PP=BS3d->Value(Par);                 
413                  Dist=P1.Distance(PP);
414                  if(Dist > myTol3d) {
415                      Degenerated = Standard_False;
416                      break;
417                  }
418               }             
419               // if the test passes a more exact test with 10 points
420               if (Degenerated) {
421                  P1.SetCoord(0.,0.,0.);
422                  NbPoint =10;
423                  DPar = (BS3d->LastParameter()-BS3d->FirstParameter())/(NbPoint-1);
424                  for (ii=0;ii<NbPoint;ii++)
425                  {
426                    Par=BS3d->FirstParameter()+ii*DPar;
427                    PP=BS3d->Value(Par);
428                    P1.SetXYZ(P1.XYZ() + PP.XYZ()/NbPoint);
429                  }
430                  for (ii=0;ii<NbPoint && Degenerated ;ii++)   
431                  {
432                    Par=BS3d->FirstParameter()+ii*DPar;
433                    PP=BS3d->Value(Par);                 
434                    Dist=P1.Distance(PP);
435                    if(Dist > myTol3d) {
436                      Degenerated = Standard_False;
437                      break;
438                    }
439                  }             
440               }
441               if (Degenerated) {
442 #ifdef OCCT_DEBUG
443                   cout << "Projection of edge "<<i<<" on face "<<j;
444                   cout << " is degenerated "<<endl<<endl;
445 #endif
446                 TopoDS_Vertex VV;
447                 BB.MakeVertex(VV);
448                 BB.UpdateVertex(VV,P1,myTol3d);
449                 BB.MakeEdge(TopoDS::Edge(prj));
450                 BB.Add(TopoDS::Edge(prj),VV.Oriented(TopAbs_FORWARD));
451                 BB.Add(TopoDS::Edge(prj),VV.Oriented(TopAbs_REVERSED));
452                 BB.Degenerated(TopoDS::Edge(prj), Standard_True);
453               }
454               else {
455                 prj = BRepLib_MakeEdge(BS3d).Edge();
456               }
457             }
458             
459             BB.UpdateEdge(TopoDS::Edge(prj), 
460                           PCur2d,
461                           TopoDS::Face(Faces->Value(j)), 
462                           appr.MaxError3d());
463             BB.UpdateVertex(TopExp::FirstVertex(TopoDS::Edge(prj)),appr.MaxError3d());
464             BB.UpdateVertex(TopExp::LastVertex(TopoDS::Edge(prj)),appr.MaxError3d());
465             if (Degenerated) {
466               BB.Range(TopoDS::Edge(prj),
467                        TopoDS::Face(Faces->Value(j)),
468                        Udeb,Ufin);
469             }
470           }
471           
472           if(myFaceBounds) {
473             // Trimming edges by face bounds 
474             // if the solution is degenerated, use of BoolTool is avoided
475 #ifdef OCCT_DEBUG_CHRONO
476             InitChron(chr_booltool);
477 #endif
478             if (!Degenerated) {
479               // Perform Boolean COMMON operation to get parts of projected edge
480               // inside the face
481               BRepAlgoAPI_Section aSection(Faces->Value(j), prj);
482               if (aSection.IsDone()) {
483                 const TopoDS_Shape& aRC = aSection.Shape();
484                 //
485                 TopExp_Explorer aExpE(aRC, TopAbs_EDGE);
486                 for (; aExpE.More(); aExpE.Next()) {
487                   const TopoDS_Shape& aE = aExpE.Current();
488                   BB.Add(myRes, aE);
489                   myAncestorMap.Bind(aE, Edges->Value(i));
490                   myCorresp.Bind(aE, Faces->Value(j));
491                 }
492               }
493               else {
494                 // if the common operation has failed, try to classify the part
495                  BRepTopAdaptor_FClass2d classifier(TopoDS::Face(Faces->Value(j)),
496                                                     Precision::Confusion());
497                  gp_Pnt2d Puv;
498                  Standard_Real f = PCur2d->FirstParameter();
499                  Standard_Real l = PCur2d->LastParameter();
500                  Standard_Real pmil = (f + l )/2;
501                  PCur2d->D0(pmil, Puv);
502                  TopAbs_State state;
503                  state = classifier.Perform(Puv);
504                  if(state == TopAbs_IN || state  == TopAbs_ON) {
505                    BB.Add(myRes, prj);
506                    DescenList.Append(prj);
507                    myAncestorMap.Bind(prj, Edges->Value(i));   
508                    myCorresp.Bind(prj, Faces->Value(j));
509                  }
510                }
511             }
512             else {
513 #ifdef OCCT_DEBUG
514                  cout << " BooleanOperations : no solution " << endl;
515 #endif
516
517               BRepTopAdaptor_FClass2d classifier(TopoDS::Face(Faces->Value(j)),
518                                                  Precision::Confusion());
519               gp_Pnt2d Puv;
520               Standard_Real f = PCur2d->FirstParameter();
521               Standard_Real l = PCur2d->LastParameter();
522               Standard_Real pmil = (f + l )/2;
523               PCur2d->D0(pmil, Puv);
524               TopAbs_State state;
525               state = classifier.Perform(Puv);
526               if(state == TopAbs_IN || state  == TopAbs_ON) {
527                  BB.Add(myRes, prj);
528                  DescenList.Append(prj);
529                  myAncestorMap.Bind(prj, Edges->Value(i));   
530                  myCorresp.Bind(prj, Faces->Value(j));
531               }
532 #ifdef OCCT_DEBUG_CHRONO
533                ResultChron(chr_booltool,t_booltool);
534                booltool_count++;
535 #endif
536             }
537           }
538           else {
539             BB.Add(myRes, prj);
540             DescenList.Append(prj);
541             myAncestorMap.Bind(prj, Edges->Value(i));   
542             myCorresp.Bind(prj, Faces->Value(j));
543           }
544         }
545       }
546     }
547     myDescendants.Bind(Edges->Value(i), DescenList);
548   }
549 // JPI : eventual wire creation is reported in a specific method 
550 //       BuilWire that can be called by the user. Otherwise, the 
551 //       relations of map myAncestorMap, myCorresp will be lost.  
552
553   if(YaVertexRes) BB.Add(myRes, VertexRes);
554   
555   myIsDone = Standard_True; 
556   
557 #ifdef OCCT_DEBUG_CHRONO
558   ResultChron(chr_total,t_total);
559   
560   cout<<"Build - Total time  : "<<t_total<<" includes:" <<endl;
561   cout<<"- Projection           : "<<t_init<<endl;
562   cout<<"  -- Initial point search : "<<t_init_point<<endl;
563   cout<<"  -- DichoBound search : "<<t_dicho_bound<<endl;
564   cout<<"- Approximation        : "<<t_approx<<endl;
565   cout<<"- Boolean operation    : "<<t_booltool<<endl;
566   cout<<"- Rest of time         : "<<t_total-(t_init + t_approx + t_booltool )<<endl<<endl;
567   if (init_count != 0)
568     t_init /= init_count;
569   if (init_point_count != 0)
570     t_init_point /= init_point_count;
571   if (dicho_bound_count != 0)
572     t_dicho_bound /= dicho_bound_count;
573   if (approx_count != 0)
574     t_approx /= approx_count;
575   if (booltool_count != 0)
576     t_booltool /= booltool_count;
577   
578   cout<<"Unitary average time  : "<<endl;
579   cout<<"- Projection          : "<<t_init<<endl;
580   cout<<"  -- Initial point search: "<<t_init_point<<endl;
581   cout<<"  -- DichoBound search : "<<t_dicho_bound<<endl;
582   cout<<"- Approximation       : "<<t_approx<<endl;
583   cout<<"- Boolean operation   :"<<t_booltool<<endl;
584   cout<<endl<<"Number of initial point computations is "<<init_point_count<<endl<<endl;
585 #endif
586 }
587
588 //=======================================================================
589 //function : IsDone
590 //purpose  : 
591 //=======================================================================
592
593  Standard_Boolean BRepAlgo_NormalProjection::IsDone() const
594 {
595   return myIsDone;
596 }
597
598 //=======================================================================
599 //function : Projection
600 //purpose  : 
601 //=======================================================================
602
603  const TopoDS_Shape& BRepAlgo_NormalProjection::Projection() const
604 {
605   return myRes;
606 }
607
608 //=======================================================================
609 //function : Ancestor
610 //purpose  : 
611 //=======================================================================
612
613  const TopoDS_Shape& BRepAlgo_NormalProjection::Ancestor(const TopoDS_Edge& E) const
614 {
615   return myAncestorMap.Find(E);
616 }
617
618 //=======================================================================
619 //function : Couple
620 //purpose  : 
621 //=======================================================================
622
623  const TopoDS_Shape& BRepAlgo_NormalProjection::Couple(const TopoDS_Edge& E) const
624 {
625   return myCorresp.Find(E);
626 }
627
628 //=======================================================================
629 //function : Generated
630 //purpose  : 
631 //=======================================================================
632
633  const TopTools_ListOfShape& BRepAlgo_NormalProjection::Generated(const TopoDS_Shape& S)
634 {
635   return myDescendants.Find(S);
636 }
637
638 //=======================================================================
639 //function : IsElementary
640 //purpose  : 
641 //=======================================================================
642
643  Standard_Boolean BRepAlgo_NormalProjection::IsElementary(const Adaptor3d_Curve& C) const
644 {
645   GeomAbs_CurveType type;
646   type = C.GetType();
647   switch(type) {
648   case GeomAbs_Line:
649   case GeomAbs_Circle:
650   case GeomAbs_Ellipse:
651   case GeomAbs_Hyperbola:
652   case GeomAbs_Parabola: return Standard_True;
653   default: return Standard_False;
654   }
655 }
656 //=======================================================================
657 //function : BuildWire
658 //purpose  : 
659 //=======================================================================
660  
661  Standard_Boolean BRepAlgo_NormalProjection::BuildWire(TopTools_ListOfShape& ListOfWire) const
662 {
663   TopExp_Explorer ExpOfWire, ExpOfShape; 
664   Standard_Boolean IsWire=Standard_False;
665   ExpOfShape.Init(myRes, TopAbs_EDGE);
666   if(ExpOfShape.More()) 
667   {
668     TopTools_ListOfShape List;
669
670     for ( ; ExpOfShape.More(); ExpOfShape.Next()) 
671     {
672       const TopoDS_Shape& CurE = ExpOfShape.Current();
673       List.Append(CurE);
674     }
675     BRepLib_MakeWire MW;
676     MW.Add(List);
677     if (MW.IsDone()) 
678     {
679       const TopoDS_Shape& Wire = MW.Shape();
680       // If the resulting wire contains the same edge as at the beginning OK
681       // otherwise the result really consists of several wires.
682       TopExp_Explorer exp2(Wire,TopAbs_EDGE);
683       Standard_Integer NbEdges = 0;
684       for (;exp2.More(); exp2.Next()) NbEdges++;
685       if ( NbEdges == List.Extent()) 
686       {
687           ListOfWire.Append(Wire);
688           IsWire = Standard_True;
689       }
690     }
691   }
692    return IsWire;
693 }