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