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