Salome HOME
0022749: [EDF] Improvement of Remove Internal Faces operation
[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     Standard_Real aPntShiftDist = 0.;
657
658     BRepTools_WireExplorer wexp(theWire) ;
659     for (; wexp.More(); wexp.Next())
660     {
661       TopoDS_Edge anEdge = wexp.Current();
662       Standard_Real fpar, lpar;
663       TopLoc_Location aLoc;
664       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
665       if (aCurve.IsNull())
666         continue;
667
668       BRepAdaptor_Curve BAcurve(anEdge);
669       GeomAbs_CurveType aType = BAcurve.GetType();
670
671       Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
672
673       if (aBasisCurve->IsPeriodic())
674         ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
675                                Precision::PConfusion(), fpar, lpar);
676
677       if (CurveSeq.IsEmpty())
678       {
679         CurveSeq.Append(aCurve);
680         TopoDS_Shape aLocShape;
681         aLocShape.Location(aLoc);
682         aLocShape.Orientation(wexp.Orientation());
683         LocSeq.Append(aLocShape);
684         FparSeq.Append(fpar);
685         LparSeq.Append(lpar);
686         CurType = aType;
687         FirstVertex = wexp.CurrentVertex();
688       }
689       else
690       {
691         Standard_Boolean Done = Standard_False;
692         Standard_Real NewFpar, NewLpar;
693         GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
694         TopoDS_Vertex CurVertex = wexp.CurrentVertex();
695         TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
696         TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
697         if (aCurve == CurveSeq.Last())
698         {
699           NewFpar = fpar;
700           NewLpar = lpar;
701           if (aBasisCurve->IsPeriodic())
702           {
703             if (NewLpar < NewFpar)
704               NewLpar += aBasisCurve->Period();
705             if (ConnectByOrigin == TopAbs_FORWARD)
706               ElCLib::AdjustPeriodic(FparSeq.Last(),
707                                      FparSeq.Last() + aBasisCurve->Period(),
708                                      Precision::PConfusion(), NewFpar, NewLpar);
709             else
710               ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
711                                      FparSeq.Last(),
712                                      Precision::PConfusion(), NewFpar, NewLpar);
713           }
714           Done = Standard_True;
715         }
716         else if (aType == CurType &&
717                  aType != GeomAbs_BezierCurve &&
718                  aType != GeomAbs_BSplineCurve &&
719                  aType != GeomAbs_OtherCurve)
720         {
721           switch (aType)
722           {
723           case GeomAbs_Line:
724             {
725               gp_Lin aLine    = BAcurve.Line();
726               gp_Lin PrevLine = GAprevcurve.Line();
727               if (aLine.Contains(PrevLine.Location(), LinTol) &&
728                   aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
729               {
730                 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
731                 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
732                 NewFpar = ElCLib::Parameter(PrevLine, P1);
733                 NewLpar = ElCLib::Parameter(PrevLine, P2);
734
735                 // Compute shift
736                 if (ConnectByOrigin == TopAbs_FORWARD) {
737                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevLine);
738
739                   aPntShiftDist += P2.Distance(aNewP2);
740                 } else {
741                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevLine);
742
743                   aPntShiftDist += P1.Distance(aNewP1);
744                 }
745
746                 if (NewLpar < NewFpar)
747                 {
748                   Standard_Real MemNewFpar = NewFpar;
749                   NewFpar = NewLpar;
750                   NewLpar = MemNewFpar;
751                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
752                 }
753                 Done = Standard_True;
754               }
755               break;
756             }
757           case GeomAbs_Circle:
758             {
759               gp_Circ aCircle    = BAcurve.Circle();
760               gp_Circ PrevCircle = GAprevcurve.Circle();
761               if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
762                   Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
763                   aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
764               {
765                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
766
767                 if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
768                 {
769                   Standard_Real memfpar = fpar;
770                   fpar = lpar;
771                   lpar = memfpar;
772                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
773                 }
774                 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
775                 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
776                 NewFpar = ElCLib::Parameter(PrevCircle, P1);
777                 NewLpar = ElCLib::Parameter(PrevCircle, P2);
778
779                 // Compute shift
780                 if (isFwd) {
781                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevCircle);
782
783                   aPntShiftDist += P2.Distance(aNewP2);
784                 } else {
785                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevCircle);
786
787                   aPntShiftDist += P1.Distance(aNewP1);
788                 }
789
790                 if (NewLpar < NewFpar)
791                   NewLpar += 2.*M_PI;
792                 //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
793                 if (ConnectByOrigin == TopAbs_FORWARD)
794                   ElCLib::AdjustPeriodic(FparSeq.Last(),
795                                          FparSeq.Last() + 2.*M_PI,
796                                          Precision::PConfusion(), NewFpar, NewLpar);
797                 else
798                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
799                                          FparSeq.Last(),
800                                          Precision::PConfusion(), NewFpar, NewLpar);
801                 Done = Standard_True;
802               }
803               break;
804             }
805           case GeomAbs_Ellipse:
806             {
807               gp_Elips anEllipse   = BAcurve.Ellipse();
808               gp_Elips PrevEllipse = GAprevcurve.Ellipse();
809               if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
810                   anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
811                   Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
812                   Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
813                   anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
814               {
815                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
816
817                 if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
818                 {
819                   Standard_Real memfpar = fpar;
820                   fpar = lpar;
821                   lpar = memfpar;
822                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
823                 }
824                 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
825                 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
826                 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
827                 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
828
829                 // Compute shift
830                 if (isFwd) {
831                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevEllipse);
832
833                   aPntShiftDist += P2.Distance(aNewP2);
834                 } else {
835                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevEllipse);
836
837                   aPntShiftDist += P1.Distance(aNewP1);
838                 }
839
840                 if (NewLpar < NewFpar)
841                   NewLpar += 2.*M_PI;
842                 if (ConnectByOrigin == TopAbs_FORWARD)
843                   ElCLib::AdjustPeriodic(FparSeq.Last(),
844                                          FparSeq.Last() + 2.*M_PI,
845                                          Precision::PConfusion(), NewFpar, NewLpar);
846                 else
847                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
848                                          FparSeq.Last(),
849                                          Precision::PConfusion(), NewFpar, NewLpar);
850                 Done = Standard_True;
851               }
852               break;
853             }
854           case GeomAbs_Hyperbola:
855             {
856               gp_Hypr aHypr    = BAcurve.Hyperbola();
857               gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
858               if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
859                   aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
860                   Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
861                   Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
862                   aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
863               {
864                 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
865                 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
866                 NewFpar = ElCLib::Parameter(PrevHypr, P1);
867                 NewLpar = ElCLib::Parameter(PrevHypr, P2);
868
869                 // Compute shift
870                 if (ConnectByOrigin == TopAbs_FORWARD) {
871                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevHypr);
872
873                   aPntShiftDist += P2.Distance(aNewP2);
874                 } else {
875                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevHypr);
876
877                   aPntShiftDist += P1.Distance(aNewP1);
878                 }
879
880                 if (NewLpar < NewFpar)
881                 {
882                   Standard_Real MemNewFpar = NewFpar;
883                   NewFpar = NewLpar;
884                   NewLpar = MemNewFpar;
885                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
886                 }
887                 Done = Standard_True;
888               }
889               break;
890             }
891           case GeomAbs_Parabola:
892             {
893               gp_Parab aParab    = BAcurve.Parabola();
894               gp_Parab PrevParab = GAprevcurve.Parabola();
895               if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
896                   aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
897                   Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
898                   aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
899               {
900                 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
901                 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
902                 NewFpar = ElCLib::Parameter(PrevParab, P1);
903                 NewLpar = ElCLib::Parameter(PrevParab, P2);
904
905                 // Compute shift
906                 if (ConnectByOrigin == TopAbs_FORWARD) {
907                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevParab);
908
909                   aPntShiftDist += P2.Distance(aNewP2);
910                 } else {
911                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevParab);
912
913                   aPntShiftDist += P1.Distance(aNewP1);
914                 }
915
916                 if (NewLpar < NewFpar)
917                 {
918                   Standard_Real MemNewFpar = NewFpar;
919                   NewFpar = NewLpar;
920                   NewLpar = MemNewFpar;
921                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
922                 }
923                 Done = Standard_True;
924               }
925               break;
926             }
927           } //end of switch (aType)
928         } // end of else if (aType == CurType && ...
929         if (Done)
930         {
931           if (NewFpar < FparSeq.Last())
932             FparSeq(FparSeq.Length()) = NewFpar;
933           else
934             LparSeq(LparSeq.Length()) = NewLpar;
935         }
936         else
937         {
938           CurveSeq.Append(aCurve);
939           TopoDS_Shape aLocShape;
940           aLocShape.Location(aLoc);
941           aLocShape.Orientation(wexp.Orientation());
942           LocSeq.Append(aLocShape);
943           FparSeq.Append(fpar);
944           LparSeq.Append(lpar);
945           TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(CurVertex));
946           aPntShiftDist = 0.;
947           CurType = aType;
948         }
949       } // end of else (CurveSeq.IsEmpty()) -> not first time
950     } // end for (; wexp.More(); wexp.Next())
951
952     LastVertex = wexp.CurrentVertex();
953     TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(LastVertex));
954
955     FirstVertex.Orientation(TopAbs_FORWARD);
956     LastVertex.Orientation(TopAbs_REVERSED);
957
958     if (!CurveSeq.IsEmpty())
959     {
960       Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
961       TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
962       TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
963
964       Standard_Integer i;
965
966       if (nb_curve > 1)
967       {
968         for (i = 1; i <= nb_curve; i++)
969         {
970           if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
971             CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
972
973           Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
974           tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
975           tab(i-1)->Transform(LocSeq(i).Location().Transformation());
976           GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
977           if (LocSeq(i).Orientation() == TopAbs_REVERSED)
978             tab(i-1)->Reverse();
979
980           //Temporary
981           //char* name = new char[100];
982           //sprintf(name, "c%d", i);
983           //DrawTrSurf::Set(name, tab(i-1));
984
985           if (i > 1)
986             tabtolvertex(i-2) = TolSeq(i-1);
987         } // end for (i = 1; i <= nb_curve; i++)
988         tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length());
989
990         Standard_Boolean closed_flag = Standard_False;
991         Standard_Real closed_tolerance = 0.;
992         if (FirstVertex.IsSame(LastVertex) &&
993             GeomLProp::Continuity(tab(0), tab(nb_curve-1),
994                                   tab(0)->FirstParameter(),
995                                   tab(nb_curve-1)->LastParameter(),
996                                   Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
997         {
998           closed_flag = Standard_True ;
999           closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
1000         }
1001
1002         Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
1003         Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
1004         GeomConvert::ConcatC1(tab,
1005                               tabtolvertex,
1006                               ArrayOfIndices,
1007                               concatcurve,
1008                               closed_flag,
1009                               closed_tolerance);   //C1 concatenation
1010
1011         if (concatcurve->Length() > 1)
1012         {
1013           GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
1014
1015           for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
1016             Concat.Add( concatcurve->Value(i), LinTol, Standard_True );
1017
1018           concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
1019         }
1020         // rnc : prevents the driver from building an edge without C1 continuity
1021         if (concatcurve->Value(concatcurve->Lower())->Continuity()==GeomAbs_C0){
1022           Standard_ConstructionError::Raise("Construction aborted : The given Wire has sharp bends between some Edges, no valid Edge can be built");
1023         }
1024
1025         Standard_Boolean isValidEndVtx = Standard_True;
1026
1027         if (closed_flag) {
1028           // Check if closed curve is reordered.
1029           Handle(Geom_Curve) aCurve  = concatcurve->Value(concatcurve->Lower());
1030           Standard_Real      aFPar   = aCurve->FirstParameter();
1031           gp_Pnt             aPFirst;
1032           gp_Pnt             aPntVtx = BRep_Tool::Pnt(FirstVertex);
1033           Standard_Real      aTolVtx = BRep_Tool::Tolerance(FirstVertex);
1034
1035           aCurve->D0(aFPar, aPFirst);
1036
1037           if (!aPFirst.IsEqual(aPntVtx, aTolVtx)) {
1038             // The curve is reordered. Find the new first and last vertices.
1039             TopTools_IndexedMapOfShape aMapVtx;
1040             TopExp::MapShapes(theWire, TopAbs_VERTEX, aMapVtx);
1041
1042             const Standard_Integer aNbVtx = aMapVtx.Extent();
1043             Standard_Integer       iVtx;
1044
1045             for (iVtx = 1; iVtx <= aNbVtx; iVtx++) {
1046               const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(iVtx));
1047               const gp_Pnt        aPnt = BRep_Tool::Pnt(aVtx);
1048               const Standard_Real aTol = BRep_Tool::Tolerance(aVtx);
1049
1050               if (aPFirst.IsEqual(aPnt, aTol)) {
1051                 // The coinsident vertex is found.
1052                 FirstVertex = aVtx;
1053                 LastVertex  = aVtx;
1054                 FirstVertex.Orientation(TopAbs_FORWARD);
1055                 LastVertex.Orientation(TopAbs_REVERSED);
1056                 break;
1057               }
1058             }
1059
1060             if (iVtx > aNbVtx) {
1061               // It is necessary to create new vertices.
1062               isValidEndVtx = Standard_False;
1063             }
1064           }
1065         }
1066
1067         if (isValidEndVtx) {
1068           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1069                                      FirstVertex, LastVertex,
1070                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1071                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1072         } else {
1073           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1074                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1075                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1076         }
1077       }
1078       else
1079       {
1080         if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1081           CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
1082
1083         Handle(Geom_Curve) aNewCurve =
1084           Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
1085
1086         aNewCurve->Transform(LocSeq(1).Location().Transformation());
1087
1088         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1089           const TopoDS_Vertex aVtxTmp = FirstVertex;
1090
1091           FirstVertex = LastVertex;
1092           LastVertex  = aVtxTmp;
1093           FirstVertex.Orientation(TopAbs_FORWARD);
1094           LastVertex.Orientation(TopAbs_REVERSED);
1095         }
1096
1097         ResEdge = BRepLib_MakeEdge(aNewCurve,
1098                                    FirstVertex, LastVertex,
1099                                    FparSeq(1), LparSeq(1));
1100
1101         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1102           ResEdge.Reverse();
1103         }
1104       }
1105     }
1106
1107     return ResEdge;
1108 }
1109
1110 //=============================================================================
1111 /*!
1112  * \brief Returns an isoline for a face.
1113  */
1114 //=============================================================================
1115
1116 TopoDS_Shape GEOMImpl_ShapeDriver::MakeIsoline
1117                             (const TopoDS_Face &theFace,
1118                              const bool         IsUIso,
1119                              const double       theParameter) const
1120 {
1121   TopoDS_Shape          aResult;
1122   GEOMUtils::Hatcher    aHatcher(theFace);
1123   const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV);
1124
1125   aHatcher.Init(aType, theParameter);
1126   aHatcher.Perform();
1127
1128   if (!aHatcher.IsDone()) {
1129     Standard_ConstructionError::Raise("MakeIsoline : Hatcher failure");
1130   }
1131
1132   const Handle(TColStd_HArray1OfInteger) &anIndices =
1133     (IsUIso ? aHatcher.GetUIndices() : aHatcher.GetVIndices());
1134
1135   if (anIndices.IsNull()) {
1136     Standard_ConstructionError::Raise("MakeIsoline : Null hatching indices");
1137   }
1138
1139   const Standard_Integer anIsoInd = anIndices->Lower();
1140   const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd);
1141
1142   if (aHatchingIndex == 0) {
1143     Standard_ConstructionError::Raise("MakeIsoline : Invalid hatching index");
1144   }
1145
1146   const Standard_Integer aNbDomains =
1147     aHatcher.GetNbDomains(aHatchingIndex);
1148
1149   if (aNbDomains < 0) {
1150     Standard_ConstructionError::Raise("MakeIsoline : Invalid number of domains");
1151   }
1152
1153   // The hatching is performed successfully. Create the 3d Curve.
1154   Handle(Geom_Surface) aSurface   = BRep_Tool::Surface(theFace);
1155   Handle(Geom_Curve)   anIsoCurve = (IsUIso ?
1156     aSurface->UIso(theParameter) : aSurface->VIso(theParameter));
1157   Handle(Geom2d_Curve) aPIsoCurve =
1158     aHatcher.GetHatching(aHatchingIndex);
1159   const Standard_Real  aTol = Precision::Confusion();
1160   Standard_Integer     anIDom = 1;
1161   Standard_Real        aV1;
1162   Standard_Real        aV2;
1163   BRep_Builder         aBuilder;
1164   Standard_Integer     aNbEdges = 0;
1165
1166   for (; anIDom <= aNbDomains; anIDom++) {
1167     if (aHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) {
1168       // Check first and last parameters.
1169       if (!aHatcher.IsDomainInfinite(aHatchingIndex, anIDom)) {
1170         // Create an edge.
1171         TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(anIsoCurve, aV1, aV2);
1172
1173         // Update it with a parametric curve on face.
1174         aBuilder.UpdateEdge(anEdge, aPIsoCurve, theFace, aTol);
1175         aNbEdges++;
1176
1177         if (aNbEdges > 1) {
1178           // Result is a compond.
1179           if (aNbEdges == 2) {
1180             // Create a new compound.
1181             TopoDS_Compound aCompound;
1182
1183             aBuilder.MakeCompound(aCompound);
1184             aBuilder.Add(aCompound, aResult);
1185             aResult = aCompound;
1186           }
1187
1188           // Add an edge to the compound.
1189           aBuilder.Add(aResult, anEdge);
1190         } else {
1191           // Result is the edge.
1192           aResult = anEdge;
1193         }
1194       }
1195     }
1196   }
1197
1198   if (aNbEdges == 0) {
1199     Standard_ConstructionError::Raise("MakeIsoline : Empty result");
1200   }
1201
1202   return aResult;
1203 }
1204
1205 //================================================================================
1206 /*!
1207  * \brief Returns a name of creation operation and names and values of creation parameters
1208  */
1209 //================================================================================
1210
1211 bool GEOMImpl_ShapeDriver::
1212 GetCreationInformation(std::string&             theOperationName,
1213                        std::vector<GEOM_Param>& theParams)
1214 {
1215   if (Label().IsNull()) return 0;
1216   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
1217
1218   GEOMImpl_IShapes aCI( function );
1219   Standard_Integer aType = function->GetType();
1220
1221   switch ( aType ) {
1222   case WIRE_EDGES:
1223     theOperationName = "WIRE";
1224     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1225     AddParam( theParams, "Tolerance", aCI.GetTolerance() );
1226     break;
1227   case FACE_WIRE:
1228     theOperationName = "FACE";
1229     AddParam( theParams, "Wire/edge", aCI.GetBase() );
1230     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1231     break;
1232   case FACE_WIRES:
1233     theOperationName = "FACE";
1234     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1235     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1236     break;
1237   case SHELL_FACES:
1238     theOperationName = "SHELL";
1239     AddParam( theParams, "Objects", aCI.GetShapes() );
1240     break;
1241   case SOLID_SHELLS:
1242     theOperationName = "SOLID";
1243     AddParam( theParams, "Objects", aCI.GetShapes() );
1244     break;
1245   case COMPOUND_SHAPES:
1246     theOperationName = "COMPOUND";
1247     AddParam( theParams, "Objects", aCI.GetShapes() );
1248     break;
1249   case EDGE_WIRE:
1250     theOperationName = "EDGE";
1251     AddParam( theParams, "Wire", aCI.GetBase() );
1252     AddParam( theParams, "Linear Tolerance", aCI.GetTolerance() );
1253     AddParam( theParams, "Angular Tolerance", aCI.GetAngularTolerance() );
1254     break;
1255   case EDGE_CURVE_LENGTH:
1256     theOperationName = "EDGE";
1257     {
1258       GEOMImpl_IVector aCI( function );
1259       AddParam( theParams, "Edge", aCI.GetPoint1() );
1260       AddParam( theParams, "Start point", aCI.GetPoint2() );
1261       AddParam( theParams, "Length", aCI.GetParameter() );
1262     }
1263     break;
1264   case SHAPES_ON_SHAPE:
1265   {
1266     theOperationName = "GetShapesOnShapeAsCompound";
1267     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1268     if ( !shapes.IsNull() && shapes->Length() > 0 )
1269       AddParam( theParams, "Check shape", shapes->Value(1) );
1270     if ( !shapes.IsNull() && shapes->Length() > 1 )
1271       AddParam( theParams, "Shape", shapes->Value(2) );
1272     AddParam( theParams, "Shape type", TopAbs_ShapeEnum( aCI.GetSubShapeType() ));
1273     AddParam( theParams, "State", TopAbs_State((int) aCI.GetTolerance() ));
1274     break;
1275   }
1276   case SHAPE_ISOLINE:
1277   {
1278     GEOMImpl_IIsoline aII (function);
1279
1280     theOperationName = "ISOLINE";
1281     AddParam(theParams, "Face", aII.GetFace());
1282     AddParam(theParams, "Isoline type", (aII.GetIsUIso() ? "U" : "V"));
1283     AddParam(theParams, "Parameter", aII.GetParameter());
1284     break;
1285   }
1286   default:
1287     return false;
1288   }
1289
1290   return true;
1291 }
1292
1293 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
1294 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
1295
1296 //modified by NIZNHY-PKV Wed Dec 28 13:48:31 2011f
1297 #include <TopoDS_Iterator.hxx>
1298 #include <TopTools_HSequenceOfShape.hxx>
1299 #include <ShapeAnalysis_FreeBounds.hxx>
1300 #include <TopTools_MapOfShape.hxx>
1301 #include <TopTools_MapOfOrientedShape.hxx>
1302 #include <BRep_Builder.hxx>
1303 #include <TopoDS_Wire.hxx>
1304
1305 //=======================================================================
1306 //function : KeepEdgesOrder
1307 //purpose  : 
1308 //=======================================================================
1309 /*
1310 void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
1311                     const Handle(TopTools_HSequenceOfShape)& aWires)
1312 {
1313   Standard_Integer aNbWires, aNbEdges;
1314   // 
1315   if (aEdges.IsNull()) {
1316     return;
1317   }
1318   //
1319   if (aWires.IsNull()) {
1320     return;
1321   }
1322   //
1323   aNbEdges=aEdges->Length();
1324   aNbWires=aWires->Length();
1325   if (!aNbEdges || !aNbWires) {
1326     return;
1327   }
1328   //-----
1329   Standard_Boolean bClosed;
1330   Standard_Integer i, j;
1331   TopoDS_Wire aWy;
1332   TopoDS_Iterator aIt;
1333   BRep_Builder aBB;
1334   TopTools_MapOfOrientedShape aMEx;
1335   //
1336   for (i=1; i<=aNbWires; ++i) {
1337     const TopoDS_Shape& aWx=aWires->Value(i);
1338     //
1339     aMEx.Clear();
1340     aIt.Initialize (aWx);
1341     for (; aIt.More(); aIt.Next()) {
1342       const TopoDS_Shape& aEx=aIt.Value();
1343       aMEx.Add(aEx);
1344     }
1345     // aWy
1346     aBB.MakeWire (aWy);
1347     for (j=1; j<=aNbEdges; ++j) {
1348       const TopoDS_Shape& aE=aEdges->Value(j);
1349       if (aMEx.Contains(aE)) {
1350         aBB.Add(aWy, aE);
1351       }
1352     }
1353     //
1354     bClosed=aWx.Closed();
1355     aWy.Closed(bClosed);
1356     //
1357     aWires->Append(aWy);
1358   }// for (i=1; i<=aNbWires; ++i) {
1359   //
1360   aWires->Remove(1, aNbWires);
1361 }
1362 */
1363 //modified by NIZNHY-PKV Wed Dec 28 13:48:34 2011t