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