]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
Salome HOME
0022753: [EDF] Extension of the curves and surfaces
[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   }
607   else {
608   }
609
610   if (aShape.IsNull()) return 0;
611
612   // Check shape validity
613   BRepCheck_Analyzer ana (aShape, false);
614   if (!ana.IsValid()) {
615     //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
616     // For Mantis issue 0021772: EDF 2336 GEOM: Non valid face created from two circles
617     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShape);
618     aSfs->Perform();
619     aShape = aSfs->Shape();
620   }
621
622   // Check if the result shape type is compatible with the expected.
623   const TopAbs_ShapeEnum aShType = aShape.ShapeType();
624
625   if (anExpectedType != TopAbs_SHAPE && anExpectedType != aShType) {
626     Standard_ConstructionError::Raise("Result type check failed");
627   }
628
629   aFunction->SetValue(aShape);
630
631   log.SetTouched(Label());
632
633   if (!aWarning.IsEmpty())
634     Standard_Failure::Raise(aWarning.ToCString());
635
636   return 1;
637 }
638
639 TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
640                                                     const Standard_Real theTolerance)
641 {
642   BRep_Builder B;
643
644   TopoDS_Wire aWire;
645   B.MakeWire(aWire);
646
647   // add edges
648   for (unsigned int ind = 1; ind <= theEdgesFuncs->Length(); ind++) {
649     Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->Value(ind));
650     TopoDS_Shape aShape_i = aRefShape->GetValue();
651     if (aShape_i.IsNull()) {
652       Standard_NullObject::Raise("Shape for wire construction is null");
653     }
654     if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
655       TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
656       for (; exp.More(); exp.Next())
657         B.Add(aWire, TopoDS::Edge(exp.Current()));
658     } else {
659       Standard_TypeMismatch::Raise
660         ("Shape for wire construction is neither an edge nor a wire");
661     }
662   }
663
664   // fix edges order
665   Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
666   aFW->Load(aWire);
667   aFW->FixReorder();
668
669   if (aFW->StatusReorder(ShapeExtend_FAIL1)) {
670     Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
671   }
672   else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
673     Standard_ConstructionError::Raise("Wire construction failed");
674   }
675   else {
676   }
677
678   // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
679   aFW->ClosedWireMode() = Standard_False;
680   aFW->FixConnected(theTolerance);
681   if (aFW->StatusConnected(ShapeExtend_FAIL)) {
682     Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
683   }
684   // IMP 0019766
685   if (aFW->StatusConnected(ShapeExtend_DONE3)) {
686     // Confused with <prec> but not Analyzer.Precision(), set the same
687     aFW->FixGapsByRangesMode() = Standard_True;
688     if (aFW->FixGaps3d()) {
689       Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
690       Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge;
691       for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) {
692         TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge));
693         aFe->FixVertexTolerance(aEdge);
694         aFe->FixSameParameter(aEdge);
695       }
696     }
697     else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) {
698       Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps");
699     }
700   }
701   aWire = aFW->WireAPIMake();
702
703   return aWire;
704 }
705
706 TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire,
707                                                    const Standard_Real LinTol,
708                                                    const Standard_Real AngTol)
709 {
710     TopoDS_Edge ResEdge;
711
712     BRepLib::BuildCurves3d(aWire);
713     Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(aWire);
714     Fixer->SetPrecision(LinTol);
715     Fixer->SetMaxTolerance(LinTol);
716     Fixer->Perform();
717     TopoDS_Wire theWire = TopoDS::Wire(Fixer->Shape());
718
719     TColGeom_SequenceOfCurve CurveSeq;
720     TopTools_SequenceOfShape LocSeq;
721     TColStd_SequenceOfReal FparSeq;
722     TColStd_SequenceOfReal LparSeq;
723     TColStd_SequenceOfReal TolSeq;
724     GeomAbs_CurveType CurType;
725     TopoDS_Vertex FirstVertex, LastVertex;
726     Standard_Real aPntShiftDist = 0.;
727
728     BRepTools_WireExplorer wexp(theWire) ;
729     for (; wexp.More(); wexp.Next())
730     {
731       TopoDS_Edge anEdge = wexp.Current();
732       Standard_Real fpar, lpar;
733       TopLoc_Location aLoc;
734       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
735       if (aCurve.IsNull())
736         continue;
737
738       BRepAdaptor_Curve BAcurve(anEdge);
739       GeomAbs_CurveType aType = BAcurve.GetType();
740
741       Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
742
743       if (aBasisCurve->IsPeriodic())
744         ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
745                                Precision::PConfusion(), fpar, lpar);
746
747       if (CurveSeq.IsEmpty())
748       {
749         CurveSeq.Append(aCurve);
750         TopoDS_Shape aLocShape;
751         aLocShape.Location(aLoc);
752         aLocShape.Orientation(wexp.Orientation());
753         LocSeq.Append(aLocShape);
754         FparSeq.Append(fpar);
755         LparSeq.Append(lpar);
756         CurType = aType;
757         FirstVertex = wexp.CurrentVertex();
758       }
759       else
760       {
761         Standard_Boolean Done = Standard_False;
762         Standard_Real NewFpar, NewLpar;
763         GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
764         TopoDS_Vertex CurVertex = wexp.CurrentVertex();
765         TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
766         TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
767         if (aCurve == CurveSeq.Last())
768         {
769           NewFpar = fpar;
770           NewLpar = lpar;
771           if (aBasisCurve->IsPeriodic())
772           {
773             if (NewLpar < NewFpar)
774               NewLpar += aBasisCurve->Period();
775             if (ConnectByOrigin == TopAbs_FORWARD)
776               ElCLib::AdjustPeriodic(FparSeq.Last(),
777                                      FparSeq.Last() + aBasisCurve->Period(),
778                                      Precision::PConfusion(), NewFpar, NewLpar);
779             else
780               ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
781                                      FparSeq.Last(),
782                                      Precision::PConfusion(), NewFpar, NewLpar);
783           }
784           Done = Standard_True;
785         }
786         else if (aType == CurType &&
787                  aType != GeomAbs_BezierCurve &&
788                  aType != GeomAbs_BSplineCurve &&
789                  aType != GeomAbs_OtherCurve)
790         {
791           switch (aType)
792           {
793           case GeomAbs_Line:
794             {
795               gp_Lin aLine    = BAcurve.Line();
796               gp_Lin PrevLine = GAprevcurve.Line();
797               if (aLine.Contains(PrevLine.Location(), LinTol) &&
798                   aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
799               {
800                 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
801                 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
802                 NewFpar = ElCLib::Parameter(PrevLine, P1);
803                 NewLpar = ElCLib::Parameter(PrevLine, P2);
804
805                 // Compute shift
806                 if (ConnectByOrigin == TopAbs_FORWARD) {
807                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevLine);
808
809                   aPntShiftDist += P2.Distance(aNewP2);
810                 } else {
811                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevLine);
812
813                   aPntShiftDist += P1.Distance(aNewP1);
814                 }
815
816                 if (NewLpar < NewFpar)
817                 {
818                   Standard_Real MemNewFpar = NewFpar;
819                   NewFpar = NewLpar;
820                   NewLpar = MemNewFpar;
821                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
822                 }
823                 Done = Standard_True;
824               }
825               break;
826             }
827           case GeomAbs_Circle:
828             {
829               gp_Circ aCircle    = BAcurve.Circle();
830               gp_Circ PrevCircle = GAprevcurve.Circle();
831               if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
832                   Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
833                   aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
834               {
835                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
836
837                 if (aCircle.Axis().Direction() * PrevCircle.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, aCircle);
845                 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
846                 NewFpar = ElCLib::Parameter(PrevCircle, P1);
847                 NewLpar = ElCLib::Parameter(PrevCircle, P2);
848
849                 // Compute shift
850                 if (isFwd) {
851                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevCircle);
852
853                   aPntShiftDist += P2.Distance(aNewP2);
854                 } else {
855                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevCircle);
856
857                   aPntShiftDist += P1.Distance(aNewP1);
858                 }
859
860                 if (NewLpar < NewFpar)
861                   NewLpar += 2.*M_PI;
862                 //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
863                 if (ConnectByOrigin == TopAbs_FORWARD)
864                   ElCLib::AdjustPeriodic(FparSeq.Last(),
865                                          FparSeq.Last() + 2.*M_PI,
866                                          Precision::PConfusion(), NewFpar, NewLpar);
867                 else
868                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
869                                          FparSeq.Last(),
870                                          Precision::PConfusion(), NewFpar, NewLpar);
871                 Done = Standard_True;
872               }
873               break;
874             }
875           case GeomAbs_Ellipse:
876             {
877               gp_Elips anEllipse   = BAcurve.Ellipse();
878               gp_Elips PrevEllipse = GAprevcurve.Ellipse();
879               if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
880                   anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
881                   Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
882                   Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
883                   anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
884               {
885                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
886
887                 if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
888                 {
889                   Standard_Real memfpar = fpar;
890                   fpar = lpar;
891                   lpar = memfpar;
892                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
893                 }
894                 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
895                 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
896                 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
897                 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
898
899                 // Compute shift
900                 if (isFwd) {
901                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevEllipse);
902
903                   aPntShiftDist += P2.Distance(aNewP2);
904                 } else {
905                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevEllipse);
906
907                   aPntShiftDist += P1.Distance(aNewP1);
908                 }
909
910                 if (NewLpar < NewFpar)
911                   NewLpar += 2.*M_PI;
912                 if (ConnectByOrigin == TopAbs_FORWARD)
913                   ElCLib::AdjustPeriodic(FparSeq.Last(),
914                                          FparSeq.Last() + 2.*M_PI,
915                                          Precision::PConfusion(), NewFpar, NewLpar);
916                 else
917                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
918                                          FparSeq.Last(),
919                                          Precision::PConfusion(), NewFpar, NewLpar);
920                 Done = Standard_True;
921               }
922               break;
923             }
924           case GeomAbs_Hyperbola:
925             {
926               gp_Hypr aHypr    = BAcurve.Hyperbola();
927               gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
928               if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
929                   aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
930                   Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
931                   Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
932                   aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
933               {
934                 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
935                 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
936                 NewFpar = ElCLib::Parameter(PrevHypr, P1);
937                 NewLpar = ElCLib::Parameter(PrevHypr, P2);
938
939                 // Compute shift
940                 if (ConnectByOrigin == TopAbs_FORWARD) {
941                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevHypr);
942
943                   aPntShiftDist += P2.Distance(aNewP2);
944                 } else {
945                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevHypr);
946
947                   aPntShiftDist += P1.Distance(aNewP1);
948                 }
949
950                 if (NewLpar < NewFpar)
951                 {
952                   Standard_Real MemNewFpar = NewFpar;
953                   NewFpar = NewLpar;
954                   NewLpar = MemNewFpar;
955                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
956                 }
957                 Done = Standard_True;
958               }
959               break;
960             }
961           case GeomAbs_Parabola:
962             {
963               gp_Parab aParab    = BAcurve.Parabola();
964               gp_Parab PrevParab = GAprevcurve.Parabola();
965               if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
966                   aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
967                   Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
968                   aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
969               {
970                 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
971                 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
972                 NewFpar = ElCLib::Parameter(PrevParab, P1);
973                 NewLpar = ElCLib::Parameter(PrevParab, P2);
974
975                 // Compute shift
976                 if (ConnectByOrigin == TopAbs_FORWARD) {
977                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevParab);
978
979                   aPntShiftDist += P2.Distance(aNewP2);
980                 } else {
981                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevParab);
982
983                   aPntShiftDist += P1.Distance(aNewP1);
984                 }
985
986                 if (NewLpar < NewFpar)
987                 {
988                   Standard_Real MemNewFpar = NewFpar;
989                   NewFpar = NewLpar;
990                   NewLpar = MemNewFpar;
991                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
992                 }
993                 Done = Standard_True;
994               }
995               break;
996             }
997           } //end of switch (aType)
998         } // end of else if (aType == CurType && ...
999         if (Done)
1000         {
1001           if (NewFpar < FparSeq.Last())
1002             FparSeq(FparSeq.Length()) = NewFpar;
1003           else
1004             LparSeq(LparSeq.Length()) = NewLpar;
1005         }
1006         else
1007         {
1008           CurveSeq.Append(aCurve);
1009           TopoDS_Shape aLocShape;
1010           aLocShape.Location(aLoc);
1011           aLocShape.Orientation(wexp.Orientation());
1012           LocSeq.Append(aLocShape);
1013           FparSeq.Append(fpar);
1014           LparSeq.Append(lpar);
1015           TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(CurVertex));
1016           aPntShiftDist = 0.;
1017           CurType = aType;
1018         }
1019       } // end of else (CurveSeq.IsEmpty()) -> not first time
1020     } // end for (; wexp.More(); wexp.Next())
1021
1022     LastVertex = wexp.CurrentVertex();
1023     TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(LastVertex));
1024
1025     FirstVertex.Orientation(TopAbs_FORWARD);
1026     LastVertex.Orientation(TopAbs_REVERSED);
1027
1028     if (!CurveSeq.IsEmpty())
1029     {
1030       Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
1031       TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
1032       TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
1033
1034       Standard_Integer i;
1035
1036       if (nb_curve > 1)
1037       {
1038         for (i = 1; i <= nb_curve; i++)
1039         {
1040           if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1041             CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
1042
1043           Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
1044           tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
1045           tab(i-1)->Transform(LocSeq(i).Location().Transformation());
1046           GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
1047           if (LocSeq(i).Orientation() == TopAbs_REVERSED)
1048             tab(i-1)->Reverse();
1049
1050           //Temporary
1051           //char* name = new char[100];
1052           //sprintf(name, "c%d", i);
1053           //DrawTrSurf::Set(name, tab(i-1));
1054
1055           if (i > 1)
1056             tabtolvertex(i-2) = TolSeq(i-1);
1057         } // end for (i = 1; i <= nb_curve; i++)
1058         tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length());
1059
1060         Standard_Boolean closed_flag = Standard_False;
1061         Standard_Real closed_tolerance = 0.;
1062         if (FirstVertex.IsSame(LastVertex) &&
1063             GeomLProp::Continuity(tab(0), tab(nb_curve-1),
1064                                   tab(0)->FirstParameter(),
1065                                   tab(nb_curve-1)->LastParameter(),
1066                                   Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
1067         {
1068           closed_flag = Standard_True ;
1069           closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
1070         }
1071
1072         Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
1073         Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
1074         GeomConvert::ConcatC1(tab,
1075                               tabtolvertex,
1076                               ArrayOfIndices,
1077                               concatcurve,
1078                               closed_flag,
1079                               closed_tolerance);   //C1 concatenation
1080
1081         if (concatcurve->Length() > 1)
1082         {
1083           GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
1084
1085           for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
1086             Concat.Add( concatcurve->Value(i), LinTol, Standard_True );
1087
1088           concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
1089         }
1090         // rnc : prevents the driver from building an edge without C1 continuity
1091         if (concatcurve->Value(concatcurve->Lower())->Continuity()==GeomAbs_C0){
1092           Standard_ConstructionError::Raise("Construction aborted : The given Wire has sharp bends between some Edges, no valid Edge can be built");
1093         }
1094
1095         Standard_Boolean isValidEndVtx = Standard_True;
1096
1097         if (closed_flag) {
1098           // Check if closed curve is reordered.
1099           Handle(Geom_Curve) aCurve  = concatcurve->Value(concatcurve->Lower());
1100           Standard_Real      aFPar   = aCurve->FirstParameter();
1101           gp_Pnt             aPFirst;
1102           gp_Pnt             aPntVtx = BRep_Tool::Pnt(FirstVertex);
1103           Standard_Real      aTolVtx = BRep_Tool::Tolerance(FirstVertex);
1104
1105           aCurve->D0(aFPar, aPFirst);
1106
1107           if (!aPFirst.IsEqual(aPntVtx, aTolVtx)) {
1108             // The curve is reordered. Find the new first and last vertices.
1109             TopTools_IndexedMapOfShape aMapVtx;
1110             TopExp::MapShapes(theWire, TopAbs_VERTEX, aMapVtx);
1111
1112             const Standard_Integer aNbVtx = aMapVtx.Extent();
1113             Standard_Integer       iVtx;
1114
1115             for (iVtx = 1; iVtx <= aNbVtx; iVtx++) {
1116               const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(iVtx));
1117               const gp_Pnt        aPnt = BRep_Tool::Pnt(aVtx);
1118               const Standard_Real aTol = BRep_Tool::Tolerance(aVtx);
1119
1120               if (aPFirst.IsEqual(aPnt, aTol)) {
1121                 // The coinsident vertex is found.
1122                 FirstVertex = aVtx;
1123                 LastVertex  = aVtx;
1124                 FirstVertex.Orientation(TopAbs_FORWARD);
1125                 LastVertex.Orientation(TopAbs_REVERSED);
1126                 break;
1127               }
1128             }
1129
1130             if (iVtx > aNbVtx) {
1131               // It is necessary to create new vertices.
1132               isValidEndVtx = Standard_False;
1133             }
1134           }
1135         }
1136
1137         if (isValidEndVtx) {
1138           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1139                                      FirstVertex, LastVertex,
1140                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1141                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1142         } else {
1143           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1144                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1145                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1146         }
1147       }
1148       else
1149       {
1150         if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1151           CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
1152
1153         Handle(Geom_Curve) aNewCurve =
1154           Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
1155
1156         aNewCurve->Transform(LocSeq(1).Location().Transformation());
1157
1158         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1159           const TopoDS_Vertex aVtxTmp = FirstVertex;
1160
1161           FirstVertex = LastVertex;
1162           LastVertex  = aVtxTmp;
1163           FirstVertex.Orientation(TopAbs_FORWARD);
1164           LastVertex.Orientation(TopAbs_REVERSED);
1165         }
1166
1167         ResEdge = BRepLib_MakeEdge(aNewCurve,
1168                                    FirstVertex, LastVertex,
1169                                    FparSeq(1), LparSeq(1));
1170
1171         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1172           ResEdge.Reverse();
1173         }
1174       }
1175     }
1176
1177     return ResEdge;
1178 }
1179
1180 //=============================================================================
1181 /*!
1182  * \brief Returns an isoline for a face.
1183  */
1184 //=============================================================================
1185
1186 TopoDS_Shape GEOMImpl_ShapeDriver::MakeIsoline
1187                             (const TopoDS_Face &theFace,
1188                              const bool         IsUIso,
1189                              const double       theParameter) const
1190 {
1191   TopoDS_Shape          aResult;
1192   GEOMUtils::Hatcher    aHatcher(theFace);
1193   const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV);
1194
1195   aHatcher.Init(aType, theParameter);
1196   aHatcher.Perform();
1197
1198   if (!aHatcher.IsDone()) {
1199     Standard_ConstructionError::Raise("MakeIsoline : Hatcher failure");
1200   }
1201
1202   const Handle(TColStd_HArray1OfInteger) &anIndices =
1203     (IsUIso ? aHatcher.GetUIndices() : aHatcher.GetVIndices());
1204
1205   if (anIndices.IsNull()) {
1206     Standard_ConstructionError::Raise("MakeIsoline : Null hatching indices");
1207   }
1208
1209   const Standard_Integer anIsoInd = anIndices->Lower();
1210   const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd);
1211
1212   if (aHatchingIndex == 0) {
1213     Standard_ConstructionError::Raise("MakeIsoline : Invalid hatching index");
1214   }
1215
1216   const Standard_Integer aNbDomains =
1217     aHatcher.GetNbDomains(aHatchingIndex);
1218
1219   if (aNbDomains < 0) {
1220     Standard_ConstructionError::Raise("MakeIsoline : Invalid number of domains");
1221   }
1222
1223   // The hatching is performed successfully. Create the 3d Curve.
1224   Handle(Geom_Surface) aSurface   = BRep_Tool::Surface(theFace);
1225   Handle(Geom_Curve)   anIsoCurve = (IsUIso ?
1226     aSurface->UIso(theParameter) : aSurface->VIso(theParameter));
1227   Handle(Geom2d_Curve) aPIsoCurve =
1228     aHatcher.GetHatching(aHatchingIndex);
1229   const Standard_Real  aTol = Precision::Confusion();
1230   Standard_Integer     anIDom = 1;
1231   Standard_Real        aV1;
1232   Standard_Real        aV2;
1233   BRep_Builder         aBuilder;
1234   Standard_Integer     aNbEdges = 0;
1235
1236   for (; anIDom <= aNbDomains; anIDom++) {
1237     if (aHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) {
1238       // Check first and last parameters.
1239       if (!aHatcher.IsDomainInfinite(aHatchingIndex, anIDom)) {
1240         // Create an edge.
1241         TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(anIsoCurve, aV1, aV2);
1242
1243         // Update it with a parametric curve on face.
1244         aBuilder.UpdateEdge(anEdge, aPIsoCurve, theFace, aTol);
1245         aNbEdges++;
1246
1247         if (aNbEdges > 1) {
1248           // Result is a compond.
1249           if (aNbEdges == 2) {
1250             // Create a new compound.
1251             TopoDS_Compound aCompound;
1252
1253             aBuilder.MakeCompound(aCompound);
1254             aBuilder.Add(aCompound, aResult);
1255             aResult = aCompound;
1256           }
1257
1258           // Add an edge to the compound.
1259           aBuilder.Add(aResult, anEdge);
1260         } else {
1261           // Result is the edge.
1262           aResult = anEdge;
1263         }
1264       }
1265     }
1266   }
1267
1268   if (aNbEdges == 0) {
1269     Standard_ConstructionError::Raise("MakeIsoline : Empty result");
1270   }
1271
1272   return aResult;
1273 }
1274
1275 //=============================================================================
1276 /*!
1277  * \brief Returns an extended edge.
1278  */
1279 //=============================================================================
1280
1281 TopoDS_Shape GEOMImpl_ShapeDriver::ExtendEdge
1282                          (const TopoDS_Edge   &theEdge,
1283                           const Standard_Real  theMin,
1284                           const Standard_Real  theMax) const
1285 {
1286   TopoDS_Shape        aResult;
1287   Standard_Real       aF;
1288   Standard_Real       aL;
1289   Handle(Geom_Curve)  aCurve   = BRep_Tool::Curve(theEdge, aF, aL);
1290   const Standard_Real aTol     = BRep_Tool::Tolerance(theEdge);
1291   Standard_Real       aRange2d = aL - aF;
1292
1293   if (aCurve.IsNull() == Standard_False && aRange2d > aTol) {
1294     Standard_Real aMin = aF + aRange2d*theMin;
1295     Standard_Real aMax = aF + aRange2d*theMax;
1296
1297     Handle(Standard_Type) aType = aCurve->DynamicType();
1298
1299     // Get the curve of original type
1300     while (aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
1301       Handle(Geom_TrimmedCurve) aTrCurve =
1302         Handle(Geom_TrimmedCurve)::DownCast(aCurve);
1303
1304       aCurve = aTrCurve->BasisCurve();
1305       aType  = aCurve->DynamicType();
1306     }
1307
1308     if (aCurve->IsPeriodic()) {
1309       // The curve is periodic. Check if a new range is less then a period.
1310       if (aMax - aMin > aCurve->Period()) {
1311         aMax = aMin + aCurve->Period();
1312       }
1313     } else {
1314       // The curve is not periodic. Check if aMin and aMax within bounds.
1315       aMin = Max(aMin, aCurve->FirstParameter());
1316       aMax = Min(aMax, aCurve->LastParameter());
1317     }
1318
1319     if (aMax - aMin > aTol) {
1320       // Create a new edge.
1321       BRepBuilderAPI_MakeEdge aME (aCurve, aMin, aMax);
1322
1323       if (aME.IsDone()) {
1324         aResult = aME.Shape();
1325       }
1326     }
1327   }
1328
1329   return aResult;
1330 }
1331
1332 //=============================================================================
1333 /*!
1334  * \brief Returns an extended face.
1335  */
1336 //=============================================================================
1337
1338 TopoDS_Shape GEOMImpl_ShapeDriver::ExtendFace
1339                          (const TopoDS_Face   &theFace,
1340                           const Standard_Real  theUMin,
1341                           const Standard_Real  theUMax,
1342                           const Standard_Real  theVMin,
1343                           const Standard_Real  theVMax) const
1344 {
1345   TopoDS_Shape         aResult;
1346   Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace);
1347   const Standard_Real  aTol     = BRep_Tool::Tolerance(theFace);
1348   Standard_Real        aU1;
1349   Standard_Real        aU2;
1350   Standard_Real        aV1;
1351   Standard_Real        aV2;
1352
1353   // Get U, V bounds of the face.
1354   ShapeAnalysis::GetFaceUVBounds(theFace, aU1, aU2, aV1, aV2);
1355
1356   const Standard_Real aURange = aU2 - aU1;
1357   const Standard_Real aVRange = aV2 - aV1;
1358
1359   if (aSurface.IsNull() == Standard_False &&
1360       aURange > aTol && aURange > aTol) {
1361     Handle(Standard_Type) aType = aSurface->DynamicType();
1362
1363     // Get the surface of original type
1364     while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1365       Handle(Geom_RectangularTrimmedSurface) aTrSurface =
1366         Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
1367
1368       aSurface = aTrSurface->BasisSurface();
1369       aType    = aSurface->DynamicType();
1370     }
1371
1372     Standard_Real aUMin = aU1 + aURange*theUMin;
1373     Standard_Real aUMax = aU1 + aURange*theUMax;
1374     Standard_Real aVMin = aV1 + aVRange*theVMin;
1375     Standard_Real aVMax = aV1 + aVRange*theVMax;
1376
1377     aSurface->Bounds(aU1, aU2, aV1, aV2);
1378
1379     if (aSurface->IsUPeriodic()) {
1380       // The surface is U-periodic. Check if a new U range is less
1381       // then a period.
1382       if (aUMax - aUMin > aSurface->UPeriod()) {
1383         aUMax = aUMin + aSurface->UPeriod();
1384       }
1385     } else {
1386       // The surface is not V-periodic. Check if aUMin and aUMax
1387       // within bounds.
1388       aUMin = Max(aUMin, aU1);
1389       aUMax = Min(aUMax, aU2);
1390     }
1391
1392     if (aSurface->IsVPeriodic()) {
1393       // The surface is V-periodic. Check if a new V range is less
1394       // then a period.
1395       if (aVMax - aVMin > aSurface->VPeriod()) {
1396         aVMax = aVMin + aSurface->VPeriod();
1397       }
1398     } else {
1399       // The surface is not V-periodic. Check if aVMin and aVMax
1400       // within bounds.
1401       aVMin = Max(aVMin, aV1);
1402       aVMax = Min(aVMax, aV2);
1403     }
1404
1405     if (aUMax - aUMin > aTol && aVMax - aVMin > aTol) {
1406       // Create a new edge.
1407       BRepBuilderAPI_MakeFace aMF
1408         (aSurface, aUMin, aUMax, aVMin, aVMax, aTol);
1409     
1410       if (aMF.IsDone()) {
1411         aResult = aMF.Shape();
1412       }
1413     }
1414   }
1415
1416   return aResult;
1417 }
1418
1419 //================================================================================
1420 /*!
1421  * \brief Returns a name of creation operation and names and values of creation parameters
1422  */
1423 //================================================================================
1424
1425 bool GEOMImpl_ShapeDriver::
1426 GetCreationInformation(std::string&             theOperationName,
1427                        std::vector<GEOM_Param>& theParams)
1428 {
1429   if (Label().IsNull()) return 0;
1430   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
1431
1432   GEOMImpl_IShapes aCI( function );
1433   Standard_Integer aType = function->GetType();
1434
1435   switch ( aType ) {
1436   case WIRE_EDGES:
1437     theOperationName = "WIRE";
1438     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1439     AddParam( theParams, "Tolerance", aCI.GetTolerance() );
1440     break;
1441   case FACE_WIRE:
1442     theOperationName = "FACE";
1443     AddParam( theParams, "Wire/edge", aCI.GetBase() );
1444     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1445     break;
1446   case FACE_WIRES:
1447     theOperationName = "FACE";
1448     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1449     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1450     break;
1451   case FACE_FROM_SURFACE:
1452   {
1453     theOperationName = "FACE";
1454
1455     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1456
1457     if (shapes.IsNull() == Standard_False) {
1458       Standard_Integer aNbShapes = shapes->Length();
1459
1460       if (aNbShapes > 0) {
1461         AddParam(theParams, "Face", shapes->Value(1));
1462
1463         if (aNbShapes > 1) {
1464           AddParam(theParams, "Wire", shapes->Value(2));
1465         }
1466       }
1467     }
1468     break;
1469   }
1470   case SHELL_FACES:
1471     theOperationName = "SHELL";
1472     AddParam( theParams, "Objects", aCI.GetShapes() );
1473     break;
1474   case SOLID_SHELLS:
1475     theOperationName = "SOLID";
1476     AddParam( theParams, "Objects", aCI.GetShapes() );
1477     break;
1478   case COMPOUND_SHAPES:
1479     theOperationName = "COMPOUND";
1480     AddParam( theParams, "Objects", aCI.GetShapes() );
1481     break;
1482   case EDGE_WIRE:
1483     theOperationName = "EDGE";
1484     AddParam( theParams, "Wire", aCI.GetBase() );
1485     AddParam( theParams, "Linear Tolerance", aCI.GetTolerance() );
1486     AddParam( theParams, "Angular Tolerance", aCI.GetAngularTolerance() );
1487     break;
1488   case EDGE_CURVE_LENGTH:
1489     theOperationName = "EDGE";
1490     {
1491       GEOMImpl_IVector aCI( function );
1492       AddParam( theParams, "Edge", aCI.GetPoint1() );
1493       AddParam( theParams, "Start point", aCI.GetPoint2() );
1494       AddParam( theParams, "Length", aCI.GetParameter() );
1495     }
1496     break;
1497   case SHAPES_ON_SHAPE:
1498   {
1499     theOperationName = "GetShapesOnShapeAsCompound";
1500     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1501     if ( !shapes.IsNull() && shapes->Length() > 0 )
1502       AddParam( theParams, "Check shape", shapes->Value(1) );
1503     if ( !shapes.IsNull() && shapes->Length() > 1 )
1504       AddParam( theParams, "Shape", shapes->Value(2) );
1505     AddParam( theParams, "Shape type", TopAbs_ShapeEnum( aCI.GetSubShapeType() ));
1506     AddParam( theParams, "State", TopAbs_State((int) aCI.GetTolerance() ));
1507     break;
1508   }
1509   case SHAPE_ISOLINE:
1510   {
1511     GEOMImpl_IIsoline aII (function);
1512
1513     theOperationName = "ISOLINE";
1514     AddParam(theParams, "Face", aII.GetFace());
1515     AddParam(theParams, "Isoline type", (aII.GetIsUIso() ? "U" : "V"));
1516     AddParam(theParams, "Parameter", aII.GetParameter());
1517     break;
1518   }
1519   case EDGE_UV:
1520   {
1521     GEOMImpl_IShapeExtend aSE (function);
1522
1523     theOperationName = "EDGE_EXTEND";
1524     AddParam(theParams, "Edge", aSE.GetShape());
1525     AddParam(theParams, "Min", aSE.GetUMin());
1526     AddParam(theParams, "Max", aSE.GetUMax());
1527     break;
1528   }
1529   case FACE_UV:
1530   {
1531     GEOMImpl_IShapeExtend aSE (function);
1532
1533     theOperationName = "FACE_EXTEND";
1534     AddParam(theParams, "Face", aSE.GetShape());
1535     AddParam(theParams, "UMin", aSE.GetUMin());
1536     AddParam(theParams, "UMax", aSE.GetUMax());
1537     AddParam(theParams, "VMin", aSE.GetVMin());
1538     AddParam(theParams, "VMax", aSE.GetVMax());
1539     break;
1540   }
1541   default:
1542     return false;
1543   }
1544
1545   return true;
1546 }
1547
1548 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
1549 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
1550
1551 //modified by NIZNHY-PKV Wed Dec 28 13:48:31 2011f
1552 #include <TopoDS_Iterator.hxx>
1553 #include <TopTools_HSequenceOfShape.hxx>
1554 #include <ShapeAnalysis_FreeBounds.hxx>
1555 #include <TopTools_MapOfShape.hxx>
1556 #include <TopTools_MapOfOrientedShape.hxx>
1557 #include <BRep_Builder.hxx>
1558 #include <TopoDS_Wire.hxx>
1559
1560 //=======================================================================
1561 //function : KeepEdgesOrder
1562 //purpose  : 
1563 //=======================================================================
1564 /*
1565 void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
1566                     const Handle(TopTools_HSequenceOfShape)& aWires)
1567 {
1568   Standard_Integer aNbWires, aNbEdges;
1569   // 
1570   if (aEdges.IsNull()) {
1571     return;
1572   }
1573   //
1574   if (aWires.IsNull()) {
1575     return;
1576   }
1577   //
1578   aNbEdges=aEdges->Length();
1579   aNbWires=aWires->Length();
1580   if (!aNbEdges || !aNbWires) {
1581     return;
1582   }
1583   //-----
1584   Standard_Boolean bClosed;
1585   Standard_Integer i, j;
1586   TopoDS_Wire aWy;
1587   TopoDS_Iterator aIt;
1588   BRep_Builder aBB;
1589   TopTools_MapOfOrientedShape aMEx;
1590   //
1591   for (i=1; i<=aNbWires; ++i) {
1592     const TopoDS_Shape& aWx=aWires->Value(i);
1593     //
1594     aMEx.Clear();
1595     aIt.Initialize (aWx);
1596     for (; aIt.More(); aIt.Next()) {
1597       const TopoDS_Shape& aEx=aIt.Value();
1598       aMEx.Add(aEx);
1599     }
1600     // aWy
1601     aBB.MakeWire (aWy);
1602     for (j=1; j<=aNbEdges; ++j) {
1603       const TopoDS_Shape& aE=aEdges->Value(j);
1604       if (aMEx.Contains(aE)) {
1605         aBB.Add(aWy, aE);
1606       }
1607     }
1608     //
1609     bClosed=aWx.Closed();
1610     aWy.Closed(bClosed);
1611     //
1612     aWires->Append(aWy);
1613   }// for (i=1; i<=aNbWires; ++i) {
1614   //
1615   aWires->Remove(1, aNbWires);
1616 }
1617 */
1618 //modified by NIZNHY-PKV Wed Dec 28 13:48:34 2011t