]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
Salome HOME
22540: Fix the case if no edges are given
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ShapeDriver.cxx
1 // Copyright (C) 2007-2014  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_IVector.hxx>
28 #include <GEOMImpl_Types.hxx>
29 #include <GEOMImpl_Block6Explorer.hxx>
30
31 #include <GEOM_Function.hxx>
32 #include <GEOMUtils_Hatcher.hxx>
33
34 // OCCT Includes
35 #include <ShapeFix_Wire.hxx>
36 #include <ShapeFix_Edge.hxx>
37 #include <ShapeFix_Shape.hxx>
38
39 #include <BRep_Builder.hxx>
40 #include <BRep_Tool.hxx>
41 #include <BRepAdaptor_Curve.hxx>
42 #include <BRepAlgo_FaceRestrictor.hxx>
43 #include <BRepBuilderAPI_Copy.hxx>
44 #include <BRepBuilderAPI_Sewing.hxx>
45 #include <BRepBuilderAPI_MakeWire.hxx>
46 #include <BRepBuilderAPI_MakeEdge.hxx>
47 #include <BRepBuilderAPI_MakeSolid.hxx>
48 #include <BRepCheck.hxx>
49 #include <BRepCheck_Analyzer.hxx>
50 #include <BRepCheck_Shell.hxx>
51 #include <BRepClass3d_SolidClassifier.hxx>
52 #include <BRepLib.hxx>
53 #include <BRepLib_MakeEdge.hxx>
54 #include <BRepTools_WireExplorer.hxx>
55
56 #include <ShapeAnalysis.hxx>
57 #include <ShapeAnalysis_FreeBounds.hxx>
58
59 #include <TopAbs.hxx>
60 #include <TopExp.hxx>
61 #include <TopExp_Explorer.hxx>
62 #include <TopoDS.hxx>
63 #include <TopoDS_Shape.hxx>
64 #include <TopoDS_Edge.hxx>
65 #include <TopoDS_Wire.hxx>
66 #include <TopoDS_Shell.hxx>
67 #include <TopoDS_Solid.hxx>
68 #include <TopoDS_Compound.hxx>
69 #include <TopoDS_Iterator.hxx>
70
71 #include <TopTools_MapOfShape.hxx>
72 #include <TopTools_HSequenceOfShape.hxx>
73
74 #include <ElCLib.hxx>
75
76 #include <GCPnts_AbscissaPoint.hxx>
77
78 #include <Geom_TrimmedCurve.hxx>
79 #include <Geom_Surface.hxx>
80 #include <GeomAbs_CurveType.hxx>
81 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
82 #include <GeomConvert.hxx>
83 #include <GeomLProp.hxx>
84
85 #include <TColStd_SequenceOfReal.hxx>
86 #include <TColStd_HSequenceOfTransient.hxx>
87 #include <TColStd_Array1OfReal.hxx>
88 #include <TColGeom_SequenceOfCurve.hxx>
89 #include <TColGeom_Array1OfBSplineCurve.hxx>
90 #include <TColGeom_HArray1OfBSplineCurve.hxx>
91
92 #include <Precision.hxx>
93
94 #include <Standard_NullObject.hxx>
95 #include <Standard_TypeMismatch.hxx>
96 #include <Standard_ConstructionError.hxx>
97
98 //modified by NIZNHY-PKV Wed Dec 28 13:48:20 2011f
99 //static
100 //  void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
101 //                    const Handle(TopTools_HSequenceOfShape)& aWires);
102 //modified by NIZNHY-PKV Wed Dec 28 13:48:23 2011t
103
104 //=======================================================================
105 //function : GetID
106 //purpose  :
107 //=======================================================================
108 const Standard_GUID& GEOMImpl_ShapeDriver::GetID()
109 {
110   static Standard_GUID aShapeDriver("FF1BBB54-5D14-4df2-980B-3A668264EA16");
111   return aShapeDriver;
112 }
113
114
115 //=======================================================================
116 //function : GEOMImpl_ShapeDriver
117 //purpose  :
118 //=======================================================================
119 GEOMImpl_ShapeDriver::GEOMImpl_ShapeDriver()
120 {
121 }
122
123 //=======================================================================
124 //function : Execute
125 //purpose  :
126 //=======================================================================
127 Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
128 {
129   if (Label().IsNull()) return 0;
130   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
131
132   GEOMImpl_IShapes aCI (aFunction);
133   Standard_Integer aType = aFunction->GetType();
134
135   TopoDS_Shape aShape;
136   TCollection_AsciiString aWarning;
137   TopAbs_ShapeEnum anExpectedType = TopAbs_SHAPE;
138
139   BRep_Builder B;
140
141   if (aType == WIRE_EDGES) {
142     anExpectedType = TopAbs_WIRE;
143
144     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
145
146     Standard_Real aTolerance = aCI.GetTolerance();
147     if (aTolerance < Precision::Confusion())
148       aTolerance = Precision::Confusion();
149
150     aShape = MakeWireFromEdges(aShapes, aTolerance);
151   }
152   else if (aType == FACE_WIRE) {
153     anExpectedType = TopAbs_FACE;
154
155     Handle(GEOM_Function) aRefBase = aCI.GetBase();
156     TopoDS_Shape aShapeBase = aRefBase->GetValue();
157     if (aShapeBase.IsNull()) Standard_NullObject::Raise("Argument Shape is null");
158     TopoDS_Wire W;
159     if (aShapeBase.ShapeType() == TopAbs_WIRE) {
160       W = TopoDS::Wire(aShapeBase);
161       // check the wire is closed
162       TopoDS_Vertex aV1, aV2;
163       TopExp::Vertices(W, aV1, aV2);
164       if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
165         aShapeBase.Closed(true);
166       else
167         Standard_NullObject::Raise
168           ("Shape for face construction is not closed");
169     }
170     else if (aShapeBase.ShapeType() == TopAbs_EDGE && aShapeBase.Closed()) {
171       BRepBuilderAPI_MakeWire MW;
172       MW.Add(TopoDS::Edge(aShapeBase));
173       if (!MW.IsDone()) {
174         Standard_ConstructionError::Raise("Wire construction failed");
175       }
176       W = MW;
177     }
178     else {
179       Standard_NullObject::Raise
180         ("Shape for face construction is neither a wire nor a closed edge");
181     }
182     aWarning = GEOMImpl_Block6Explorer::MakeFace(W, aCI.GetIsPlanar(), aShape);
183     if (aShape.IsNull()) {
184       Standard_ConstructionError::Raise("Face construction failed");
185     }
186   }
187   else if (aType == FACE_WIRES) {
188     anExpectedType = TopAbs_FACE;
189
190     // Try to build a face from a set of wires and edges
191     int ind;
192
193     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
194     int nbshapes = aShapes->Length();
195     if (nbshapes < 1) {
196       Standard_ConstructionError::Raise("No wires or edges given");
197     }
198
199     // 1. Extract all edges from the given arguments
200     TopTools_MapOfShape aMapEdges;
201     Handle(TopTools_HSequenceOfShape) aSeqEdgesIn = new TopTools_HSequenceOfShape;
202
203     for (ind = 1; ind <= nbshapes; ind++) {
204       Handle(GEOM_Function) aRefSh_i = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
205       TopoDS_Shape aSh_i = aRefSh_i->GetValue();
206
207       TopExp_Explorer anExpE_i (aSh_i, TopAbs_EDGE);
208       for (; anExpE_i.More(); anExpE_i.Next()) {
209         if (aMapEdges.Add(anExpE_i.Current())) {
210           aSeqEdgesIn->Append(anExpE_i.Current());
211         }
212       }
213     }
214
215     if (aSeqEdgesIn->IsEmpty()) {
216       Standard_ConstructionError::Raise("No edges given");
217     }
218
219     // 2. Connect edges to wires of maximum length
220     Handle(TopTools_HSequenceOfShape) aSeqWiresOut;
221     ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdgesIn, Precision::Confusion(),
222                                                   /*shared*/Standard_False, aSeqWiresOut);
223     //modified by NIZNHY-PKV Wed Dec 28 13:46:55 2011f
224     //KeepEdgesOrder(aSeqEdgesIn, aSeqWiresOut);
225     //modified by NIZNHY-PKV Wed Dec 28 13:46:59 2011t
226
227     // 3. Separate closed wires
228     Handle(TopTools_HSequenceOfShape) aSeqClosedWires = new TopTools_HSequenceOfShape;
229     Handle(TopTools_HSequenceOfShape) aSeqOpenWires = new TopTools_HSequenceOfShape;
230     for (ind = 1; ind <= aSeqWiresOut->Length(); ind++) {
231       if (aSeqWiresOut->Value(ind).Closed())
232         aSeqClosedWires->Append(aSeqWiresOut->Value(ind));
233       else
234         aSeqOpenWires->Append(aSeqWiresOut->Value(ind));
235     }
236
237     if (aSeqClosedWires->Length() < 1) {
238       Standard_ConstructionError::Raise
239         ("There is no closed contour can be built from the given arguments");
240     }
241
242     // 4. Build a face / list of faces from all the obtained closed wires
243
244     // 4.a. Basic face
245     TopoDS_Shape aFFace;
246     TopoDS_Wire aW1 = TopoDS::Wire(aSeqClosedWires->Value(1));
247     aWarning = GEOMImpl_Block6Explorer::MakeFace(aW1, aCI.GetIsPlanar(), aFFace);
248     if (aFFace.IsNull()) {
249       Standard_ConstructionError::Raise("Face construction failed");
250     }
251
252     // 4.b. Add other wires
253     if (aSeqClosedWires->Length() == 1) {
254       aShape = aFFace;
255     }
256     else {
257       TopoDS_Compound C;
258       BRep_Builder aBuilder;
259       aBuilder.MakeCompound(C);
260       BRepAlgo_FaceRestrictor FR;
261
262       TopAbs_Orientation OriF = aFFace.Orientation();
263       TopoDS_Shape aLocalS = aFFace.Oriented(TopAbs_FORWARD);
264       FR.Init(TopoDS::Face(aLocalS), Standard_False, Standard_True);
265
266       for (ind = 1; ind <= aSeqClosedWires->Length(); ind++) {
267         TopoDS_Wire aW = TopoDS::Wire(aSeqClosedWires->Value(ind));
268         FR.Add(aW);
269       }
270
271       FR.Perform();
272
273       if (FR.IsDone()) {
274         int k = 0;
275         TopoDS_Shape aFace;
276         for (; FR.More(); FR.Next()) {
277           aFace = FR.Current().Oriented(OriF);
278           aBuilder.Add(C, aFace);
279           k++;
280         }
281         if (k == 1) {
282           aShape = aFace;
283         } else {
284           aShape = C;
285         }
286       }
287     }
288
289     // 5. Add all open wires to the result
290     if (aSeqOpenWires->Length() > 0) {
291       //Standard_ConstructionError::Raise("There are some open wires");
292       TopoDS_Compound C;
293       BRep_Builder aBuilder;
294       if (aSeqClosedWires->Length() == 1) {
295         aBuilder.MakeCompound(C);
296         aBuilder.Add(C, aShape);
297       }
298       else {
299         C = TopoDS::Compound(aShape);
300       }
301
302       for (ind = 1; ind <= aSeqOpenWires->Length(); ind++) {
303         aBuilder.Add(C, aSeqOpenWires->Value(ind));
304       }
305
306       aShape = C;
307     }
308   }
309   else if (aType == SHELL_FACES) {
310     anExpectedType = TopAbs_SHELL;
311
312     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
313     unsigned int ind, nbshapes = aShapes->Length();
314
315     // add faces
316     BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0);
317     for (ind = 1; ind <= nbshapes; ind++) {
318       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
319       TopoDS_Shape aShape_i = aRefShape->GetValue();
320       if (aShape_i.IsNull()) {
321         Standard_NullObject::Raise("Face for shell construction is null");
322       }
323       aSewing.Add(aShape_i);
324     }
325
326     aSewing.Perform();
327
328     TopoDS_Shape sh = aSewing.SewedShape();
329
330     if (sh.ShapeType()==TopAbs_FACE && nbshapes==1) {
331       // case for creation of shell from one face - PAL12722 (skl 26.06.2006)
332       TopoDS_Shell ss;
333       B.MakeShell(ss);
334       B.Add(ss,sh);
335       aShape = ss;
336     }
337     else {
338       //TopExp_Explorer exp (aSewing.SewedShape(), TopAbs_SHELL);
339       TopExp_Explorer exp (sh, TopAbs_SHELL);
340       Standard_Integer ish = 0;
341       for (; exp.More(); exp.Next()) {
342         aShape = exp.Current();
343         ish++;
344       }
345
346       if (ish != 1) {
347         // try the case of one face (Mantis issue 0021809)
348         TopExp_Explorer expF (sh, TopAbs_FACE);
349         Standard_Integer ifa = 0;
350         for (; expF.More(); expF.Next()) {
351           aShape = expF.Current();
352           ifa++;
353         }
354
355         if (ifa == 1) {
356           TopoDS_Shell ss;
357           B.MakeShell(ss);
358           B.Add(ss,aShape);
359           aShape = ss;
360         }
361         else {
362           aShape = aSewing.SewedShape();
363         }
364       }
365     }
366
367   }
368   else if (aType == SOLID_SHELLS) {
369     anExpectedType = TopAbs_SOLID;
370
371     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
372     unsigned int ind, nbshapes = aShapes->Length();
373     Standard_Integer ish = 0;
374     BRepBuilderAPI_MakeSolid aMkSolid;
375
376     // add shapes
377     for (ind = 1; ind <= nbshapes; ind++) {
378       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
379       TopoDS_Shape aShapeShell = aRefShape->GetValue();
380       if (aShapeShell.IsNull()) {
381         Standard_NullObject::Raise("Shell for solid construction is null");
382       }
383       if (aShapeShell.ShapeType() == TopAbs_COMPOUND) {
384         TopoDS_Iterator It (aShapeShell, Standard_True, Standard_True);
385         if (It.More()) aShapeShell = It.Value();
386       }
387       if (aShapeShell.ShapeType() == TopAbs_SHELL) {
388         aMkSolid.Add(TopoDS::Shell(aShapeShell));
389         ish++;
390       }
391     }
392     if (ish == 0 || !aMkSolid.IsDone()) return 0;
393
394     TopoDS_Solid Sol = aMkSolid.Solid();
395     BRepClass3d_SolidClassifier SC (Sol);
396     SC.PerformInfinitePoint(Precision::Confusion());
397     if (SC.State() == TopAbs_IN)
398       aShape = Sol.Reversed();
399     else
400       aShape = Sol;
401   }
402   else if (aType == COMPOUND_SHAPES) {
403     anExpectedType = TopAbs_COMPOUND;
404
405     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
406     unsigned int ind, nbshapes = aShapes->Length();
407
408     // add shapes
409     TopoDS_Compound C;
410     B.MakeCompound(C);
411     for (ind = 1; ind <= nbshapes; ind++) {
412       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
413       TopoDS_Shape aShape_i = aRefShape->GetValue();
414       if (aShape_i.IsNull()) {
415         Standard_NullObject::Raise("Shape for compound construction is null");
416       }
417       B.Add(C, aShape_i);
418     }
419
420     aShape = C;
421
422   }
423   else if (aType == EDGE_WIRE) {
424     anExpectedType = TopAbs_EDGE;
425
426     Handle(GEOM_Function) aRefBase = aCI.GetBase();
427     TopoDS_Shape aWire = aRefBase->GetValue();
428     Standard_Real LinTol = aCI.GetTolerance();
429     Standard_Real AngTol = aCI.GetAngularTolerance();
430     if (aWire.IsNull()) Standard_NullObject::Raise("Argument Wire is null");
431
432     aShape = MakeEdgeFromWire(aWire, LinTol, AngTol);
433   }
434   else if (aType == EDGE_CURVE_LENGTH) {
435     anExpectedType = TopAbs_EDGE;
436
437     GEOMImpl_IVector aVI (aFunction);
438
439     // RefCurve
440     Handle(GEOM_Function) aRefCurve = aVI.GetPoint1();
441     if (aRefCurve.IsNull()) Standard_NullObject::Raise("Argument Curve is null");
442     TopoDS_Shape aRefShape1 = aRefCurve->GetValue();
443     if (aRefShape1.ShapeType() != TopAbs_EDGE) {
444       Standard_TypeMismatch::Raise
445         ("Edge On Curve creation aborted : curve shape is not an edge");
446     }
447     TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
448     TopoDS_Vertex V1, V2;
449     TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
450
451     // RefPoint
452     TopoDS_Vertex aRefVertex;
453     Handle(GEOM_Function) aRefPoint = aVI.GetPoint2();
454     if (aRefPoint.IsNull()) {
455       aRefVertex = V1;
456     }
457     else {
458       TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
459       if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
460         Standard_TypeMismatch::Raise
461           ("Edge On Curve creation aborted : start point shape is not a vertex");
462       }
463       aRefVertex = TopoDS::Vertex(aRefShape2);
464     }
465     gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
466
467     // Length
468     Standard_Real aLength = aVI.GetParameter();
469     //Standard_Real aCurveLength = IntTools::Length(aRefEdge);
470     //if (aLength > aCurveLength) {
471     //  Standard_ConstructionError::Raise
472     //    ("Edge On Curve creation aborted : given length is greater than edges length");
473     //}
474     if (fabs(aLength) < Precision::Confusion()) {
475       Standard_ConstructionError::Raise
476         ("Edge On Curve creation aborted : given length is smaller than Precision::Confusion()");
477     }
478
479     // Check orientation
480     Standard_Real UFirst, ULast;
481     Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
482     Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
483
484     Standard_Real dU = ULast - UFirst;
485     Standard_Real par1 = UFirst + 0.1 * dU;
486     Standard_Real par2 = ULast  - 0.1 * dU;
487
488     gp_Pnt P1 = EdgeCurve->Value(par1);
489     gp_Pnt P2 = EdgeCurve->Value(par2);
490
491     if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
492       ReOrientedCurve = EdgeCurve->Reversed();
493       UFirst = EdgeCurve->ReversedParameter(ULast);
494     }
495
496     // Get the point by length
497     GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
498     GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst);
499     Standard_Real aParam = anAbsPnt.Parameter();
500
501     if (AdapCurve.IsClosed() && aLength < 0.0) {
502       Standard_Real aTmp = aParam;
503       aParam = UFirst;
504       UFirst = aTmp;
505     }
506
507     BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam);
508     if (aME.IsDone())
509       aShape = aME.Shape();
510   } else if (aType == SHAPE_ISOLINE) {
511     GEOMImpl_IIsoline     aII (aFunction);
512     Handle(GEOM_Function) aRefFace = aII.GetFace();
513     TopoDS_Shape          aShapeFace = aRefFace->GetValue();
514
515     if (aShapeFace.ShapeType() == TopAbs_FACE) {
516       TopoDS_Face   aFace  = TopoDS::Face(aShapeFace);
517       bool          isUIso = aII.GetIsUIso();
518       Standard_Real aParam = aII.GetParameter();
519       Standard_Real U1,U2,V1,V2;
520
521       // Construct a real geometric parameter.
522       aFace.Orientation(TopAbs_FORWARD);
523       ShapeAnalysis::GetFaceUVBounds(aFace,U1,U2,V1,V2);
524
525       if (isUIso) {
526         aParam = U1 + (U2 - U1)*aParam;
527       } else {
528         aParam = V1 + (V2 - V1)*aParam;
529       }
530
531       aShape = MakeIsoline(aFace, isUIso, aParam);
532     } else {
533       Standard_NullObject::Raise
534         ("Shape for isoline construction is not a face");
535     }
536   }
537   else {
538   }
539
540   if (aShape.IsNull()) return 0;
541
542   // Check shape validity
543   BRepCheck_Analyzer ana (aShape, false);
544   if (!ana.IsValid()) {
545     //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
546     // For Mantis issue 0021772: EDF 2336 GEOM: Non valid face created from two circles
547     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShape);
548     aSfs->Perform();
549     aShape = aSfs->Shape();
550   }
551
552   // Check if the result shape type is compatible with the expected.
553   const TopAbs_ShapeEnum aShType = aShape.ShapeType();
554
555   if (anExpectedType != TopAbs_SHAPE && anExpectedType != aShType) {
556     Standard_ConstructionError::Raise("Result type check failed");
557   }
558
559   aFunction->SetValue(aShape);
560
561   log.SetTouched(Label());
562
563   if (!aWarning.IsEmpty())
564     Standard_Failure::Raise(aWarning.ToCString());
565
566   return 1;
567 }
568
569 TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
570                                                     const Standard_Real theTolerance)
571 {
572   BRep_Builder B;
573
574   TopoDS_Wire aWire;
575   B.MakeWire(aWire);
576
577   // add edges
578   for (unsigned int ind = 1; ind <= theEdgesFuncs->Length(); ind++) {
579     Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->Value(ind));
580     TopoDS_Shape aShape_i = aRefShape->GetValue();
581     if (aShape_i.IsNull()) {
582       Standard_NullObject::Raise("Shape for wire construction is null");
583     }
584     if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
585       TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
586       for (; exp.More(); exp.Next())
587         B.Add(aWire, TopoDS::Edge(exp.Current()));
588     } else {
589       Standard_TypeMismatch::Raise
590         ("Shape for wire construction is neither an edge nor a wire");
591     }
592   }
593
594   // fix edges order
595   Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
596   aFW->Load(aWire);
597   aFW->FixReorder();
598
599   if (aFW->StatusReorder(ShapeExtend_FAIL1)) {
600     Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
601   }
602   else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
603     Standard_ConstructionError::Raise("Wire construction failed");
604   }
605   else {
606   }
607
608   // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
609   aFW->ClosedWireMode() = Standard_False;
610   aFW->FixConnected(theTolerance);
611   if (aFW->StatusConnected(ShapeExtend_FAIL)) {
612     Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
613   }
614   // IMP 0019766
615   if (aFW->StatusConnected(ShapeExtend_DONE3)) {
616     // Confused with <prec> but not Analyzer.Precision(), set the same
617     aFW->FixGapsByRangesMode() = Standard_True;
618     if (aFW->FixGaps3d()) {
619       Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
620       Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge;
621       for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) {
622         TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge));
623         aFe->FixVertexTolerance(aEdge);
624         aFe->FixSameParameter(aEdge);
625       }
626     }
627     else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) {
628       Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps");
629     }
630   }
631   aWire = aFW->WireAPIMake();
632
633   return aWire;
634 }
635
636 TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire,
637                                                    const Standard_Real LinTol,
638                                                    const Standard_Real AngTol)
639 {
640     TopoDS_Edge ResEdge;
641
642     BRepLib::BuildCurves3d(aWire);
643     Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(aWire);
644     Fixer->SetPrecision(LinTol);
645     Fixer->SetMaxTolerance(LinTol);
646     Fixer->Perform();
647     TopoDS_Wire theWire = TopoDS::Wire(Fixer->Shape());
648
649     TColGeom_SequenceOfCurve CurveSeq;
650     TopTools_SequenceOfShape LocSeq;
651     TColStd_SequenceOfReal FparSeq;
652     TColStd_SequenceOfReal LparSeq;
653     TColStd_SequenceOfReal TolSeq;
654     GeomAbs_CurveType CurType;
655     TopoDS_Vertex FirstVertex, LastVertex;
656
657     BRepTools_WireExplorer wexp(theWire) ;
658     for (; wexp.More(); wexp.Next())
659     {
660       TopoDS_Edge anEdge = wexp.Current();
661       Standard_Real fpar, lpar;
662       TopLoc_Location aLoc;
663       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
664       if (aCurve.IsNull())
665         continue;
666
667       BRepAdaptor_Curve BAcurve(anEdge);
668       GeomAbs_CurveType aType = BAcurve.GetType();
669
670       Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
671
672       if (aBasisCurve->IsPeriodic())
673         ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
674                                Precision::PConfusion(), fpar, lpar);
675
676       if (CurveSeq.IsEmpty())
677       {
678         CurveSeq.Append(aCurve);
679         TopoDS_Shape aLocShape;
680         aLocShape.Location(aLoc);
681         aLocShape.Orientation(wexp.Orientation());
682         LocSeq.Append(aLocShape);
683         FparSeq.Append(fpar);
684         LparSeq.Append(lpar);
685         CurType = aType;
686         FirstVertex = wexp.CurrentVertex();
687       }
688       else
689       {
690         Standard_Boolean Done = Standard_False;
691         Standard_Real NewFpar, NewLpar;
692         GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
693         TopoDS_Vertex CurVertex = wexp.CurrentVertex();
694         TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
695         TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
696         if (aCurve == CurveSeq.Last())
697         {
698           NewFpar = fpar;
699           NewLpar = lpar;
700           if (aBasisCurve->IsPeriodic())
701           {
702             if (NewLpar < NewFpar)
703               NewLpar += aBasisCurve->Period();
704             if (ConnectByOrigin == TopAbs_FORWARD)
705               ElCLib::AdjustPeriodic(FparSeq.Last(),
706                                      FparSeq.Last() + aBasisCurve->Period(),
707                                      Precision::PConfusion(), NewFpar, NewLpar);
708             else
709               ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
710                                      FparSeq.Last(),
711                                      Precision::PConfusion(), NewFpar, NewLpar);
712           }
713           Done = Standard_True;
714         }
715         else if (aType == CurType &&
716                  aType != GeomAbs_BezierCurve &&
717                  aType != GeomAbs_BSplineCurve &&
718                  aType != GeomAbs_OtherCurve)
719         {
720           switch (aType)
721           {
722           case GeomAbs_Line:
723             {
724               gp_Lin aLine    = BAcurve.Line();
725               gp_Lin PrevLine = GAprevcurve.Line();
726               if (aLine.Contains(PrevLine.Location(), LinTol) &&
727                   aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
728               {
729                 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
730                 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
731                 NewFpar = ElCLib::Parameter(PrevLine, P1);
732                 NewLpar = ElCLib::Parameter(PrevLine, P2);
733                 if (NewLpar < NewFpar)
734                 {
735                   Standard_Real MemNewFpar = NewFpar;
736                   NewFpar = NewLpar;
737                   NewLpar = MemNewFpar;
738                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
739                 }
740                 Done = Standard_True;
741               }
742               break;
743             }
744           case GeomAbs_Circle:
745             {
746               gp_Circ aCircle    = BAcurve.Circle();
747               gp_Circ PrevCircle = GAprevcurve.Circle();
748               if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
749                   Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
750                   aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
751               {
752                 if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
753                 {
754                   Standard_Real memfpar = fpar;
755                   fpar = lpar;
756                   lpar = memfpar;
757                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
758                 }
759                 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
760                 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
761                 NewFpar = ElCLib::Parameter(PrevCircle, P1);
762                 NewLpar = ElCLib::Parameter(PrevCircle, P2);
763                 if (NewLpar < NewFpar)
764                   NewLpar += 2.*M_PI;
765                 //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
766                 if (ConnectByOrigin == TopAbs_FORWARD)
767                   ElCLib::AdjustPeriodic(FparSeq.Last(),
768                                          FparSeq.Last() + 2.*M_PI,
769                                          Precision::PConfusion(), NewFpar, NewLpar);
770                 else
771                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
772                                          FparSeq.Last(),
773                                          Precision::PConfusion(), NewFpar, NewLpar);
774                 Done = Standard_True;
775               }
776               break;
777             }
778           case GeomAbs_Ellipse:
779             {
780               gp_Elips anEllipse   = BAcurve.Ellipse();
781               gp_Elips PrevEllipse = GAprevcurve.Ellipse();
782               if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
783                   anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
784                   Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
785                   Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
786                   anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
787               {
788                 if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
789                 {
790                   Standard_Real memfpar = fpar;
791                   fpar = lpar;
792                   lpar = memfpar;
793                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
794                 }
795                 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
796                 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
797                 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
798                 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
799                 if (NewLpar < NewFpar)
800                   NewLpar += 2.*M_PI;
801                 if (ConnectByOrigin == TopAbs_FORWARD)
802                   ElCLib::AdjustPeriodic(FparSeq.Last(),
803                                          FparSeq.Last() + 2.*M_PI,
804                                          Precision::PConfusion(), NewFpar, NewLpar);
805                 else
806                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
807                                          FparSeq.Last(),
808                                          Precision::PConfusion(), NewFpar, NewLpar);
809                 Done = Standard_True;
810               }
811               break;
812             }
813           case GeomAbs_Hyperbola:
814             {
815               gp_Hypr aHypr    = BAcurve.Hyperbola();
816               gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
817               if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
818                   aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
819                   Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
820                   Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
821                   aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
822               {
823                 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
824                 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
825                 NewFpar = ElCLib::Parameter(PrevHypr, P1);
826                 NewLpar = ElCLib::Parameter(PrevHypr, P2);
827                 if (NewLpar < NewFpar)
828                 {
829                   Standard_Real MemNewFpar = NewFpar;
830                   NewFpar = NewLpar;
831                   NewLpar = MemNewFpar;
832                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
833                 }
834                 Done = Standard_True;
835               }
836               break;
837             }
838           case GeomAbs_Parabola:
839             {
840               gp_Parab aParab    = BAcurve.Parabola();
841               gp_Parab PrevParab = GAprevcurve.Parabola();
842               if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
843                   aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
844                   Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
845                   aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
846               {
847                 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
848                 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
849                 NewFpar = ElCLib::Parameter(PrevParab, P1);
850                 NewLpar = ElCLib::Parameter(PrevParab, P2);
851                 if (NewLpar < NewFpar)
852                 {
853                   Standard_Real MemNewFpar = NewFpar;
854                   NewFpar = NewLpar;
855                   NewLpar = MemNewFpar;
856                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
857                 }
858                 Done = Standard_True;
859               }
860               break;
861             }
862           } //end of switch (aType)
863         } // end of else if (aType == CurType && ...
864         if (Done)
865         {
866           if (NewFpar < FparSeq.Last())
867             FparSeq(FparSeq.Length()) = NewFpar;
868           else
869             LparSeq(LparSeq.Length()) = NewLpar;
870         }
871         else
872         {
873           CurveSeq.Append(aCurve);
874           TopoDS_Shape aLocShape;
875           aLocShape.Location(aLoc);
876           aLocShape.Orientation(wexp.Orientation());
877           LocSeq.Append(aLocShape);
878           FparSeq.Append(fpar);
879           LparSeq.Append(lpar);
880           TolSeq.Append(BRep_Tool::Tolerance(CurVertex));
881           CurType = aType;
882         }
883       } // end of else (CurveSeq.IsEmpty()) -> not first time
884     } // end for (; wexp.More(); wexp.Next())
885
886     LastVertex = wexp.CurrentVertex();
887     TolSeq.Append(BRep_Tool::Tolerance(LastVertex));
888
889     FirstVertex.Orientation(TopAbs_FORWARD);
890     LastVertex.Orientation(TopAbs_REVERSED);
891
892     if (!CurveSeq.IsEmpty())
893     {
894       Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
895       TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
896       TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
897
898       Standard_Integer i;
899
900       if (nb_curve > 1)
901       {
902         for (i = 1; i <= nb_curve; i++)
903         {
904           if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
905             CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
906
907           Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
908           tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
909           tab(i-1)->Transform(LocSeq(i).Location().Transformation());
910           GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
911           if (LocSeq(i).Orientation() == TopAbs_REVERSED)
912             tab(i-1)->Reverse();
913
914           //Temporary
915           //char* name = new char[100];
916           //sprintf(name, "c%d", i);
917           //DrawTrSurf::Set(name, tab(i-1));
918
919           if (i > 1)
920             tabtolvertex(i-2) = TolSeq(i-1);
921         } // end for (i = 1; i <= nb_curve; i++)
922         tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length());
923
924         Standard_Boolean closed_flag = Standard_False;
925         Standard_Real closed_tolerance = 0.;
926         if (FirstVertex.IsSame(LastVertex) &&
927             GeomLProp::Continuity(tab(0), tab(nb_curve-1),
928                                   tab(0)->FirstParameter(),
929                                   tab(nb_curve-1)->LastParameter(),
930                                   Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
931         {
932           closed_flag = Standard_True ;
933           closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
934         }
935
936         Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
937         Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
938         GeomConvert::ConcatC1(tab,
939                               tabtolvertex,
940                               ArrayOfIndices,
941                               concatcurve,
942                               closed_flag,
943                               closed_tolerance);   //C1 concatenation
944
945         if (concatcurve->Length() > 1)
946         {
947           GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
948
949           for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
950             Concat.Add( concatcurve->Value(i), LinTol, Standard_True );
951
952           concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
953         }
954         // rnc : prevents the driver from building an edge without C1 continuity
955         if (concatcurve->Value(concatcurve->Lower())->Continuity()==GeomAbs_C0){
956           Standard_ConstructionError::Raise("Construction aborted : The given Wire has sharp bends between some Edges, no valid Edge can be built");
957         }
958
959         Standard_Boolean isValidEndVtx = Standard_True;
960
961         if (closed_flag) {
962           // Check if closed curve is reordered.
963           Handle(Geom_Curve) aCurve  = concatcurve->Value(concatcurve->Lower());
964           Standard_Real      aFPar   = aCurve->FirstParameter();
965           gp_Pnt             aPFirst;
966           gp_Pnt             aPntVtx = BRep_Tool::Pnt(FirstVertex);
967           Standard_Real      aTolVtx = BRep_Tool::Tolerance(FirstVertex);
968
969           aCurve->D0(aFPar, aPFirst);
970
971           if (!aPFirst.IsEqual(aPntVtx, aTolVtx)) {
972             // The curve is reordered. Find the new first and last vertices.
973             TopTools_IndexedMapOfShape aMapVtx;
974             TopExp::MapShapes(theWire, TopAbs_VERTEX, aMapVtx);
975
976             const Standard_Integer aNbVtx = aMapVtx.Extent();
977             Standard_Integer       iVtx;
978
979             for (iVtx = 1; iVtx <= aNbVtx; iVtx++) {
980               const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(iVtx));
981               const gp_Pnt        aPnt = BRep_Tool::Pnt(aVtx);
982               const Standard_Real aTol = BRep_Tool::Tolerance(aVtx);
983
984               if (aPFirst.IsEqual(aPnt, aTol)) {
985                 // The coinsident vertex is found.
986                 FirstVertex = aVtx;
987                 LastVertex  = aVtx;
988                 FirstVertex.Orientation(TopAbs_FORWARD);
989                 LastVertex.Orientation(TopAbs_REVERSED);
990                 break;
991               }
992             }
993
994             if (iVtx > aNbVtx) {
995               // It is necessary to create new vertices.
996               isValidEndVtx = Standard_False;
997             }
998           }
999         }
1000
1001         if (isValidEndVtx) {
1002           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1003                                      FirstVertex, LastVertex,
1004                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1005                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1006         } else {
1007           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1008                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1009                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1010         }
1011       }
1012       else
1013       {
1014         if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1015           CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
1016
1017         Handle(Geom_Curve) aNewCurve =
1018           Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
1019
1020         aNewCurve->Transform(LocSeq(1).Location().Transformation());
1021
1022         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1023           const TopoDS_Vertex aVtxTmp = FirstVertex;
1024
1025           FirstVertex = LastVertex;
1026           LastVertex  = aVtxTmp;
1027           FirstVertex.Orientation(TopAbs_FORWARD);
1028           LastVertex.Orientation(TopAbs_REVERSED);
1029         }
1030
1031         ResEdge = BRepLib_MakeEdge(aNewCurve,
1032                                    FirstVertex, LastVertex,
1033                                    FparSeq(1), LparSeq(1));
1034
1035         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1036           ResEdge.Reverse();
1037         }
1038       }
1039     }
1040
1041     return ResEdge;
1042 }
1043
1044 //=============================================================================
1045 /*!
1046  * \brief Returns an isoline for a face.
1047  */
1048 //=============================================================================
1049
1050 TopoDS_Shape GEOMImpl_ShapeDriver::MakeIsoline
1051                             (const TopoDS_Face &theFace,
1052                              const bool         IsUIso,
1053                              const double       theParameter) const
1054 {
1055   TopoDS_Shape          aResult;
1056   GEOMUtils::Hatcher    aHatcher(theFace);
1057   const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV);
1058
1059   aHatcher.Init(aType, theParameter);
1060   aHatcher.Perform();
1061
1062   if (!aHatcher.IsDone()) {
1063     Standard_ConstructionError::Raise("MakeIsoline : Hatcher failure");
1064   }
1065
1066   const Handle(TColStd_HArray1OfInteger) &anIndices =
1067     (IsUIso ? aHatcher.GetUIndices() : aHatcher.GetVIndices());
1068
1069   if (anIndices.IsNull()) {
1070     Standard_ConstructionError::Raise("MakeIsoline : Null hatching indices");
1071   }
1072
1073   const Standard_Integer anIsoInd = anIndices->Lower();
1074   const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd);
1075
1076   if (aHatchingIndex == 0) {
1077     Standard_ConstructionError::Raise("MakeIsoline : Invalid hatching index");
1078   }
1079
1080   const Standard_Integer aNbDomains =
1081     aHatcher.GetNbDomains(aHatchingIndex);
1082
1083   if (aNbDomains < 0) {
1084     Standard_ConstructionError::Raise("MakeIsoline : Invalid number of domains");
1085   }
1086
1087   // The hatching is performed successfully. Create the 3d Curve.
1088   Handle(Geom_Surface) aSurface   = BRep_Tool::Surface(theFace);
1089   Handle(Geom_Curve)   anIsoCurve = (IsUIso ?
1090     aSurface->UIso(theParameter) : aSurface->VIso(theParameter));
1091   Handle(Geom2d_Curve) aPIsoCurve =
1092     aHatcher.GetHatching(aHatchingIndex);
1093   const Standard_Real  aTol = Precision::Confusion();
1094   Standard_Integer     anIDom = 1;
1095   Standard_Real        aV1;
1096   Standard_Real        aV2;
1097   BRep_Builder         aBuilder;
1098   Standard_Integer     aNbEdges = 0;
1099
1100   for (; anIDom <= aNbDomains; anIDom++) {
1101     if (aHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) {
1102       // Check first and last parameters.
1103       if (!aHatcher.IsDomainInfinite(aHatchingIndex, anIDom)) {
1104         // Create an edge.
1105         TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(anIsoCurve, aV1, aV2);
1106
1107         // Update it with a parametric curve on face.
1108         aBuilder.UpdateEdge(anEdge, aPIsoCurve, theFace, aTol);
1109         aNbEdges++;
1110
1111         if (aNbEdges > 1) {
1112           // Result is a compond.
1113           if (aNbEdges == 2) {
1114             // Create a new compound.
1115             TopoDS_Compound aCompound;
1116
1117             aBuilder.MakeCompound(aCompound);
1118             aBuilder.Add(aCompound, aResult);
1119             aResult = aCompound;
1120           }
1121
1122           // Add an edge to the compound.
1123           aBuilder.Add(aResult, anEdge);
1124         } else {
1125           // Result is the edge.
1126           aResult = anEdge;
1127         }
1128       }
1129     }
1130   }
1131
1132   if (aNbEdges == 0) {
1133     Standard_ConstructionError::Raise("MakeIsoline : Empty result");
1134   }
1135
1136   return aResult;
1137 }
1138
1139 //================================================================================
1140 /*!
1141  * \brief Returns a name of creation operation and names and values of creation parameters
1142  */
1143 //================================================================================
1144
1145 bool GEOMImpl_ShapeDriver::
1146 GetCreationInformation(std::string&             theOperationName,
1147                        std::vector<GEOM_Param>& theParams)
1148 {
1149   if (Label().IsNull()) return 0;
1150   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
1151
1152   GEOMImpl_IShapes aCI( function );
1153   Standard_Integer aType = function->GetType();
1154
1155   switch ( aType ) {
1156   case WIRE_EDGES:
1157     theOperationName = "WIRE";
1158     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1159     AddParam( theParams, "Tolerance", aCI.GetTolerance() );
1160     break;
1161   case FACE_WIRE:
1162     theOperationName = "FACE";
1163     AddParam( theParams, "Wire/edge", aCI.GetBase() );
1164     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1165     break;
1166   case FACE_WIRES:
1167     theOperationName = "FACE";
1168     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1169     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1170     break;
1171   case SHELL_FACES:
1172     theOperationName = "SHELL";
1173     AddParam( theParams, "Objects", aCI.GetShapes() );
1174     break;
1175   case SOLID_SHELLS:
1176     theOperationName = "SOLID";
1177     AddParam( theParams, "Objects", aCI.GetShapes() );
1178     break;
1179   case COMPOUND_SHAPES:
1180     theOperationName = "COMPOUND";
1181     AddParam( theParams, "Objects", aCI.GetShapes() );
1182     break;
1183   case EDGE_WIRE:
1184     theOperationName = "EDGE";
1185     AddParam( theParams, "Wire", aCI.GetBase() );
1186     AddParam( theParams, "Linear Tolerance", aCI.GetTolerance() );
1187     AddParam( theParams, "Angular Tolerance", aCI.GetAngularTolerance() );
1188     break;
1189   case EDGE_CURVE_LENGTH:
1190     theOperationName = "EDGE";
1191     {
1192       GEOMImpl_IVector aCI( function );
1193       AddParam( theParams, "Edge", aCI.GetPoint1() );
1194       AddParam( theParams, "Start point", aCI.GetPoint2() );
1195       AddParam( theParams, "Length", aCI.GetParameter() );
1196     }
1197     break;
1198   case SHAPES_ON_SHAPE:
1199   {
1200     theOperationName = "GetShapesOnShapeAsCompound";
1201     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1202     if ( !shapes.IsNull() && shapes->Length() > 0 )
1203       AddParam( theParams, "Check shape", shapes->Value(1) );
1204     if ( !shapes.IsNull() && shapes->Length() > 1 )
1205       AddParam( theParams, "Shape", shapes->Value(2) );
1206     AddParam( theParams, "Shape type", TopAbs_ShapeEnum( aCI.GetSubShapeType() ));
1207     AddParam( theParams, "State", TopAbs_State((int) aCI.GetTolerance() ));
1208     break;
1209   }
1210   case SHAPE_ISOLINE:
1211   {
1212     GEOMImpl_IIsoline aII (function);
1213
1214     theOperationName = "ISOLINE";
1215     AddParam(theParams, "Face", aII.GetFace());
1216     AddParam(theParams, "Isoline type", (aII.GetIsUIso() ? "U" : "V"));
1217     AddParam(theParams, "Parameter", aII.GetParameter());
1218     break;
1219   }
1220   default:
1221     return false;
1222   }
1223
1224   return true;
1225 }
1226
1227 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
1228 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
1229
1230 //modified by NIZNHY-PKV Wed Dec 28 13:48:31 2011f
1231 #include <TopoDS_Iterator.hxx>
1232 #include <TopTools_HSequenceOfShape.hxx>
1233 #include <ShapeAnalysis_FreeBounds.hxx>
1234 #include <TopTools_MapOfShape.hxx>
1235 #include <TopTools_MapOfOrientedShape.hxx>
1236 #include <BRep_Builder.hxx>
1237 #include <TopoDS_Wire.hxx>
1238
1239 //=======================================================================
1240 //function : KeepEdgesOrder
1241 //purpose  : 
1242 //=======================================================================
1243 /*
1244 void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
1245                     const Handle(TopTools_HSequenceOfShape)& aWires)
1246 {
1247   Standard_Integer aNbWires, aNbEdges;
1248   // 
1249   if (aEdges.IsNull()) {
1250     return;
1251   }
1252   //
1253   if (aWires.IsNull()) {
1254     return;
1255   }
1256   //
1257   aNbEdges=aEdges->Length();
1258   aNbWires=aWires->Length();
1259   if (!aNbEdges || !aNbWires) {
1260     return;
1261   }
1262   //-----
1263   Standard_Boolean bClosed;
1264   Standard_Integer i, j;
1265   TopoDS_Wire aWy;
1266   TopoDS_Iterator aIt;
1267   BRep_Builder aBB;
1268   TopTools_MapOfOrientedShape aMEx;
1269   //
1270   for (i=1; i<=aNbWires; ++i) {
1271     const TopoDS_Shape& aWx=aWires->Value(i);
1272     //
1273     aMEx.Clear();
1274     aIt.Initialize (aWx);
1275     for (; aIt.More(); aIt.Next()) {
1276       const TopoDS_Shape& aEx=aIt.Value();
1277       aMEx.Add(aEx);
1278     }
1279     // aWy
1280     aBB.MakeWire (aWy);
1281     for (j=1; j<=aNbEdges; ++j) {
1282       const TopoDS_Shape& aE=aEdges->Value(j);
1283       if (aMEx.Contains(aE)) {
1284         aBB.Add(aWy, aE);
1285       }
1286     }
1287     //
1288     bClosed=aWx.Closed();
1289     aWy.Closed(bClosed);
1290     //
1291     aWires->Append(aWy);
1292   }// for (i=1; i<=aNbWires; ++i) {
1293   //
1294   aWires->Remove(1, aNbWires);
1295 }
1296 */
1297 //modified by NIZNHY-PKV Wed Dec 28 13:48:34 2011t