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