]> SALOME platform Git repositories - modules/geom.git/blob - src/GEOMImpl/GEOMImpl_ShapeDriver.cxx
Salome HOME
6dee4254b731a34d417514fa12d82e983fb3151b
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ShapeDriver.cxx
1 // Copyright (C) 2007-2013  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.
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_IShapes.hxx>
26 #include <GEOMImpl_IVector.hxx>
27 #include <GEOMImpl_Types.hxx>
28 #include <GEOMImpl_Block6Explorer.hxx>
29
30 #include <GEOM_Function.hxx>
31
32 // OCCT Includes
33 #include <ShapeFix_Wire.hxx>
34 #include <ShapeFix_Edge.hxx>
35 #include <ShapeFix_Shape.hxx>
36
37 #include <BRep_Builder.hxx>
38 #include <BRep_Tool.hxx>
39 #include <BRepAdaptor_Curve.hxx>
40 #include <BRepAlgo_FaceRestrictor.hxx>
41 #include <BRepBuilderAPI_Copy.hxx>
42 #include <BRepBuilderAPI_Sewing.hxx>
43 #include <BRepBuilderAPI_MakeWire.hxx>
44 #include <BRepBuilderAPI_MakeEdge.hxx>
45 #include <BRepCheck.hxx>
46 #include <BRepCheck_Analyzer.hxx>
47 #include <BRepCheck_Shell.hxx>
48 #include <BRepClass3d_SolidClassifier.hxx>
49 #include <BRepLib.hxx>
50 #include <BRepLib_MakeEdge.hxx>
51 #include <BRepTools_WireExplorer.hxx>
52
53 #include <ShapeAnalysis_FreeBounds.hxx>
54
55 #include <TopAbs.hxx>
56 #include <TopExp.hxx>
57 #include <TopExp_Explorer.hxx>
58 #include <TopoDS.hxx>
59 #include <TopoDS_Shape.hxx>
60 #include <TopoDS_Edge.hxx>
61 #include <TopoDS_Wire.hxx>
62 #include <TopoDS_Shell.hxx>
63 #include <TopoDS_Solid.hxx>
64 #include <TopoDS_Compound.hxx>
65 #include <TopoDS_Iterator.hxx>
66
67 #include <TopTools_MapOfShape.hxx>
68 #include <TopTools_HSequenceOfShape.hxx>
69
70 #include <ElCLib.hxx>
71
72 #include <GCPnts_AbscissaPoint.hxx>
73
74 #include <Geom_TrimmedCurve.hxx>
75 #include <GeomAbs_CurveType.hxx>
76 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
77 #include <GeomConvert.hxx>
78 #include <GeomLProp.hxx>
79
80 #include <TColStd_SequenceOfReal.hxx>
81 #include <TColStd_HSequenceOfTransient.hxx>
82 #include <TColStd_Array1OfReal.hxx>
83 #include <TColGeom_SequenceOfCurve.hxx>
84 #include <TColGeom_Array1OfBSplineCurve.hxx>
85 #include <TColGeom_HArray1OfBSplineCurve.hxx>
86
87 #include <Precision.hxx>
88
89 #include <Standard_NullObject.hxx>
90 #include <Standard_TypeMismatch.hxx>
91 #include <Standard_ConstructionError.hxx>
92
93 //modified by NIZNHY-PKV Wed Dec 28 13:48:20 2011f
94 //static
95 //  void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
96 //                    const Handle(TopTools_HSequenceOfShape)& aWires);
97 //modified by NIZNHY-PKV Wed Dec 28 13:48:23 2011t
98
99 //=======================================================================
100 //function : GetID
101 //purpose  :
102 //=======================================================================
103 const Standard_GUID& GEOMImpl_ShapeDriver::GetID()
104 {
105   static Standard_GUID aShapeDriver("FF1BBB54-5D14-4df2-980B-3A668264EA16");
106   return aShapeDriver;
107 }
108
109
110 //=======================================================================
111 //function : GEOMImpl_ShapeDriver
112 //purpose  :
113 //=======================================================================
114 GEOMImpl_ShapeDriver::GEOMImpl_ShapeDriver()
115 {
116 }
117
118 //=======================================================================
119 //function : Execute
120 //purpose  :
121 //=======================================================================
122 Standard_Integer GEOMImpl_ShapeDriver::Execute(TFunction_Logbook& log) const
123 {
124   if (Label().IsNull()) return 0;
125   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
126
127   GEOMImpl_IShapes aCI (aFunction);
128   Standard_Integer aType = aFunction->GetType();
129
130   TopoDS_Shape aShape;
131   TCollection_AsciiString aWarning;
132
133   BRep_Builder B;
134
135   if (aType == WIRE_EDGES) {
136     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
137
138     Standard_Real aTolerance = aCI.GetTolerance();
139     if (aTolerance < Precision::Confusion())
140       aTolerance = Precision::Confusion();
141
142     aShape = MakeWireFromEdges(aShapes, aTolerance);
143   }
144   else if (aType == FACE_WIRE) {
145     Handle(GEOM_Function) aRefBase = aCI.GetBase();
146     TopoDS_Shape aShapeBase = aRefBase->GetValue();
147     if (aShapeBase.IsNull()) Standard_NullObject::Raise("Argument Shape is null");
148     TopoDS_Wire W;
149     if (aShapeBase.ShapeType() == TopAbs_WIRE) {
150       W = TopoDS::Wire(aShapeBase);
151       // check the wire is closed
152       TopoDS_Vertex aV1, aV2;
153       TopExp::Vertices(W, aV1, aV2);
154       if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
155         aShapeBase.Closed(true);
156       else
157         Standard_NullObject::Raise
158           ("Shape for face construction is not closed");
159     }
160     else if (aShapeBase.ShapeType() == TopAbs_EDGE && aShapeBase.Closed()) {
161       BRepBuilderAPI_MakeWire MW;
162       MW.Add(TopoDS::Edge(aShapeBase));
163       if (!MW.IsDone()) {
164         Standard_ConstructionError::Raise("Wire construction failed");
165       }
166       W = MW;
167     }
168     else {
169       Standard_NullObject::Raise
170         ("Shape for face construction is neither a wire nor a closed edge");
171     }
172     aWarning = GEOMImpl_Block6Explorer::MakeFace(W, aCI.GetIsPlanar(), aShape);
173     if (aShape.IsNull()) {
174       Standard_ConstructionError::Raise("Face construction failed");
175     }
176   }
177   else if (aType == FACE_WIRES) {
178     // Try to build a face from a set of wires and edges
179     int ind;
180
181     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
182     int nbshapes = aShapes->Length();
183     if (nbshapes < 1) {
184       Standard_ConstructionError::Raise("No wires or edges given");
185     }
186
187     // 1. Extract all edges from the given arguments
188     TopTools_MapOfShape aMapEdges;
189     Handle(TopTools_HSequenceOfShape) aSeqEdgesIn = new TopTools_HSequenceOfShape;
190
191     for (ind = 1; ind <= nbshapes; ind++) {
192       Handle(GEOM_Function) aRefSh_i = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
193       TopoDS_Shape aSh_i = aRefSh_i->GetValue();
194
195       TopExp_Explorer anExpE_i (aSh_i, TopAbs_EDGE);
196       for (; anExpE_i.More(); anExpE_i.Next()) {
197         if (aMapEdges.Add(anExpE_i.Current())) {
198           aSeqEdgesIn->Append(anExpE_i.Current());
199         }
200       }
201     }
202
203     // 2. Connect edges to wires of maximum length
204     Handle(TopTools_HSequenceOfShape) aSeqWiresOut;
205     ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdgesIn, Precision::Confusion(),
206                                                   /*shared*/Standard_False, aSeqWiresOut);
207     //modified by NIZNHY-PKV Wed Dec 28 13:46:55 2011f
208     //KeepEdgesOrder(aSeqEdgesIn, aSeqWiresOut);
209     //modified by NIZNHY-PKV Wed Dec 28 13:46:59 2011t
210
211     // 3. Separate closed wires
212     Handle(TopTools_HSequenceOfShape) aSeqClosedWires = new TopTools_HSequenceOfShape;
213     Handle(TopTools_HSequenceOfShape) aSeqOpenWires = new TopTools_HSequenceOfShape;
214     for (ind = 1; ind <= aSeqWiresOut->Length(); ind++) {
215       if (aSeqWiresOut->Value(ind).Closed())
216         aSeqClosedWires->Append(aSeqWiresOut->Value(ind));
217       else
218         aSeqOpenWires->Append(aSeqWiresOut->Value(ind));
219     }
220
221     if (aSeqClosedWires->Length() < 1) {
222       Standard_ConstructionError::Raise
223         ("There is no closed contour can be built from the given arguments");
224     }
225
226     // 4. Build a face / list of faces from all the obtained closed wires
227
228     // 4.a. Basic face
229     TopoDS_Shape aFFace;
230     TopoDS_Wire aW1 = TopoDS::Wire(aSeqClosedWires->Value(1));
231     aWarning = GEOMImpl_Block6Explorer::MakeFace(aW1, aCI.GetIsPlanar(), aFFace);
232     if (aFFace.IsNull()) {
233       Standard_ConstructionError::Raise("Face construction failed");
234     }
235
236     // 4.b. Add other wires
237     if (aSeqClosedWires->Length() == 1) {
238       aShape = aFFace;
239     }
240     else {
241       TopoDS_Compound C;
242       BRep_Builder aBuilder;
243       aBuilder.MakeCompound(C);
244       BRepAlgo_FaceRestrictor FR;
245
246       TopAbs_Orientation OriF = aFFace.Orientation();
247       TopoDS_Shape aLocalS = aFFace.Oriented(TopAbs_FORWARD);
248       FR.Init(TopoDS::Face(aLocalS), Standard_False, Standard_True);
249
250       for (ind = 1; ind <= aSeqClosedWires->Length(); ind++) {
251         TopoDS_Wire aW = TopoDS::Wire(aSeqClosedWires->Value(ind));
252         FR.Add(aW);
253       }
254
255       FR.Perform();
256
257       if (FR.IsDone()) {
258         int k = 0;
259         TopoDS_Shape aFace;
260         for (; FR.More(); FR.Next()) {
261           aFace = FR.Current().Oriented(OriF);
262           aBuilder.Add(C, aFace);
263           k++;
264         }
265         if (k == 1) {
266           aShape = aFace;
267         } else {
268           aShape = C;
269         }
270       }
271     }
272
273     // 5. Add all open wires to the result
274     if (aSeqOpenWires->Length() > 0) {
275       //Standard_ConstructionError::Raise("There are some open wires");
276       TopoDS_Compound C;
277       BRep_Builder aBuilder;
278       if (aSeqClosedWires->Length() == 1) {
279         aBuilder.MakeCompound(C);
280         aBuilder.Add(C, aShape);
281       }
282       else {
283         C = TopoDS::Compound(aShape);
284       }
285
286       for (ind = 1; ind <= aSeqOpenWires->Length(); ind++) {
287         aBuilder.Add(C, aSeqOpenWires->Value(ind));
288       }
289
290       aShape = C;
291     }
292   }
293   else if (aType == SHELL_FACES) {
294     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
295     unsigned int ind, nbshapes = aShapes->Length();
296
297     // add faces
298     BRepBuilderAPI_Sewing aSewing (Precision::Confusion()*10.0);
299     for (ind = 1; ind <= nbshapes; ind++) {
300       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
301       TopoDS_Shape aShape_i = aRefShape->GetValue();
302       if (aShape_i.IsNull()) {
303         Standard_NullObject::Raise("Face for shell construction is null");
304       }
305       aSewing.Add(aShape_i);
306     }
307
308     aSewing.Perform();
309
310     TopoDS_Shape sh = aSewing.SewedShape();
311
312     if (sh.ShapeType()==TopAbs_FACE && nbshapes==1) {
313       // case for creation of shell from one face - PAL12722 (skl 26.06.2006)
314       TopoDS_Shell ss;
315       B.MakeShell(ss);
316       B.Add(ss,sh);
317       aShape = ss;
318     }
319     else {
320       //TopExp_Explorer exp (aSewing.SewedShape(), TopAbs_SHELL);
321       TopExp_Explorer exp (sh, TopAbs_SHELL);
322       Standard_Integer ish = 0;
323       for (; exp.More(); exp.Next()) {
324         aShape = exp.Current();
325         ish++;
326       }
327
328       if (ish != 1) {
329         // try the case of one face (Mantis issue 0021809)
330         TopExp_Explorer expF (sh, TopAbs_FACE);
331         Standard_Integer ifa = 0;
332         for (; expF.More(); expF.Next()) {
333           aShape = expF.Current();
334           ifa++;
335         }
336
337         if (ifa == 1) {
338           TopoDS_Shell ss;
339           B.MakeShell(ss);
340           B.Add(ss,aShape);
341           aShape = ss;
342         }
343         else {
344           aShape = aSewing.SewedShape();
345         }
346       }
347     }
348
349   }
350   else if (aType == SOLID_SHELL) {
351     Handle(GEOM_Function) aRefShell = aCI.GetBase();
352     TopoDS_Shape aShapeShell = aRefShell->GetValue();
353     if (!aShapeShell.IsNull() && aShapeShell.ShapeType() == TopAbs_COMPOUND) {
354       TopoDS_Iterator It (aShapeShell, Standard_True, Standard_True);
355       if (It.More()) aShapeShell = It.Value();
356     }
357     if (aShapeShell.IsNull() || aShapeShell.ShapeType() != TopAbs_SHELL) {
358       Standard_NullObject::Raise("Shape for solid construction is null or not a shell");
359     }
360
361     BRepCheck_Shell chkShell(TopoDS::Shell(aShapeShell));
362     if (chkShell.Closed() == BRepCheck_NotClosed) return 0;
363
364     TopoDS_Solid Sol;
365     B.MakeSolid(Sol);
366     B.Add(Sol, aShapeShell);
367     BRepClass3d_SolidClassifier SC (Sol);
368     SC.PerformInfinitePoint(Precision::Confusion());
369     if (SC.State() == TopAbs_IN) {
370       B.MakeSolid(Sol);
371       B.Add(Sol, aShapeShell.Reversed());
372     }
373
374     aShape = Sol;
375
376   }
377   else if (aType == SOLID_SHELLS) {
378     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
379     unsigned int ind, nbshapes = aShapes->Length();
380     Standard_Integer ish = 0;
381     TopoDS_Solid Sol;
382     B.MakeSolid(Sol);
383
384     // add shapes
385     for (ind = 1; ind <= nbshapes; ind++) {
386       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
387       TopoDS_Shape aShapeShell = aRefShape->GetValue();
388       if (aShapeShell.IsNull()) {
389         Standard_NullObject::Raise("Shell for solid construction is null");
390       }
391       if (aShapeShell.ShapeType() == TopAbs_COMPOUND) {
392         TopoDS_Iterator It (aShapeShell, Standard_True, Standard_True);
393         if (It.More()) aShapeShell = It.Value();
394       }
395       if (aShapeShell.ShapeType() == TopAbs_SHELL) {
396         B.Add(Sol, aShapeShell);
397         ish++;
398       }
399     }
400     if (ish == 0) return 0;
401     BRepClass3d_SolidClassifier SC (Sol);
402     SC.PerformInfinitePoint(Precision::Confusion());
403     if (SC.State() == TopAbs_IN)
404       aShape = Sol.Reversed();
405     else
406       aShape = Sol;
407   }
408   else if (aType == COMPOUND_SHAPES) {
409     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
410     unsigned int ind, nbshapes = aShapes->Length();
411
412     // add shapes
413     TopoDS_Compound C;
414     B.MakeCompound(C);
415     for (ind = 1; ind <= nbshapes; ind++) {
416       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
417       TopoDS_Shape aShape_i = aRefShape->GetValue();
418       if (aShape_i.IsNull()) {
419         Standard_NullObject::Raise("Shape for compound construction is null");
420       }
421       B.Add(C, aShape_i);
422     }
423
424     aShape = C;
425
426   }
427   /*
428   else if (aType == REVERSE_ORIENTATION) {
429     Handle(GEOM_Function) aRefShape = aCI.GetBase();
430     TopoDS_Shape aShape_i = aRefShape->GetValue();
431     if (aShape_i.IsNull()) {
432        Standard_NullObject::Raise("Shape for reverse is null");
433     }
434
435     BRepBuilderAPI_Copy Copy(aShape_i);
436     if( Copy.IsDone() ) {
437       TopoDS_Shape tds = Copy.Shape();
438       if( tds.IsNull() ) {
439         Standard_ConstructionError::Raise("Orientation aborted : Can not reverse the shape");
440       }
441
442       if( tds.Orientation() == TopAbs_FORWARD)
443         tds.Orientation(TopAbs_REVERSED);
444       else
445         tds.Orientation(TopAbs_FORWARD);
446
447       aShape = tds;
448     }
449   }
450   */
451   else if (aType == EDGE_WIRE) {
452     Handle(GEOM_Function) aRefBase = aCI.GetBase();
453     TopoDS_Shape aWire = aRefBase->GetValue();
454     Standard_Real LinTol = aCI.GetTolerance();
455     Standard_Real AngTol = aCI.GetAngularTolerance();
456     if (aWire.IsNull()) Standard_NullObject::Raise("Argument Wire is null");
457
458     aShape = MakeEdgeFromWire(aWire, LinTol, AngTol);
459   }
460   else if (aType == EDGE_CURVE_LENGTH) {
461     GEOMImpl_IVector aVI (aFunction);
462
463     // RefCurve
464     Handle(GEOM_Function) aRefCurve = aVI.GetPoint1();
465     if (aRefCurve.IsNull()) Standard_NullObject::Raise("Argument Curve is null");
466     TopoDS_Shape aRefShape1 = aRefCurve->GetValue();
467     if (aRefShape1.ShapeType() != TopAbs_EDGE) {
468       Standard_TypeMismatch::Raise
469         ("Edge On Curve creation aborted : curve shape is not an edge");
470     }
471     TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
472     TopoDS_Vertex V1, V2;
473     TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
474
475     // RefPoint
476     TopoDS_Vertex aRefVertex;
477     Handle(GEOM_Function) aRefPoint = aVI.GetPoint2();
478     if (aRefPoint.IsNull()) {
479       aRefVertex = V1;
480     }
481     else {
482       TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
483       if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
484         Standard_TypeMismatch::Raise
485           ("Edge On Curve creation aborted : start point shape is not a vertex");
486       }
487       aRefVertex = TopoDS::Vertex(aRefShape2);
488     }
489     gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
490
491     // Length
492     Standard_Real aLength = aVI.GetParameter();
493     //Standard_Real aCurveLength = IntTools::Length(aRefEdge);
494     //if (aLength > aCurveLength) {
495     //  Standard_ConstructionError::Raise
496     //    ("Edge On Curve creation aborted : given length is greater than edges length");
497     //}
498     if (fabs(aLength) < Precision::Confusion()) {
499       Standard_ConstructionError::Raise
500         ("Edge On Curve creation aborted : given length is smaller than Precision::Confusion()");
501     }
502
503     // Check orientation
504     Standard_Real UFirst, ULast;
505     Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
506     Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
507
508     Standard_Real dU = ULast - UFirst;
509     Standard_Real par1 = UFirst + 0.1 * dU;
510     Standard_Real par2 = ULast  - 0.1 * dU;
511
512     gp_Pnt P1 = EdgeCurve->Value(par1);
513     gp_Pnt P2 = EdgeCurve->Value(par2);
514
515     if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
516       ReOrientedCurve = EdgeCurve->Reversed();
517       UFirst = EdgeCurve->ReversedParameter(ULast);
518     }
519
520     // Get the point by length
521     GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
522     GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst);
523     Standard_Real aParam = anAbsPnt.Parameter();
524
525     if (AdapCurve.IsClosed() && aLength < 0.0) {
526       Standard_Real aTmp = aParam;
527       aParam = UFirst;
528       UFirst = aTmp;
529     }
530
531     BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam);
532     if (aME.IsDone())
533       aShape = aME.Shape();
534   }
535   else {
536   }
537
538   if (aShape.IsNull()) return 0;
539
540   // Check shape validity
541   BRepCheck_Analyzer ana (aShape, false);
542   if (!ana.IsValid()) {
543     //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
544     // For Mantis issue 0021772: EDF 2336 GEOM: Non valid face created from two circles
545     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShape);
546     aSfs->Perform();
547     aShape = aSfs->Shape();
548   }
549
550   aFunction->SetValue(aShape);
551
552   log.SetTouched(Label());
553
554   if (!aWarning.IsEmpty())
555     Standard_Failure::Raise(aWarning.ToCString());
556
557   return 1;
558 }
559
560 TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
561                                                     const Standard_Real theTolerance)
562 {
563   BRep_Builder B;
564
565   TopoDS_Wire aWire;
566   B.MakeWire(aWire);
567
568   // add edges
569   for (unsigned int ind = 1; ind <= theEdgesFuncs->Length(); ind++) {
570     Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->Value(ind));
571     TopoDS_Shape aShape_i = aRefShape->GetValue();
572     if (aShape_i.IsNull()) {
573       Standard_NullObject::Raise("Shape for wire construction is null");
574     }
575     if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
576       TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
577       for (; exp.More(); exp.Next())
578         B.Add(aWire, TopoDS::Edge(exp.Current()));
579     } else {
580       Standard_TypeMismatch::Raise
581         ("Shape for wire construction is neither an edge nor a wire");
582     }
583   }
584
585   // fix edges order
586   Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
587   aFW->Load(aWire);
588   aFW->FixReorder();
589
590   if (aFW->StatusReorder(ShapeExtend_FAIL1)) {
591     Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
592   }
593   else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
594     Standard_ConstructionError::Raise("Wire construction failed");
595   }
596   else {
597   }
598
599   // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
600   aFW->ClosedWireMode() = Standard_False;
601   aFW->FixConnected(theTolerance);
602   if (aFW->StatusConnected(ShapeExtend_FAIL)) {
603     Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
604   }
605   // IMP 0019766
606   if (aFW->StatusConnected(ShapeExtend_DONE3)) {
607     // Confused with <prec> but not Analyzer.Precision(), set the same
608     aFW->FixGapsByRangesMode() = Standard_True;
609     if (aFW->FixGaps3d()) {
610       Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
611       Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge;
612       for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) {
613         TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge));
614         aFe->FixVertexTolerance(aEdge);
615         aFe->FixSameParameter(aEdge);
616       }
617     }
618     else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) {
619       Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps");
620     }
621   }
622   aWire = aFW->WireAPIMake();
623
624   return aWire;
625 }
626
627 TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire,
628                                                    const Standard_Real LinTol,
629                                                    const Standard_Real AngTol)
630 {
631     TopoDS_Edge ResEdge;
632
633     BRepLib::BuildCurves3d(aWire);
634     Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(aWire);
635     Fixer->SetPrecision(LinTol);
636     Fixer->SetMaxTolerance(LinTol);
637     Fixer->Perform();
638     TopoDS_Wire theWire = TopoDS::Wire(Fixer->Shape());
639
640     TColGeom_SequenceOfCurve CurveSeq;
641     TopTools_SequenceOfShape LocSeq;
642     TColStd_SequenceOfReal FparSeq;
643     TColStd_SequenceOfReal LparSeq;
644     TColStd_SequenceOfReal TolSeq;
645     GeomAbs_CurveType CurType;
646     TopoDS_Vertex FirstVertex, LastVertex;
647     Standard_Boolean FinalReverse = Standard_False;
648
649     BRepTools_WireExplorer wexp(theWire) ;
650     for (; wexp.More(); wexp.Next())
651     {
652       TopoDS_Edge anEdge = wexp.Current();
653       Standard_Real fpar, lpar;
654       TopLoc_Location aLoc;
655       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
656       if (aCurve.IsNull())
657         continue;
658
659       BRepAdaptor_Curve BAcurve(anEdge);
660       GeomAbs_CurveType aType = BAcurve.GetType();
661
662       Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
663
664       if (aBasisCurve->IsPeriodic())
665         ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
666                                Precision::PConfusion(), fpar, lpar);
667
668       if (CurveSeq.IsEmpty())
669       {
670         CurveSeq.Append(aCurve);
671         TopoDS_Shape aLocShape;
672         aLocShape.Location(aLoc);
673         aLocShape.Orientation(wexp.Orientation());
674         LocSeq.Append(aLocShape);
675         FparSeq.Append(fpar);
676         LparSeq.Append(lpar);
677         CurType = aType;
678         FirstVertex = wexp.CurrentVertex();
679         if (anEdge.Orientation() == TopAbs_REVERSED)
680           FinalReverse = Standard_True;
681       }
682       else
683       {
684         Standard_Boolean Done = Standard_False;
685         Standard_Real NewFpar, NewLpar;
686         GeomAdaptor_Curve GAprevcurve(CurveSeq.Last());
687         TopoDS_Vertex CurVertex = wexp.CurrentVertex();
688         TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
689         TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
690         if (aCurve == CurveSeq.Last())
691         {
692           NewFpar = fpar;
693           NewLpar = lpar;
694           if (aBasisCurve->IsPeriodic())
695           {
696             if (NewLpar < NewFpar)
697               NewLpar += aBasisCurve->Period();
698             if (ConnectByOrigin == TopAbs_FORWARD)
699               ElCLib::AdjustPeriodic(FparSeq.Last(),
700                                      FparSeq.Last() + aBasisCurve->Period(),
701                                      Precision::PConfusion(), NewFpar, NewLpar);
702             else
703               ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
704                                      FparSeq.Last(),
705                                      Precision::PConfusion(), NewFpar, NewLpar);
706           }
707           Done = Standard_True;
708         }
709         else if (aType == CurType &&
710                  aType != GeomAbs_BezierCurve &&
711                  aType != GeomAbs_BSplineCurve &&
712                  aType != GeomAbs_OtherCurve)
713         {
714           switch (aType)
715           {
716           case GeomAbs_Line:
717             {
718               gp_Lin aLine    = BAcurve.Line();
719               gp_Lin PrevLine = GAprevcurve.Line();
720               if (aLine.Contains(PrevLine.Location(), LinTol) &&
721                   aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
722               {
723                 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
724                 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
725                 NewFpar = ElCLib::Parameter(PrevLine, P1);
726                 NewLpar = ElCLib::Parameter(PrevLine, P2);
727                 if (NewLpar < NewFpar)
728                 {
729                   Standard_Real MemNewFpar = NewFpar;
730                   NewFpar = NewLpar;
731                   NewLpar = MemNewFpar;
732                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
733                 }
734                 Done = Standard_True;
735               }
736               break;
737             }
738           case GeomAbs_Circle:
739             {
740               gp_Circ aCircle    = BAcurve.Circle();
741               gp_Circ PrevCircle = GAprevcurve.Circle();
742               if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
743                   Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
744                   aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
745               {
746                 if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
747                 {
748                   Standard_Real memfpar = fpar;
749                   fpar = lpar;
750                   lpar = memfpar;
751                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
752                 }
753                 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
754                 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
755                 NewFpar = ElCLib::Parameter(PrevCircle, P1);
756                 NewLpar = ElCLib::Parameter(PrevCircle, P2);
757                 if (NewLpar < NewFpar)
758                   NewLpar += 2.*M_PI;
759                 //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
760                 if (ConnectByOrigin == TopAbs_FORWARD)
761                   ElCLib::AdjustPeriodic(FparSeq.Last(),
762                                          FparSeq.Last() + 2.*M_PI,
763                                          Precision::PConfusion(), NewFpar, NewLpar);
764                 else
765                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
766                                          FparSeq.Last(),
767                                          Precision::PConfusion(), NewFpar, NewLpar);
768                 Done = Standard_True;
769               }
770               break;
771             }
772           case GeomAbs_Ellipse:
773             {
774               gp_Elips anEllipse   = BAcurve.Ellipse();
775               gp_Elips PrevEllipse = GAprevcurve.Ellipse();
776               if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
777                   anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
778                   Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
779                   Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
780                   anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
781               {
782                 if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
783                 {
784                   Standard_Real memfpar = fpar;
785                   fpar = lpar;
786                   lpar = memfpar;
787                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
788                 }
789                 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
790                 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
791                 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
792                 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
793                 if (NewLpar < NewFpar)
794                   NewLpar += 2.*M_PI;
795                 if (ConnectByOrigin == TopAbs_FORWARD)
796                   ElCLib::AdjustPeriodic(FparSeq.Last(),
797                                          FparSeq.Last() + 2.*M_PI,
798                                          Precision::PConfusion(), NewFpar, NewLpar);
799                 else
800                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
801                                          FparSeq.Last(),
802                                          Precision::PConfusion(), NewFpar, NewLpar);
803                 Done = Standard_True;
804               }
805               break;
806             }
807           case GeomAbs_Hyperbola:
808             {
809               gp_Hypr aHypr    = BAcurve.Hyperbola();
810               gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
811               if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
812                   aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
813                   Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
814                   Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
815                   aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
816               {
817                 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
818                 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
819                 NewFpar = ElCLib::Parameter(PrevHypr, P1);
820                 NewLpar = ElCLib::Parameter(PrevHypr, P2);
821                 if (NewLpar < NewFpar)
822                 {
823                   Standard_Real MemNewFpar = NewFpar;
824                   NewFpar = NewLpar;
825                   NewLpar = MemNewFpar;
826                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
827                 }
828                 Done = Standard_True;
829               }
830               break;
831             }
832           case GeomAbs_Parabola:
833             {
834               gp_Parab aParab    = BAcurve.Parabola();
835               gp_Parab PrevParab = GAprevcurve.Parabola();
836               if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
837                   aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
838                   Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
839                   aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
840               {
841                 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
842                 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
843                 NewFpar = ElCLib::Parameter(PrevParab, P1);
844                 NewLpar = ElCLib::Parameter(PrevParab, P2);
845                 if (NewLpar < NewFpar)
846                 {
847                   Standard_Real MemNewFpar = NewFpar;
848                   NewFpar = NewLpar;
849                   NewLpar = MemNewFpar;
850                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
851                 }
852                 Done = Standard_True;
853               }
854               break;
855             }
856           } //end of switch (aType)
857         } // end of else if (aType == CurType && ...
858         if (Done)
859         {
860           if (NewFpar < FparSeq.Last())
861             FparSeq(FparSeq.Length()) = NewFpar;
862           else
863             LparSeq(LparSeq.Length()) = NewLpar;
864         }
865         else
866         {
867           CurveSeq.Append(aCurve);
868           TopoDS_Shape aLocShape;
869           aLocShape.Location(aLoc);
870           aLocShape.Orientation(wexp.Orientation());
871           LocSeq.Append(aLocShape);
872           FparSeq.Append(fpar);
873           LparSeq.Append(lpar);
874           TolSeq.Append(BRep_Tool::Tolerance(CurVertex));
875           CurType = aType;
876         }
877       } // end of else (CurveSeq.IsEmpty()) -> not first time
878     } // end for (; wexp.More(); wexp.Next())
879
880     LastVertex = wexp.CurrentVertex();
881     TolSeq.Append(BRep_Tool::Tolerance(LastVertex));
882
883     TopoDS_Vertex FirstVtx_final = (FinalReverse)? LastVertex : FirstVertex;
884     FirstVtx_final.Orientation(TopAbs_FORWARD);
885     TopoDS_Vertex LastVtx_final = (FinalReverse)? FirstVertex : LastVertex;
886     LastVtx_final.Orientation(TopAbs_REVERSED);
887
888     if (!CurveSeq.IsEmpty())
889     {
890       Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
891       TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
892       TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
893
894       Standard_Integer i;
895
896       if (nb_curve > 1)
897       {
898         for (i = 1; i <= nb_curve; i++)
899         {
900           if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
901             CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
902
903           Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
904           tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
905           tab(i-1)->Transform(LocSeq(i).Location().Transformation());
906           GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
907           if (LocSeq(i).Orientation() == TopAbs_REVERSED)
908             tab(i-1)->Reverse();
909
910           //Temporary
911           //char* name = new char[100];
912           //sprintf(name, "c%d", i);
913           //DrawTrSurf::Set(name, tab(i-1));
914
915           if (i > 1)
916             tabtolvertex(i-2) = TolSeq(i-1);
917         } // end for (i = 1; i <= nb_curve; i++)
918         tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length());
919
920         Standard_Boolean closed_flag = Standard_False;
921         Standard_Real closed_tolerance = 0.;
922         if (FirstVertex.IsSame(LastVertex) &&
923             GeomLProp::Continuity(tab(0), tab(nb_curve-1),
924                                   tab(0)->FirstParameter(),
925                                   tab(nb_curve-1)->LastParameter(),
926                                   Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
927         {
928           closed_flag = Standard_True ;
929           closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
930         }
931
932         Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
933         Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
934         GeomConvert::ConcatC1(tab,
935                               tabtolvertex,
936                               ArrayOfIndices,
937                               concatcurve,
938                               closed_flag,
939                               closed_tolerance);   //C1 concatenation
940
941         if (concatcurve->Length() > 1)
942         {
943           GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
944
945           for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
946             Concat.Add( concatcurve->Value(i), LinTol, Standard_True );
947
948           concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
949         }
950         // rnc : prevents the driver from building an edge without C1 continuity
951         if (concatcurve->Value(concatcurve->Lower())->Continuity()==GeomAbs_C0){
952           Standard_ConstructionError::Raise("Construction aborted : The given Wire has sharp bends between some Edges, no valid Edge can be built");
953         }
954         ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
955                                    FirstVtx_final, LastVtx_final,
956                                    concatcurve->Value(concatcurve->Lower())->FirstParameter(),
957                                    concatcurve->Value(concatcurve->Lower())->LastParameter());
958       }
959       else
960       {
961         if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
962           CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
963
964         CurveSeq(1)->Transform(LocSeq(1).Location().Transformation());
965         ResEdge = BRepLib_MakeEdge(CurveSeq(1),
966                                    FirstVtx_final, LastVtx_final,
967                                    FparSeq(1), LparSeq(1));
968       }
969     }
970
971     if (FinalReverse)
972       ResEdge.Reverse();
973
974     return ResEdge;
975 }
976
977 //=======================================================================
978 //function :  GEOMImpl_ShapeDriver_Type_
979 //purpose  :
980 //=======================================================================
981 Standard_EXPORT Handle_Standard_Type& GEOMImpl_ShapeDriver_Type_()
982 {
983
984   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
985   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
986   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
987   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
988   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
989   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
990
991
992   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
993   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_ShapeDriver",
994                                                          sizeof(GEOMImpl_ShapeDriver),
995                                                          1,
996                                                          (Standard_Address)_Ancestors,
997                                                          (Standard_Address)NULL);
998
999   return _aType;
1000 }
1001
1002 //=======================================================================
1003 //function : DownCast
1004 //purpose  :
1005 //=======================================================================
1006 const Handle(GEOMImpl_ShapeDriver) Handle(GEOMImpl_ShapeDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
1007 {
1008   Handle(GEOMImpl_ShapeDriver) _anOtherObject;
1009
1010   if (!AnObject.IsNull()) {
1011      if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_ShapeDriver))) {
1012        _anOtherObject = Handle(GEOMImpl_ShapeDriver)((Handle(GEOMImpl_ShapeDriver)&)AnObject);
1013      }
1014   }
1015
1016   return _anOtherObject;
1017 }
1018
1019 //modified by NIZNHY-PKV Wed Dec 28 13:48:31 2011f
1020 #include <TopoDS_Iterator.hxx>
1021 #include <TopTools_HSequenceOfShape.hxx>
1022 #include <ShapeAnalysis_FreeBounds.hxx>
1023 #include <TopTools_MapOfShape.hxx>
1024 #include <TopTools_MapOfOrientedShape.hxx>
1025 #include <BRep_Builder.hxx>
1026 #include <TopoDS_Wire.hxx>
1027
1028 //=======================================================================
1029 //function : KeepEdgesOrder
1030 //purpose  : 
1031 //=======================================================================
1032 /*
1033 void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
1034                     const Handle(TopTools_HSequenceOfShape)& aWires)
1035 {
1036   Standard_Integer aNbWires, aNbEdges;
1037   // 
1038   if (aEdges.IsNull()) {
1039     return;
1040   }
1041   //
1042   if (aWires.IsNull()) {
1043     return;
1044   }
1045   //
1046   aNbEdges=aEdges->Length();
1047   aNbWires=aWires->Length();
1048   if (!aNbEdges || !aNbWires) {
1049     return;
1050   }
1051   //-----
1052   Standard_Boolean bClosed;
1053   Standard_Integer i, j;
1054   TopoDS_Wire aWy;
1055   TopoDS_Iterator aIt;
1056   BRep_Builder aBB;
1057   TopTools_MapOfOrientedShape aMEx;
1058   //
1059   for (i=1; i<=aNbWires; ++i) {
1060     const TopoDS_Shape& aWx=aWires->Value(i);
1061     //
1062     aMEx.Clear();
1063     aIt.Initialize (aWx);
1064     for (; aIt.More(); aIt.Next()) {
1065       const TopoDS_Shape& aEx=aIt.Value();
1066       aMEx.Add(aEx);
1067     }
1068     // aWy
1069     aBB.MakeWire (aWy);
1070     for (j=1; j<=aNbEdges; ++j) {
1071       const TopoDS_Shape& aE=aEdges->Value(j);
1072       if (aMEx.Contains(aE)) {
1073         aBB.Add(aWy, aE);
1074       }
1075     }
1076     //
1077     bClosed=aWx.Closed();
1078     aWy.Closed(bClosed);
1079     //
1080     aWires->Append(aWy);
1081   }// for (i=1; i<=aNbWires; ++i) {
1082   //
1083   aWires->Remove(1, aNbWires);
1084 }
1085 */
1086 //modified by NIZNHY-PKV Wed Dec 28 13:48:34 2011t