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