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