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