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