1 // Created on: 1994-12-02
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1994-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 #include <Adaptor3d_CurveOnSurface.hxx>
18 #include <Adaptor3d_CurveOnSurface.hxx>
19 #include <GeomAdaptor_SurfaceOfLinearExtrusion.hxx>
20 #include <Approx_CurveOnSurface.hxx>
21 #include <BRep_Builder.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepExtrema_ExtCF.hxx>
24 #include <BRepExtrema_ExtPC.hxx>
25 #include <BRepLib_MakeFace.hxx>
26 #include <BRepTools.hxx>
27 #include <Draft_EdgeInfo.hxx>
28 #include <Draft_FaceInfo.hxx>
29 #include <Draft_Modification.hxx>
30 #include <Draft_VertexInfo.hxx>
31 #include <ElCLib.hxx>
32 #include <ElSLib.hxx>
33 #include <Extrema_ExtPC.hxx>
34 #include <Geom2d_BezierCurve.hxx>
35 #include <Geom2d_BSplineCurve.hxx>
36 #include <Geom2d_Curve.hxx>
37 #include <Geom2d_Line.hxx>
38 #include <Geom2d_TrimmedCurve.hxx>
39 #include <Geom2dAdaptor_Curve.hxx>
40 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
41 #include <Geom2dConvert.hxx>
42 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
43 #include <Geom_BSplineCurve.hxx>
44 #include <Geom_Circle.hxx>
45 #include <Geom_Conic.hxx>
46 #include <Geom_ConicalSurface.hxx>
47 #include <Geom_Curve.hxx>
48 #include <Geom_CylindricalSurface.hxx>
49 #include <Geom_ElementarySurface.hxx>
50 #include <Geom_Ellipse.hxx>
51 #include <Geom_Hyperbola.hxx>
52 #include <Geom_Line.hxx>
53 #include <Geom_Parabola.hxx>
54 #include <Geom_Plane.hxx>
55 #include <Geom_RectangularTrimmedSurface.hxx>
56 #include <Geom_Surface.hxx>
57 #include <Geom_SurfaceOfLinearExtrusion.hxx>
58 #include <Geom_TrimmedCurve.hxx>
59 #include <GeomAdaptor_Curve.hxx>
60 #include <GeomAdaptor_Curve.hxx>
61 #include <GeomAdaptor_Surface.hxx>
62 #include <GeomAdaptor_Surface.hxx>
63 #include <GeomAPI_ProjectPointOnCurve.hxx>
64 #include <GeomAPI_ProjectPointOnSurf.hxx>
65 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
66 #include <GeomInt_IntSS.hxx>
67 #include <GeomProjLib.hxx>
68 #include <gp.hxx>
69 #include <gp_Circ.hxx>
70 #include <gp_Dir.hxx>
71 #include <gp_Elips.hxx>
72 #include <gp_Hypr.hxx>
73 #include <gp_Lin.hxx>
74 #include <gp_Parab.hxx>
75 #include <gp_Pln.hxx>
76 #include <gp_Pnt.hxx>
77 #include <gp_Vec.hxx>
78 #include <IntAna_IntConicQuad.hxx>
79 #include <IntAna_QuadQuadGeo.hxx>
80 #include <IntCurveSurface_HInter.hxx>
81 #include <IntCurveSurface_IntersectionPoint.hxx>
82 #include <Precision.hxx>
83 #include <ProjLib_CompProjectedCurve.hxx>
84 #include <ProjLib_HCompProjectedCurve.hxx>
85 #include <Standard_ConstructionError.hxx>
86 #include <Standard_DomainError.hxx>
87 #include <Standard_Failure.hxx>
88 #include <Standard_NoSuchObject.hxx>
89 #include <Standard_NotImplemented.hxx>
90 #include <StdFail_NotDone.hxx>
91 #include <TColgp_Array1OfPnt2d.hxx>
92 #include <TopExp.hxx>
93 #include <TopExp_Explorer.hxx>
94 #include <TopLoc_Location.hxx>
95 #include <TopoDS.hxx>
96 #include <TopoDS_Edge.hxx>
97 #include <TopoDS_Face.hxx>
98 #include <TopoDS_Shape.hxx>
99 #include <TopoDS_Vertex.hxx>
100 #include <TopTools_ListIteratorOfListOfShape.hxx>
101 #include <TopTools_MapIteratorOfMapOfShape.hxx>
102 #include <TopTools_MapOfShape.hxx>
103 
104 static Standard_Boolean Choose(const Draft_IndexedDataMapOfFaceFaceInfo&,
105   Draft_IndexedDataMapOfEdgeEdgeInfo&,
106   const TopoDS_Vertex&,
107   Draft_VertexInfo&,
108   GeomAdaptor_Curve&,
109   GeomAdaptor_Surface&);
110 
111 static Standard_Real Parameter(const Handle(Geom_Curve)&,
112   const gp_Pnt&,
113   Standard_Integer&);
114 
115 static Standard_Real SmartParameter(Draft_EdgeInfo&,
116   const Standard_Real EdgeTol,
117   const gp_Pnt&,
118   const Standard_Integer,
119   const Handle(Geom_Surface)&,
120   const Handle(Geom_Surface)&);
121 
122 static TopAbs_Orientation Orientation(const TopoDS_Shape&,
123   const TopoDS_Face&);
124 
125 static Standard_Boolean FindRotation(const gp_Pln&,
126   const TopAbs_Orientation,
127   const gp_Dir&,
128   const Standard_Real,
129   const gp_Pln&,
130   gp_Ax1&,
131   Standard_Real&);
132 
133 
134 //=======================================================================
135 //function : InternalAdd
136 //purpose  :
137 //=======================================================================
138 
InternalAdd(const TopoDS_Face & F,const gp_Dir & Direction,const Standard_Real Angle,const gp_Pln & NeutralPlane,const Standard_Boolean Flag)139 Standard_Boolean Draft_Modification::InternalAdd(const TopoDS_Face& F,
140   const gp_Dir& Direction,
141   const Standard_Real Angle,
142   const gp_Pln& NeutralPlane,
143   const Standard_Boolean Flag)
144 {
145 
146   if (myFMap.Contains(F)) {
147     return (badShape.IsNull());
148   }
149 
150   TopAbs_Orientation oris = Orientation(myShape,F);
151   TopLoc_Location Lo;
152   //gp_Dir NewDirection = Direction;
153   //Standard_Real NewAngle = Angle;
154   Handle(Geom_Surface) S = BRep_Tool::Surface(F,Lo);
155   S = Handle(Geom_Surface)::DownCast(S->Transformed(Lo.Transformation()));
156   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
157     S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
158   }
159   Handle(Geom_Surface) NewS;
160   Handle(Geom_Circle) theCircle;
161 
162   Standard_Boolean postponed = (Flag == Standard_False);
163   if (postponed) {
164     Handle(Standard_Type) typS = S->DynamicType();
165     if (typS == STANDARD_TYPE(Geom_CylindricalSurface) ||
166         typS == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
167       gp_Circ Cir;
168       if (typS == STANDARD_TYPE(Geom_CylindricalSurface)) {
169         gp_Cylinder cyl =
170           Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();
171         gp_Ax1 axcyl = cyl.Axis();
172         Cir = ElSLib::CylinderVIso( cyl.Position(), cyl.Radius(), 0.);
173         gp_Vec VV(cyl.Location(),NeutralPlane.Location());
174         Cir.Translate(VV.Dot(axcyl.Direction())*axcyl.Direction());
175       }
176       else {
177         Handle(Geom_Curve) Cbas =
178           Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S)->BasisCurve();
179         gp_Dir theDirextr =
180           Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S)->Direction();
181 
182         if (Cbas->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
183           Cbas = Handle(Geom_TrimmedCurve)::DownCast(Cbas)->BasisCurve();
184         }
185         if (Cbas->IsKind(STANDARD_TYPE(Geom_Circle))) {
186           Cir = Handle(Geom_Circle)::DownCast(Cbas)->Circ();
187           gp_Dir dircir = Cir.Axis().Direction();
188           if (!Direction.IsParallel(dircir,Precision::Angular())) {
189             badShape = F;
190             errStat = Draft_FaceRecomputation;
191             return Standard_False;
192           }
193         }
194         else {
195           badShape = F;
196           errStat = Draft_FaceRecomputation;
197           return Standard_False;
198         }
199 
200         gp_Ax3 Axis = NeutralPlane.Position();
201         Standard_Real L =
202           gp_Vec(Cir.Location(),Axis.Location()).
203           Dot(Axis.Direction());
204         Standard_Real Cos = theDirextr.Dot(Axis.Direction());
205         gp_Vec VV = ( L / Cos) * theDirextr;
206         Cir.Translate(VV);
207       }
208 
209       theCircle = new Geom_Circle(Cir);
210 
211     }
212     else {
213       postponed = Standard_False;
214     }
215   }
216 
217 
218   if (!postponed) {
219     NewS = NewSurface(S,oris,Direction,Angle,NeutralPlane);
220     if (NewS.IsNull()) {
221       badShape = F;
222       errStat = Draft_FaceRecomputation;
223       return Standard_False;
224     }
225     // To avoid some problems with infinite restrictions
226     const Handle(Standard_Type)& typs = NewS->DynamicType();
227     if (typs == STANDARD_TYPE(Geom_CylindricalSurface) ||
228         typs == STANDARD_TYPE(Geom_ConicalSurface)) {
229       Standard_Real umin,umax,vmin,vmax;
230       BRepTools::UVBounds(F,umin,umax,vmin,vmax);
231       if (!Precision::IsNegativeInfinite(vmin) &&
232           !Precision::IsPositiveInfinite(vmax)) {
233         Standard_Real deltav = 10.*(vmax-vmin);
234         if(typs == STANDARD_TYPE(Geom_CylindricalSurface)) {
235           vmin = vmin - deltav;
236           vmax = vmax + deltav;
237         }
238         else {
239           gp_Cone Co = Handle(Geom_ConicalSurface)::DownCast(NewS)->Cone();
240           Standard_Real Vapex = - Co.RefRadius()/Sin(Co.SemiAngle());
241           if (vmin < Vapex) { // vmax should not exceed Vapex
242             if (vmax + deltav > Vapex) {
243               vmax = Vapex;
244               vmin = vmin - 10.*(vmax - vmin);
245               // JAG debug to avoid apex
246               vmax = vmax-Precision::Confusion();
247             }
248             else {
249               vmin = vmin - deltav;
250               vmax = vmax + deltav;
251             }
252           }
253           else { // Vapex <= vmin < vmax
254             if (vmin - deltav < Vapex) {
255               vmin = Vapex;
256               vmax = vmax + 10.*(vmax - vmin);
257               // JAG debug to avoid apex
258               vmin = vmin+Precision::Confusion();
259             }
260             else {
261               vmin = vmin - deltav;
262               vmax = vmax + deltav;
263             }
264           }
265         }
266         NewS = new Geom_RectangularTrimmedSurface(NewS,0.,2.*M_PI,vmin,vmax);
267       }
268     }
269   }
270 
271   if (postponed || S != NewS) {
272     Draft_FaceInfo FI(NewS,Standard_True);
273     FI.RootFace(curFace);
274     myFMap.Add(F,FI);
275     if (postponed) {
276       myFMap.ChangeFromKey(F).ChangeCurve() = theCircle;
277     }
278   }
279 
280   TopExp_Explorer aExp(F,TopAbs_EDGE);
281   TopTools_MapOfShape MapOfE;
282   while (aExp.More() && badShape.IsNull()) {
283     const TopoDS_Edge& edg = TopoDS::Edge(aExp.Current());
284     if (!myEMap.Contains(edg)) {
285       Standard_Boolean addedg  = Standard_False;
286       Standard_Boolean addface = Standard_False;
287       TopoDS_Face OtherF;
288       //if (BRep_Tool::IsClosed(edg,F)) {
289       if (BRepTools::IsReallyClosed(edg,F)) {
290         addedg = Standard_True;
291         addface = Standard_False;
292       }
293       else {
294         // Find the other face containing the edge.
295         TopTools_ListIteratorOfListOfShape it;
296         it.Initialize(myEFMap.FindFromKey(edg));
297         Standard_Integer nbother = 0;
298         while (it.More()) {
299           if (!it.Value().IsSame(F)) {
300             if (OtherF.IsNull()) {
301               OtherF = TopoDS::Face(it.Value());
302             }
303             nbother++;
304           }
305           it.Next();
306         }
307         if (nbother >=2) {
308           badShape = edg;
309           errStat = Draft_EdgeRecomputation;
310         }
311         else if (! OtherF.IsNull() &&
312                  BRep_Tool::Continuity(edg,F,OtherF) >= GeomAbs_G1) {
313           addface= Standard_True;
314           addedg = Standard_True;
315         }
316         else if (nbother == 0) {
317           //	    badShape = F;
318         }
319       }
320       if (addedg) {
321         if (postponed) {
322           myFMap.ChangeFromKey(F).Add(OtherF);
323         }
324         Standard_Real f,l;
325         TopLoc_Location L;
326         Handle(Geom_Curve) C = BRep_Tool::Curve(edg,L,f,l);
327         C = Handle(Geom_Curve)::DownCast(C->Transformed(L));
328         if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
329           C = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
330         }
331         Handle(Geom_Curve) NewC;
332         Draft_EdgeInfo EInf(Standard_True);
333         if(postponed) {
334           EInf.Add(F);
335           EInf.Add(OtherF);
336 
337           // find fixed point
338           Handle(Geom_Line) aLocalGeom = Handle(Geom_Line)::DownCast(C);
339           if (aLocalGeom.IsNull()) {
340             badShape = edg;
341             errStat = Draft_EdgeRecomputation;
342           }
343           else {
344             gp_Lin lin = aLocalGeom->Lin();
345             IntAna_IntConicQuad ilipl(lin,NeutralPlane,Precision::Angular());
346             if (ilipl.IsDone() && ilipl.NbPoints() != 0){
347               EInf.Tangent(ilipl.Point(1));
348             }
349             else {
350               badShape = edg;
351               errStat = Draft_EdgeRecomputation;
352             }
353           }
354         }
355         else {
356           NewC = NewCurve(C,S,oris,Direction,Angle,NeutralPlane, Flag);
357           if (NewC.IsNull()) {
358             badShape = edg;
359             errStat = Draft_EdgeRecomputation;
360           }
361         }
362 
363         Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(NewC);
364         if (!T.IsNull()) NewC = T->BasisCurve();
365         EInf.ChangeGeometry() = NewC;
366 
367         EInf.RootFace(curFace);
368         myEMap.Add(edg,EInf);
369         MapOfE.Add(edg);
370         if (addface) {
371           Standard_Boolean Fl = Flag;
372           Handle(Geom_Surface) alocalSurface = BRep_Tool::Surface(OtherF,Lo);
373           if (alocalSurface->DynamicType() ==
374               STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
375             alocalSurface = Handle(Geom_RectangularTrimmedSurface)::
376               DownCast(alocalSurface)->BasisSurface();
377           }
378           Handle(Standard_Type) typS = alocalSurface->DynamicType();
379           if (typS == STANDARD_TYPE(Geom_CylindricalSurface) ||
380               typS == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
381             if ( myFMap.Contains(F)) {
382               if ( Flag == Standard_False && !postponed) {
383                 myFMap.RemoveKey(F);
384                 TopTools_MapIteratorOfMapOfShape itm(MapOfE);
385                 for ( ; itm.More(); itm.Next())
386                 {
387                   myEMap.RemoveKey(TopoDS::Edge(itm.Key()));
388                 }
389               }
390             }
391           }
392           InternalAdd(OtherF,Direction,Angle,NeutralPlane, Fl);
393         }
394       }
395     }
396     aExp.Next();
397   }
398   return (badShape.IsNull());
399 }
400 
401 
402 //=======================================================================
403 //function : Propagate
404 //purpose  :
405 //=======================================================================
406 
Propagate()407 Standard_Boolean Draft_Modification::Propagate ()
408 {
409 
410   if (!badShape.IsNull()) return Standard_False;
411 
412   // Set all edges and vertices of modified faces
413   TopoDS_Face F;
414   TopoDS_Edge E;
415   TopoDS_Vertex V;
416   TopExp_Explorer editer;
417   TopExp_Explorer vtiter;
418 
419   for (Standard_Integer i = 1; i <= myFMap.Extent(); i++)
420   {
421     const TopoDS_Face& Fc = myFMap.FindKey(i);
422 
423     // Exploration of the edges of the face
424     editer.Init(Fc,TopAbs_EDGE);
425     while (editer.More()) {
426       E = TopoDS::Edge(editer.Current());
427 
428       if (!myEMap.Contains(E)) {
429         Draft_EdgeInfo EInf(Standard_True);
430         myEMap.Add(E,EInf);
431       }
432       myEMap.ChangeFromKey(E).Add(Fc);
433 
434       // Exploration of the vertices of the edge
435       vtiter.Init(E,TopAbs_VERTEX);
436       while (vtiter.More()) {
437         V = TopoDS::Vertex(vtiter.Current());
438         if (!myVMap.Contains(V)) {
439           Draft_VertexInfo VInf;
440           myVMap.Add(V,VInf);
441         }
442 
443         myVMap.ChangeFromKey(V).Add(E);
444         myVMap.ChangeFromKey(V).ChangeParameter(E) = BRep_Tool::Parameter(V, E);
445         vtiter.Next();
446       }
447       editer.Next();
448     }
449   }
450 
451 
452   TopExp_Explorer anc;
453   Standard_Boolean found;
454 
455   // Set edges containing modified vertices.
456 
457   for (Standard_Integer i = 1; i <= myVMap.Extent(); i++)
458   {
459     const TopoDS_Vertex& Vt = myVMap.FindKey(i);
460 
461     // Exploration of the ancestors of the vertex
462     anc.Init(myShape,TopAbs_EDGE);
463 
464     while (anc.More()) {
465       E = TopoDS::Edge(anc.Current());
466       vtiter.Init(E,TopAbs_VERTEX);
467       found = Standard_False;
468       while (vtiter.More()) {
469         if (Vt.IsSame(TopoDS::Vertex(vtiter.Current()))) {
470           found = Standard_True;
471           break;
472         }
473         vtiter.Next();
474       }
475       if (found) {
476         if (!myEMap.Contains(E)) {
477           Draft_EdgeInfo EInf(Standard_False);
478           myEMap.Add(E,EInf);
479         }
480         myVMap.ChangeFromKey(Vt).Add(E);
481         myVMap.ChangeFromKey(Vt).ChangeParameter(E) = BRep_Tool::Parameter(Vt, E);
482       }
483       anc.Next();
484     }
485   }
486 
487 
488   // Set faces containing modified edges
489   for (Standard_Integer i = 1; i <= myEMap.Extent(); i++)
490   {
491     const TopoDS_Edge& Ed = myEMap.FindKey(i);
492     TopTools_ListIteratorOfListOfShape it;
493     for (it.Initialize(myEFMap.FindFromKey(Ed)); it.More(); it.Next()) {
494       F = TopoDS::Face(it.Value());
495       if (!myFMap.Contains(F)) {
496         TopLoc_Location L;
497         Handle(Geom_Surface) S = BRep_Tool::Surface(F,L);
498         Handle(Geom_Surface) NewS =
499           Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
500 
501         const Handle(Standard_Type)& typs = S->DynamicType();
502         if (typs == STANDARD_TYPE(Geom_CylindricalSurface) ||
503             typs == STANDARD_TYPE(Geom_ConicalSurface)) {
504           Standard_Real umin,umax,vmin,vmax;
505           BRepTools::UVBounds(F,umin,umax,vmin,vmax);
506           if (!Precision::IsNegativeInfinite(vmin) &&
507               !Precision::IsPositiveInfinite(vmax)) {
508             Standard_Real deltav = 10.*(vmax-vmin);
509             vmin = vmin - deltav;
510             vmax = vmax + deltav;
511             NewS = new Geom_RectangularTrimmedSurface(NewS,0.,2.*M_PI,vmin,vmax);
512           }
513         }
514 
515         Draft_FaceInfo FInf(NewS,Standard_False);
516         myFMap.Add(F,FInf);
517       }
518       myEMap.ChangeFromKey(Ed).Add(F);
519     }
520   }
521 
522   //  Try to add faces for free borders...
523   // JAG 09.11.95
524   for (Standard_Integer i = 1; i <= myEMap.Extent(); i++)
525   {
526     Draft_EdgeInfo& Einf = myEMap.ChangeFromIndex(i);
527     if (Einf.NewGeometry() &&
528         Einf.Geometry().IsNull() &&
529         Einf.SecondFace().IsNull()) {
530 
531       TopLoc_Location Loc;
532       Handle(Geom_Surface) S1 = BRep_Tool::Surface(Einf.FirstFace(),Loc);
533       S1 = Handle(Geom_Surface)::
534         DownCast(S1->Transformed(Loc.Transformation()));
535       Handle(Geom_Surface) S2;
536 
537       Standard_Real f,l;
538       const TopoDS_Edge& EK = myEMap.FindKey(i);
539       Handle(Geom_Curve) C = BRep_Tool::Curve(EK,Loc,f,l);
540       C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
541       if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
542         C = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
543       }
544       if (!S1->IsKind(STANDARD_TYPE(Geom_Plane))) {
545         if (C->IsKind(STANDARD_TYPE(Geom_Conic))) {
546           gp_Ax3 thePl(Handle(Geom_Conic)::DownCast(C)->Position());
547           S2 = new Geom_Plane(thePl);
548         }
549         else if (C->DynamicType() == STANDARD_TYPE(Geom_Line)) {
550           gp_Ax1 axis;
551           if (S1->DynamicType()== STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
552             axis = Handle(Geom_ElementarySurface)::DownCast
553               (Handle(Geom_RectangularTrimmedSurface)::DownCast(S1)->
554               BasisSurface())->Axis();
555           }
556           else {
557             axis = Handle(Geom_ElementarySurface)::DownCast(S1)->Axis();
558           }
559           gp_Vec they(axis.Location(), C->Value(0.));
560           gp_Dir axz(axis.Direction().Crossed(they));
561           S2=new Geom_Plane(gp_Ax3(axis.Location(),axz,axis.Direction()));
562 
563         }
564         else {
565           badShape = EK;
566           errStat = Draft_EdgeRecomputation;
567           break; // leave from for
568         }
569       }
570       else { // on the plane
571         for (Standard_Integer j = 1; j <= myVMap.Extent(); j++)
572         {
573           Draft_VertexInfo& Vinf = myVMap.ChangeFromIndex(j);
574           for (Vinf.InitEdgeIterator();Vinf.MoreEdge();Vinf.NextEdge()) {
575             if (Vinf.Edge().IsSame(EK)) {
576               break;
577             }
578           }
579           if (Vinf.MoreEdge()) {
580             for (Vinf.InitEdgeIterator();Vinf.MoreEdge();Vinf.NextEdge()) {
581               const TopoDS_Edge& edg = Vinf.Edge();
582               if (!edg.IsSame(EK)) {
583                 const Draft_EdgeInfo& EI = myEMap.FindFromKey(edg);
584                 if (!EI.FirstFace().IsSame(Einf.FirstFace()) &&
585                   (EI.SecondFace().IsNull() ||
586                   !EI.SecondFace().IsSame(Einf.FirstFace()))) {
587                     break;
588                 }
589               }
590             }
591             if (Vinf.MoreEdge()) {
592               Handle(Geom_Curve) C2 = BRep_Tool::Curve(Vinf.Edge(), Loc,f,l);
593               Handle(GeomAdaptor_Curve) HCur;
594               gp_Vec Direc;
595               C2 = Handle(Geom_Curve)::DownCast
596                 (C2->Transformed(Loc.Transformation()));
597               if (C2->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) {
598                 C2 = Handle(Geom_TrimmedCurve)::DownCast(C2)->BasisCurve();
599               }
600               if (C->DynamicType() == STANDARD_TYPE(Geom_Line)) {
601                 Direc = Handle(Geom_Line)::DownCast(C)->Lin().Direction();
602                 HCur = new GeomAdaptor_Curve(C2);
603 
604               }
605               else if (C2->DynamicType() == STANDARD_TYPE(Geom_Line)) {
606                 Direc = Handle(Geom_Line)::DownCast(C2)->Lin().Direction();
607                 HCur = new GeomAdaptor_Curve(C);
608               }
609               else {
610                 badShape = EK;
611                 errStat = Draft_EdgeRecomputation;
612                 break; // leave from while
613               }
614               GeomAdaptor_SurfaceOfLinearExtrusion SLE(HCur,Direc);
615               switch(SLE.GetType()){
616 
617               case GeomAbs_Plane :
618                 {
619                   S2 = new Geom_Plane(SLE.Plane());
620                 }
621                 break;
622               case GeomAbs_Cylinder :
623                 {
624                   S2 =   new Geom_CylindricalSurface(SLE.Cylinder());
625                 }
626                 break;
627               default :
628                 {
629                   S2 = new Geom_SurfaceOfLinearExtrusion (HCur->Curve(), Direc);
630                 }
631                 break;
632               }
633 
634             }
635             else {
636               badShape = EK;
637               errStat = Draft_EdgeRecomputation;
638               break; // leave from while
639             }
640             break;
641           }
642           //j++;
643         }
644       }
645 
646       if (badShape.IsNull()) {
647         BRep_Builder B;
648         TopoDS_Face TheNewFace;
649         B.MakeFace(TheNewFace,S2,Precision::Confusion());
650         Einf.Add(TheNewFace);
651         Draft_FaceInfo FI(S2,Standard_False);
652         myFMap.Add(TheNewFace,FI);
653       }
654       else {
655         break; // leave from for
656       }
657       // Fin JAG 09.11.95
658     }
659   }
660   return (badShape.IsNull());
661 }
662 
663 
664 
665 
666 //=======================================================================
667 //function : Perform
668 //purpose  :
669 //=======================================================================
670 
Perform()671 void Draft_Modification::Perform ()
672 {
673   if (!badShape.IsNull())  throw Standard_ConstructionError();
674 
675   if (!myComp) {
676     myComp = Standard_True;
677     if (!Propagate()) {
678       return;
679     }
680 
681     // Calculate eventual faces
682 
683     for (Standard_Integer i = 1; i <= myFMap.Extent(); i++)
684     {
685       const TopoDS_Face& FK = myFMap.FindKey(i);
686       Draft_FaceInfo& Finf = myFMap.ChangeFromIndex(i);
687       if (Finf.NewGeometry() && Finf.Geometry().IsNull()) {
688         const TopoDS_Face& F1 = Finf.FirstFace();
689         const TopoDS_Face& F2 = Finf.SecondFace();
690 
691         if (F1.IsNull() || F2.IsNull()) {
692           errStat = Draft_FaceRecomputation;
693           badShape = FK;
694           return;
695         }
696         Handle(Geom_Surface) S1 = myFMap.FindFromKey(F1).Geometry();
697         Handle(Geom_Surface) S2 = myFMap.FindFromKey(F2).Geometry();
698         if (S1.IsNull() || S2.IsNull()) {
699           errStat = Draft_FaceRecomputation;
700           badShape = FK;
701           return;
702         }
703         if (S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
704           S1 = Handle(Geom_RectangularTrimmedSurface)::
705             DownCast(S1)->BasisSurface();
706         }
707         if (S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
708           S2 = Handle(Geom_RectangularTrimmedSurface)::
709             DownCast(S2)->BasisSurface();
710         }
711         Handle(Geom_Plane) P1 = Handle(Geom_Plane)::DownCast(S1);
712         Handle(Geom_Plane) P2 = Handle(Geom_Plane)::DownCast(S2);
713         if (P1.IsNull() || P2.IsNull()) {
714           errStat = Draft_FaceRecomputation;
715           badShape = FK;
716           return;
717         }
718         gp_Pln pp1 = P1->Pln();
719         gp_Pln pp2 = P2->Pln();
720         IntAna_QuadQuadGeo i2p(pp1,pp2,
721           Precision::Angular(),Precision::Confusion());
722         if (!i2p.IsDone() || i2p.TypeInter() != IntAna_Line) {
723           errStat = Draft_FaceRecomputation;
724           badShape = FK;
725           return;
726         }
727 
728         gp_Dir extrdir = i2p.Line(1).Direction();
729 
730         // Preserve the same direction as the base face
731         Handle(Geom_Surface) RefSurf =
732           BRep_Tool::Surface(FK);
733         if (RefSurf->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
734           RefSurf =
735             Handle(Geom_RectangularTrimmedSurface)::DownCast(RefSurf)
736             ->BasisSurface();
737         }
738         gp_Dir DirRef;
739 
740         if ( RefSurf->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
741           gp_Ax3 AxeRef =
742             Handle(Geom_CylindricalSurface)::DownCast(RefSurf)
743             ->Cylinder().Position();
744           DirRef = AxeRef.Direction();
745         }
746         else if (RefSurf->DynamicType() ==
747                  STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
748           DirRef =
749             Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(RefSurf)->Direction();
750         }
751 
752         if (extrdir.Dot(DirRef) < 0.) extrdir.Reverse();
753 
754         // it is possible to accelerate speed by storing the info during
755         // InternalAdd --> modification of FaceInfo to preserve the circle
756 
757         Handle(Geom_Circle) CCir =
758           Handle(Geom_Circle)::DownCast(Finf.Curve());
759         Handle(Geom_Surface) NewS =
760           new Geom_SurfaceOfLinearExtrusion(CCir, extrdir);
761 
762         Standard_Real umin, umax, vmin, vmax;
763         BRepTools::UVBounds(FK,umin,umax,vmin,vmax);
764         if (!Precision::IsNegativeInfinite(vmin) &&
765             !Precision::IsPositiveInfinite(vmax)) {
766           Standard_Real deltav = 2.*(vmax-vmin);
767           vmin = vmin - deltav;
768           vmax = vmax + deltav;
769         }
770 
771         // very temporary
772         else {
773           vmax = 300;
774           vmin = -300;
775         }
776 
777         NewS = new Geom_RectangularTrimmedSurface(NewS,0.,1.9*M_PI,vmin,vmax);
778         Finf.ChangeGeometry() = NewS;
779       }
780     }
781 
782     // Calculate new edges.
783     for (Standard_Integer ii = 1; ii <= myEMap.Extent(); ii++)
784     {
785       Draft_EdgeInfo& Einf = myEMap.ChangeFromIndex(ii);
786 
787       const TopoDS_Edge& theEdge = TopoDS::Edge(myEMap.FindKey(ii));
788 
789       Handle(Geom_Surface) S1,S2;
790       Handle(Geom_Curve) C, newC;
791       Standard_Real f,l;
792       TopLoc_Location L;
793       C = BRep_Tool::Curve(theEdge,L,f,l);
794       C = Handle(Geom_Curve)::DownCast(C->Transformed(L.Transformation()));
795 
796       if (Einf.NewGeometry() && Einf.Geometry().IsNull()) {
797         gp_Pnt ptfixe;
798         if (!Einf.IsTangent(ptfixe)) {
799           const TopoDS_Face& FirstFace = Einf.FirstFace();
800           const TopoDS_Face& SecondFace = Einf.SecondFace();
801 
802           S1 = myFMap.FindFromKey(FirstFace).Geometry();
803           S2 = myFMap.FindFromKey(SecondFace).Geometry();
804 
805           Standard_Integer detrompeur = 0;
806 
807           // Return FirstVertex and the tangent at this point.
808           TopoDS_Vertex FV = TopExp::FirstVertex(theEdge);
809           TopoDS_Vertex LV = TopExp::LastVertex(theEdge);
810           Standard_Real pmin = 0.;
811           Standard_Real prmfv = BRep_Tool::Parameter(FV, theEdge);
812           Standard_Real prmlv = BRep_Tool::Parameter(LV, theEdge);
813           gp_Pnt pfv, plv;
814           gp_Vec d1fv,d1lv, newd1;
815           C->D1(prmfv,pfv,d1fv);
816           C->D1(prmlv,plv,d1lv);
817 
818           Standard_Real TolF1 = BRep_Tool::Tolerance (FirstFace);
819           Standard_Real TolF2 = BRep_Tool::Tolerance (SecondFace);
820 
821           //Pass the tolerance of the face to project
822           GeomAPI_ProjectPointOnSurf proj1 (pfv, S1, TolF1);
823           GeomAPI_ProjectPointOnSurf proj2 (plv, S1, TolF1);
824           GeomAPI_ProjectPointOnSurf proj3 (pfv, S2, TolF2);
825           GeomAPI_ProjectPointOnSurf proj4 (plv, S2, TolF2);
826 
827           if (proj1.IsDone () && proj2.IsDone ()) {
828             if(proj1.LowerDistance()<= Precision::Confusion() &&
829                proj2.LowerDistance()<= Precision::Confusion())  {
830                detrompeur = 1;
831             }
832           }
833 
834           if (proj3.IsDone () && proj4.IsDone ()) {
835             if(proj3.LowerDistance() <= Precision::Confusion() &&
836                proj4.LowerDistance() <= Precision::Confusion())  {
837                detrompeur = 2;
838             }
839           }
840 
841           gp_Dir TheDirExtr;
842           gp_Ax3 Axis;
843           Handle(Geom_Curve) TheNewCurve;
844           Standard_Boolean KPart = Standard_False;
845 
846           if ( S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
847             S1 = Handle(Geom_RectangularTrimmedSurface)::
848               DownCast(S1)->BasisSurface();
849           }
850           if ( S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
851             S2 = Handle(Geom_RectangularTrimmedSurface)::
852               DownCast(S2)->BasisSurface();
853           }
854 
855           Standard_Boolean PC1 = Standard_True; // KPart on S1
856           if (S1->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) &&
857               S2->DynamicType() == STANDARD_TYPE(Geom_Plane) ) {
858             KPart = Standard_True;
859             Axis = Handle(Geom_Plane)::DownCast(S2)->Position();
860             TheNewCurve = Handle(Geom_SurfaceOfLinearExtrusion)::
861               DownCast(S1)->BasisCurve();
862             TheDirExtr = Handle(Geom_SurfaceOfLinearExtrusion)::
863               DownCast(S1)->Direction();
864           }
865           else if (S2->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) &&
866                    S1->DynamicType() == STANDARD_TYPE(Geom_Plane) ) {
867             KPart = Standard_True;
868             PC1 = Standard_False;
869             Axis = Handle(Geom_Plane)::DownCast(S1)->Position();
870             TheNewCurve = Handle(Geom_SurfaceOfLinearExtrusion)::
871               DownCast(S2)->BasisCurve();
872             TheDirExtr = Handle(Geom_SurfaceOfLinearExtrusion)::
873               DownCast(S2)->Direction();
874           }
875           Handle(Geom_Circle) aCirc ;
876           if ( KPart) {  // very temporary on circles !!!
877             aCirc = Handle(Geom_Circle)::DownCast(TheNewCurve);
878             if (aCirc.IsNull())
879               KPart = Standard_False;
880             else
881             {
882               gp_Dir AxofCirc = aCirc->Position().Direction();
883               if (AxofCirc.IsParallel(Axis.Direction(),Precision::Angular()))
884                 KPart = Standard_True;
885               else
886                 KPart = Standard_False;
887             }
888           }
889 
890           Standard_Integer imin;
891           GeomInt_IntSS i2s;
892           if ( KPart) {
893             // direct calculation of NewC
894             Standard_Real aLocalReal =
895               gp_Vec(aCirc->Circ().Location(),Axis.Location()).
896               Dot(Axis.Direction());
897             Standard_Real Cos = TheDirExtr.Dot(Axis.Direction());
898             gp_Vec VV = ( aLocalReal / Cos) * TheDirExtr;
899             newC = Handle(Geom_Curve)::DownCast(TheNewCurve->Translated(VV));
900             // it is possible to calculate PCurve
901             Handle(Geom2d_Line) L2d
902               = new Geom2d_Line(gp_Pnt2d(0.,aLocalReal/Cos),
903               gp::DX2d());
904 
905             if ( PC1)
906               Einf.ChangeFirstPC() = L2d;
907             else
908               Einf.ChangeSecondPC() = L2d;
909           }
910           else {
911             S1 = myFMap.FindFromKey(Einf.FirstFace()).Geometry();
912             S2 = myFMap.FindFromKey(Einf.SecondFace()).Geometry();
913 
914 
915             // PCurves are not calculated immediately for 2 reasons:
916             // 1 - If ProjLib should make an Approx, it is stupid to approximate the
917             //     entire intersection curve.
918             // 2 - Additionally, if YaRev, there is a risk to not be SameRange.
919             i2s.Perform(S1,S2,Precision::Confusion(),
920               Standard_True,Standard_False,Standard_False);
921 
922             if (!i2s.IsDone() || i2s.NbLines() <= 0) {
923               errStat = Draft_EdgeRecomputation;
924               badShape = theEdge;
925               return;
926             }
927 
928             Standard_Real Glob2Min = RealLast();
929             GeomAdaptor_Curve TheCurve;
930 
931             Standard_Integer i,j; //,jmin;
932 
933             if (i2s.Line(1)->DynamicType() != STANDARD_TYPE(Geom_BSplineCurve))
934             {
935               Standard_Real Dist2Min = RealLast();
936               imin = 0;
937               for (i=1; i<= i2s.NbLines(); i++) {
938                 TheCurve.Load(i2s.Line(i));
939                 Extrema_ExtPC myExtPC(pfv,TheCurve);
940 
941                 Standard_Real locpmin = 0.;
942                 if (myExtPC.IsDone()) {
943                   if(myExtPC.NbExt() >= 1) {
944                     Dist2Min = myExtPC.SquareDistance(1);
945                     locpmin = myExtPC.Point(1).Parameter();
946                   }
947                   if(myExtPC.NbExt() == 2 && Dist2Min > Precision::SquareConfusion()) {
948                     //to avoid incorrectly choosing the image
949                     //of the first vertex of the initial edge
950                     Standard_Real d1_2 = myExtPC.SquareDistance(1);
951                     Standard_Real d2_2 = myExtPC.SquareDistance(2);
952                     if(d1_2 > 1.21*d2_2) {
953                       Dist2Min = myExtPC.SquareDistance(2);
954                       locpmin = myExtPC.Point(2).Parameter();
955                     }
956                     else if(d2_2 > 1.21*d1_2) {
957                       Dist2Min = myExtPC.SquareDistance(1);
958                       locpmin = myExtPC.Point(1).Parameter();
959                     }
960                     else {
961                       Standard_Real pfvpar = myExtPC.Point(1).Parameter();
962                       Standard_Real plvpar = myExtPC.Point(2).Parameter();
963                       newC = i2s.Line(i);
964 
965                       gp_Pnt pfvprim, plvprim;
966 
967                       newC->D0(pfvpar,pfvprim);
968                       newC->D0(plvpar,plvprim);
969 
970                       Handle(Geom_Surface) theSurf;
971                       if(detrompeur == 1) {
972                         if(S1->DynamicType() ==
973                            STANDARD_TYPE(Geom_RectangularTrimmedSurface))
974                           S1 = Handle(Geom_RectangularTrimmedSurface)::
975                           DownCast(S1)->BasisSurface();
976                         theSurf = S1;
977 
978                       }
979                       else if(detrompeur == 2) {
980                         if(S2->DynamicType() ==
981                            STANDARD_TYPE(Geom_RectangularTrimmedSurface))
982                           S2 = Handle(Geom_RectangularTrimmedSurface)::
983                           DownCast(S2)->BasisSurface();
984                         theSurf = S2;
985                       }
986                       if(detrompeur != 0 && detrompeur != 4) {
987                         Standard_Real ul = 0., vl = 0., uf = 0., vf = 0.;
988                         Standard_Real ufprim = 0., ulprim = 0., vfprim = 0., vlprim = 0.;
989 
990                         if(theSurf->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
991                           gp_Pln pl = Handle(Geom_Plane)::DownCast(S2)->Pln();
992                           ElSLib::Parameters(pl, plv, ul, vl);
993                           ElSLib::Parameters(pl, pfv, uf, vf);
994                           ElSLib::Parameters(pl, plvprim, ulprim, vlprim);
995                           ElSLib::Parameters(pl, pfvprim, ufprim, vfprim);
996                         }
997                         else if(theSurf->DynamicType() ==
998                                 STANDARD_TYPE(Geom_CylindricalSurface)) {
999                           gp_Cylinder cy = Handle(Geom_CylindricalSurface)
1000                             ::DownCast(S2)->Cylinder();
1001                           ElSLib::Parameters(cy, plv, ul, vl);
1002                           ElSLib::Parameters(cy, pfv, uf, vf);
1003                           ElSLib::Parameters(cy, plvprim, ulprim, vlprim);
1004                           ElSLib::Parameters(cy, pfvprim, ufprim, vfprim);
1005                         }
1006                         else detrompeur = 4;
1007 
1008                         if(detrompeur == 1 || detrompeur == 2) {
1009                           gp_Vec2d v1((ul-ufprim), (vl-vfprim));
1010                           gp_Vec2d norm((vf-vfprim), (ufprim-uf));
1011                           gp_Vec2d v2((ulprim-ufprim), (vlprim-vfprim));
1012                           if( (v1.Dot(norm))*(v2.Dot(norm)) < 0) {
1013                             Dist2Min = myExtPC.SquareDistance(2);
1014                             locpmin = myExtPC.Point(2).Parameter();
1015                           }
1016                         }
1017                       }
1018                     }
1019                   }
1020                   if (myExtPC.NbExt() == 1 || myExtPC.NbExt() > 2 || detrompeur ==4) {
1021                     Dist2Min = myExtPC.SquareDistance(1);
1022                     locpmin = myExtPC.Point(1).Parameter();
1023                     for (j=2; j<=myExtPC.NbExt(); j++) {
1024                       const Standard_Real Dist2 = myExtPC.SquareDistance(j);
1025                       if (Dist2 < Dist2Min) {
1026                         Dist2Min = Dist2;
1027                         locpmin = myExtPC.Point(j).Parameter();
1028                       }
1029                     }
1030                   }
1031                   else if(myExtPC.NbExt() < 1){
1032                     Standard_Real dist1_2,dist2_2;
1033                     gp_Pnt p1b,p2b;
1034                     myExtPC.TrimmedSquareDistances(dist1_2,dist2_2,p1b,p2b);
1035                     if (dist1_2 < dist2_2) {
1036                       Dist2Min = dist1_2;
1037                       locpmin = TheCurve.FirstParameter();
1038                     }
1039                     else {
1040                       Dist2Min = dist2_2;
1041                       locpmin = TheCurve.LastParameter();
1042                     }
1043                   }
1044 
1045                   if (Dist2Min  < Glob2Min) {
1046                     Glob2Min = Dist2Min;
1047                     imin = i;
1048                     pmin = locpmin;
1049                   }
1050                 }
1051               }
1052               if (imin == 0) {
1053                 errStat = Draft_EdgeRecomputation;
1054                 badShape = theEdge;
1055                 return;
1056               }
1057 
1058               newC = i2s.Line(imin);
1059 
1060               newC->D1(pmin,pfv,newd1);
1061               Standard_Boolean YaRev = d1fv.Dot(newd1) <0.;
1062 
1063               if (YaRev)
1064                 newC->Reverse();
1065 
1066               if (i2s.HasLineOnS1(imin)) {
1067                 Einf.ChangeFirstPC() = i2s.LineOnS1(imin);
1068                 if ( YaRev)
1069                   Einf.ChangeFirstPC()->Reverse();
1070               }
1071 
1072               if (i2s.HasLineOnS2(imin)) {
1073                 Einf.ChangeSecondPC() = i2s.LineOnS2(imin);
1074                 if ( YaRev)
1075                   Einf.ChangeSecondPC()->Reverse();
1076               }
1077             } // if (i2s.Line(1)->DynamicType() != STANDARD_TYPE(Geom_BSplineCurve))
1078             else // i2s.Line(1) is BSplineCurve
1079             {
1080               //Find the first curve to glue
1081               TColGeom_SequenceOfCurve Candidates;
1082               if (S1->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface) ||
1083                   S1->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
1084               {
1085                 for (i = 1; i <= i2s.NbLines(); i++)
1086                 {
1087                   Handle( Geom_Curve ) aCurve = i2s.Line(i);
1088                   gp_Pnt Pnt = aCurve->Value( aCurve->FirstParameter() );
1089                   GeomAPI_ProjectPointOnSurf projector( Pnt, S1, Precision::Confusion() );
1090                   Standard_Real U, V;
1091                   projector.LowerDistanceParameters( U, V );
1092                   if (Abs(U) <= Precision::Confusion() || Abs(U-2.*M_PI) <= Precision::Confusion())
1093                     Candidates.Append( aCurve );
1094                   else
1095                   {
1096                     Pnt = aCurve->Value( aCurve->LastParameter() );
1097                     projector.Init( Pnt, S1, Precision::Confusion() );
1098                     projector.LowerDistanceParameters( U, V );
1099                     if (Abs(U) <= Precision::Confusion() || Abs(U-2.*M_PI) <= Precision::Confusion())
1100                     {
1101                       aCurve->Reverse();
1102                       Candidates.Append( aCurve );
1103                     }
1104                   }
1105                 }
1106 
1107                 if(Candidates.Length() == 0)
1108                 {
1109                   //errStat = Draft_EdgeRecomputation;
1110                   //badShape = TopoDS::Edge(ite.Key());
1111                   //return;
1112                   for (i = 1; i <= i2s.NbLines(); i++)
1113                     Candidates.Append( i2s.Line(i) );
1114                 }
1115               }
1116               else
1117               {
1118                 for (i = 1; i <= i2s.NbLines(); i++)
1119                   Candidates.Append( i2s.Line(i) );
1120               }
1121 
1122               Handle( Geom_Curve ) FirstCurve;
1123               if (Candidates.Length() > 1)
1124               {
1125                 Standard_Real DistMin = Precision::Infinite();
1126                 for (i = 1; i <= Candidates.Length(); i++)
1127                 {
1128                   Handle( Geom_Curve ) aCurve = Candidates(i);
1129                   gp_Pnt Pnt = aCurve->Value( aCurve->FirstParameter() );
1130                   const Standard_Real Dist = Pnt.Distance( pfv );
1131                   if (Dist - DistMin < -Precision::Confusion())
1132                   {
1133                     DistMin = Dist;
1134                     FirstCurve = aCurve;
1135                   }
1136                 }
1137               }
1138               else
1139                 FirstCurve = Candidates(1);
1140 
1141               //Glueing
1142               TColGeom_SequenceOfCurve Curves;
1143               for (i = 1; i <= i2s.NbLines(); i++)
1144                 if (FirstCurve != i2s.Line(i))
1145                   Curves.Append( i2s.Line(i) );
1146 
1147               TColGeom_SequenceOfCurve ToGlue;
1148               gp_Pnt EndPoint = FirstCurve->Value( FirstCurve->LastParameter() );
1149               Standard_Boolean added = Standard_True;
1150               while (added)
1151               {
1152                 added = Standard_False;
1153                 for (i = 1; i <= Curves.Length(); i++)
1154                 {
1155                   Handle( Geom_Curve ) aCurve = Curves(i);
1156                   gp_Pnt pfirst, plast;
1157                   pfirst = aCurve->Value( aCurve->FirstParameter() );
1158                   plast = aCurve->Value( aCurve->LastParameter() );
1159                   if (pfirst.Distance( EndPoint ) <= Precision::Confusion())
1160                   {
1161                     ToGlue.Append( aCurve );
1162                     EndPoint = plast;
1163                     Curves.Remove(i);
1164                     added = Standard_True;
1165                     break;
1166                   }
1167                   if (plast.Distance( EndPoint ) <= Precision::Confusion())
1168                   {
1169                     aCurve->Reverse();
1170                     ToGlue.Append( aCurve );
1171                     EndPoint = pfirst;
1172                     Curves.Remove(i);
1173                     added = Standard_True;
1174                     break;
1175                   }
1176                 }
1177               }
1178 
1179               if (FirstCurve.IsNull()) {
1180                 errStat = Draft_EdgeRecomputation;
1181                 badShape = theEdge;
1182                 return;
1183               }
1184 
1185               GeomConvert_CompCurveToBSplineCurve Concat( Handle(Geom_BSplineCurve)::DownCast(FirstCurve) );
1186               for (i = 1; i <= ToGlue.Length(); i++)
1187                 Concat.Add( Handle(Geom_BSplineCurve)::DownCast(ToGlue(i)), Precision::Confusion(), Standard_True );
1188 
1189               newC = Concat.BSplineCurve();
1190 
1191               TheCurve.Load( newC );
1192               Extrema_ExtPC myExtPC( pfv, TheCurve );
1193               Standard_Real Dist2Min = RealLast();
1194               for (i = 1; i <= myExtPC.NbExt(); i++)
1195               {
1196                 if (myExtPC.IsMin(i))
1197                 {
1198                   const Standard_Real Dist2 = myExtPC.SquareDistance(i);
1199                   if (Dist2 < Dist2Min)
1200                   {
1201                     Dist2Min = Dist2;
1202                     pmin = myExtPC.Point(i).Parameter();
1203                   }
1204                 }
1205               }
1206               newC->D1(pmin,pfv,newd1);
1207               Standard_Boolean YaRev = d1fv.Dot(newd1) < 0.;
1208 
1209               if (YaRev)
1210                 newC->Reverse();
1211               /*
1212               if (i2s.HasLineOnS1(imin)) {
1213               Einf.ChangeFirstPC() = i2s.LineOnS1(imin);
1214               if ( YaRev)
1215               Einf.ChangeFirstPC()->Reverse();
1216               }
1217 
1218               if (i2s.HasLineOnS2(imin)) {
1219               Einf.ChangeSecondPC() = i2s.LineOnS2(imin);
1220               if ( YaRev)
1221               Einf.ChangeSecondPC()->Reverse();
1222               }
1223               */
1224             } // else: i2s.NbLines() > 2 && S1 is Cylinder or Cone
1225 
1226             Einf.Tolerance(Max(Einf.Tolerance(), i2s.TolReached3d()));
1227           }  // End step KPart
1228         }
1229         else { // case of tangency
1230           const TopoDS_Face& F1 = Einf.FirstFace();
1231           const TopoDS_Face& F2 = Einf.SecondFace();
1232 
1233           Handle(Geom_Surface) aLocalS1 = myFMap.FindFromKey(F1).Geometry();
1234           Handle(Geom_Surface) aLocalS2 = myFMap.FindFromKey(F2).Geometry();
1235           if (aLocalS1.IsNull() || aLocalS2.IsNull()) {
1236             errStat = Draft_EdgeRecomputation;
1237             badShape = theEdge;
1238             return;
1239           }
1240           if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1241             aLocalS1 = Handle(Geom_RectangularTrimmedSurface)::
1242               DownCast(aLocalS1)->BasisSurface();
1243           }
1244           if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1245             aLocalS2 = Handle(Geom_RectangularTrimmedSurface)::
1246               DownCast(aLocalS2)->BasisSurface();
1247           }
1248 
1249           gp_Dir dirextr;
1250           //Standard_Boolean dirfound = Standard_False;
1251           if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
1252             gp_Cylinder cyl =
1253               Handle(Geom_CylindricalSurface)::DownCast(aLocalS1)->Cylinder();
1254             dirextr = cyl.Axis().Direction();
1255             //dirfound = Standard_True;
1256             // see direction...
1257 
1258           }
1259           else if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
1260             dirextr = Handle(Geom_SurfaceOfLinearExtrusion)::
1261               DownCast(aLocalS1)->Direction();
1262             //dirfound = Standard_True;
1263             // see direction...
1264 
1265             // Here it is possible to calculate PCurve.
1266             Handle(Geom_SurfaceOfLinearExtrusion) SEL =
1267               Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aLocalS1);
1268             Handle(Geom_Circle) GCir =
1269               Handle(Geom_Circle)::DownCast(SEL->BasisCurve());
1270             if ( !GCir.IsNull()) {
1271               Standard_Real U = ElCLib::Parameter(GCir->Circ(),ptfixe);
1272               Handle(Geom2d_Line) PC1 =
1273                 new Geom2d_Line(gp_Pnt2d(U,0.),gp::DY2d());
1274               Einf.ChangeFirstPC() = PC1;
1275             }
1276           }
1277 
1278           else if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)) {
1279             gp_Cylinder cyl =
1280               Handle(Geom_CylindricalSurface)::DownCast(aLocalS2)->Cylinder();
1281             dirextr = cyl.Axis().Direction();
1282             // dirfound = Standard_True;
1283             // see direction...
1284 
1285           }
1286           else if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
1287             dirextr = Handle(Geom_SurfaceOfLinearExtrusion)::
1288               DownCast(aLocalS2)->Direction();
1289             // dirfound = Standard_True;
1290             // see direction...
1291 
1292             // Here it is possible to calculate PCurve.
1293             Handle(Geom_SurfaceOfLinearExtrusion) SEL =
1294               Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aLocalS2);
1295             Handle(Geom_Circle) GCir =
1296               Handle(Geom_Circle)::DownCast(SEL->BasisCurve());
1297             if ( !GCir.IsNull()) {
1298               Standard_Real U = ElCLib::Parameter(GCir->Circ(),ptfixe);
1299               Handle(Geom2d_Line) PC2 =
1300                 new Geom2d_Line(gp_Pnt2d(U,0.),gp::DY2d());
1301               Einf.ChangeSecondPC() = PC2;
1302             }
1303           }
1304           newC = new Geom_Line(ptfixe,dirextr);
1305 
1306           gp_Pnt pfv;
1307           gp_Vec d1fv,newd1;
1308           C->D1(0.,pfv,d1fv);
1309           newC->D1(0.,pfv,newd1);
1310           Standard_Boolean YaRev = d1fv.Dot(newd1) <0.;
1311           if (YaRev) {
1312             newC->Reverse();
1313             if(!Einf.FirstPC().IsNull()) {
1314               Einf.ChangeFirstPC()->Reverse();
1315             }
1316             if(!Einf.SecondPC().IsNull()) {
1317               Einf.ChangeSecondPC()->Reverse();
1318             }
1319           }
1320         }
1321 
1322         Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(newC);
1323         if (!T.IsNull()) newC = T->BasisCurve();
1324         Einf.ChangeGeometry() = newC;
1325       }
1326       else if (!Einf.NewGeometry()){
1327         // set existing curve 3D
1328         Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(C);
1329         if (!T.IsNull()) C = T->BasisCurve();
1330         Einf.ChangeGeometry() = C;
1331       }
1332     }
1333 
1334     // Calculate new vertices.
1335 
1336     Handle(GeomAdaptor_Curve)   HAC = new GeomAdaptor_Curve;
1337     Handle(GeomAdaptor_Surface) HAS = new GeomAdaptor_Surface;
1338 
1339     for (Standard_Integer ii = 1; ii <= myVMap.Extent(); ii++)
1340     {
1341       GeomAdaptor_Curve&   AC = *HAC;
1342       GeomAdaptor_Surface& AS = *HAS;
1343 
1344       const TopoDS_Vertex& TVV = myVMap.FindKey(ii);
1345       Draft_VertexInfo& Vinf = myVMap.ChangeFromIndex(ii);
1346       if (!Choose(myFMap,myEMap,TVV,Vinf,AC,AS)) {
1347 
1348         // no concerted edge => alignment of two consecutive edges.
1349         gp_Pnt pvt;
1350         Vinf.ChangeGeometry() = pvt;
1351         Vinf.InitEdgeIterator();
1352         if (Vinf.MoreEdge()) {
1353           const TopoDS_Edge& Edg1 = Vinf.Edge();
1354           //const Draft_EdgeInfo& Einf1 = myEMap(Edg1);
1355           Draft_EdgeInfo& Einf1 = myEMap.ChangeFromKey(Edg1);
1356           gp_Pnt vtori = BRep_Tool::Pnt(TVV);
1357           //Einf1.Geometry()->D0(Vinf.Parameter(Edg1), pvt);
1358           GeomAPI_ProjectPointOnCurve Projector( vtori, Einf1.Geometry() ); //patch
1359           pvt = Projector.NearestPoint();
1360 
1361 #ifdef OCCT_DEBUG
1362           static Standard_Integer VertexRecomp = 1;
1363           if (VertexRecomp!=0) {
1364             std::cout << "pori :" << vtori.X() << " " << vtori.Y() << " " << vtori.Z() << std::endl;
1365             std::cout << "  Edg 1 :" << Vinf.Parameter(Edg1) << std::endl;
1366             std::cout << "pvt :" << pvt.X() << " " << pvt.Y() << " " << pvt.Z() << std::endl;
1367           }
1368 #endif
1369 
1370           Standard_Real dion=pvt.SquareDistance(vtori);
1371           Vinf.NextEdge();
1372           if (Vinf.MoreEdge()) {
1373             const TopoDS_Edge& Edg2 = Vinf.Edge();
1374             //const Draft_EdgeInfo& Einf2 = myEMap(Edg2);
1375             Draft_EdgeInfo& Einf2 = myEMap.ChangeFromKey(Edg2);
1376             //	    Standard_Real f;
1377             gp_Pnt opvt;
1378             Einf2.Geometry()->D0(Vinf.Parameter(Edg2), opvt);
1379 
1380 #ifdef OCCT_DEBUG
1381             if (VertexRecomp!=0) {
1382               std::cout << "  Edg 2 :" << Vinf.Parameter(Vinf.Edge()) << std::endl;
1383               std::cout << "opvt " << opvt.X() << " " << opvt.Y() << " " << opvt.Z() << std::endl;
1384             }
1385 #endif
1386 
1387             if (opvt.SquareDistance(vtori) < dion) {
1388               pvt = opvt;
1389             }
1390             //Vinf.ChangeParameter(Edg2) = Parameter(Einf2.Geometry(), pvt);
1391             Standard_Integer done;
1392             Standard_Real param = Parameter(Einf2.Geometry(), pvt, done);
1393             if (done != 0)
1394             {
1395               Handle(Geom_Surface) S1 = myFMap.FindFromKey(Einf2.FirstFace()).Geometry();
1396               Handle(Geom_Surface) S2 = myFMap.FindFromKey(Einf2.SecondFace()).Geometry();
1397               Vinf.ChangeParameter(Edg2) = SmartParameter( Einf2, BRep_Tool::Tolerance(Edg2), pvt, done, S1, S2 );
1398             }
1399             else
1400               Vinf.ChangeParameter(Edg2) = param;
1401           }
1402 
1403           Vinf.ChangeGeometry() = pvt;
1404           //Vinf.ChangeParameter(Edg1) = Parameter(Einf1.Geometry(), pvt);
1405           Standard_Integer done;
1406           Standard_Real param = Parameter(Einf1.Geometry(), pvt, done);
1407           if (done != 0)
1408           {
1409             Handle(Geom_Surface) S1 = myFMap.FindFromKey(Einf1.FirstFace()).Geometry();
1410             Handle(Geom_Surface) S2 = myFMap.FindFromKey(Einf1.SecondFace()).Geometry();
1411             Vinf.ChangeParameter(Edg1) = SmartParameter( Einf1, BRep_Tool::Tolerance(Edg1), pvt, done, S1, S2 );
1412           }
1413           else
1414             Vinf.ChangeParameter(Edg1) = param;
1415           continue;
1416         }
1417 
1418 
1419         errStat = Draft_VertexRecomputation;
1420         badShape = TVV;
1421         return;
1422       }
1423 
1424       IntCurveSurface_HInter myintcs;
1425       myintcs.Perform(HAC,HAS);
1426       if (!myintcs.IsDone()) {
1427         errStat = Draft_VertexRecomputation;
1428         badShape = TVV;
1429         return;
1430       }
1431 
1432       gp_Pnt vtori = BRep_Tool::Pnt(TVV);
1433       gp_Pnt pvt;
1434 
1435       Standard_Integer nbsol = myintcs.NbPoints();
1436       if (nbsol <= 0)
1437       {
1438         Extrema_ExtCS extr( AC, AS, Precision::PConfusion(), Precision::PConfusion() );
1439 
1440         if(!extr.IsDone() || extr.NbExt() == 0) {
1441           errStat = Draft_VertexRecomputation;
1442           badShape = TVV;
1443           return;
1444         }
1445 
1446 
1447         Standard_Real disref = RealLast();
1448         Standard_Integer iref = 0;
1449         Extrema_POnCurv Pc;
1450         Extrema_POnSurf Ps;
1451         for (Standard_Integer i = 1; i <= extr.NbExt(); i++)
1452         {
1453           extr.Points( i, Pc, Ps );
1454           Standard_Real distemp = Pc.Value().SquareDistance(vtori);
1455           if ( distemp < disref)
1456           {
1457             disref = distemp;
1458             iref = i;
1459           }
1460         }
1461         extr.Points( iref, Pc, Ps );
1462         pvt = Pc.Value();
1463       }
1464       else
1465       {
1466         Standard_Real disref = RealLast();
1467         Standard_Integer iref = 0;
1468         for (Standard_Integer i = 1; i <= nbsol; i++)
1469         {
1470           Standard_Real distemp = myintcs.Point(i).Pnt().SquareDistance(vtori);
1471           if ( distemp < disref)
1472           {
1473             disref = distemp;
1474             iref = i;
1475           }
1476         }
1477         pvt = myintcs.Point(iref).Pnt();
1478       }
1479 
1480       Vinf.ChangeGeometry() = pvt;
1481 
1482       for (Vinf.InitEdgeIterator();Vinf.MoreEdge(); Vinf.NextEdge()) {
1483         const TopoDS_Edge& Edg = Vinf.Edge();
1484         Standard_Real initpar = Vinf.Parameter(Edg);
1485         //const Draft_EdgeInfo& Einf = myEMap(Edg);
1486         Draft_EdgeInfo& Einf = myEMap.ChangeFromKey(Edg);
1487         //Vinf.ChangeParameter(Edg) = Parameter(Einf.Geometry(),pvt);
1488         Standard_Integer done;
1489         Standard_Real param = Parameter(Einf.Geometry(), pvt, done);
1490         if (done != 0)
1491         {
1492           Handle(Geom_Surface) S1 = myFMap.FindFromKey(Einf.FirstFace()).Geometry();
1493           Handle(Geom_Surface) S2 = myFMap.FindFromKey(Einf.SecondFace()).Geometry();
1494           Vinf.ChangeParameter(Edg) = SmartParameter( Einf, BRep_Tool::Tolerance(Edg), pvt, done, S1, S2 );
1495         }
1496         else
1497         {
1498           if(Abs(initpar - param) > Precision::PConfusion())
1499           {
1500             Standard_Real f, l;
1501             TopLoc_Location Loc;
1502             const Handle(Geom_Curve)& aC = BRep_Tool::Curve(Edg, Loc, f, l);
1503             if(aC->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
1504             {
1505               Einf.SetNewGeometry(Standard_True);
1506             }
1507           }
1508           Vinf.ChangeParameter(Edg) = param;
1509         }
1510       }
1511     }
1512   }
1513 
1514   // small loop of validation/protection
1515 
1516   for (Standard_Integer i = 1; i <= myEMap.Extent(); i++)
1517   {
1518     const TopoDS_Edge& edg = TopoDS::Edge(myEMap.FindKey(i));
1519 
1520     TopoDS_Vertex Vf,Vl;
1521     TopExp::Vertices(edg,Vf,Vl);
1522     if (edg.Orientation() == TopAbs_REVERSED) {
1523       Vf.Reverse();
1524       Vl.Reverse();
1525     }
1526 
1527     if(myVMap.Contains(Vf) && myVMap.Contains(Vl))
1528     {
1529       //Here, we compare directions of the source edge (from input shape)
1530       //and corresponding selected part of the intersection edge.
1531       //If these directions are opposite then we reverse intersection edge
1532       //and recompute corresponding vertex-parameters.
1533 
1534       Standard_Real aParF = myVMap.ChangeFromKey(Vf).Parameter(edg);
1535       Standard_Real aParL = myVMap.ChangeFromKey(Vl).Parameter(edg);
1536 
1537       if(aParL < aParF)
1538       {
1539         Draft_EdgeInfo& aEinf = myEMap.ChangeFromKey(edg);
1540         TopLoc_Location aLoc;
1541         Standard_Real aF = 0.0, aL = 0.0;
1542         const Handle(Geom_Curve) aSCurve = BRep_Tool::Curve(edg, aF, aL);
1543         Handle(Geom_Curve) anIntCurv = aEinf.Geometry();
1544         gp_Pnt aPf, aPl;
1545         gp_Vec aDirNF, aDirNL, aDirOF, aDirOL;
1546         aSCurve->D1(BRep_Tool::Parameter(Vf, edg), aPf, aDirOF);
1547         aSCurve->D1(BRep_Tool::Parameter(Vl, edg), aPl, aDirOL);
1548         anIntCurv->D1(aParF, aPf, aDirNF);
1549         anIntCurv->D1(aParL, aPl, aDirNL);
1550 
1551         Standard_Real aSqMagn = aDirNF.SquareMagnitude();
1552 
1553         if (aSqMagn > Precision::SquareConfusion())
1554           aDirNF.Divide(sqrt(aSqMagn));
1555 
1556         aSqMagn = aDirNL.SquareMagnitude();
1557         if (aSqMagn > Precision::SquareConfusion())
1558           aDirNL.Divide(sqrt(aSqMagn));
1559 
1560         aSqMagn = aDirOF.SquareMagnitude();
1561         if (aSqMagn > Precision::SquareConfusion())
1562           aDirOF.Divide(sqrt(aSqMagn));
1563 
1564         aSqMagn = aDirOL.SquareMagnitude();
1565         if (aSqMagn > Precision::SquareConfusion())
1566           aDirOL.Divide(sqrt(aSqMagn));
1567 
1568         const Standard_Real aCosF = aDirNF.Dot(aDirOF), aCosL = aDirNL.Dot(aDirOL);
1569         const Standard_Real aCosMax = Abs(aCosF) > Abs(aCosL) ? aCosF : aCosL;
1570 
1571         if(aCosMax < 0.0)
1572         {
1573           Standard_Integer anErr = 0;
1574           anIntCurv->Reverse();
1575           aEinf.ChangeGeometry() = anIntCurv;
1576           Standard_Real aPar = Parameter(aEinf.Geometry(), aPf, anErr);
1577           if(anErr == 0)
1578           {
1579             myVMap.ChangeFromKey(Vf).ChangeParameter(edg) = aPar;
1580           }
1581           aPar = Parameter(aEinf.Geometry(), aPl, anErr);
1582           if(anErr == 0)
1583           {
1584             myVMap.ChangeFromKey(Vl).ChangeParameter(edg) = aPar;
1585           }
1586         }
1587       }
1588     }
1589 
1590     Standard_Real pf,pl,tolerance;
1591     if (!NewParameter(Vf,edg,pf,tolerance)) {
1592       pf = BRep_Tool::Parameter(Vf,edg);
1593     }
1594     if (!NewParameter(Vl,edg,pl,tolerance)) {
1595       pl = BRep_Tool::Parameter(Vl,edg);
1596     }
1597     if (pl <= pf) {
1598       //      const Handle(Geom_Curve) gc=ite.Value().Geometry();
1599       //      if (!gc.IsNull()) {
1600       //	pl = gc->LastParameter();
1601       //	pf = gc->FirstParameter();
1602       //      }
1603       Handle( Geom_Curve ) theCurve = myEMap.FindFromKey(edg).Geometry();
1604       if (theCurve->IsClosed())
1605       {
1606         // pf >= pl
1607         Standard_Real FirstPar = theCurve->FirstParameter(), LastPar = theCurve->LastParameter();
1608         Standard_Real pconf = Precision::PConfusion();
1609         if (Abs( pf - LastPar ) <= pconf)
1610           pf = FirstPar;
1611         else if (Abs( pl - FirstPar ) <= pconf)
1612           pl = LastPar;
1613 
1614         if(pl <= pf) {
1615           pl += (LastPar-FirstPar);
1616         }
1617 
1618       }
1619       if (pl <= pf) {
1620         errStat = Draft_EdgeRecomputation;
1621         badShape = edg;
1622         return;
1623       }
1624     }
1625     if (myVMap.Contains( Vf ))
1626       myVMap.ChangeFromKey(Vf).ChangeParameter(edg) = pf;
1627     if (myVMap.Contains( Vl ))
1628       myVMap.ChangeFromKey(Vl).ChangeParameter(edg) = pl;
1629   }
1630 }
1631 
1632 
1633 
1634 //=======================================================================
1635 //function : NewSurface
1636 //purpose  :
1637 //=======================================================================
1638 
Handle(Geom_Surface)1639 Handle(Geom_Surface) Draft_Modification::NewSurface
1640   (const Handle(Geom_Surface)& S,
1641   const TopAbs_Orientation Oris,
1642   const gp_Dir& Direction,
1643   const Standard_Real Angle,
1644   const gp_Pln& NeutralPlane)
1645 {
1646   Handle(Geom_Surface) NewS;
1647 
1648   Handle(Standard_Type) TypeS = S->DynamicType();
1649 
1650   if (TypeS == STANDARD_TYPE(Geom_Plane)) {
1651     gp_Pln Pl = Handle(Geom_Plane)::DownCast(S)->Pln();
1652     gp_Ax1 Axe;
1653     Standard_Real Theta;
1654     if (FindRotation(Pl,Oris,Direction,Angle,NeutralPlane,Axe,Theta)) {
1655       if ( Abs(Theta) > Precision::Angular()) {
1656         NewS = Handle(Geom_Surface)::DownCast(S->Rotated(Axe,Theta));
1657       }
1658       else {
1659         NewS = S;
1660       }
1661     }
1662   }
1663   else if (TypeS == STANDARD_TYPE(Geom_CylindricalSurface)) {
1664     Standard_Real testdir = Direction.Dot(NeutralPlane.Axis().Direction());
1665     if (Abs(testdir) <= 1.-Precision::Angular()) {
1666 #ifdef OCCT_DEBUG
1667       std::cout << "NewSurfaceCyl:Draft_Direction_and_Neutral_Perpendicular" << std::endl;
1668 #endif
1669       return NewS;
1670     }
1671     gp_Cylinder Cy = Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();
1672     testdir = Direction.Dot(Cy.Axis().Direction());
1673     if (Abs(testdir) <= 1.-Precision::Angular()) {
1674 #ifdef OCCT_DEBUG
1675       std::cout << "NewSurfaceCyl:Draft_Direction_and_Cylinder_Perpendicular" << std::endl;
1676 #endif
1677       return NewS;
1678     }
1679     if (Abs(Angle) > Precision::Angular())
1680     {
1681       IntAna_QuadQuadGeo i2s;
1682       i2s.Perform(NeutralPlane,Cy,Precision::Angular(),Precision::Confusion());
1683       Standard_Boolean isIntDone = i2s.IsDone();
1684 
1685       if(i2s.TypeInter() == IntAna_Ellipse)
1686       {
1687         const gp_Elips anEl = i2s.Ellipse(1);
1688         const Standard_Real aMajorR = anEl.MajorRadius();
1689         const Standard_Real aMinorR = anEl.MinorRadius();
1690         isIntDone = (aMajorR < 100000.0 * aMinorR);
1691       }
1692 
1693       if (!isIntDone || i2s.TypeInter() != IntAna_Circle) {
1694 #ifdef OCCT_DEBUG
1695         std::cout << "NewSurfaceCyl:Draft_Intersection_Neutral_Cylinder_NotDone" << std::endl;
1696 #endif
1697         return NewS;
1698       }
1699       gp_Ax3 axcone = Cy.Position();
1700       // Pb : Where is the material???
1701       Standard_Real alpha = Angle;
1702       Standard_Boolean direct(axcone.Direct());
1703       if ((direct && Oris == TopAbs_REVERSED) ||
1704          (!direct && Oris == TopAbs_FORWARD)) {
1705         alpha = -alpha;
1706       }
1707 
1708       gp_Pnt Center = i2s.Circle(1).Location();
1709       if (testdir <0.) {
1710         alpha = -alpha;
1711       }
1712       Standard_Real Z = ElCLib::LineParameter(Cy.Axis(),Center);
1713       Standard_Real Rad = Cy.Radius()+Z*Tan(alpha);
1714       if (Rad < 0.) {
1715         Rad = -Rad;
1716       }
1717       else {
1718         alpha = -alpha;
1719       }
1720       gp_Cone co(axcone,alpha,Rad);
1721       NewS = new Geom_ConicalSurface(co);
1722     }
1723     else {
1724       NewS = S;
1725     }
1726   }
1727   else if (TypeS == STANDARD_TYPE(Geom_ConicalSurface)) {
1728 
1729     Standard_Real testdir = Direction.Dot(NeutralPlane.Axis().Direction());
1730     if (Abs(testdir) <= 1.-Precision::Angular()) {
1731 #ifdef OCCT_DEBUG
1732       std::cout << "NewSurfaceCone:Draft_Direction_and_Neutral_Perpendicular" << std::endl;
1733 #endif
1734       return NewS;
1735     }
1736 
1737     gp_Cone Co1 = Handle(Geom_ConicalSurface)::DownCast(S)->Cone();
1738 
1739     testdir = Direction.Dot(Co1.Axis().Direction());
1740     if (Abs(testdir) <= 1.-Precision::Angular()) {
1741 #ifdef OCCT_DEBUG
1742       std::cout << "NewSurfaceCone:Draft_Direction_and_Cone_Perpendicular" << std::endl;
1743 #endif
1744       return NewS;
1745     }
1746 
1747 
1748     IntAna_QuadQuadGeo i2s;
1749     i2s.Perform(NeutralPlane,Co1,Precision::Angular(),Precision::Confusion());
1750     if (!i2s.IsDone() || i2s.TypeInter() != IntAna_Circle) {
1751 #ifdef OCCT_DEBUG
1752       std::cout << "NewSurfaceCone:Draft_Intersection_Neutral_Conical_NotDone" << std::endl;
1753 #endif
1754       return NewS;
1755     }
1756     gp_Ax3 axcone = Co1.Position();
1757     // Pb : Where is the material???
1758     Standard_Real alpha = Angle;
1759     Standard_Boolean direct(axcone.Direct());
1760     if ((direct && Oris == TopAbs_REVERSED) ||
1761        (!direct && Oris == TopAbs_FORWARD)) {
1762       alpha = -alpha;
1763     }
1764 
1765     gp_Pnt Center = i2s.Circle(1).Location();
1766     if (Abs(Angle) > Precision::Angular()) {
1767       if (testdir <0.) {
1768         alpha = -alpha;
1769       }
1770       Standard_Real Z = ElCLib::LineParameter(Co1.Axis(),Center);
1771       Standard_Real Rad = i2s.Circle(1).Radius()+Z*Tan(alpha);
1772       if (Rad < 0.) {
1773         Rad = -Rad;
1774       }
1775       else {
1776         alpha = -alpha;
1777       }
1778       if (Abs(alpha-Co1.SemiAngle()) < Precision::Angular()) {
1779         NewS = S;
1780       }
1781       else {
1782         gp_Cone co(axcone,alpha,Rad);
1783         NewS = new Geom_ConicalSurface(co);
1784       }
1785     }
1786     else {
1787       NewS = new
1788         Geom_CylindricalSurface(gp_Cylinder(axcone,i2s.Circle(1).Radius()));
1789     }
1790   }
1791   else {
1792 #ifdef OCCT_DEBUG
1793     std::cout << "NewSurface:Draft_SurfNotYetImplemented" << std::endl;
1794 #endif
1795   }
1796   return NewS;
1797 }
1798 
1799 
1800 //=======================================================================
1801 //function : NewCurve
1802 //purpose  :
1803 //=======================================================================
1804 
Handle(Geom_Curve)1805 Handle(Geom_Curve) Draft_Modification::NewCurve
1806   (const Handle(Geom_Curve)& C,
1807   const Handle(Geom_Surface)& S,
1808   const TopAbs_Orientation Oris,
1809   const gp_Dir& Direction,
1810   const Standard_Real Angle,
1811   const gp_Pln& NeutralPlane,
1812   const Standard_Boolean )
1813 
1814 {
1815   Handle(Geom_Curve) NewC;
1816 
1817   Handle(Standard_Type) TypeS = S->DynamicType();
1818 
1819   if (TypeS == STANDARD_TYPE(Geom_Plane)) {
1820     gp_Pln Pl = Handle(Geom_Plane)::DownCast(S)->Pln();
1821     gp_Ax1 Axe;
1822     Standard_Real Theta;
1823     if (FindRotation(Pl,Oris,Direction,Angle,NeutralPlane,Axe,Theta)) {
1824       if ( Abs(Theta) > Precision::Angular()) {
1825         NewC = Handle(Geom_Curve)::DownCast(C->Rotated(Axe,Theta));
1826       }
1827       else {
1828         NewC = C;
1829       }
1830     }
1831     return NewC;
1832   }
1833 
1834 
1835   if (C->DynamicType() != STANDARD_TYPE(Geom_Line)) {
1836     return NewC;
1837   }
1838 
1839 
1840   gp_Lin lin = Handle(Geom_Line)::DownCast(C)->Lin();
1841   //  Standard_Real testdir = Direction.Dot(lin.Direction());
1842   //  if (Abs(testdir) <= 1.-Precision::Angular()) {
1843   //    return NewC;
1844   //  }
1845   gp_Dir Norm;
1846   if (TypeS == STANDARD_TYPE(Geom_CylindricalSurface)) {
1847     Standard_Real U,V;
1848     gp_Vec d1u,d1v;
1849     gp_Pnt pbid;
1850     gp_Cylinder Cy = Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();
1851     ElSLib::Parameters(Cy,lin.Location(),U,V);
1852     ElSLib::D1(U,V,Cy,pbid,d1u,d1v);
1853     Norm = d1u.Crossed(d1v);
1854   }
1855   else if (TypeS == STANDARD_TYPE(Geom_ConicalSurface)) {
1856     Standard_Real U,V;
1857     gp_Vec d1u,d1v;
1858     gp_Pnt pbid;
1859     gp_Cone Co = Handle(Geom_ConicalSurface)::DownCast(S)->Cone();
1860     ElSLib::Parameters(Co,lin.Location(),U,V);
1861     ElSLib::D1(U,V,Co,pbid,d1u,d1v);
1862     Norm = d1u.Crossed(d1v);
1863   }
1864 
1865   IntAna_IntConicQuad ilipl(lin,NeutralPlane,Precision::Angular());
1866   if (ilipl.IsDone() && ilipl.NbPoints() != 0){
1867     if (Oris == TopAbs_REVERSED) {
1868       Norm.Reverse();
1869     }
1870     gp_Ax1 axrot(ilipl.Point(1), Norm.Crossed(Direction));
1871     gp_Lin lires = gp_Lin(gp_Ax1(ilipl.Point(1),Direction)).
1872       Rotated(axrot,Angle);
1873     if (lires.Direction().Dot(lin.Direction()) < 0.) {
1874       lires.Reverse();
1875     }
1876     NewC = new Geom_Line(lires);
1877   }
1878   return NewC;
1879 }
1880 
1881 
1882 //=======================================================================
1883 //function : Choose
1884 //purpose  :
1885 //=======================================================================
1886 
Choose(const Draft_IndexedDataMapOfFaceFaceInfo & theFMap,Draft_IndexedDataMapOfEdgeEdgeInfo & theEMap,const TopoDS_Vertex & Vtx,Draft_VertexInfo & Vinf,GeomAdaptor_Curve & AC,GeomAdaptor_Surface & AS)1887 static Standard_Boolean Choose(const Draft_IndexedDataMapOfFaceFaceInfo& theFMap,
1888   Draft_IndexedDataMapOfEdgeEdgeInfo& theEMap,
1889   const TopoDS_Vertex& Vtx,
1890   Draft_VertexInfo& Vinf,
1891   GeomAdaptor_Curve& AC,
1892   GeomAdaptor_Surface& AS)
1893 {
1894   gp_Vec tgref;
1895   Vinf.InitEdgeIterator();
1896 
1897   // Find a regular edge with null SecondFace
1898   while (Vinf.MoreEdge()) {
1899     const TopoDS_Edge& E1 = Vinf.Edge();
1900     const Draft_EdgeInfo& Einf1 = theEMap.FindFromKey(E1);
1901     if (Einf1.SecondFace().IsNull()) {
1902       break;
1903     }
1904     else {
1905       GeomAbs_Shape te = BRep_Tool::Continuity(E1,Einf1.FirstFace(),
1906         Einf1.SecondFace());
1907       if (te >= GeomAbs_G1) {
1908         break;
1909       }
1910     }
1911     Vinf.NextEdge();
1912   }
1913   if (!Vinf.MoreEdge()) { // take the first edge
1914     Vinf.InitEdgeIterator();
1915   }
1916 
1917   const TopoDS_Edge& Eref = Vinf.Edge();
1918   //const Draft_EdgeInfo& Einf = theEMap(Eref);
1919   Draft_EdgeInfo& Einf = theEMap.ChangeFromKey(Eref);
1920 
1921   AC.Load(Einf.Geometry());
1922 
1923   Standard_Real f,l,prm;
1924   TopLoc_Location Loc;
1925   Handle(Geom_Curve) C = BRep_Tool::Curve(Eref,Loc,f,l);
1926   C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
1927   gp_Pnt ptbid;
1928   //prm = Parameter(C,BRep_Tool::Pnt(Vtx));
1929   Standard_Integer done;
1930   Standard_Real param = Parameter( C, BRep_Tool::Pnt(Vtx), done );
1931   if (done != 0)
1932   {
1933     Handle( Geom_Surface ) S1 = theFMap.FindFromKey(Einf.FirstFace()).Geometry();
1934     Handle( Geom_Surface ) S2 = theFMap.FindFromKey(Einf.SecondFace()).Geometry();
1935     prm = SmartParameter( Einf, BRep_Tool::Tolerance(Eref), BRep_Tool::Pnt(Vtx), done, S1, S2 );
1936   }
1937   else
1938     prm = param;
1939   C->D1(prm,ptbid,tgref);
1940 
1941 
1942   Vinf.InitEdgeIterator();
1943   while (Vinf.MoreEdge()) {
1944     // Find a non tangent edge
1945     const TopoDS_Edge& Edg = Vinf.Edge();
1946     if (!Edg.IsSame(Eref)) {
1947       //const Draft_EdgeInfo& Einfo = theEMap(Edg);
1948       Draft_EdgeInfo& Einfo = theEMap.ChangeFromKey(Edg);
1949       if (!Einfo.SecondFace().IsNull() &&
1950           BRep_Tool::Continuity(Edg,Einfo.FirstFace(),Einfo.SecondFace())
1951           <= GeomAbs_C0) {
1952         C = BRep_Tool::Curve(Edg,Loc,f,l);
1953         C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
1954         //prm = Parameter(C,BRep_Tool::Pnt(Vtx));
1955         Standard_Integer anewdone;
1956         Standard_Real anewparam = Parameter( C, BRep_Tool::Pnt(Vtx), anewdone );
1957         if (anewdone != 0)
1958         {
1959           Handle( Geom_Surface ) S1 = theFMap.FindFromKey(Einfo.FirstFace()).Geometry();
1960           Handle( Geom_Surface ) S2 = theFMap.FindFromKey(Einfo.SecondFace()).Geometry();
1961           prm = SmartParameter( Einfo, BRep_Tool::Tolerance(Edg), BRep_Tool::Pnt(Vtx), anewdone, S1, S2 );
1962         }
1963         else
1964           prm = anewparam;
1965         gp_Vec tg;
1966         C->D1(prm,ptbid,tg);
1967         if (tg.CrossMagnitude(tgref) > Precision::Confusion()) {
1968           break;
1969         }
1970       }
1971     }
1972     Vinf.NextEdge();
1973   }
1974   if (!Vinf.MoreEdge()) {
1975     return Standard_False;
1976   }
1977 
1978   const Draft_EdgeInfo& Einf2 = theEMap.FindFromKey(Vinf.Edge());
1979   if (!Einf.SecondFace().IsNull()) {
1980 
1981     if (Einf2.FirstFace().IsSame(Einf.FirstFace()) ||
1982         Einf2.FirstFace().IsSame(Einf.SecondFace())) {
1983       AS.Load(theFMap.FindFromKey(Einf2.SecondFace()).Geometry());
1984     }
1985     else {
1986       AS.Load(theFMap.FindFromKey(Einf2.FirstFace()).Geometry());
1987     }
1988   }
1989   else {
1990     if (Einf2.FirstFace().IsSame(Einf.FirstFace())) {
1991       AS.Load(theFMap.FindFromKey(Einf2.SecondFace()).Geometry());
1992     }
1993     else {
1994       AS.Load(theFMap.FindFromKey(Einf2.FirstFace()).Geometry());
1995     }
1996   }
1997   return Standard_True;
1998 }
1999 
2000 
2001 //=======================================================================
2002 //function : Parameter
2003 //purpose  :
2004 //=======================================================================
2005 
Parameter(const Handle (Geom_Curve)& C,const gp_Pnt & P,Standard_Integer & done)2006 static Standard_Real Parameter(const Handle(Geom_Curve)& C,
2007   const gp_Pnt& P,
2008   Standard_Integer& done)
2009 {
2010   done = 0;
2011   Handle(Geom_Curve) cbase = C;
2012   Handle(Standard_Type) ctyp = C->DynamicType();
2013   if (ctyp == STANDARD_TYPE(Geom_TrimmedCurve)) {
2014     cbase = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
2015     ctyp = cbase->DynamicType();
2016   }
2017   Standard_Real param;
2018   if (ctyp == STANDARD_TYPE(Geom_Line)) {
2019     param = ElCLib::Parameter(Handle(Geom_Line)::DownCast(cbase)->Lin(),P);
2020   }
2021   else if (ctyp == STANDARD_TYPE(Geom_Circle)) {
2022     param = ElCLib::Parameter(Handle(Geom_Circle)::DownCast(cbase)->Circ(),P);
2023     if (Abs(2.*M_PI-param) <=Epsilon(2.*M_PI)) {
2024       param = 0.;
2025     }
2026   }
2027   else if (ctyp == STANDARD_TYPE(Geom_Ellipse)) {
2028     param = ElCLib::Parameter(Handle(Geom_Ellipse)::DownCast(cbase)->Elips(),P);
2029     if (Abs(2.*M_PI-param) <=Epsilon(2.*M_PI)) {
2030       param = 0.;
2031     }
2032   }
2033   else if (ctyp == STANDARD_TYPE(Geom_Parabola)) {
2034     param = ElCLib::Parameter(Handle(Geom_Parabola)::DownCast(cbase)->Parab(),P);
2035   }
2036   else if (ctyp == STANDARD_TYPE(Geom_Hyperbola)) {
2037     param = ElCLib::Parameter(Handle(Geom_Hyperbola)::DownCast(cbase)->Hypr(),P);
2038   }
2039   else {
2040     GeomAdaptor_Curve TheCurve(C);
2041     Extrema_ExtPC myExtPC(P,TheCurve);
2042     if (!myExtPC.IsDone()) {
2043       throw Standard_Failure("Draft_Modification_1::Parameter: ExtremaPC not done.");
2044     }
2045     if (myExtPC.NbExt() >= 1) {
2046       Standard_Real Dist2, Dist2Min = myExtPC.SquareDistance(1);
2047       Standard_Integer j, jmin = 1;
2048       for (j = 2; j <= myExtPC.NbExt(); j++) {
2049         Dist2 = myExtPC.SquareDistance(j);
2050         if (Dist2 < Dist2Min) {
2051           Dist2Min = Dist2;
2052           jmin = j;
2053         }
2054       }
2055       param = myExtPC.Point(jmin).Parameter();
2056     }
2057     else {
2058       Standard_Real dist1_2,dist2_2;
2059       gp_Pnt p1b,p2b;
2060       myExtPC.TrimmedSquareDistances(dist1_2,dist2_2,p1b,p2b);
2061       if (dist1_2 < dist2_2) {
2062         done = -1;
2063         param = TheCurve.FirstParameter();
2064       }
2065       else {
2066         done = 1;
2067         param = TheCurve.LastParameter();
2068       }
2069     }
2070 
2071     if (cbase->IsPeriodic()) {
2072       Standard_Real Per  = cbase->Period();
2073       Standard_Real Tolp = Precision::Parametric(Precision::Confusion());
2074       if (Abs(Per-param) <= Tolp) {
2075         param = 0.;
2076       }
2077     }
2078   }
2079   return param;
2080 }
2081 
2082 //=======================================================================
2083 //function : SmartParameter
2084 //purpose  :
2085 //=======================================================================
2086 
SmartParameter(Draft_EdgeInfo & Einf,const Standard_Real EdgeTol,const gp_Pnt & Pnt,const Standard_Integer sign,const Handle (Geom_Surface)& S1,const Handle (Geom_Surface)& S2)2087 static Standard_Real SmartParameter(Draft_EdgeInfo& Einf,
2088   const Standard_Real EdgeTol,
2089   const gp_Pnt& Pnt,
2090   const Standard_Integer sign,
2091   const Handle(Geom_Surface)& S1,
2092   const Handle(Geom_Surface)& S2)
2093 {
2094   Handle( Geom2d_Curve ) NewC2d;
2095   Standard_Real Tol = Precision::Confusion();
2096   Standard_Real Etol = EdgeTol;
2097 
2098   Handle( Geom2d_Curve ) pcu1 = Einf.FirstPC();
2099   Handle( Geom2d_Curve ) pcu2 = Einf.SecondPC();
2100 
2101   if (pcu1.IsNull())
2102   {
2103     Handle( Geom_Curve ) theCurve = Einf.Geometry();
2104     pcu1 = GeomProjLib::Curve2d( theCurve, theCurve->FirstParameter(), theCurve->LastParameter(), S1, Etol );
2105     Einf.ChangeFirstPC() = pcu1;
2106   }
2107   if (pcu2.IsNull())
2108   {
2109     Handle( Geom_Curve ) theCurve = Einf.Geometry();
2110     pcu2 = GeomProjLib::Curve2d( theCurve, theCurve->FirstParameter(), theCurve->LastParameter(), S2, Etol );
2111     Einf.ChangeSecondPC() = pcu2;
2112   }
2113 
2114   GeomAPI_ProjectPointOnSurf Projector( Pnt, S1 );
2115   Standard_Real U, V;
2116   Projector.LowerDistanceParameters( U, V );
2117 
2118   NewC2d = Einf.FirstPC();
2119   if (NewC2d->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
2120     NewC2d = (Handle(Geom2d_TrimmedCurve)::DownCast(NewC2d))->BasisCurve();
2121 
2122   gp_Pnt2d P2d( U, V );
2123   Geom2dAPI_ProjectPointOnCurve Projector2d( P2d, NewC2d );
2124   if (Projector2d.NbPoints() == 0 || Projector2d.LowerDistance() > Tol)
2125   {
2126     Handle( Geom2d_BSplineCurve ) BCurve;
2127     if (NewC2d->DynamicType() != STANDARD_TYPE(Geom2d_BSplineCurve))
2128       BCurve = Geom2dConvert::CurveToBSplineCurve( NewC2d );
2129     else
2130       BCurve = Handle( Geom2d_BSplineCurve )::DownCast( NewC2d );
2131     if (sign == -1)
2132     {
2133       TColgp_Array1OfPnt2d PntArray( 1, 2 );
2134       PntArray(1) = P2d;
2135       PntArray(2) = BCurve->Pole(1);
2136       Handle( Geom2d_BezierCurve ) Patch = new Geom2d_BezierCurve( PntArray );
2137       Geom2dConvert_CompCurveToBSplineCurve Concat( BCurve, Convert_QuasiAngular );
2138       Concat.Add( Patch, Tol, Standard_False );
2139       BCurve = Concat.BSplineCurve();
2140     }
2141     else
2142     {
2143       TColgp_Array1OfPnt2d PntArray( 1, 2 );
2144       PntArray(1) = BCurve->Pole( BCurve->NbPoles() );
2145       PntArray(2) = P2d;
2146       Handle( Geom2d_BezierCurve ) Patch = new Geom2d_BezierCurve( PntArray );
2147       Geom2dConvert_CompCurveToBSplineCurve Concat( BCurve, Convert_QuasiAngular );
2148       Concat.Add( Patch, Tol, Standard_True );
2149       BCurve = Concat.BSplineCurve();
2150     }
2151     NewC2d = BCurve;
2152   }
2153   Einf.ChangeFirstPC() = NewC2d;
2154   Handle( Geom2dAdaptor_Curve ) hcur = new Geom2dAdaptor_Curve( NewC2d );
2155   Handle( GeomAdaptor_Surface ) hsur = new GeomAdaptor_Surface( S1 );
2156   Adaptor3d_CurveOnSurface cons( hcur, hsur );
2157   Handle( Adaptor3d_CurveOnSurface ) hcons = new Adaptor3d_CurveOnSurface( cons );
2158   Handle( GeomAdaptor_Surface ) hsur2 = new GeomAdaptor_Surface( S2 );
2159   Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve (hsur2, hcons, Tol, Tol);
2160   Standard_Real Udeb, Ufin;
2161   HProjector->Bounds(1, Udeb, Ufin);
2162   Standard_Integer MaxSeg = 20 + HProjector->NbIntervals(GeomAbs_C3);
2163   Approx_CurveOnSurface appr(HProjector, hsur2, Udeb, Ufin, Tol);
2164   appr.Perform(MaxSeg, 10, GeomAbs_C1, Standard_False, Standard_False);
2165   Einf.ChangeSecondPC() = appr.Curve2d();
2166   Einf.ChangeGeometry() = appr.Curve3d();
2167   Einf.SetNewGeometry( Standard_True );
2168 
2169   if (sign == -1)
2170     return Einf.Geometry()->FirstParameter();
2171   else
2172     return Einf.Geometry()->LastParameter();
2173 
2174 }
2175 
2176 //=======================================================================
2177 //function : Orientation
2178 //purpose  :
2179 //=======================================================================
2180 
Orientation(const TopoDS_Shape & S,const TopoDS_Face & F)2181 static TopAbs_Orientation Orientation(const TopoDS_Shape& S,
2182   const TopoDS_Face& F)
2183 {
2184   //
2185   // change porting NT
2186   //
2187   TopExp_Explorer expl ;
2188   expl.Init(S,
2189     TopAbs_FACE) ;
2190   while (expl.More()) {
2191     if (TopoDS::Face(expl.Current()).IsSame(F)) {
2192       return expl.Current().Orientation();
2193     }
2194     expl.Next();
2195   }
2196   return TopAbs_FORWARD;
2197 }
2198 
2199 
2200 //=======================================================================
2201 //function : FindRotation
2202 //purpose  :
2203 //=======================================================================
2204 
FindRotation(const gp_Pln & Pl,const TopAbs_Orientation Oris,const gp_Dir & Direction,const Standard_Real Angle,const gp_Pln & NeutralPlane,gp_Ax1 & Axe,Standard_Real & theta)2205 static Standard_Boolean FindRotation(const gp_Pln& Pl,
2206   const TopAbs_Orientation Oris,
2207   const gp_Dir& Direction,
2208   const Standard_Real Angle,
2209   const gp_Pln& NeutralPlane,
2210   gp_Ax1& Axe,
2211   Standard_Real& theta)
2212 {
2213   IntAna_QuadQuadGeo i2pl(Pl,NeutralPlane,
2214     Precision::Angular(),Precision::Confusion());
2215 
2216   if (i2pl.IsDone() && i2pl.TypeInter() == IntAna_Line) {
2217     gp_Lin li = i2pl.Line(1);
2218     // Try to turn around this line
2219     gp_Dir nx = li.Direction();
2220     gp_Dir ny = Pl.Axis().Direction().Crossed(nx);
2221     Standard_Real a = Direction.Dot(nx);
2222     if (Abs(a) <=1-Precision::Angular()) {
2223       Standard_Real b = Direction.Dot(ny);
2224       Standard_Real c = Direction.Dot(Pl.Axis().Direction());
2225       Standard_Boolean direct(Pl.Position().Direct());
2226       if ((direct && Oris == TopAbs_REVERSED) ||
2227         (!direct && Oris == TopAbs_FORWARD)) {
2228           b = -b;
2229           c = -c;
2230       }
2231       Standard_Real denom = Sqrt(1-a*a);
2232       Standard_Real Sina = Sin(Angle);
2233       if (denom>Abs(Sina)) {
2234         Standard_Real phi = ATan2(b/denom,c/denom);
2235         Standard_Real theta0 = ACos(Sina/denom);
2236         theta = theta0 - phi;
2237         if (Cos(theta) <0.) {
2238           theta = -theta0 -phi;
2239         }
2240         //  modified by NIZHNY-EAP Tue Nov 16 15:51:38 1999 ___BEGIN___
2241         while (Abs(theta)>M_PI) {
2242           theta = theta + M_PI*(theta<0 ? 1 : -1);
2243         }
2244         //  modified by NIZHNY-EAP Tue Nov 16 15:53:32 1999 ___END___
2245         Axe = li.Position();
2246         return Standard_True;
2247       }
2248     }
2249   }
2250   return Standard_False;
2251 }
2252 
2253