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