Salome HOME
Copyrights update 2015.
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ShapeDriver.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <GEOMImpl_ShapeDriver.hxx>
24
25 #include <GEOMImpl_IIsoline.hxx>
26 #include <GEOMImpl_IShapes.hxx>
27 #include <GEOMImpl_IShapeExtend.hxx>
28 #include <GEOMImpl_IVector.hxx>
29 #include <GEOMImpl_Types.hxx>
30 #include <GEOMImpl_Block6Explorer.hxx>
31
32 #include <GEOM_Function.hxx>
33 #include <GEOMUtils_Hatcher.hxx>
34
35 // OCCT Includes
36 #include <ShapeFix_Wire.hxx>
37 #include <ShapeFix_Edge.hxx>
38 #include <ShapeFix_Shape.hxx>
39
40 #include <BRep_Builder.hxx>
41 #include <BRep_Tool.hxx>
42 #include <BRepAdaptor_Curve.hxx>
43 #include <BRepAlgo_FaceRestrictor.hxx>
44 #include <BRepBuilderAPI_Copy.hxx>
45 #include <BRepBuilderAPI_Sewing.hxx>
46 #include <BRepBuilderAPI_MakeFace.hxx>
47 #include <BRepBuilderAPI_MakeWire.hxx>
48 #include <BRepBuilderAPI_MakeEdge.hxx>
49 #include <BRepBuilderAPI_MakeSolid.hxx>
50 #include <BRepCheck.hxx>
51 #include <BRepCheck_Analyzer.hxx>
52 #include <BRepCheck_Shell.hxx>
53 #include <BRepClass3d_SolidClassifier.hxx>
54 #include <BRepLib.hxx>
55 #include <BRepLib_MakeEdge.hxx>
56 #include <BRepTools_WireExplorer.hxx>
57
58 #include <ShapeAnalysis.hxx>
59 #include <ShapeAnalysis_FreeBounds.hxx>
60
61 #include <TopAbs.hxx>
62 #include <TopExp.hxx>
63 #include <TopExp_Explorer.hxx>
64 #include <TopoDS.hxx>
65 #include <TopoDS_Shape.hxx>
66 #include <TopoDS_Edge.hxx>
67 #include <TopoDS_Wire.hxx>
68 #include <TopoDS_Shell.hxx>
69 #include <TopoDS_Solid.hxx>
70 #include <TopoDS_Compound.hxx>
71 #include <TopoDS_Iterator.hxx>
72
73 #include <TopTools_MapOfShape.hxx>
74 #include <TopTools_HSequenceOfShape.hxx>
75
76 #include <ElCLib.hxx>
77
78 #include <GCPnts_AbscissaPoint.hxx>
79
80 #include <Geom_TrimmedCurve.hxx>
81 #include <Geom_RectangularTrimmedSurface.hxx>
82 #include <Geom_Surface.hxx>
83 #include <GeomAbs_CurveType.hxx>
84 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
85 #include <GeomConvert.hxx>
86 #include <GeomLProp.hxx>
87
88 #include <TColStd_SequenceOfReal.hxx>
89 #include <TColStd_HSequenceOfTransient.hxx>
90 #include <TColStd_Array1OfReal.hxx>
91 #include <TColGeom_SequenceOfCurve.hxx>
92 #include <TColGeom_Array1OfBSplineCurve.hxx>
93 #include <TColGeom_HArray1OfBSplineCurve.hxx>
94
95 #include <Precision.hxx>
96
97 #include <Standard_NullObject.hxx>
98 #include <Standard_TypeMismatch.hxx>
99 #include <Standard_ConstructionError.hxx>
100
101 #include <BOPAlgo_PaveFiller.hxx>
102 #include <BOPAlgo_MakerVolume.hxx>
103
104 #include <list>
105
106 //modified by NIZNHY-PKV Wed Dec 28 13:48:20 2011f
107 //static
108 //  void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
109 //                    const Handle(TopTools_HSequenceOfShape)& aWires);
110 //modified by NIZNHY-PKV Wed Dec 28 13:48:23 2011t
111
112 //=======================================================================
113 //function : GetID
114 //purpose  :
115 //=======================================================================
116 const Standard_GUID& GEOMImpl_ShapeDriver::GetID()
117 {
118   static Standard_GUID aShapeDriver("FF1BBB54-5D14-4df2-980B-3A668264EA16");
119   return aShapeDriver;
120 }
121
122
123 //=======================================================================
124 //function : GEOMImpl_ShapeDriver
125 //purpose  :
126 //=======================================================================
127 GEOMImpl_ShapeDriver::GEOMImpl_ShapeDriver()
128 {
129 }
130
131 //=======================================================================
132 //function : Execute
133 //purpose  :
134 //=======================================================================
135 Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
136 {
137   if (Label().IsNull()) return 0;
138   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
139
140   GEOMImpl_IShapes aCI (aFunction);
141   Standard_Integer aType = aFunction->GetType();
142
143   TopoDS_Shape aShape;
144   TCollection_AsciiString aWarning;
145   std::list<TopAbs_ShapeEnum> anExpectedType;
146
147   BRep_Builder B;
148
149   if (aType == WIRE_EDGES) {
150     anExpectedType.push_back(TopAbs_WIRE);
151
152     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
153
154     Standard_Real aTolerance = aCI.GetTolerance();
155     if (aTolerance < Precision::Confusion())
156       aTolerance = Precision::Confusion();
157
158     aShape = MakeWireFromEdges(aShapes, aTolerance);
159   }
160   else if (aType == FACE_WIRE) {
161     anExpectedType.push_back(TopAbs_FACE);
162
163     Handle(GEOM_Function) aRefBase = aCI.GetBase();
164     TopoDS_Shape aShapeBase = aRefBase->GetValue();
165     if (aShapeBase.IsNull()) Standard_NullObject::Raise("Argument Shape is null");
166     TopoDS_Wire W;
167     if (aShapeBase.ShapeType() == TopAbs_WIRE) {
168       W = TopoDS::Wire(aShapeBase);
169       // check the wire is closed
170       TopoDS_Vertex aV1, aV2;
171       TopExp::Vertices(W, aV1, aV2);
172       if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
173         aShapeBase.Closed(true);
174       else
175         Standard_NullObject::Raise
176           ("Shape for face construction is not closed");
177     }
178     else if (aShapeBase.ShapeType() == TopAbs_EDGE && aShapeBase.Closed()) {
179       BRepBuilderAPI_MakeWire MW;
180       MW.Add(TopoDS::Edge(aShapeBase));
181       if (!MW.IsDone()) {
182         Standard_ConstructionError::Raise("Wire construction failed");
183       }
184       W = MW;
185     }
186     else {
187       Standard_NullObject::Raise
188         ("Shape for face construction is neither a wire nor a closed edge");
189     }
190     aWarning = GEOMImpl_Block6Explorer::MakeFace(W, aCI.GetIsPlanar(), aShape);
191     if (aShape.IsNull()) {
192       Standard_ConstructionError::Raise("Face construction failed");
193     }
194   }
195   else if (aType == FACE_WIRES) {
196     anExpectedType.push_back(TopAbs_FACE);
197
198     // Try to build a face from a set of wires and edges
199     int ind;
200
201     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
202     int nbshapes = aShapes->Length();
203     if (nbshapes < 1) {
204       Standard_ConstructionError::Raise("No wires or edges given");
205     }
206
207     // 1. Extract all edges from the given arguments
208     TopTools_MapOfShape aMapEdges;
209     Handle(TopTools_HSequenceOfShape) aSeqEdgesIn = new TopTools_HSequenceOfShape;
210
211     for (ind = 1; ind <= nbshapes; ind++) {
212       Handle(GEOM_Function) aRefSh_i = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
213       TopoDS_Shape aSh_i = aRefSh_i->GetValue();
214
215       TopExp_Explorer anExpE_i (aSh_i, TopAbs_EDGE);
216       for (; anExpE_i.More(); anExpE_i.Next()) {
217         if (aMapEdges.Add(anExpE_i.Current())) {
218           aSeqEdgesIn->Append(anExpE_i.Current());
219         }
220       }
221     }
222
223     if (aSeqEdgesIn->IsEmpty()) {
224       Standard_ConstructionError::Raise("No edges given");
225     }
226
227     // 2. Connect edges to wires of maximum length
228     Handle(TopTools_HSequenceOfShape) aSeqWiresOut;
229     ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdgesIn, Precision::Confusion(),
230                                                   /*shared*/Standard_False, aSeqWiresOut);
231     //modified by NIZNHY-PKV Wed Dec 28 13:46:55 2011f
232     //KeepEdgesOrder(aSeqEdgesIn, aSeqWiresOut);
233     //modified by NIZNHY-PKV Wed Dec 28 13:46:59 2011t
234
235     // 3. Separate closed wires
236     Handle(TopTools_HSequenceOfShape) aSeqClosedWires = new TopTools_HSequenceOfShape;
237     Handle(TopTools_HSequenceOfShape) aSeqOpenWires = new TopTools_HSequenceOfShape;
238     for (ind = 1; ind <= aSeqWiresOut->Length(); ind++) {
239       if (aSeqWiresOut->Value(ind).Closed())
240         aSeqClosedWires->Append(aSeqWiresOut->Value(ind));
241       else
242         aSeqOpenWires->Append(aSeqWiresOut->Value(ind));
243     }
244
245     if (aSeqClosedWires->Length() < 1) {
246       Standard_ConstructionError::Raise
247         ("There is no closed contour can be built from the given arguments");
248     }
249
250     // 4. Build a face / list of faces from all the obtained closed wires
251
252     // 4.a. Basic face
253     TopoDS_Shape aFFace;
254     TopoDS_Wire aW1 = TopoDS::Wire(aSeqClosedWires->Value(1));
255     aWarning = GEOMImpl_Block6Explorer::MakeFace(aW1, aCI.GetIsPlanar(), aFFace);
256     if (aFFace.IsNull()) {
257       Standard_ConstructionError::Raise("Face construction failed");
258     }
259
260     // 4.b. Add other wires
261     if (aSeqClosedWires->Length() == 1) {
262       aShape = aFFace;
263     }
264     else {
265       TopoDS_Compound C;
266       BRep_Builder aBuilder;
267       aBuilder.MakeCompound(C);
268       BRepAlgo_FaceRestrictor FR;
269
270       TopAbs_Orientation OriF = aFFace.Orientation();
271       TopoDS_Shape aLocalS = aFFace.Oriented(TopAbs_FORWARD);
272       FR.Init(TopoDS::Face(aLocalS), Standard_False, Standard_True);
273
274       for (ind = 1; ind <= aSeqClosedWires->Length(); ind++) {
275         TopoDS_Wire aW = TopoDS::Wire(aSeqClosedWires->Value(ind));
276         FR.Add(aW);
277       }
278
279       FR.Perform();
280
281       if (FR.IsDone()) {
282         int k = 0;
283         TopoDS_Shape aFace;
284         for (; FR.More(); FR.Next()) {
285           aFace = FR.Current().Oriented(OriF);
286           aBuilder.Add(C, aFace);
287           k++;
288         }
289         if (k == 1) {
290           aShape = aFace;
291         } else {
292           aShape = C;
293         }
294       }
295     }
296
297     // 5. Add all open wires to the result
298     if (aSeqOpenWires->Length() > 0) {
299       //Standard_ConstructionError::Raise("There are some open wires");
300       TopoDS_Compound C;
301       BRep_Builder aBuilder;
302       if (aSeqClosedWires->Length() == 1) {
303         aBuilder.MakeCompound(C);
304         aBuilder.Add(C, aShape);
305       }
306       else {
307         C = TopoDS::Compound(aShape);
308       }
309
310       for (ind = 1; ind <= aSeqOpenWires->Length(); ind++) {
311         aBuilder.Add(C, aSeqOpenWires->Value(ind));
312       }
313
314       aShape = C;
315     }
316   }
317   else if (aType == FACE_FROM_SURFACE) {
318     anExpectedType.push_back(TopAbs_FACE);
319
320     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
321
322     if (aShapes.IsNull() == Standard_False) {
323       Standard_Integer aNbShapes = aShapes->Length();
324
325       if (aNbShapes == 2) {
326         Handle(GEOM_Function) aRefFace =
327           Handle(GEOM_Function)::DownCast(aShapes->Value(1));
328         Handle(GEOM_Function) aRefWire =
329           Handle(GEOM_Function)::DownCast(aShapes->Value(2));
330
331         if (aRefFace.IsNull() == Standard_False &&
332             aRefWire.IsNull() == Standard_False) {
333           TopoDS_Shape aShFace = aRefFace->GetValue();
334           TopoDS_Shape aShWire = aRefWire->GetValue();
335
336           if (aShFace.IsNull()    == Standard_False &&
337               aShFace.ShapeType() == TopAbs_FACE    &&
338               aShWire.IsNull()    == Standard_False &&
339               aShWire.ShapeType() == TopAbs_WIRE) {
340             TopoDS_Face             aFace = TopoDS::Face(aShFace);
341             TopoDS_Wire             aWire = TopoDS::Wire(aShWire);
342             Handle(Geom_Surface)    aSurf = BRep_Tool::Surface(aFace);
343             BRepBuilderAPI_MakeFace aMkFace(aSurf, aWire);
344
345             if (aMkFace.IsDone()) {
346               aShape = aMkFace.Shape();
347             }
348           }
349         }
350       }
351     }
352   }
353   else if (aType == SHELL_FACES) {
354     anExpectedType.push_back(TopAbs_SHELL);
355
356     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
357     unsigned int ind, nbshapes = aShapes->Length();
358
359     // add faces
360     BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0);
361     for (ind = 1; ind <= nbshapes; ind++) {
362       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
363       TopoDS_Shape aShape_i = aRefShape->GetValue();
364       if (aShape_i.IsNull()) {
365         Standard_NullObject::Raise("Face for shell construction is null");
366       }
367       aSewing.Add(aShape_i);
368     }
369
370     aSewing.Perform();
371
372     TopoDS_Shape sh = aSewing.SewedShape();
373
374     if (sh.ShapeType()==TopAbs_FACE && nbshapes==1) {
375       // case for creation of shell from one face - PAL12722 (skl 26.06.2006)
376       TopoDS_Shell ss;
377       B.MakeShell(ss);
378       B.Add(ss,sh);
379       aShape = ss;
380     }
381     else {
382       //TopExp_Explorer exp (aSewing.SewedShape(), TopAbs_SHELL);
383       TopExp_Explorer exp (sh, TopAbs_SHELL);
384       Standard_Integer ish = 0;
385       for (; exp.More(); exp.Next()) {
386         aShape = exp.Current();
387         ish++;
388       }
389
390       if (ish != 1) {
391         // try the case of one face (Mantis issue 0021809)
392         TopExp_Explorer expF (sh, TopAbs_FACE);
393         Standard_Integer ifa = 0;
394         for (; expF.More(); expF.Next()) {
395           aShape = expF.Current();
396           ifa++;
397         }
398
399         if (ifa == 1) {
400           TopoDS_Shell ss;
401           B.MakeShell(ss);
402           B.Add(ss,aShape);
403           aShape = ss;
404         }
405         else {
406           aShape = aSewing.SewedShape();
407         }
408       }
409     }
410
411   }
412   else if (aType == SOLID_SHELLS) {
413     anExpectedType.push_back(TopAbs_SOLID);
414
415     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
416     unsigned int ind, nbshapes = aShapes->Length();
417     Standard_Integer ish = 0;
418     BRepBuilderAPI_MakeSolid aMkSolid;
419
420     // add shapes
421     for (ind = 1; ind <= nbshapes; ind++) {
422       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
423       TopoDS_Shape aShapeShell = aRefShape->GetValue();
424       if (aShapeShell.IsNull()) {
425         Standard_NullObject::Raise("Shell for solid construction is null");
426       }
427       if (aShapeShell.ShapeType() == TopAbs_COMPOUND) {
428         TopoDS_Iterator It (aShapeShell, Standard_True, Standard_True);
429         if (It.More()) aShapeShell = It.Value();
430       }
431       if (aShapeShell.ShapeType() == TopAbs_SHELL) {
432         aMkSolid.Add(TopoDS::Shell(aShapeShell));
433         ish++;
434       }
435     }
436     if (ish == 0 || !aMkSolid.IsDone()) return 0;
437
438     TopoDS_Solid Sol = aMkSolid.Solid();
439     BRepClass3d_SolidClassifier SC (Sol);
440     SC.PerformInfinitePoint(Precision::Confusion());
441     if (SC.State() == TopAbs_IN)
442       aShape = Sol.Reversed();
443     else
444       aShape = Sol;
445   }
446   else if (aType == COMPOUND_SHAPES) {
447     anExpectedType.push_back(TopAbs_COMPOUND);
448
449     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
450     unsigned int ind, nbshapes = aShapes->Length();
451
452     // add shapes
453     TopoDS_Compound C;
454     B.MakeCompound(C);
455     for (ind = 1; ind <= nbshapes; ind++) {
456       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
457       TopoDS_Shape aShape_i = aRefShape->GetValue();
458       if (aShape_i.IsNull()) {
459         Standard_NullObject::Raise("Shape for compound construction is null");
460       }
461       B.Add(C, aShape_i);
462     }
463
464     aShape = C;
465
466   }
467   else if (aType == EDGE_WIRE) {
468     anExpectedType.push_back(TopAbs_EDGE);
469
470     Handle(GEOM_Function) aRefBase = aCI.GetBase();
471     TopoDS_Shape aWire = aRefBase->GetValue();
472     Standard_Real LinTol = aCI.GetTolerance();
473     Standard_Real AngTol = aCI.GetAngularTolerance();
474     if (aWire.IsNull()) Standard_NullObject::Raise("Argument Wire is null");
475
476     aShape = MakeEdgeFromWire(aWire, LinTol, AngTol);
477   }
478   else if (aType == SOLID_FACES) {
479     anExpectedType.push_back(TopAbs_SOLID);
480     anExpectedType.push_back(TopAbs_COMPOUND);
481     anExpectedType.push_back(TopAbs_COMPSOLID);
482     
483     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
484     unsigned int ind, nbshapes = aShapes->Length();
485     
486     // add faces
487     BOPCol_ListOfShape aLS;
488     for (ind = 1; ind <= nbshapes; ind++) {
489       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
490       TopoDS_Shape aShape_i = aRefShape->GetValue();
491       if (aShape_i.IsNull()) {
492         Standard_NullObject::Raise("Shape for solid construction is null");
493       }
494       aLS.Append(aShape_i);
495     }
496
497     BOPAlgo_MakerVolume aMV;
498     aMV.SetArguments(aLS);
499     aMV.SetIntersect(aCI.GetIsIntersect());
500     aMV.Perform();
501     if (aMV.ErrorStatus()) return 0;
502
503     aShape = aMV.Shape();
504   }
505   else if (aType == EDGE_CURVE_LENGTH) {
506     anExpectedType.push_back(TopAbs_EDGE);
507
508     GEOMImpl_IVector aVI (aFunction);
509
510     // RefCurve
511     Handle(GEOM_Function) aRefCurve = aVI.GetPoint1();
512     if (aRefCurve.IsNull()) Standard_NullObject::Raise("Argument Curve is null");
513     TopoDS_Shape aRefShape1 = aRefCurve->GetValue();
514     if (aRefShape1.ShapeType() != TopAbs_EDGE) {
515       Standard_TypeMismatch::Raise
516         ("Edge On Curve creation aborted : curve shape is not an edge");
517     }
518     TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
519     TopoDS_Vertex V1, V2;
520     TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
521
522     // RefPoint
523     TopoDS_Vertex aRefVertex;
524     Handle(GEOM_Function) aRefPoint = aVI.GetPoint2();
525     if (aRefPoint.IsNull()) {
526       aRefVertex = V1;
527     }
528     else {
529       TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
530       if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
531         Standard_TypeMismatch::Raise
532           ("Edge On Curve creation aborted : start point shape is not a vertex");
533       }
534       aRefVertex = TopoDS::Vertex(aRefShape2);
535     }
536     gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
537
538     // Length
539     Standard_Real aLength = aVI.GetParameter();
540     //Standard_Real aCurveLength = IntTools::Length(aRefEdge);
541     //if (aLength > aCurveLength) {
542     //  Standard_ConstructionError::Raise
543     //    ("Edge On Curve creation aborted : given length is greater than edges length");
544     //}
545     if (fabs(aLength) < Precision::Confusion()) {
546       Standard_ConstructionError::Raise
547         ("Edge On Curve creation aborted : given length is smaller than Precision::Confusion()");
548     }
549
550     // Check orientation
551     Standard_Real UFirst, ULast;
552     Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
553     Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
554
555     Standard_Real dU = ULast - UFirst;
556     Standard_Real par1 = UFirst + 0.1 * dU;
557     Standard_Real par2 = ULast  - 0.1 * dU;
558
559     gp_Pnt P1 = EdgeCurve->Value(par1);
560     gp_Pnt P2 = EdgeCurve->Value(par2);
561
562     if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
563       ReOrientedCurve = EdgeCurve->Reversed();
564       UFirst = EdgeCurve->ReversedParameter(ULast);
565     }
566
567     // Get the point by length
568     GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
569     GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst);
570     Standard_Real aParam = anAbsPnt.Parameter();
571
572     if (AdapCurve.IsClosed() && aLength < 0.0) {
573       Standard_Real aTmp = aParam;
574       aParam = UFirst;
575       UFirst = aTmp;
576     }
577
578     BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam);
579     if (aME.IsDone())
580       aShape = aME.Shape();
581   } else if (aType == SHAPE_ISOLINE) {
582     GEOMImpl_IIsoline     aII (aFunction);
583     Handle(GEOM_Function) aRefFace = aII.GetFace();
584     TopoDS_Shape          aShapeFace = aRefFace->GetValue();
585
586     if (aShapeFace.ShapeType() == TopAbs_FACE) {
587       TopoDS_Face   aFace  = TopoDS::Face(aShapeFace);
588       bool          isUIso = aII.GetIsUIso();
589       Standard_Real aParam = aII.GetParameter();
590       Standard_Real U1,U2,V1,V2;
591
592       // Construct a real geometric parameter.
593       aFace.Orientation(TopAbs_FORWARD);
594       ShapeAnalysis::GetFaceUVBounds(aFace,U1,U2,V1,V2);
595
596       if (isUIso) {
597         aParam = U1 + (U2 - U1)*aParam;
598       } else {
599         aParam = V1 + (V2 - V1)*aParam;
600       }
601
602       aShape = MakeIsoline(aFace, isUIso, aParam);
603     } else {
604       Standard_NullObject::Raise
605         ("Shape for isoline construction is not a face");
606     }
607   } else if (aType == EDGE_UV) {
608     anExpectedType.push_back(TopAbs_EDGE);
609     GEOMImpl_IShapeExtend aSE (aFunction);
610     Handle(GEOM_Function) aRefEdge   = aSE.GetShape();
611     TopoDS_Shape          aShapeEdge = aRefEdge->GetValue();
612
613     if (aShapeEdge.ShapeType() == TopAbs_EDGE) {
614       TopoDS_Edge anEdge = TopoDS::Edge(aShapeEdge);
615
616       aShape = ExtendEdge(anEdge, aSE.GetUMin(), aSE.GetUMax());
617     }
618   } else if (aType == FACE_UV) {
619     anExpectedType.push_back(TopAbs_FACE);
620
621     GEOMImpl_IShapeExtend aSE (aFunction);
622     Handle(GEOM_Function) aRefFace   = aSE.GetShape();
623     TopoDS_Shape          aShapeFace = aRefFace->GetValue();
624
625     if (aShapeFace.ShapeType() == TopAbs_FACE) {
626       TopoDS_Face aFace = TopoDS::Face(aShapeFace);
627
628       aFace.Orientation(TopAbs_FORWARD);
629       aShape = ExtendFace(aFace, aSE.GetUMin(), aSE.GetUMax(),
630                           aSE.GetVMin(), aSE.GetVMax()); 
631     }
632   } else if (aType == SURFACE_FROM_FACE) {
633     anExpectedType.push_back(TopAbs_FACE);
634
635     GEOMImpl_IShapeExtend aSE (aFunction);
636     Handle(GEOM_Function) aRefFace   = aSE.GetShape();
637     TopoDS_Shape          aShapeFace = aRefFace->GetValue();
638
639     if (aShapeFace.ShapeType() == TopAbs_FACE) {
640       TopoDS_Face          aFace    = TopoDS::Face(aShapeFace);
641       Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
642
643       if (aSurface.IsNull() == Standard_False) {
644         Handle(Standard_Type) aType = aSurface->DynamicType();
645         Standard_Real         aU1;
646         Standard_Real         aU2;
647         Standard_Real         aV1;
648         Standard_Real         aV2;
649
650          // Get U, V bounds of the face.
651         aFace.Orientation(TopAbs_FORWARD);
652         ShapeAnalysis::GetFaceUVBounds(aFace, aU1, aU2, aV1, aV2);
653
654         // Get the surface of original type
655         while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
656           Handle(Geom_RectangularTrimmedSurface) aTrSurface =
657             Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
658
659           aSurface = aTrSurface->BasisSurface();
660           aType    = aSurface->DynamicType();
661         }
662
663         const Standard_Real     aTol = BRep_Tool::Tolerance(aFace);
664         BRepBuilderAPI_MakeFace aMF(aSurface, aU1, aU2, aV1, aV2, aTol);
665
666         if (aMF.IsDone()) {
667           aShape = aMF.Shape();
668         }
669       }
670     }
671   }
672   else {
673   }
674
675   if (aShape.IsNull()) return 0;
676
677   // Check shape validity
678   BRepCheck_Analyzer ana (aShape, false);
679   if (!ana.IsValid()) {
680     //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
681     // For Mantis issue 0021772: EDF 2336 GEOM: Non valid face created from two circles
682     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShape);
683     aSfs->Perform();
684     aShape = aSfs->Shape();
685   }
686
687   // Check if the result shape type is compatible with the expected.
688   const TopAbs_ShapeEnum aShType = aShape.ShapeType();
689
690   if (!anExpectedType.empty()) {
691     bool ok = false;
692     std::list<TopAbs_ShapeEnum>::const_iterator it;
693     for (it = anExpectedType.begin(); it != anExpectedType.end() && !ok; ++it)
694       ok = (*it == TopAbs_SHAPE || *it == aShType);
695     if (!ok)
696       Standard_ConstructionError::Raise("Result type check failed");
697   }
698
699   aFunction->SetValue(aShape);
700
701   log.SetTouched(Label());
702
703   if (!aWarning.IsEmpty())
704     Standard_Failure::Raise(aWarning.ToCString());
705
706   return 1;
707 }
708
709 TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
710                                                     const Standard_Real theTolerance)
711 {
712   BRep_Builder B;
713
714   TopoDS_Wire aWire;
715   B.MakeWire(aWire);
716
717   // add edges
718   for (unsigned int ind = 1; ind <= theEdgesFuncs->Length(); ind++) {
719     Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->Value(ind));
720     TopoDS_Shape aShape_i = aRefShape->GetValue();
721     if (aShape_i.IsNull()) {
722       Standard_NullObject::Raise("Shape for wire construction is null");
723     }
724     if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
725       TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
726       for (; exp.More(); exp.Next())
727         B.Add(aWire, TopoDS::Edge(exp.Current()));
728     } else {
729       Standard_TypeMismatch::Raise
730         ("Shape for wire construction is neither an edge nor a wire");
731     }
732   }
733
734   // fix edges order
735   Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
736   aFW->Load(aWire);
737   aFW->FixReorder();
738
739   if (aFW->StatusReorder(ShapeExtend_FAIL1)) {
740     Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
741   }
742   else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
743     Standard_ConstructionError::Raise("Wire construction failed");
744   }
745   else {
746   }
747
748   // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
749   aFW->ClosedWireMode() = Standard_False;
750   aFW->FixConnected(theTolerance);
751   if (aFW->StatusConnected(ShapeExtend_FAIL)) {
752     Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
753   }
754   // IMP 0019766
755   if (aFW->StatusConnected(ShapeExtend_DONE3)) {
756     // Confused with <prec> but not Analyzer.Precision(), set the same
757     aFW->FixGapsByRangesMode() = Standard_True;
758     if (aFW->FixGaps3d()) {
759       Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
760       Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge;
761       for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) {
762         TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge));
763         aFe->FixVertexTolerance(aEdge);
764         aFe->FixSameParameter(aEdge);
765       }
766     }
767     else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) {
768       Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps");
769     }
770   }
771   aWire = aFW->WireAPIMake();
772
773   return aWire;
774 }
775
776 TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire,
777                                                    const Standard_Real LinTol,
778                                                    const Standard_Real AngTol)
779 {
780     TopoDS_Edge ResEdge;
781
782     BRepLib::BuildCurves3d(aWire);
783     Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(aWire);
784     Fixer->SetPrecision(LinTol);
785     Fixer->SetMaxTolerance(LinTol);
786     Fixer->Perform();
787     TopoDS_Wire theWire = TopoDS::Wire(Fixer->Shape());
788
789     TColGeom_SequenceOfCurve CurveSeq;
790     TopTools_SequenceOfShape LocSeq;
791     TColStd_SequenceOfReal FparSeq;
792     TColStd_SequenceOfReal LparSeq;
793     TColStd_SequenceOfReal TolSeq;
794     GeomAbs_CurveType CurType;
795     TopoDS_Vertex FirstVertex, LastVertex;
796     Standard_Real aPntShiftDist = 0.;
797
798     BRepTools_WireExplorer wexp(theWire) ;
799     for (; wexp.More(); wexp.Next())
800     {
801       TopoDS_Edge anEdge = wexp.Current();
802       Standard_Real fpar, lpar;
803       TopLoc_Location aLoc;
804       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
805       if (aCurve.IsNull())
806         continue;
807
808       BRepAdaptor_Curve BAcurve(anEdge);
809       GeomAbs_CurveType aType = BAcurve.GetType();
810
811       Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
812
813       if (aBasisCurve->IsPeriodic())
814         ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
815                                Precision::PConfusion(), fpar, lpar);
816
817       if (CurveSeq.IsEmpty())
818       {
819         CurveSeq.Append(aCurve);
820         TopoDS_Shape aLocShape;
821         aLocShape.Location(aLoc);
822         aLocShape.Orientation(wexp.Orientation());
823         LocSeq.Append(aLocShape);
824         FparSeq.Append(fpar);
825         LparSeq.Append(lpar);
826         CurType = aType;
827         FirstVertex = wexp.CurrentVertex();
828       }
829       else
830       {
831         Standard_Boolean Done = Standard_False;
832         Standard_Real NewFpar, NewLpar;
833         GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
834         TopoDS_Vertex CurVertex = wexp.CurrentVertex();
835         TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
836         TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
837         if (aCurve == CurveSeq.Last())
838         {
839           NewFpar = fpar;
840           NewLpar = lpar;
841           if (aBasisCurve->IsPeriodic())
842           {
843             if (NewLpar < NewFpar)
844               NewLpar += aBasisCurve->Period();
845             if (ConnectByOrigin == TopAbs_FORWARD)
846               ElCLib::AdjustPeriodic(FparSeq.Last(),
847                                      FparSeq.Last() + aBasisCurve->Period(),
848                                      Precision::PConfusion(), NewFpar, NewLpar);
849             else
850               ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
851                                      FparSeq.Last(),
852                                      Precision::PConfusion(), NewFpar, NewLpar);
853           }
854           Done = Standard_True;
855         }
856         else if (aType == CurType &&
857                  aType != GeomAbs_BezierCurve &&
858                  aType != GeomAbs_BSplineCurve &&
859                  aType != GeomAbs_OtherCurve)
860         {
861           switch (aType)
862           {
863           case GeomAbs_Line:
864             {
865               gp_Lin aLine    = BAcurve.Line();
866               gp_Lin PrevLine = GAprevcurve.Line();
867               if (aLine.Contains(PrevLine.Location(), LinTol) &&
868                   aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
869               {
870                 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
871                 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
872                 NewFpar = ElCLib::Parameter(PrevLine, P1);
873                 NewLpar = ElCLib::Parameter(PrevLine, P2);
874
875                 // Compute shift
876                 if (ConnectByOrigin == TopAbs_FORWARD) {
877                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevLine);
878
879                   aPntShiftDist += P2.Distance(aNewP2);
880                 } else {
881                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevLine);
882
883                   aPntShiftDist += P1.Distance(aNewP1);
884                 }
885
886                 if (NewLpar < NewFpar)
887                 {
888                   Standard_Real MemNewFpar = NewFpar;
889                   NewFpar = NewLpar;
890                   NewLpar = MemNewFpar;
891                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
892                 }
893                 Done = Standard_True;
894               }
895               break;
896             }
897           case GeomAbs_Circle:
898             {
899               gp_Circ aCircle    = BAcurve.Circle();
900               gp_Circ PrevCircle = GAprevcurve.Circle();
901               if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
902                   Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
903                   aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
904               {
905                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
906
907                 if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
908                 {
909                   Standard_Real memfpar = fpar;
910                   fpar = lpar;
911                   lpar = memfpar;
912                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
913                 }
914                 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
915                 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
916                 NewFpar = ElCLib::Parameter(PrevCircle, P1);
917                 NewLpar = ElCLib::Parameter(PrevCircle, P2);
918
919                 // Compute shift
920                 if (isFwd) {
921                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevCircle);
922
923                   aPntShiftDist += P2.Distance(aNewP2);
924                 } else {
925                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevCircle);
926
927                   aPntShiftDist += P1.Distance(aNewP1);
928                 }
929
930                 if (NewLpar < NewFpar)
931                   NewLpar += 2.*M_PI;
932                 //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
933                 if (ConnectByOrigin == TopAbs_FORWARD)
934                   ElCLib::AdjustPeriodic(FparSeq.Last(),
935                                          FparSeq.Last() + 2.*M_PI,
936                                          Precision::PConfusion(), NewFpar, NewLpar);
937                 else
938                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
939                                          FparSeq.Last(),
940                                          Precision::PConfusion(), NewFpar, NewLpar);
941                 Done = Standard_True;
942               }
943               break;
944             }
945           case GeomAbs_Ellipse:
946             {
947               gp_Elips anEllipse   = BAcurve.Ellipse();
948               gp_Elips PrevEllipse = GAprevcurve.Ellipse();
949               if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
950                   anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
951                   Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
952                   Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
953                   anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
954               {
955                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
956
957                 if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
958                 {
959                   Standard_Real memfpar = fpar;
960                   fpar = lpar;
961                   lpar = memfpar;
962                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
963                 }
964                 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
965                 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
966                 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
967                 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
968
969                 // Compute shift
970                 if (isFwd) {
971                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevEllipse);
972
973                   aPntShiftDist += P2.Distance(aNewP2);
974                 } else {
975                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevEllipse);
976
977                   aPntShiftDist += P1.Distance(aNewP1);
978                 }
979
980                 if (NewLpar < NewFpar)
981                   NewLpar += 2.*M_PI;
982                 if (ConnectByOrigin == TopAbs_FORWARD)
983                   ElCLib::AdjustPeriodic(FparSeq.Last(),
984                                          FparSeq.Last() + 2.*M_PI,
985                                          Precision::PConfusion(), NewFpar, NewLpar);
986                 else
987                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
988                                          FparSeq.Last(),
989                                          Precision::PConfusion(), NewFpar, NewLpar);
990                 Done = Standard_True;
991               }
992               break;
993             }
994           case GeomAbs_Hyperbola:
995             {
996               gp_Hypr aHypr    = BAcurve.Hyperbola();
997               gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
998               if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
999                   aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
1000                   Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
1001                   Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
1002                   aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
1003               {
1004                 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
1005                 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
1006                 NewFpar = ElCLib::Parameter(PrevHypr, P1);
1007                 NewLpar = ElCLib::Parameter(PrevHypr, P2);
1008
1009                 // Compute shift
1010                 if (ConnectByOrigin == TopAbs_FORWARD) {
1011                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevHypr);
1012
1013                   aPntShiftDist += P2.Distance(aNewP2);
1014                 } else {
1015                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevHypr);
1016
1017                   aPntShiftDist += P1.Distance(aNewP1);
1018                 }
1019
1020                 if (NewLpar < NewFpar)
1021                 {
1022                   Standard_Real MemNewFpar = NewFpar;
1023                   NewFpar = NewLpar;
1024                   NewLpar = MemNewFpar;
1025                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1026                 }
1027                 Done = Standard_True;
1028               }
1029               break;
1030             }
1031           case GeomAbs_Parabola:
1032             {
1033               gp_Parab aParab    = BAcurve.Parabola();
1034               gp_Parab PrevParab = GAprevcurve.Parabola();
1035               if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
1036                   aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
1037                   Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
1038                   aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
1039               {
1040                 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
1041                 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
1042                 NewFpar = ElCLib::Parameter(PrevParab, P1);
1043                 NewLpar = ElCLib::Parameter(PrevParab, P2);
1044
1045                 // Compute shift
1046                 if (ConnectByOrigin == TopAbs_FORWARD) {
1047                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevParab);
1048
1049                   aPntShiftDist += P2.Distance(aNewP2);
1050                 } else {
1051                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevParab);
1052
1053                   aPntShiftDist += P1.Distance(aNewP1);
1054                 }
1055
1056                 if (NewLpar < NewFpar)
1057                 {
1058                   Standard_Real MemNewFpar = NewFpar;
1059                   NewFpar = NewLpar;
1060                   NewLpar = MemNewFpar;
1061                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1062                 }
1063                 Done = Standard_True;
1064               }
1065               break;
1066             }
1067           } //end of switch (aType)
1068         } // end of else if (aType == CurType && ...
1069         if (Done)
1070         {
1071           if (NewFpar < FparSeq.Last())
1072             FparSeq(FparSeq.Length()) = NewFpar;
1073           else
1074             LparSeq(LparSeq.Length()) = NewLpar;
1075         }
1076         else
1077         {
1078           CurveSeq.Append(aCurve);
1079           TopoDS_Shape aLocShape;
1080           aLocShape.Location(aLoc);
1081           aLocShape.Orientation(wexp.Orientation());
1082           LocSeq.Append(aLocShape);
1083           FparSeq.Append(fpar);
1084           LparSeq.Append(lpar);
1085           TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(CurVertex));
1086           aPntShiftDist = 0.;
1087           CurType = aType;
1088         }
1089       } // end of else (CurveSeq.IsEmpty()) -> not first time
1090     } // end for (; wexp.More(); wexp.Next())
1091
1092     LastVertex = wexp.CurrentVertex();
1093     TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(LastVertex));
1094
1095     FirstVertex.Orientation(TopAbs_FORWARD);
1096     LastVertex.Orientation(TopAbs_REVERSED);
1097
1098     if (!CurveSeq.IsEmpty())
1099     {
1100       Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
1101       TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
1102       TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
1103
1104       Standard_Integer i;
1105
1106       if (nb_curve > 1)
1107       {
1108         for (i = 1; i <= nb_curve; i++)
1109         {
1110           if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1111             CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
1112
1113           Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
1114           tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
1115           tab(i-1)->Transform(LocSeq(i).Location().Transformation());
1116           GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
1117           if (LocSeq(i).Orientation() == TopAbs_REVERSED)
1118             tab(i-1)->Reverse();
1119
1120           //Temporary
1121           //char* name = new char[100];
1122           //sprintf(name, "c%d", i);
1123           //DrawTrSurf::Set(name, tab(i-1));
1124
1125           if (i > 1)
1126             tabtolvertex(i-2) = TolSeq(i-1);
1127         } // end for (i = 1; i <= nb_curve; i++)
1128         tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length());
1129
1130         Standard_Boolean closed_flag = Standard_False;
1131         Standard_Real closed_tolerance = 0.;
1132         if (FirstVertex.IsSame(LastVertex) &&
1133             GeomLProp::Continuity(tab(0), tab(nb_curve-1),
1134                                   tab(0)->FirstParameter(),
1135                                   tab(nb_curve-1)->LastParameter(),
1136                                   Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
1137         {
1138           closed_flag = Standard_True ;
1139           closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
1140         }
1141
1142         Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
1143         Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
1144         GeomConvert::ConcatC1(tab,
1145                               tabtolvertex,
1146                               ArrayOfIndices,
1147                               concatcurve,
1148                               closed_flag,
1149                               closed_tolerance);   //C1 concatenation
1150
1151         if (concatcurve->Length() > 1)
1152         {
1153           GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
1154
1155           for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
1156             Concat.Add( concatcurve->Value(i), LinTol, Standard_True );
1157
1158           concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
1159         }
1160         // rnc : prevents the driver from building an edge without C1 continuity
1161         if (concatcurve->Value(concatcurve->Lower())->Continuity()==GeomAbs_C0){
1162           Standard_ConstructionError::Raise("Construction aborted : The given Wire has sharp bends between some Edges, no valid Edge can be built");
1163         }
1164
1165         Standard_Boolean isValidEndVtx = Standard_True;
1166
1167         if (closed_flag) {
1168           // Check if closed curve is reordered.
1169           Handle(Geom_Curve) aCurve  = concatcurve->Value(concatcurve->Lower());
1170           Standard_Real      aFPar   = aCurve->FirstParameter();
1171           gp_Pnt             aPFirst;
1172           gp_Pnt             aPntVtx = BRep_Tool::Pnt(FirstVertex);
1173           Standard_Real      aTolVtx = BRep_Tool::Tolerance(FirstVertex);
1174
1175           aCurve->D0(aFPar, aPFirst);
1176
1177           if (!aPFirst.IsEqual(aPntVtx, aTolVtx)) {
1178             // The curve is reordered. Find the new first and last vertices.
1179             TopTools_IndexedMapOfShape aMapVtx;
1180             TopExp::MapShapes(theWire, TopAbs_VERTEX, aMapVtx);
1181
1182             const Standard_Integer aNbVtx = aMapVtx.Extent();
1183             Standard_Integer       iVtx;
1184
1185             for (iVtx = 1; iVtx <= aNbVtx; iVtx++) {
1186               const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(iVtx));
1187               const gp_Pnt        aPnt = BRep_Tool::Pnt(aVtx);
1188               const Standard_Real aTol = BRep_Tool::Tolerance(aVtx);
1189
1190               if (aPFirst.IsEqual(aPnt, aTol)) {
1191                 // The coinsident vertex is found.
1192                 FirstVertex = aVtx;
1193                 LastVertex  = aVtx;
1194                 FirstVertex.Orientation(TopAbs_FORWARD);
1195                 LastVertex.Orientation(TopAbs_REVERSED);
1196                 break;
1197               }
1198             }
1199
1200             if (iVtx > aNbVtx) {
1201               // It is necessary to create new vertices.
1202               isValidEndVtx = Standard_False;
1203             }
1204           }
1205         }
1206
1207         if (isValidEndVtx) {
1208           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1209                                      FirstVertex, LastVertex,
1210                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1211                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1212         } else {
1213           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1214                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1215                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1216         }
1217       }
1218       else
1219       {
1220         if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1221           CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
1222
1223         Handle(Geom_Curve) aNewCurve =
1224           Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
1225
1226         aNewCurve->Transform(LocSeq(1).Location().Transformation());
1227
1228         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1229           const TopoDS_Vertex aVtxTmp = FirstVertex;
1230
1231           FirstVertex = LastVertex;
1232           LastVertex  = aVtxTmp;
1233           FirstVertex.Orientation(TopAbs_FORWARD);
1234           LastVertex.Orientation(TopAbs_REVERSED);
1235         }
1236
1237         ResEdge = BRepLib_MakeEdge(aNewCurve,
1238                                    FirstVertex, LastVertex,
1239                                    FparSeq(1), LparSeq(1));
1240
1241         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1242           ResEdge.Reverse();
1243         }
1244       }
1245     }
1246
1247     return ResEdge;
1248 }
1249
1250 //=============================================================================
1251 /*!
1252  * \brief Returns an isoline for a face.
1253  */
1254 //=============================================================================
1255
1256 TopoDS_Shape GEOMImpl_ShapeDriver::MakeIsoline
1257                             (const TopoDS_Face &theFace,
1258                              const bool         IsUIso,
1259                              const double       theParameter) const
1260 {
1261   TopoDS_Shape          aResult;
1262   GEOMUtils::Hatcher    aHatcher(theFace);
1263   const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV);
1264
1265   aHatcher.Init(aType, theParameter);
1266   aHatcher.Perform();
1267
1268   if (!aHatcher.IsDone()) {
1269     Standard_ConstructionError::Raise("MakeIsoline : Hatcher failure");
1270   }
1271
1272   const Handle(TColStd_HArray1OfInteger) &anIndices =
1273     (IsUIso ? aHatcher.GetUIndices() : aHatcher.GetVIndices());
1274
1275   if (anIndices.IsNull()) {
1276     Standard_ConstructionError::Raise("MakeIsoline : Null hatching indices");
1277   }
1278
1279   const Standard_Integer anIsoInd = anIndices->Lower();
1280   const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd);
1281
1282   if (aHatchingIndex == 0) {
1283     Standard_ConstructionError::Raise("MakeIsoline : Invalid hatching index");
1284   }
1285
1286   const Standard_Integer aNbDomains =
1287     aHatcher.GetNbDomains(aHatchingIndex);
1288
1289   if (aNbDomains < 0) {
1290     Standard_ConstructionError::Raise("MakeIsoline : Invalid number of domains");
1291   }
1292
1293   // The hatching is performed successfully. Create the 3d Curve.
1294   Handle(Geom_Surface) aSurface   = BRep_Tool::Surface(theFace);
1295   Handle(Geom_Curve)   anIsoCurve = (IsUIso ?
1296     aSurface->UIso(theParameter) : aSurface->VIso(theParameter));
1297   Handle(Geom2d_Curve) aPIsoCurve =
1298     aHatcher.GetHatching(aHatchingIndex);
1299   const Standard_Real  aTol = Precision::Confusion();
1300   Standard_Integer     anIDom = 1;
1301   Standard_Real        aV1;
1302   Standard_Real        aV2;
1303   BRep_Builder         aBuilder;
1304   Standard_Integer     aNbEdges = 0;
1305
1306   for (; anIDom <= aNbDomains; anIDom++) {
1307     if (aHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) {
1308       // Check first and last parameters.
1309       if (!aHatcher.IsDomainInfinite(aHatchingIndex, anIDom)) {
1310         // Create an edge.
1311         TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(anIsoCurve, aV1, aV2);
1312
1313         // Update it with a parametric curve on face.
1314         aBuilder.UpdateEdge(anEdge, aPIsoCurve, theFace, aTol);
1315         aNbEdges++;
1316
1317         if (aNbEdges > 1) {
1318           // Result is a compond.
1319           if (aNbEdges == 2) {
1320             // Create a new compound.
1321             TopoDS_Compound aCompound;
1322
1323             aBuilder.MakeCompound(aCompound);
1324             aBuilder.Add(aCompound, aResult);
1325             aResult = aCompound;
1326           }
1327
1328           // Add an edge to the compound.
1329           aBuilder.Add(aResult, anEdge);
1330         } else {
1331           // Result is the edge.
1332           aResult = anEdge;
1333         }
1334       }
1335     }
1336   }
1337
1338   if (aNbEdges == 0) {
1339     Standard_ConstructionError::Raise("MakeIsoline : Empty result");
1340   }
1341
1342   return aResult;
1343 }
1344
1345 //=============================================================================
1346 /*!
1347  * \brief Returns an extended edge.
1348  */
1349 //=============================================================================
1350
1351 TopoDS_Shape GEOMImpl_ShapeDriver::ExtendEdge
1352                          (const TopoDS_Edge   &theEdge,
1353                           const Standard_Real  theMin,
1354                           const Standard_Real  theMax) const
1355 {
1356   TopoDS_Shape        aResult;
1357   Standard_Real       aF;
1358   Standard_Real       aL;
1359   Handle(Geom_Curve)  aCurve   = BRep_Tool::Curve(theEdge, aF, aL);
1360   const Standard_Real aTol     = BRep_Tool::Tolerance(theEdge);
1361   Standard_Real       aRange2d = aL - aF;
1362
1363   if (aCurve.IsNull() == Standard_False && aRange2d > aTol) {
1364     Standard_Real aMin = aF + aRange2d*theMin;
1365     Standard_Real aMax = aF + aRange2d*theMax;
1366
1367     Handle(Standard_Type) aType = aCurve->DynamicType();
1368
1369     // Get the curve of original type
1370     while (aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
1371       Handle(Geom_TrimmedCurve) aTrCurve =
1372         Handle(Geom_TrimmedCurve)::DownCast(aCurve);
1373
1374       aCurve = aTrCurve->BasisCurve();
1375       aType  = aCurve->DynamicType();
1376     }
1377
1378     if (aCurve->IsPeriodic()) {
1379       // The curve is periodic. Check if a new range is less then a period.
1380       if (aMax - aMin > aCurve->Period()) {
1381         aMax = aMin + aCurve->Period();
1382       }
1383     } else {
1384       // The curve is not periodic. Check if aMin and aMax within bounds.
1385       aMin = Max(aMin, aCurve->FirstParameter());
1386       aMax = Min(aMax, aCurve->LastParameter());
1387     }
1388
1389     if (aMax - aMin > aTol) {
1390       // Create a new edge.
1391       BRepBuilderAPI_MakeEdge aME (aCurve, aMin, aMax);
1392
1393       if (aME.IsDone()) {
1394         aResult = aME.Shape();
1395       }
1396     }
1397   }
1398
1399   return aResult;
1400 }
1401
1402 //=============================================================================
1403 /*!
1404  * \brief Returns an extended face.
1405  */
1406 //=============================================================================
1407
1408 TopoDS_Shape GEOMImpl_ShapeDriver::ExtendFace
1409                          (const TopoDS_Face   &theFace,
1410                           const Standard_Real  theUMin,
1411                           const Standard_Real  theUMax,
1412                           const Standard_Real  theVMin,
1413                           const Standard_Real  theVMax) const
1414 {
1415   TopoDS_Shape         aResult;
1416   Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace);
1417   const Standard_Real  aTol     = BRep_Tool::Tolerance(theFace);
1418   Standard_Real        aU1;
1419   Standard_Real        aU2;
1420   Standard_Real        aV1;
1421   Standard_Real        aV2;
1422
1423   // Get U, V bounds of the face.
1424   ShapeAnalysis::GetFaceUVBounds(theFace, aU1, aU2, aV1, aV2);
1425
1426   const Standard_Real aURange = aU2 - aU1;
1427   const Standard_Real aVRange = aV2 - aV1;
1428
1429   if (aSurface.IsNull() == Standard_False &&
1430       aURange > aTol && aURange > aTol) {
1431     Handle(Standard_Type) aType = aSurface->DynamicType();
1432
1433     // Get the surface of original type
1434     while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1435       Handle(Geom_RectangularTrimmedSurface) aTrSurface =
1436         Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
1437
1438       aSurface = aTrSurface->BasisSurface();
1439       aType    = aSurface->DynamicType();
1440     }
1441
1442     Standard_Real aUMin = aU1 + aURange*theUMin;
1443     Standard_Real aUMax = aU1 + aURange*theUMax;
1444     Standard_Real aVMin = aV1 + aVRange*theVMin;
1445     Standard_Real aVMax = aV1 + aVRange*theVMax;
1446
1447     aSurface->Bounds(aU1, aU2, aV1, aV2);
1448
1449     if (aSurface->IsUPeriodic()) {
1450       // The surface is U-periodic. Check if a new U range is less
1451       // then a period.
1452       if (aUMax - aUMin > aSurface->UPeriod()) {
1453         aUMax = aUMin + aSurface->UPeriod();
1454       }
1455     } else {
1456       // The surface is not V-periodic. Check if aUMin and aUMax
1457       // within bounds.
1458       aUMin = Max(aUMin, aU1);
1459       aUMax = Min(aUMax, aU2);
1460     }
1461
1462     if (aSurface->IsVPeriodic()) {
1463       // The surface is V-periodic. Check if a new V range is less
1464       // then a period.
1465       if (aVMax - aVMin > aSurface->VPeriod()) {
1466         aVMax = aVMin + aSurface->VPeriod();
1467       }
1468     } else {
1469       // The surface is not V-periodic. Check if aVMin and aVMax
1470       // within bounds.
1471       aVMin = Max(aVMin, aV1);
1472       aVMax = Min(aVMax, aV2);
1473     }
1474
1475     if (aUMax - aUMin > aTol && aVMax - aVMin > aTol) {
1476       // Create a new edge.
1477       BRepBuilderAPI_MakeFace aMF
1478         (aSurface, aUMin, aUMax, aVMin, aVMax, aTol);
1479     
1480       if (aMF.IsDone()) {
1481         aResult = aMF.Shape();
1482       }
1483     }
1484   }
1485
1486   return aResult;
1487 }
1488
1489 //================================================================================
1490 /*!
1491  * \brief Returns a name of creation operation and names and values of creation parameters
1492  */
1493 //================================================================================
1494
1495 bool GEOMImpl_ShapeDriver::
1496 GetCreationInformation(std::string&             theOperationName,
1497                        std::vector<GEOM_Param>& theParams)
1498 {
1499   if (Label().IsNull()) return 0;
1500   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
1501
1502   GEOMImpl_IShapes aCI( function );
1503   Standard_Integer aType = function->GetType();
1504
1505   switch ( aType ) {
1506   case WIRE_EDGES:
1507     theOperationName = "WIRE";
1508     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1509     AddParam( theParams, "Tolerance", aCI.GetTolerance() );
1510     break;
1511   case FACE_WIRE:
1512     theOperationName = "FACE";
1513     AddParam( theParams, "Wire/edge", aCI.GetBase() );
1514     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1515     break;
1516   case FACE_WIRES:
1517     theOperationName = "FACE";
1518     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1519     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1520     break;
1521   case FACE_FROM_SURFACE:
1522   {
1523     theOperationName = "FACE";
1524
1525     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1526
1527     if (shapes.IsNull() == Standard_False) {
1528       Standard_Integer aNbShapes = shapes->Length();
1529
1530       if (aNbShapes > 0) {
1531         AddParam(theParams, "Face", shapes->Value(1));
1532
1533         if (aNbShapes > 1) {
1534           AddParam(theParams, "Wire", shapes->Value(2));
1535         }
1536       }
1537     }
1538     break;
1539   }
1540   case SHELL_FACES:
1541     theOperationName = "SHELL";
1542     AddParam( theParams, "Objects", aCI.GetShapes() );
1543     break;
1544   case SOLID_SHELLS:
1545     theOperationName = "SOLID";
1546     AddParam( theParams, "Objects", aCI.GetShapes() );
1547     break;
1548   case SOLID_FACES:
1549     theOperationName = "SOLID_FROM_FACES";
1550     AddParam( theParams, "Objects", aCI.GetShapes() );
1551     AddParam( theParams, "Is intersect", aCI.GetIsIntersect() );
1552     break;
1553   case COMPOUND_SHAPES:
1554     theOperationName = "COMPOUND";
1555     AddParam( theParams, "Objects", aCI.GetShapes() );
1556     break;
1557   case EDGE_WIRE:
1558     theOperationName = "EDGE";
1559     AddParam( theParams, "Wire", aCI.GetBase() );
1560     AddParam( theParams, "Linear Tolerance", aCI.GetTolerance() );
1561     AddParam( theParams, "Angular Tolerance", aCI.GetAngularTolerance() );
1562     break;
1563   case EDGE_CURVE_LENGTH:
1564     theOperationName = "EDGE";
1565     {
1566       GEOMImpl_IVector aCI( function );
1567       AddParam( theParams, "Edge", aCI.GetPoint1() );
1568       AddParam( theParams, "Start point", aCI.GetPoint2() );
1569       AddParam( theParams, "Length", aCI.GetParameter() );
1570     }
1571     break;
1572   case SHAPES_ON_SHAPE:
1573   {
1574     theOperationName = "GetShapesOnShapeAsCompound";
1575     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1576     if ( !shapes.IsNull() && shapes->Length() > 0 )
1577       AddParam( theParams, "Check shape", shapes->Value(1) );
1578     if ( !shapes.IsNull() && shapes->Length() > 1 )
1579       AddParam( theParams, "Shape", shapes->Value(2) );
1580     AddParam( theParams, "Shape type", TopAbs_ShapeEnum( aCI.GetSubShapeType() ));
1581     AddParam( theParams, "State", TopAbs_State((int) aCI.GetTolerance() ));
1582     break;
1583   }
1584   case SHAPE_ISOLINE:
1585   {
1586     GEOMImpl_IIsoline aII (function);
1587
1588     theOperationName = "ISOLINE";
1589     AddParam(theParams, "Face", aII.GetFace());
1590     AddParam(theParams, "Isoline type", (aII.GetIsUIso() ? "U" : "V"));
1591     AddParam(theParams, "Parameter", aII.GetParameter());
1592     break;
1593   }
1594   case EDGE_UV:
1595   {
1596     GEOMImpl_IShapeExtend aSE (function);
1597
1598     theOperationName = "EDGE_EXTEND";
1599     AddParam(theParams, "Edge", aSE.GetShape());
1600     AddParam(theParams, "Min", aSE.GetUMin());
1601     AddParam(theParams, "Max", aSE.GetUMax());
1602     break;
1603   }
1604   case FACE_UV:
1605   {
1606     GEOMImpl_IShapeExtend aSE (function);
1607
1608     theOperationName = "FACE_EXTEND";
1609     AddParam(theParams, "Face", aSE.GetShape());
1610     AddParam(theParams, "UMin", aSE.GetUMin());
1611     AddParam(theParams, "UMax", aSE.GetUMax());
1612     AddParam(theParams, "VMin", aSE.GetVMin());
1613     AddParam(theParams, "VMax", aSE.GetVMax());
1614     break;
1615   }
1616   case SURFACE_FROM_FACE:
1617   {
1618     GEOMImpl_IShapeExtend aSE (function);
1619
1620     theOperationName = "SURFACE_FROM_FACE";
1621     AddParam(theParams, "Face", aSE.GetShape());
1622     break;
1623   }
1624   default:
1625     return false;
1626   }
1627
1628   return true;
1629 }
1630
1631 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
1632 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
1633
1634 //modified by NIZNHY-PKV Wed Dec 28 13:48:31 2011f
1635 #include <TopoDS_Iterator.hxx>
1636 #include <TopTools_HSequenceOfShape.hxx>
1637 #include <ShapeAnalysis_FreeBounds.hxx>
1638 #include <TopTools_MapOfShape.hxx>
1639 #include <TopTools_MapOfOrientedShape.hxx>
1640 #include <BRep_Builder.hxx>
1641 #include <TopoDS_Wire.hxx>
1642
1643 //=======================================================================
1644 //function : KeepEdgesOrder
1645 //purpose  : 
1646 //=======================================================================
1647 /*
1648 void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
1649                     const Handle(TopTools_HSequenceOfShape)& aWires)
1650 {
1651   Standard_Integer aNbWires, aNbEdges;
1652   // 
1653   if (aEdges.IsNull()) {
1654     return;
1655   }
1656   //
1657   if (aWires.IsNull()) {
1658     return;
1659   }
1660   //
1661   aNbEdges=aEdges->Length();
1662   aNbWires=aWires->Length();
1663   if (!aNbEdges || !aNbWires) {
1664     return;
1665   }
1666   //-----
1667   Standard_Boolean bClosed;
1668   Standard_Integer i, j;
1669   TopoDS_Wire aWy;
1670   TopoDS_Iterator aIt;
1671   BRep_Builder aBB;
1672   TopTools_MapOfOrientedShape aMEx;
1673   //
1674   for (i=1; i<=aNbWires; ++i) {
1675     const TopoDS_Shape& aWx=aWires->Value(i);
1676     //
1677     aMEx.Clear();
1678     aIt.Initialize (aWx);
1679     for (; aIt.More(); aIt.Next()) {
1680       const TopoDS_Shape& aEx=aIt.Value();
1681       aMEx.Add(aEx);
1682     }
1683     // aWy
1684     aBB.MakeWire (aWy);
1685     for (j=1; j<=aNbEdges; ++j) {
1686       const TopoDS_Shape& aE=aEdges->Value(j);
1687       if (aMEx.Contains(aE)) {
1688         aBB.Add(aWy, aE);
1689       }
1690     }
1691     //
1692     bClosed=aWx.Closed();
1693     aWy.Closed(bClosed);
1694     //
1695     aWires->Append(aWy);
1696   }// for (i=1; i<=aNbWires; ++i) {
1697   //
1698   aWires->Remove(1, aNbWires);
1699 }
1700 */
1701 //modified by NIZNHY-PKV Wed Dec 28 13:48:34 2011t