Salome HOME
Copyright update 2022
[modules/geom.git] / src / GEOMImpl / GEOMImpl_ShapeDriver.cxx
1 // Copyright (C) 2007-2022  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_IExtract.hxx>
26 #include <GEOMImpl_IIsoline.hxx>
27 #include <GEOMImpl_IShapes.hxx>
28 #include <GEOMImpl_IShapeExtend.hxx>
29 #include <GEOMImpl_IVector.hxx>
30 #include <GEOMImpl_Types.hxx>
31 #include <GEOMImpl_Block6Explorer.hxx>
32
33 #include <GEOM_Function.hxx>
34 #include <GEOMUtils_Hatcher.hxx>
35 #include <GEOMAlgo_State.hxx>
36 #include <GEOMAlgo_Extractor.hxx>
37
38 // OCCT Includes
39 #include <ShapeFix_Wire.hxx>
40 #include <ShapeFix_Edge.hxx>
41 #include <ShapeFix_Shape.hxx>
42
43 #include <BRep_Builder.hxx>
44 #include <BRep_Tool.hxx>
45 #include <BRepAdaptor_Curve.hxx>
46 #include <BRepAlgo_FaceRestrictor.hxx>
47 #include <BRepBuilderAPI_Copy.hxx>
48 #include <BRepBuilderAPI_Sewing.hxx>
49 #include <BRepBuilderAPI_MakeFace.hxx>
50 #include <BRepBuilderAPI_MakeWire.hxx>
51 #include <BRepBuilderAPI_MakeEdge.hxx>
52 #include <BRepBuilderAPI_MakeSolid.hxx>
53 #include <BRepCheck.hxx>
54 #include <BRepCheck_Analyzer.hxx>
55 #include <BRepCheck_Shell.hxx>
56 #include <BRepClass3d_SolidClassifier.hxx>
57 #include <BRepLib.hxx>
58 #include <BRepLib_MakeEdge.hxx>
59 #include <BRepTools_WireExplorer.hxx>
60
61 #include <ShapeAnalysis.hxx>
62 #include <ShapeAnalysis_FreeBounds.hxx>
63
64 #include <TNaming_CopyShape.hxx>
65
66 #include <TopAbs.hxx>
67 #include <TopExp.hxx>
68 #include <TopExp_Explorer.hxx>
69 #include <TopoDS.hxx>
70 #include <TopoDS_Shape.hxx>
71 #include <TopoDS_Edge.hxx>
72 #include <TopoDS_Wire.hxx>
73 #include <TopoDS_Shell.hxx>
74 #include <TopoDS_Solid.hxx>
75 #include <TopoDS_Compound.hxx>
76 #include <TopoDS_Iterator.hxx>
77
78 #include <TopTools_ListIteratorOfListOfShape.hxx>
79 #include <TopTools_ListOfShape.hxx>
80 #include <TopTools_MapOfShape.hxx>
81 #include <TopTools_HSequenceOfShape.hxx>
82
83 #include <ElCLib.hxx>
84
85 #include <GCPnts_AbscissaPoint.hxx>
86
87 #include <Geom_TrimmedCurve.hxx>
88 #include <Geom_RectangularTrimmedSurface.hxx>
89 #include <Geom_Surface.hxx>
90 #include <GeomAbs_CurveType.hxx>
91 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
92 #include <GeomConvert.hxx>
93 #include <GeomLProp.hxx>
94
95 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
96 #include <TColStd_SequenceOfReal.hxx>
97 #include <TColStd_HSequenceOfTransient.hxx>
98 #include <TColStd_Array1OfReal.hxx>
99 #include <TColGeom_SequenceOfCurve.hxx>
100 #include <TColGeom_Array1OfBSplineCurve.hxx>
101 #include <TColGeom_HArray1OfBSplineCurve.hxx>
102
103 #include <Precision.hxx>
104
105 #include <Standard_NullObject.hxx>
106 #include <Standard_TypeMismatch.hxx>
107 #include <Standard_ConstructionError.hxx>
108
109 #include <BOPAlgo_PaveFiller.hxx>
110 #include <BOPAlgo_MakerVolume.hxx>
111
112 #include <list>
113
114 /**
115  * \brief This static function converts the list of shapes into an array
116  *  of their IDs. If the input list is empty, null handle will be returned.
117  *  this method doesn't check if a shape presents in theIndices map.
118  *
119  * \param theListOfShapes the list of shapes.
120  * \param theIndices the indexed map of shapes.
121  * \return the array of shape IDs.
122  */
123 static Handle(TColStd_HArray1OfInteger) GetShapeIDs
124                   (const TopTools_ListOfShape       &theListOfShapes,
125                    const TopTools_IndexedMapOfShape &theIndices)
126 {
127   Handle(TColStd_HArray1OfInteger) aResult;
128
129   if (!theListOfShapes.IsEmpty()) {
130     const Standard_Integer             aNbShapes = theListOfShapes.Extent();
131     TopTools_ListIteratorOfListOfShape anIter(theListOfShapes);
132     Standard_Integer                   i;
133
134     aResult = new TColStd_HArray1OfInteger(1, aNbShapes);
135
136     for (i = 1; anIter.More(); anIter.Next(), ++i) {
137       const TopoDS_Shape     &aShape  = anIter.Value();
138       const Standard_Integer  anIndex = theIndices.FindIndex(aShape);
139
140       aResult->SetValue(i, anIndex);
141     }
142   }
143
144   return aResult;
145 }
146
147 namespace
148 {
149   // check that compound includes only shapes of expected type
150   bool checkCompound( TopoDS_Shape& c, TopAbs_ShapeEnum t )
151   {
152     TopoDS_Iterator it( c, Standard_True, Standard_True );
153
154     // empty compound is OK only if we explicitly create a compound of shapes
155     bool result = true;
156
157     // => if expected type is TopAbs_SHAPE, we allow compound consisting of any shapes, this above check is enough
158     // => otherwise we have to check compound's content
159     // => compound sometimes can contain enclosed compound(s), we process them recursively and rebuild initial compound
160
161     if ( t != TopAbs_SHAPE ) {
162       result = it.More();
163       std::list<TopoDS_Shape> compounds, shapes;
164       compounds.push_back( c );
165       while ( !compounds.empty() && result ) {
166         // check that compound contains only shapes of expected type
167         TopoDS_Shape cc = compounds.front();
168         compounds.pop_front();
169         it.Initialize( cc, Standard_True, Standard_True );
170         for ( ; it.More() && result; it.Next() ) {
171           TopAbs_ShapeEnum tt = it.Value().ShapeType();
172           if ( tt == TopAbs_COMPOUND || tt == TopAbs_COMPSOLID ) {
173             compounds.push_back( it.Value() );
174             continue;
175           }
176           shapes.push_back( it.Value() );
177           result = tt == t;
178         }
179       }
180       if ( result ) {
181         if ( shapes.empty() ) {
182           result = false;
183         }
184         else if ( shapes.size() == 1 ) {
185           c = shapes.front();
186         }
187         else {
188           BRep_Builder b;
189           TopoDS_Compound newc;
190           b.MakeCompound( newc );
191           std::list<TopoDS_Shape> ::const_iterator sit;
192           for ( sit = shapes.begin(); sit != shapes.end(); ++sit )
193           b.Add( newc, *sit );
194           c = newc;
195         }
196       }
197     }
198
199     return result;
200   }
201
202   /**
203    * This function adds faces from the input shape into the list of faces. If
204    * the input shape is a face, it is added itself. If it is a shell, its
205    * sub-shapes (faces) are added. If it is a compound, its sub-shapes
206    * (faces or shells) are added in the list. For null shapes and for other
207    * types of shapes an exception is thrown.
208    *
209    * @param theShape the shape to be added. Either face or shell or a compound
210    *        of faces and/or shells.
211    * @param theListFaces the list of faces that is modified on output.
212    * @param theMapFence the map that protects from adding the same faces in
213    *        the list.
214    */
215   void addFaces(const TopoDS_Shape         &theShape,
216                       TopTools_ListOfShape &theListFaces,
217                       TopTools_MapOfShape  &theMapFence)
218   {
219     if (theShape.IsNull()) {
220       Standard_NullObject::Raise("Face for shell construction is null");
221     }
222
223     // Append the shape is the mapFence
224     if (theMapFence.Add(theShape)) {
225       // Shape type
226       const TopAbs_ShapeEnum aType = theShape.ShapeType();
227
228       if (aType == TopAbs_FACE) {
229         theListFaces.Append(theShape);
230       } else if (aType == TopAbs_SHELL || aType == TopAbs_COMPOUND) {
231         TopoDS_Iterator anIter(theShape);
232
233         for (; anIter.More(); anIter.Next()) {
234           // Add sub-shapes: faces for shell or faces/shells for compound.
235           const TopoDS_Shape &aSubShape = anIter.Value();
236
237           addFaces(aSubShape, theListFaces, theMapFence);
238         }
239       } else {
240         Standard_TypeMismatch::Raise
241           ("Shape for shell construction is neither a shell nor a face");
242       }
243     }
244   }
245
246   /**
247    * This function constructs a shell or a compound of shells
248    * from a set of faces and/or shells.
249    *
250    * @param theShapes is a set of faces, shells and/or
251    *        compounds of faces/shells.
252    * @return a shell or a compound of shells.
253    */
254   TopoDS_Shape makeShellFromFaces
255         (const Handle(TColStd_HSequenceOfTransient) &theShapes)
256   {
257     const Standard_Integer aNbShapes = theShapes->Length();
258     Standard_Integer       i;
259     TopTools_ListOfShape   aListFaces;
260     TopTools_MapOfShape    aMapFence;
261     BRep_Builder           aBuilder;
262
263     // Fill the list of unique faces
264     for (i = 1; i <= aNbShapes; ++i) {
265       // Function
266       const Handle(GEOM_Function) aRefShape =
267         Handle(GEOM_Function)::DownCast(theShapes->Value(i));
268
269       if (aRefShape.IsNull()) {
270         Standard_NullObject::Raise("Face for shell construction is null");
271       }
272
273       // Shape
274       const TopoDS_Shape aShape = aRefShape->GetValue();
275
276       addFaces(aShape, aListFaces, aMapFence);
277     }
278
279     // Perform computation of shells.
280     TopTools_ListOfShape               aListShells;
281     TopTools_ListIteratorOfListOfShape anIter;
282
283     while (!aListFaces.IsEmpty()) {
284       // Perform sewing
285       BRepBuilderAPI_Sewing aSewing(Precision::Confusion()*10.0);
286
287       for (anIter.Initialize(aListFaces); anIter.More(); anIter.Next()) {
288         aSewing.Add(anIter.Value());
289       }
290
291       aSewing.Perform();
292
293       // Fill list of shells.
294       const TopoDS_Shape &aSewed = aSewing.SewedShape();
295       TopExp_Explorer     anExp(aSewed, TopAbs_SHELL);
296       Standard_Boolean    isNewShells = Standard_False;
297
298       // Append shells
299       for (; anExp.More(); anExp.Next()) {
300         aListShells.Append(anExp.Current());
301         isNewShells = Standard_True;
302       }
303
304       // Append single faces.
305       anExp.Init(aSewed, TopAbs_FACE, TopAbs_SHELL);
306
307       for (; anExp.More(); anExp.Next()) {
308         TopoDS_Shell aShell;
309
310         aBuilder.MakeShell(aShell);
311         aBuilder.Add(aShell, anExp.Current());
312         aListShells.Append(aShell);
313         isNewShells = Standard_True;
314       }
315
316       if (!isNewShells) {
317         // There are no more shell can be obtained. Break the loop.
318         break;
319       }
320
321       // Remove faces that are in the result from the list.
322       TopTools_IndexedMapOfShape aMapFaces;
323
324       TopExp::MapShapes(aSewed, TopAbs_FACE, aMapFaces);
325
326       // Add deleted faces to the map
327       const Standard_Integer aNbDelFaces = aSewing.NbDeletedFaces();
328
329       for (i = 1; i <= aNbDelFaces; ++i) {
330         aMapFaces.Add(aSewing.DeletedFace(i));
331       }
332
333       for (anIter.Initialize(aListFaces); anIter.More();) {
334         const TopoDS_Shape &aFace      = anIter.Value();
335         //Standard_Boolean    isFaceUsed = Standard_False;
336
337         if (aMapFaces.Contains(aFace) || aSewing.IsModified(aFace)) {
338           // Remove face from the list.
339           aListFaces.Remove(anIter);
340         } else {
341           // Go to the next face.
342           anIter.Next();
343         }
344       }
345     }
346
347     // If there are faces not used in shells create a shell for each face.
348     for (anIter.Initialize(aListFaces); anIter.More(); anIter.Next()) {
349       TopoDS_Shell aShell;
350
351       aBuilder.MakeShell(aShell);
352       aBuilder.Add(aShell, anIter.Value());
353       aListShells.Append(aShell);
354     }
355
356     // Construct the result that can be either a shell or a compound of shells
357     TopoDS_Shape aResult;
358
359     if (!aListShells.IsEmpty()) {
360       if (aListShells.Extent() == 1) {
361         aResult = aListShells.First();
362       } else {
363         // There are more then one shell.
364         TopoDS_Compound aCompound;
365
366         aBuilder.MakeCompound(aCompound);
367
368         for (anIter.Initialize(aListShells); anIter.More(); anIter.Next()) {
369           aBuilder.Add(aCompound, anIter.Value());
370         }
371
372         aResult = aCompound;
373       }
374     }
375
376     return aResult;
377   }
378
379   // End of namespace
380 }
381
382 //modified by NIZNHY-PKV Wed Dec 28 13:48:20 2011f
383 //static
384 //  void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
385 //                    const Handle(TopTools_HSequenceOfShape)& aWires);
386 //modified by NIZNHY-PKV Wed Dec 28 13:48:23 2011t
387
388 //=======================================================================
389 //function : GetID
390 //purpose  :
391 //=======================================================================
392 const Standard_GUID& GEOMImpl_ShapeDriver::GetID()
393 {
394   static Standard_GUID aShapeDriver("FF1BBB54-5D14-4df2-980B-3A668264EA16");
395   return aShapeDriver;
396 }
397
398
399 //=======================================================================
400 //function : GEOMImpl_ShapeDriver
401 //purpose  :
402 //=======================================================================
403 GEOMImpl_ShapeDriver::GEOMImpl_ShapeDriver()
404 {
405 }
406
407 //=======================================================================
408 //function : Execute
409 //purpose  :
410 //=======================================================================
411 Standard_Integer GEOMImpl_ShapeDriver::Execute(Handle(TFunction_Logbook)& log) const
412 {
413   if (Label().IsNull()) return 0;
414   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
415
416   GEOMImpl_IShapes aCI (aFunction);
417   Standard_Integer aType = aFunction->GetType();
418
419   TopoDS_Shape aShape;
420   TCollection_AsciiString aWarning;
421
422   // this is an exact type of expected shape, or shape in a compound if compound is allowed as a result (see below)
423   TopAbs_ShapeEnum anExpectedType = TopAbs_SHAPE;
424   // this should be true if result can be a compound of shapes of strict type (see above)
425   bool allowCompound = false;
426
427   BRep_Builder B;
428
429   if (aType == WIRE_EDGES) {
430     // result may be only a single wire
431     anExpectedType = TopAbs_WIRE;
432
433     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
434
435     Standard_Real aTolerance = aCI.GetTolerance();
436     if (aTolerance < Precision::Confusion())
437       aTolerance = Precision::Confusion();
438
439     aShape = MakeWireFromEdges(aShapes, aTolerance);
440   }
441   else if (aType == FACE_WIRE) {
442     // result may be a face or a compound of faces
443     anExpectedType = TopAbs_FACE;
444     allowCompound = true;
445
446     Handle(GEOM_Function) aRefBase = aCI.GetBase();
447     TopoDS_Shape aShapeBase = aRefBase->GetValue();
448     if (aShapeBase.IsNull()) Standard_NullObject::Raise("Argument Shape is null");
449     TopoDS_Wire W;
450     if (aShapeBase.ShapeType() == TopAbs_WIRE) {
451       W = TopoDS::Wire(aShapeBase);
452       // check the wire is closed
453       TopoDS_Vertex aV1, aV2;
454       TopExp::Vertices(W, aV1, aV2);
455       if ( !aV1.IsNull() && !aV2.IsNull() && aV1.IsSame(aV2) )
456         aShapeBase.Closed(true);
457       else
458         Standard_NullObject::Raise
459           ("Shape for face construction is not closed");
460     }
461     else if (aShapeBase.ShapeType() == TopAbs_EDGE && BRep_Tool::IsClosed(aShapeBase)) {
462       BRepBuilderAPI_MakeWire MW;
463       MW.Add(TopoDS::Edge(aShapeBase));
464       if (!MW.IsDone()) {
465         Standard_ConstructionError::Raise("Wire construction failed");
466       }
467       W = MW;
468     }
469     else {
470       Standard_NullObject::Raise
471         ("Shape for face construction is neither a wire nor a closed edge");
472     }
473     aWarning = GEOMImpl_Block6Explorer::MakeFace(W, aCI.GetIsPlanar(), aShape);
474     if (aShape.IsNull()) {
475       Standard_ConstructionError::Raise("Face construction failed");
476     }
477   }
478   else if (aType == FACE_WIRES) {
479     // result may be a face or a compound of faces
480     anExpectedType = TopAbs_FACE;
481     allowCompound = true;
482
483     // Try to build a face from a set of wires and edges
484     int ind;
485
486     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
487     int nbshapes = aShapes->Length();
488     if (nbshapes < 1) {
489       Standard_ConstructionError::Raise("No wires or edges given");
490     }
491
492     // 1. Extract all edges from the given arguments
493     TopTools_MapOfShape aMapEdges;
494     Handle(TopTools_HSequenceOfShape) aSeqEdgesIn = new TopTools_HSequenceOfShape;
495     TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
496
497     for (ind = 1; ind <= nbshapes; ind++) {
498       Handle(GEOM_Function) aRefSh_i = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
499       TopoDS_Shape aSh_i = aRefSh_i->GetValue();
500
501       TopExp_Explorer anExpE_i (aSh_i, TopAbs_EDGE);
502       for (; anExpE_i.More(); anExpE_i.Next()) {
503         if (aMapEdges.Add(anExpE_i.Current())) {
504           // Copy the original shape.
505           TopoDS_Shape aShapeCopy;
506
507           TNaming_CopyShape::CopyTool
508             (anExpE_i.Current(), aMapTShapes, aShapeCopy);
509           aSeqEdgesIn->Append(aShapeCopy);
510         }
511       }
512     }
513
514     if (aSeqEdgesIn->IsEmpty()) {
515       Standard_ConstructionError::Raise("No edges given");
516     }
517
518     // 2. Connect edges to wires of maximum length
519     Handle(TopTools_HSequenceOfShape) aSeqWiresOut;
520     ShapeAnalysis_FreeBounds::ConnectEdgesToWires(aSeqEdgesIn, Precision::Confusion(),
521                                                   /*shared*/Standard_False, aSeqWiresOut);
522     //modified by NIZNHY-PKV Wed Dec 28 13:46:55 2011f
523     //KeepEdgesOrder(aSeqEdgesIn, aSeqWiresOut);
524     //modified by NIZNHY-PKV Wed Dec 28 13:46:59 2011t
525
526     // 3. Separate closed wires
527     Handle(TopTools_HSequenceOfShape) aSeqClosedWires = new TopTools_HSequenceOfShape;
528     Handle(TopTools_HSequenceOfShape) aSeqOpenWires = new TopTools_HSequenceOfShape;
529     for (ind = 1; ind <= aSeqWiresOut->Length(); ind++) {
530       if (aSeqWiresOut->Value(ind).Closed())
531         aSeqClosedWires->Append(aSeqWiresOut->Value(ind));
532       else
533         aSeqOpenWires->Append(aSeqWiresOut->Value(ind));
534     }
535
536     if (aSeqClosedWires->Length() < 1) {
537       Standard_ConstructionError::Raise
538         ("There is no closed contour can be built from the given arguments");
539     }
540
541     // 4. Build a face / list of faces from all the obtained closed wires
542
543     // 4.a. Basic face
544     TopoDS_Shape aFFace;
545     TopoDS_Wire aW1 = TopoDS::Wire(aSeqClosedWires->Value(1));
546     aWarning = GEOMImpl_Block6Explorer::MakeFace(aW1, aCI.GetIsPlanar(), aFFace);
547     if (aFFace.IsNull()) {
548       Standard_ConstructionError::Raise("Face construction failed");
549     }
550
551     // 4.b. Add other wires
552     if (aSeqClosedWires->Length() == 1) {
553       aShape = aFFace;
554     }
555     else {
556       TopoDS_Compound C;
557       BRep_Builder aBuilder;
558       aBuilder.MakeCompound(C);
559       BRepAlgo_FaceRestrictor FR;
560
561       TopAbs_Orientation OriF = aFFace.Orientation();
562       TopoDS_Shape aLocalS = aFFace.Oriented(TopAbs_FORWARD);
563       FR.Init(TopoDS::Face(aLocalS), Standard_False, Standard_True);
564
565       for (ind = 1; ind <= aSeqClosedWires->Length(); ind++) {
566         TopoDS_Wire aW = TopoDS::Wire(aSeqClosedWires->Value(ind));
567         FR.Add(aW);
568       }
569
570       FR.Perform();
571
572       if (FR.IsDone()) {
573         int k = 0;
574         TopoDS_Shape aFace;
575         for (; FR.More(); FR.Next()) {
576           aFace = FR.Current().Oriented(OriF);
577           aBuilder.Add(C, aFace);
578           k++;
579         }
580         if (k == 1) {
581           aShape = aFace;
582         } else {
583           aShape = C;
584         }
585       }
586     }
587
588     // 5. Add all open wires to the result
589     if (aSeqOpenWires->Length() > 0) {
590       //Standard_ConstructionError::Raise("There are some open wires");
591       TopoDS_Compound C;
592       BRep_Builder aBuilder;
593       if (aSeqClosedWires->Length() == 1) {
594         aBuilder.MakeCompound(C);
595         aBuilder.Add(C, aShape);
596       }
597       else {
598         C = TopoDS::Compound(aShape);
599       }
600
601       for (ind = 1; ind <= aSeqOpenWires->Length(); ind++) {
602         aBuilder.Add(C, aSeqOpenWires->Value(ind));
603       }
604
605       aShape = C;
606     }
607   }
608   else if (aType == FACE_FROM_SURFACE) {
609     // result may be only a face
610     anExpectedType = TopAbs_FACE;
611
612     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
613
614     if (aShapes.IsNull() == Standard_False) {
615       Standard_Integer aNbShapes = aShapes->Length();
616
617       if (aNbShapes == 2) {
618         Handle(GEOM_Function) aRefFace =
619           Handle(GEOM_Function)::DownCast(aShapes->Value(1));
620         Handle(GEOM_Function) aRefWire =
621           Handle(GEOM_Function)::DownCast(aShapes->Value(2));
622
623         if (aRefFace.IsNull() == Standard_False &&
624             aRefWire.IsNull() == Standard_False) {
625           TopoDS_Shape aShFace = aRefFace->GetValue();
626           TopoDS_Shape aShWire = aRefWire->GetValue();
627
628           if (aShFace.IsNull()    == Standard_False &&
629               aShFace.ShapeType() == TopAbs_FACE    &&
630               aShWire.IsNull()    == Standard_False &&
631               aShWire.ShapeType() == TopAbs_WIRE) {
632             TopoDS_Face             aFace = TopoDS::Face(aShFace);
633             TopoDS_Wire             aWire = TopoDS::Wire(aShWire);
634             Handle(Geom_Surface)    aSurf = BRep_Tool::Surface(aFace);
635             BRepBuilderAPI_MakeFace aMkFace(aSurf, aWire);
636
637             if (aMkFace.IsDone()) {
638               aShape = aMkFace.Shape();
639             }
640           }
641         }
642       }
643     }
644   }
645   else if (aType == SHELL_FACES) {
646     // result may be only a shell or a compound of shells
647     anExpectedType = TopAbs_SHELL;
648     allowCompound = true;
649
650     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
651
652     if (aShapes.IsNull()) {
653       Standard_NullObject::Raise("Argument Shapes is null");
654     }
655
656     // Compute a shell or a compound of shells.
657     aShape = makeShellFromFaces(aShapes);
658   }
659   else if (aType == SOLID_SHELLS) {
660     // result may be only a solid or a compound of solids
661     anExpectedType = TopAbs_SOLID;
662     allowCompound = true;
663
664     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
665     unsigned int ind, nbshapes = aShapes->Length();
666     Standard_Integer ish = 0;
667     BRepBuilderAPI_MakeSolid aMkSolid;
668
669     // add shapes
670     for (ind = 1; ind <= nbshapes; ind++) {
671       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
672       TopoDS_Shape aShapeShell = aRefShape->GetValue();
673       if (aShapeShell.IsNull()) {
674         Standard_NullObject::Raise("Shell for solid construction is null");
675       }
676       if (aShapeShell.ShapeType() == TopAbs_COMPOUND) {
677         TopoDS_Iterator It (aShapeShell, Standard_True, Standard_True);
678         for (; It.More(); It.Next()) {
679           TopoDS_Shape aSubShape = It.Value();
680           if (aSubShape.ShapeType() == TopAbs_SHELL) {
681             aMkSolid.Add(TopoDS::Shell(aSubShape));
682             ish++;
683           }
684           else
685             Standard_TypeMismatch::Raise
686               ("Shape for solid construction is neither a shell nor a compound of shells");
687         }
688       }
689       else if (aShapeShell.ShapeType() == TopAbs_SHELL) {
690         aMkSolid.Add(TopoDS::Shell(aShapeShell));
691         ish++;
692       }
693     }
694     if (ish == 0 || !aMkSolid.IsDone()) return 0;
695
696     TopoDS_Solid Sol = aMkSolid.Solid();
697     BRepClass3d_SolidClassifier SC (Sol);
698     SC.PerformInfinitePoint(Precision::Confusion());
699     if (SC.State() == TopAbs_IN)
700       aShape = Sol.Reversed();
701     else
702       aShape = Sol;
703   }
704   else if (aType == COMPOUND_SHAPES) {
705     // result may be only a compound of any shapes
706     allowCompound = true;
707
708     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
709     unsigned int ind, nbshapes = aShapes->Length();
710
711     // add shapes
712     TopoDS_Compound C;
713     B.MakeCompound(C);
714     for (ind = 1; ind <= nbshapes; ind++) {
715       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
716       TopoDS_Shape aShape_i = aRefShape->GetValue();
717       if (aShape_i.IsNull()) {
718         Standard_NullObject::Raise("Shape for compound construction is null");
719       }
720       B.Add(C, aShape_i);
721     }
722
723     aShape = C;
724
725   }
726   else if (aType == EDGE_WIRE) {
727     // result may be only an edge
728     anExpectedType = TopAbs_EDGE;
729
730     Handle(GEOM_Function) aRefBase = aCI.GetBase();
731     TopoDS_Shape aWire = aRefBase->GetValue();
732     Standard_Real LinTol = aCI.GetTolerance();
733     Standard_Real AngTol = aCI.GetAngularTolerance();
734     if (aWire.IsNull()) Standard_NullObject::Raise("Argument Wire is null");
735
736     aShape = MakeEdgeFromWire(aWire, LinTol, AngTol);
737   }
738   else if (aType == SOLID_FACES) {
739     // result may be only a solid or a compound of solids
740     anExpectedType = TopAbs_SOLID;
741     allowCompound = true;
742     
743     Handle(TColStd_HSequenceOfTransient) aShapes = aCI.GetShapes();
744     unsigned int ind, nbshapes = aShapes->Length();
745     
746     // add faces
747     TopTools_ListOfShape aLS;
748     for (ind = 1; ind <= nbshapes; ind++) {
749       Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(aShapes->Value(ind));
750       TopoDS_Shape aShape_i = aRefShape->GetValue();
751       if (aShape_i.IsNull()) {
752         Standard_NullObject::Raise("Shape for solid construction is null");
753       }
754       if (aShape_i.ShapeType() == TopAbs_COMPOUND) {
755         TopoDS_Iterator It (aShape_i, Standard_True, Standard_True);
756         for (; It.More(); It.Next()) {
757           TopoDS_Shape aSubShape = It.Value();
758           if (aSubShape.ShapeType() == TopAbs_FACE || aSubShape.ShapeType() == TopAbs_SHELL)
759             aLS.Append(aSubShape);
760           else
761             Standard_TypeMismatch::Raise
762               ("Shape for solid construction is neither a list of faces and/or shells "
763                "nor a compound of faces and/or shells");
764         }
765       }
766       aLS.Append(aShape_i);
767     }
768
769     BOPAlgo_MakerVolume aMV;
770     aMV.SetArguments(aLS);
771     aMV.SetIntersect(aCI.GetIsIntersect());
772     aMV.Perform();
773     if (aMV.HasErrors()) return 0;
774
775     aShape = aMV.Shape();
776   }
777   else if (aType == EDGE_CURVE_LENGTH) {
778     // result may be only an edge
779     anExpectedType = TopAbs_EDGE;
780
781     GEOMImpl_IVector aVI (aFunction);
782
783     // RefCurve
784     Handle(GEOM_Function) aRefCurve = aVI.GetPoint1();
785     if (aRefCurve.IsNull()) Standard_NullObject::Raise("Argument Curve is null");
786     TopoDS_Shape aRefShape1 = aRefCurve->GetValue();
787     if (aRefShape1.ShapeType() != TopAbs_EDGE) {
788       Standard_TypeMismatch::Raise
789         ("Edge On Curve creation aborted : curve shape is not an edge");
790     }
791     TopoDS_Edge aRefEdge = TopoDS::Edge(aRefShape1);
792     TopoDS_Vertex V1, V2;
793     TopExp::Vertices(aRefEdge, V1, V2, Standard_True);
794
795     // RefPoint
796     TopoDS_Vertex aRefVertex;
797     Handle(GEOM_Function) aRefPoint = aVI.GetPoint2();
798     if (aRefPoint.IsNull()) {
799       aRefVertex = V1;
800     }
801     else {
802       TopoDS_Shape aRefShape2 = aRefPoint->GetValue();
803       if (aRefShape2.ShapeType() != TopAbs_VERTEX) {
804         Standard_TypeMismatch::Raise
805           ("Edge On Curve creation aborted : start point shape is not a vertex");
806       }
807       aRefVertex = TopoDS::Vertex(aRefShape2);
808     }
809     gp_Pnt aRefPnt = BRep_Tool::Pnt(aRefVertex);
810
811     // Length
812     Standard_Real aLength = aVI.GetParameter();
813     //Standard_Real aCurveLength = IntTools::Length(aRefEdge);
814     //if (aLength > aCurveLength) {
815     //  Standard_ConstructionError::Raise
816     //    ("Edge On Curve creation aborted : given length is greater than edges length");
817     //}
818     if (fabs(aLength) < Precision::Confusion()) {
819       Standard_ConstructionError::Raise
820         ("Edge On Curve creation aborted : given length is smaller than Precision::Confusion()");
821     }
822
823     // Check orientation
824     Standard_Real UFirst, ULast;
825     Handle(Geom_Curve) EdgeCurve = BRep_Tool::Curve(aRefEdge, UFirst, ULast);
826     Handle(Geom_Curve) ReOrientedCurve = EdgeCurve;
827
828     Standard_Real dU = ULast - UFirst;
829     Standard_Real par1 = UFirst + 0.1 * dU;
830     Standard_Real par2 = ULast  - 0.1 * dU;
831
832     gp_Pnt P1 = EdgeCurve->Value(par1);
833     gp_Pnt P2 = EdgeCurve->Value(par2);
834
835     if (aRefPnt.SquareDistance(P2) < aRefPnt.SquareDistance(P1)) {
836       ReOrientedCurve = EdgeCurve->Reversed();
837       UFirst = EdgeCurve->ReversedParameter(ULast);
838     }
839
840     // Get the point by length
841     GeomAdaptor_Curve AdapCurve = GeomAdaptor_Curve(ReOrientedCurve);
842     GCPnts_AbscissaPoint anAbsPnt (AdapCurve, aLength, UFirst);
843     Standard_Real aParam = anAbsPnt.Parameter();
844
845     if (AdapCurve.IsClosed() && aLength < 0.0) {
846       Standard_Real aTmp = aParam;
847       aParam = UFirst;
848       UFirst = aTmp;
849     }
850
851     BRepBuilderAPI_MakeEdge aME (ReOrientedCurve, UFirst, aParam);
852     if (aME.IsDone())
853       aShape = aME.Shape();
854   }
855   else if (aType == SHAPE_ISOLINE) {
856     // result may be only an edge or compound of edges
857     anExpectedType = TopAbs_EDGE;
858     allowCompound = true;
859
860     GEOMImpl_IIsoline     aII (aFunction);
861     Handle(GEOM_Function) aRefFace = aII.GetFace();
862     TopoDS_Shape          aShapeFace = aRefFace->GetValue();
863
864     if (aShapeFace.ShapeType() == TopAbs_FACE) {
865       TopoDS_Face   aFace  = TopoDS::Face(aShapeFace);
866       bool          isUIso = aII.GetIsUIso();
867       Standard_Real aParam = aII.GetParameter();
868       Standard_Real U1,U2,V1,V2;
869
870       // Construct a real geometric parameter.
871       aFace.Orientation(TopAbs_FORWARD);
872       ShapeAnalysis::GetFaceUVBounds(aFace,U1,U2,V1,V2);
873
874       if (isUIso) {
875         aParam = U1 + (U2 - U1)*aParam;
876       } else {
877         aParam = V1 + (V2 - V1)*aParam;
878       }
879
880       aShape = MakeIsoline(aFace, isUIso, aParam);
881     } else {
882       Standard_NullObject::Raise
883         ("Shape for isoline construction is not a face");
884     }
885   }
886   else if (aType == EDGE_UV) {
887     // result may be only an edge
888     anExpectedType = TopAbs_EDGE;
889
890     GEOMImpl_IShapeExtend aSE (aFunction);
891     Handle(GEOM_Function) aRefEdge   = aSE.GetShape();
892     TopoDS_Shape          aShapeEdge = aRefEdge->GetValue();
893
894     if (aShapeEdge.ShapeType() == TopAbs_EDGE) {
895       TopoDS_Edge anEdge = TopoDS::Edge(aShapeEdge);
896
897       aShape = ExtendEdge(anEdge, aSE.GetUMin(), aSE.GetUMax());
898     }
899   }
900   else if (aType == FACE_UV) {
901     // result may be only a face
902     anExpectedType = TopAbs_FACE;
903
904     GEOMImpl_IShapeExtend aSE (aFunction);
905     Handle(GEOM_Function) aRefFace   = aSE.GetShape();
906     TopoDS_Shape          aShapeFace = aRefFace->GetValue();
907
908     if (aShapeFace.ShapeType() == TopAbs_FACE) {
909       TopoDS_Face aFace = TopoDS::Face(aShapeFace);
910
911       aFace.Orientation(TopAbs_FORWARD);
912       aShape = ExtendFace(aFace, aSE.GetUMin(), aSE.GetUMax(),
913                           aSE.GetVMin(), aSE.GetVMax()); 
914     }
915   }
916   else if (aType == SURFACE_FROM_FACE) {
917     // result may be only a face
918     anExpectedType = TopAbs_FACE;
919
920     GEOMImpl_IShapeExtend aSE (aFunction);
921     Handle(GEOM_Function) aRefFace   = aSE.GetShape();
922     TopoDS_Shape          aShapeFace = aRefFace->GetValue();
923
924     if (aShapeFace.ShapeType() == TopAbs_FACE) {
925       TopoDS_Face          aFace    = TopoDS::Face(aShapeFace);
926       Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
927
928       if (aSurface.IsNull() == Standard_False) {
929         Handle(Standard_Type) aType = aSurface->DynamicType();
930         Standard_Real         aU1;
931         Standard_Real         aU2;
932         Standard_Real         aV1;
933         Standard_Real         aV2;
934
935          // Get U, V bounds of the face.
936         aFace.Orientation(TopAbs_FORWARD);
937         ShapeAnalysis::GetFaceUVBounds(aFace, aU1, aU2, aV1, aV2);
938
939         // Get the surface of original type
940         while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
941           Handle(Geom_RectangularTrimmedSurface) aTrSurface =
942             Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
943
944           aSurface = aTrSurface->BasisSurface();
945           aType    = aSurface->DynamicType();
946         }
947
948         const Standard_Real     aTol = BRep_Tool::Tolerance(aFace);
949         BRepBuilderAPI_MakeFace aMF(aSurface, aU1, aU2, aV1, aV2, aTol);
950
951         if (aMF.IsDone()) {
952           aShape = aMF.Shape();
953         }
954       }
955     }
956   } else if (aType == EXTRACTION) {
957     allowCompound = true;
958
959     GEOMImpl_IExtract     aCI(aFunction);
960     Handle(GEOM_Function) aRefShape  = aCI.GetShape();
961     TopoDS_Shape          aShapeBase = aRefShape->GetValue();
962
963     if (aShapeBase.IsNull()) {
964       Standard_NullObject::Raise("Argument Shape is null");
965       return 0;
966     }
967
968     Handle(TColStd_HArray1OfInteger) anIDs = aCI.GetSubShapeIDs();
969     TopTools_ListOfShape             aListSubShapes;
970     TopTools_IndexedMapOfShape       anIndices;
971     int                              i;
972
973     TopExp::MapShapes(aShapeBase, anIndices);
974
975     if (!anIDs.IsNull()) {
976       const int anUpperID = anIDs->Upper();
977       const int aNbShapes = anIndices.Extent();
978
979       for (i = anIDs->Lower(); i <= anUpperID; ++i) {
980         const Standard_Integer anIndex = anIDs->Value(i);
981
982         if (anIndex < 1 || anIndex > aNbShapes) {
983           TCollection_AsciiString aMsg(" Invalid index: ");
984
985           aMsg += TCollection_AsciiString(anIndex);
986           StdFail_NotDone::Raise(aMsg.ToCString());
987           return 0;
988         }
989
990         const TopoDS_Shape &aSubShape = anIndices.FindKey(anIndex);
991
992         aListSubShapes.Append(aSubShape);
993       }
994     }
995
996     // Compute extraction.
997     GEOMAlgo_Extractor anExtractor;
998
999     anExtractor.SetShape(aShapeBase);
1000     anExtractor.SetShapesToRemove(aListSubShapes);
1001
1002     anExtractor.Perform();
1003
1004     // Interpret results
1005     Standard_Integer iErr = anExtractor.ErrorStatus();
1006
1007     // The detailed description of error codes is in GEOMAlgo_Extractor.cxx
1008     if (iErr) {
1009       TCollection_AsciiString aMsg(" iErr : ");
1010
1011       aMsg += TCollection_AsciiString(iErr);
1012       StdFail_NotDone::Raise(aMsg.ToCString());
1013       return 0;
1014     }
1015
1016     aShape = anExtractor.GetResult();
1017
1018     if (aShape.IsNull()) {
1019       Standard_ConstructionError::Raise("Result of extraction is empty");
1020     }
1021
1022     // Get statistics.
1023     const TopTools_ListOfShape       &aRemoved    = anExtractor.GetRemoved();
1024     const TopTools_ListOfShape       &aModified   = anExtractor.GetModified();
1025     const TopTools_ListOfShape       &aNew        = anExtractor.GetNew();
1026     Handle(TColStd_HArray1OfInteger) aRemovedIDs  =
1027                           GetShapeIDs(aRemoved, anIndices);
1028     Handle(TColStd_HArray1OfInteger) aModifiedIDs =
1029                           GetShapeIDs(aModified, anIndices);
1030     Handle(TColStd_HArray1OfInteger) aNewIDs;
1031
1032     if (!aShape.IsNull()) {
1033       // Get newly created sub-shapes
1034       TopTools_IndexedMapOfShape aNewIndices;
1035
1036       TopExp::MapShapes(aShape, aNewIndices);
1037       aNewIDs = GetShapeIDs(aNew, aNewIndices);
1038     }
1039
1040     if (!aRemovedIDs.IsNull()) {
1041       aCI.SetRemovedIDs(aRemovedIDs);
1042     }
1043
1044     if (!aModifiedIDs.IsNull()) {
1045       aCI.SetModifiedIDs(aModifiedIDs);
1046     }
1047
1048     if (!aNewIDs.IsNull()) {
1049       aCI.SetAddedIDs(aNewIDs);
1050     }
1051   }
1052   else {
1053   }
1054
1055   if (aShape.IsNull()) return 0;
1056
1057   // Check shape validity
1058   BRepCheck_Analyzer ana (aShape, true);
1059   if (!ana.IsValid()) {
1060     //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
1061     // For Mantis issue 0021772: EDF 2336 GEOM: Non valid face created from two circles
1062     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShape);
1063     aSfs->Perform();
1064     aShape = aSfs->Shape();
1065   }
1066
1067   // Check if the result shape is of expected type.
1068   const TopAbs_ShapeEnum aShType = aShape.ShapeType();
1069
1070   bool ok = false;
1071   if ( aShType == TopAbs_COMPOUND || aShType == TopAbs_COMPSOLID ) {
1072     ok = allowCompound && checkCompound( aShape, anExpectedType );
1073   }
1074   else {
1075     ok = ( anExpectedType == TopAbs_SHAPE ) || ( aShType == anExpectedType );
1076   }
1077   if (!ok)
1078     Standard_ConstructionError::Raise("Result type check failed");
1079
1080   aFunction->SetValue(aShape);
1081
1082   log->SetTouched(Label());
1083
1084   if (!aWarning.IsEmpty())
1085     Standard_Failure::Raise(aWarning.ToCString());
1086
1087   return 1;
1088 }
1089
1090 TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
1091                                                     const Standard_Real theTolerance)
1092 {
1093   BRep_Builder B;
1094
1095   TopoDS_Wire aWire;
1096   B.MakeWire(aWire);
1097
1098   // add edges
1099   for (int ind = 1; ind <= theEdgesFuncs->Length(); ind++) {
1100     Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->Value(ind));
1101     TopoDS_Shape aShape_i = aRefShape->GetValue();
1102     if (aShape_i.IsNull()) {
1103       Standard_NullObject::Raise("Shape for wire construction is null");
1104     }
1105     if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
1106       TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
1107       for (; exp.More(); exp.Next())
1108         B.Add(aWire, TopoDS::Edge(exp.Current()));
1109     } else {
1110       Standard_TypeMismatch::Raise
1111         ("Shape for wire construction is neither an edge nor a wire");
1112     }
1113   }
1114
1115   // fix edges order
1116   Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
1117   aFW->Load(aWire);
1118   aFW->FixReorder();
1119
1120   if (aFW->StatusReorder(ShapeExtend_FAIL1)) {
1121     Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
1122   }
1123   else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
1124     Standard_ConstructionError::Raise("Wire construction failed");
1125   }
1126   else {
1127   }
1128
1129   // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
1130   // aaajfa
1131   bool isClosed = false;
1132   Handle(ShapeAnalysis_Wire) asaw = aFW->Analyzer();
1133   if (asaw->CheckGap3d(1)) { // between last and first edges
1134     Standard_Real dist = asaw->MinDistance3d();
1135     if (dist < theTolerance)
1136       isClosed = true;
1137   }
1138   aFW->ClosedWireMode() = isClosed;
1139   // aaajfa
1140   //aFW->ClosedWireMode() = Standard_False;
1141   aFW->FixConnected(theTolerance);
1142   if (aFW->StatusConnected(ShapeExtend_FAIL)) {
1143     Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
1144   }
1145   // IMP 0019766
1146   if (aFW->StatusConnected(ShapeExtend_DONE3)) {
1147     // Confused with <prec> but not Analyzer.Precision(), set the same
1148     aFW->FixGapsByRangesMode() = Standard_True;
1149     if (aFW->FixGaps3d()) {
1150       Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
1151       Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge;
1152       for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) {
1153         TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge));
1154         aFe->FixVertexTolerance(aEdge);
1155         aFe->FixSameParameter(aEdge);
1156       }
1157     }
1158     else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) {
1159       Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps");
1160     }
1161   }
1162   aWire = aFW->WireAPIMake();
1163
1164   return aWire;
1165 }
1166
1167 TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire,
1168                                                    const Standard_Real LinTol,
1169                                                    const Standard_Real AngTol)
1170 {
1171     TopoDS_Edge ResEdge;
1172
1173     BRepLib::BuildCurves3d(aWire);
1174     Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(aWire);
1175     Fixer->SetPrecision(LinTol);
1176     Fixer->SetMaxTolerance(LinTol);
1177     Fixer->Perform();
1178     TopoDS_Wire theWire = TopoDS::Wire(Fixer->Shape());
1179
1180     TColGeom_SequenceOfCurve CurveSeq;
1181     TopTools_SequenceOfShape LocSeq;
1182     TColStd_SequenceOfReal FparSeq;
1183     TColStd_SequenceOfReal LparSeq;
1184     TColStd_SequenceOfReal TolSeq;
1185     GeomAbs_CurveType CurType = GeomAbs_OtherCurve; // todo: refactor: CurType must be explicitly initialized to avoid warning (see below)
1186     TopoDS_Vertex FirstVertex, LastVertex;
1187     Standard_Real aPntShiftDist = 0.;
1188
1189     BRepTools_WireExplorer wexp(theWire) ;
1190     for (; wexp.More(); wexp.Next())
1191     {
1192       TopoDS_Edge anEdge = wexp.Current();
1193       Standard_Real fpar, lpar;
1194       TopLoc_Location aLoc;
1195       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
1196       if (aCurve.IsNull())
1197         continue;
1198
1199       BRepAdaptor_Curve BAcurve(anEdge);
1200       GeomAbs_CurveType aType = BAcurve.GetType();
1201
1202       Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
1203
1204       if (aBasisCurve->IsPeriodic())
1205         ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
1206                                Precision::PConfusion(), fpar, lpar);
1207
1208       if (CurveSeq.IsEmpty())
1209       {
1210         CurveSeq.Append(aCurve);
1211         TopoDS_Shape aLocShape;
1212         aLocShape.Location(aLoc);
1213         aLocShape.Orientation(wexp.Orientation());
1214         LocSeq.Append(aLocShape);
1215         FparSeq.Append(fpar);
1216         LparSeq.Append(lpar);
1217         CurType = aType;                     // todo: refactor: CurType must be explicitly initialized to avoid warning (see above)
1218         FirstVertex = wexp.CurrentVertex();
1219       }
1220       else
1221       {
1222         Standard_Boolean Done = Standard_False;
1223         Standard_Real NewFpar, NewLpar;
1224         Handle(Geom_Geometry) aTrsfGeom = CurveSeq.Last()->Transformed
1225                       (LocSeq.Last().Location().Transformation());
1226         GeomAdaptor_Curve GAprevcurve(Handle(Geom_Curve)::DownCast(aTrsfGeom));
1227         TopoDS_Vertex CurVertex = wexp.CurrentVertex();
1228         TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
1229         TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
1230         if (aCurve == CurveSeq.Last() && aLoc.IsEqual(LocSeq.Last().Location()))
1231         {
1232           NewFpar = fpar;
1233           NewLpar = lpar;
1234           if (aBasisCurve->IsPeriodic())
1235           {
1236             if (NewLpar < NewFpar)
1237               NewLpar += aBasisCurve->Period();
1238             if (ConnectByOrigin == TopAbs_FORWARD)
1239               ElCLib::AdjustPeriodic(FparSeq.Last(),
1240                                      FparSeq.Last() + aBasisCurve->Period(),
1241                                      Precision::PConfusion(), NewFpar, NewLpar);
1242             else
1243               ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
1244                                      FparSeq.Last(),
1245                                      Precision::PConfusion(), NewFpar, NewLpar);
1246           }
1247           Done = Standard_True;
1248         }
1249         else if (aType == CurType &&
1250                  aType != GeomAbs_BezierCurve &&
1251                  aType != GeomAbs_BSplineCurve &&
1252                  aType != GeomAbs_OtherCurve)
1253         {
1254           switch (aType)
1255           {
1256           case GeomAbs_Line:
1257             {
1258               gp_Lin aLine    = BAcurve.Line();
1259               gp_Lin PrevLine = GAprevcurve.Line();
1260               if (aLine.Contains(PrevLine.Location(), LinTol) &&
1261                   aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
1262               {
1263                 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
1264                 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
1265                 NewFpar = ElCLib::Parameter(PrevLine, P1);
1266                 NewLpar = ElCLib::Parameter(PrevLine, P2);
1267
1268                 // Compute shift
1269                 if (ConnectByOrigin == TopAbs_FORWARD) {
1270                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevLine);
1271
1272                   aPntShiftDist += P2.Distance(aNewP2);
1273                 } else {
1274                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevLine);
1275
1276                   aPntShiftDist += P1.Distance(aNewP1);
1277                 }
1278
1279                 if (NewLpar < NewFpar)
1280                 {
1281                   Standard_Real MemNewFpar = NewFpar;
1282                   NewFpar = NewLpar;
1283                   NewLpar = MemNewFpar;
1284                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1285                 }
1286                 Done = Standard_True;
1287               }
1288               break;
1289             }
1290           case GeomAbs_Circle:
1291             {
1292               gp_Circ aCircle    = BAcurve.Circle();
1293               gp_Circ PrevCircle = GAprevcurve.Circle();
1294               if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
1295                   Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
1296                   aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
1297               {
1298                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
1299
1300                 if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
1301                 {
1302                   Standard_Real memfpar = fpar;
1303                   fpar = lpar;
1304                   lpar = memfpar;
1305                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1306                 }
1307                 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
1308                 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
1309                 NewFpar = ElCLib::Parameter(PrevCircle, P1);
1310                 NewLpar = ElCLib::Parameter(PrevCircle, P2);
1311
1312                 // Compute shift
1313                 if (isFwd) {
1314                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevCircle);
1315
1316                   aPntShiftDist += P2.Distance(aNewP2);
1317                 } else {
1318                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevCircle);
1319
1320                   aPntShiftDist += P1.Distance(aNewP1);
1321                 }
1322
1323                 if (NewLpar < NewFpar)
1324                   NewLpar += 2.*M_PI;
1325                 //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
1326                 if (ConnectByOrigin == TopAbs_FORWARD)
1327                   ElCLib::AdjustPeriodic(FparSeq.Last(),
1328                                          FparSeq.Last() + 2.*M_PI,
1329                                          Precision::PConfusion(), NewFpar, NewLpar);
1330                 else
1331                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
1332                                          FparSeq.Last(),
1333                                          Precision::PConfusion(), NewFpar, NewLpar);
1334                 Done = Standard_True;
1335               }
1336               break;
1337             }
1338           case GeomAbs_Ellipse:
1339             {
1340               gp_Elips anEllipse   = BAcurve.Ellipse();
1341               gp_Elips PrevEllipse = GAprevcurve.Ellipse();
1342               if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
1343                   anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
1344                   Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
1345                   Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
1346                   anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
1347               {
1348                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
1349
1350                 if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
1351                 {
1352                   Standard_Real memfpar = fpar;
1353                   fpar = lpar;
1354                   lpar = memfpar;
1355                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1356                 }
1357                 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
1358                 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
1359                 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
1360                 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
1361
1362                 // Compute shift
1363                 if (isFwd) {
1364                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevEllipse);
1365
1366                   aPntShiftDist += P2.Distance(aNewP2);
1367                 } else {
1368                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevEllipse);
1369
1370                   aPntShiftDist += P1.Distance(aNewP1);
1371                 }
1372
1373                 if (NewLpar < NewFpar)
1374                   NewLpar += 2.*M_PI;
1375                 if (ConnectByOrigin == TopAbs_FORWARD)
1376                   ElCLib::AdjustPeriodic(FparSeq.Last(),
1377                                          FparSeq.Last() + 2.*M_PI,
1378                                          Precision::PConfusion(), NewFpar, NewLpar);
1379                 else
1380                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
1381                                          FparSeq.Last(),
1382                                          Precision::PConfusion(), NewFpar, NewLpar);
1383                 Done = Standard_True;
1384               }
1385               break;
1386             }
1387           case GeomAbs_Hyperbola:
1388             {
1389               gp_Hypr aHypr    = BAcurve.Hyperbola();
1390               gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
1391               if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
1392                   aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
1393                   Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
1394                   Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
1395                   aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
1396               {
1397                 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
1398                 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
1399                 NewFpar = ElCLib::Parameter(PrevHypr, P1);
1400                 NewLpar = ElCLib::Parameter(PrevHypr, P2);
1401
1402                 // Compute shift
1403                 if (ConnectByOrigin == TopAbs_FORWARD) {
1404                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevHypr);
1405
1406                   aPntShiftDist += P2.Distance(aNewP2);
1407                 } else {
1408                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevHypr);
1409
1410                   aPntShiftDist += P1.Distance(aNewP1);
1411                 }
1412
1413                 if (NewLpar < NewFpar)
1414                 {
1415                   Standard_Real MemNewFpar = NewFpar;
1416                   NewFpar = NewLpar;
1417                   NewLpar = MemNewFpar;
1418                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1419                 }
1420                 Done = Standard_True;
1421               }
1422               break;
1423             }
1424           case GeomAbs_Parabola:
1425             {
1426               gp_Parab aParab    = BAcurve.Parabola();
1427               gp_Parab PrevParab = GAprevcurve.Parabola();
1428               if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
1429                   aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
1430                   Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
1431                   aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
1432               {
1433                 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
1434                 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
1435                 NewFpar = ElCLib::Parameter(PrevParab, P1);
1436                 NewLpar = ElCLib::Parameter(PrevParab, P2);
1437
1438                 // Compute shift
1439                 if (ConnectByOrigin == TopAbs_FORWARD) {
1440                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevParab);
1441
1442                   aPntShiftDist += P2.Distance(aNewP2);
1443                 } else {
1444                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevParab);
1445
1446                   aPntShiftDist += P1.Distance(aNewP1);
1447                 }
1448
1449                 if (NewLpar < NewFpar)
1450                 {
1451                   Standard_Real MemNewFpar = NewFpar;
1452                   NewFpar = NewLpar;
1453                   NewLpar = MemNewFpar;
1454                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1455                 }
1456                 Done = Standard_True;
1457               }
1458               break;
1459             }
1460           default:
1461             break;
1462           } //end of switch (aType)
1463         } // end of else if (aType == CurType && ...
1464         if (Done)
1465         {
1466           if (NewFpar < FparSeq.Last())
1467             FparSeq(FparSeq.Length()) = NewFpar;
1468           else
1469             LparSeq(LparSeq.Length()) = NewLpar;
1470         }
1471         else
1472         {
1473           CurveSeq.Append(aCurve);
1474           TopoDS_Shape aLocShape;
1475           aLocShape.Location(aLoc);
1476           aLocShape.Orientation(wexp.Orientation());
1477           LocSeq.Append(aLocShape);
1478           FparSeq.Append(fpar);
1479           LparSeq.Append(lpar);
1480           TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(CurVertex));
1481           aPntShiftDist = 0.;
1482           CurType = aType;
1483         }
1484       } // end of else (CurveSeq.IsEmpty()) -> not first time
1485     } // end for (; wexp.More(); wexp.Next())
1486
1487     LastVertex = wexp.CurrentVertex();
1488     TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(LastVertex));
1489
1490     FirstVertex.Orientation(TopAbs_FORWARD);
1491     LastVertex.Orientation(TopAbs_REVERSED);
1492
1493     if (!CurveSeq.IsEmpty())
1494     {
1495       Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
1496       TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
1497       TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
1498
1499       Standard_Integer i;
1500
1501       if (nb_curve > 1)
1502       {
1503         for (i = 1; i <= nb_curve; i++)
1504         {
1505           if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1506             CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
1507
1508           Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
1509           tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
1510           tab(i-1)->Transform(LocSeq(i).Location().Transformation());
1511           GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
1512           if (LocSeq(i).Orientation() == TopAbs_REVERSED)
1513             tab(i-1)->Reverse();
1514
1515           //Temporary
1516           //char* name = new char[100];
1517           //sprintf(name, "c%d", i);
1518           //DrawTrSurf::Set(name, tab(i-1));
1519
1520           if (i > 1)
1521             tabtolvertex(i-2) = TolSeq(i-1);
1522         } // end for (i = 1; i <= nb_curve; i++)
1523         tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length());
1524
1525         Standard_Boolean closed_flag = Standard_False;
1526         Standard_Real closed_tolerance = 0.;
1527         if (FirstVertex.IsSame(LastVertex) &&
1528             GeomLProp::Continuity(tab(0), tab(nb_curve-1),
1529                                   tab(0)->FirstParameter(),
1530                                   tab(nb_curve-1)->LastParameter(),
1531                                   Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
1532         {
1533           closed_flag = Standard_True ;
1534           closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
1535         }
1536
1537         Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
1538         Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
1539         GeomConvert::ConcatC1(tab,
1540                               tabtolvertex,
1541                               ArrayOfIndices,
1542                               concatcurve,
1543                               closed_flag,
1544                               closed_tolerance);   //C1 concatenation
1545
1546         if (concatcurve->Length() > 1)
1547         {
1548           GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
1549
1550           for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
1551             Concat.Add( concatcurve->Value(i), LinTol, Standard_True );
1552
1553           concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
1554         }
1555         // rnc : prevents the driver from building an edge without C1 continuity
1556         if (concatcurve->Value(concatcurve->Lower())->Continuity()==GeomAbs_C0){
1557           Standard_ConstructionError::Raise("Construction aborted : The given Wire has sharp bends between some Edges, no valid Edge can be built");
1558         }
1559
1560         Standard_Boolean isValidEndVtx = Standard_True;
1561
1562         if (closed_flag) {
1563           // Check if closed curve is reordered.
1564           Handle(Geom_BSplineCurve) aCurve  = concatcurve->Value(concatcurve->Lower());
1565           Standard_Real      aFPar   = aCurve->FirstParameter();
1566           gp_Pnt             aPFirst;
1567           gp_Pnt             aPntVtx = BRep_Tool::Pnt(FirstVertex);
1568           Standard_Real      aTolVtx = BRep_Tool::Tolerance(FirstVertex);
1569
1570           aCurve->D0(aFPar, aPFirst);
1571
1572           if (!aPFirst.IsEqual(aPntVtx, aTolVtx)) {
1573             // The curve is reordered. Find the new first and last vertices.
1574             TopTools_IndexedMapOfShape aMapVtx;
1575             TopExp::MapShapes(theWire, TopAbs_VERTEX, aMapVtx);
1576
1577             const Standard_Integer aNbVtx = aMapVtx.Extent();
1578             Standard_Integer       iVtx;
1579
1580             for (iVtx = 1; iVtx <= aNbVtx; iVtx++) {
1581               const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(iVtx));
1582               const gp_Pnt        aPnt = BRep_Tool::Pnt(aVtx);
1583               const Standard_Real aTol = BRep_Tool::Tolerance(aVtx);
1584
1585               if (aPFirst.IsEqual(aPnt, aTol)) {
1586                 // The coincident vertex is found.
1587                 FirstVertex = aVtx;
1588                 LastVertex  = aVtx;
1589                 FirstVertex.Orientation(TopAbs_FORWARD);
1590                 LastVertex.Orientation(TopAbs_REVERSED);
1591                 break;
1592               }
1593             }
1594
1595             if (iVtx > aNbVtx) {
1596               // It is necessary to create new vertices.
1597               isValidEndVtx = Standard_False;
1598             }
1599           }
1600         }
1601
1602         if (isValidEndVtx) {
1603           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1604                                      FirstVertex, LastVertex,
1605                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1606                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1607         } else {
1608           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1609                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1610                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1611         }
1612       }
1613       else
1614       {
1615         if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1616           CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
1617
1618         Handle(Geom_Curve) aNewCurve =
1619           Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
1620
1621         aNewCurve->Transform(LocSeq(1).Location().Transformation());
1622
1623         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1624           const TopoDS_Vertex aVtxTmp = FirstVertex;
1625
1626           FirstVertex = LastVertex;
1627           LastVertex  = aVtxTmp;
1628           FirstVertex.Orientation(TopAbs_FORWARD);
1629           LastVertex.Orientation(TopAbs_REVERSED);
1630         }
1631
1632         ResEdge = BRepLib_MakeEdge(aNewCurve,
1633                                    FirstVertex, LastVertex,
1634                                    FparSeq(1), LparSeq(1));
1635
1636         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1637           ResEdge.Reverse();
1638         }
1639       }
1640     }
1641
1642     return ResEdge;
1643 }
1644
1645 //=============================================================================
1646 /*!
1647  * \brief Returns an isoline for a face.
1648  */
1649 //=============================================================================
1650
1651 TopoDS_Shape GEOMImpl_ShapeDriver::MakeIsoline
1652                             (const TopoDS_Face &theFace,
1653                              const bool         IsUIso,
1654                              const double       theParameter) const
1655 {
1656   TopoDS_Shape          aResult;
1657   GEOMUtils::Hatcher    aHatcher(theFace);
1658   const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV);
1659
1660   aHatcher.Init(aType, theParameter);
1661   aHatcher.Perform();
1662
1663   if (!aHatcher.IsDone()) {
1664     Standard_ConstructionError::Raise("MakeIsoline : Hatcher failure");
1665   }
1666
1667   const Handle(TColStd_HArray1OfInteger) &anIndices =
1668     (IsUIso ? aHatcher.GetUIndices() : aHatcher.GetVIndices());
1669
1670   if (anIndices.IsNull()) {
1671     Standard_ConstructionError::Raise("MakeIsoline : Null hatching indices");
1672   }
1673
1674   const Standard_Integer anIsoInd = anIndices->Lower();
1675   const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd);
1676
1677   if (aHatchingIndex == 0) {
1678     Standard_ConstructionError::Raise("MakeIsoline : Invalid hatching index");
1679   }
1680
1681   const Standard_Integer aNbDomains =
1682     aHatcher.GetNbDomains(aHatchingIndex);
1683
1684   if (aNbDomains < 0) {
1685     Standard_ConstructionError::Raise("MakeIsoline : Invalid number of domains");
1686   }
1687
1688   // The hatching is performed successfully. Create the 3d Curve.
1689   Handle(Geom_Surface) aSurface   = BRep_Tool::Surface(theFace);
1690   Handle(Geom_Curve)   anIsoCurve = (IsUIso ?
1691     aSurface->UIso(theParameter) : aSurface->VIso(theParameter));
1692   Handle(Geom2d_Curve) aPIsoCurve = aHatcher.GetHatching(aHatchingIndex);
1693
1694   Standard_Real aTol = BRep_Tool::MaxTolerance(theFace, TopAbs_EDGE);
1695
1696   Standard_Integer     anIDom = 1;
1697   Standard_Real        aV1;
1698   Standard_Real        aV2;
1699   BRep_Builder         aBuilder;
1700   Standard_Integer     aNbEdges = 0;
1701
1702   for (; anIDom <= aNbDomains; anIDom++) {
1703     if (aHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) {
1704       // Check first and last parameters.
1705       if (!aHatcher.IsDomainInfinite(aHatchingIndex, anIDom)) {
1706         // Create an edge.
1707         TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(anIsoCurve, aV1, aV2);
1708
1709         // Update it with a parametric curve on face.
1710         aBuilder.UpdateEdge(anEdge, aPIsoCurve, theFace, aTol);
1711         for (TopExp_Explorer ExV (anEdge, TopAbs_VERTEX); ExV.More(); ExV.Next()) {
1712           TopoDS_Vertex V = TopoDS::Vertex(ExV.Current());
1713           aBuilder.UpdateVertex(V, aTol);
1714         }
1715         aNbEdges++;
1716
1717         if (aNbEdges > 1) {
1718           // Result is a compond.
1719           if (aNbEdges == 2) {
1720             // Create a new compound.
1721             TopoDS_Compound aCompound;
1722
1723             aBuilder.MakeCompound(aCompound);
1724             aBuilder.Add(aCompound, aResult);
1725             aResult = aCompound;
1726           }
1727
1728           // Add an edge to the compound.
1729           aBuilder.Add(aResult, anEdge);
1730         } else {
1731           // Result is the edge.
1732           aResult = anEdge;
1733         }
1734       }
1735     }
1736   }
1737
1738   if (aNbEdges == 0) {
1739     Standard_ConstructionError::Raise("MakeIsoline : Empty result");
1740   }
1741
1742   return aResult;
1743 }
1744
1745 //=============================================================================
1746 /*!
1747  * \brief Returns an extended edge.
1748  */
1749 //=============================================================================
1750
1751 TopoDS_Shape GEOMImpl_ShapeDriver::ExtendEdge
1752                          (const TopoDS_Edge   &theEdge,
1753                           const Standard_Real  theMin,
1754                           const Standard_Real  theMax) const
1755 {
1756   TopoDS_Shape        aResult;
1757   Standard_Real       aF;
1758   Standard_Real       aL;
1759   Handle(Geom_Curve)  aCurve   = BRep_Tool::Curve(theEdge, aF, aL);
1760   const Standard_Real aTol     = BRep_Tool::Tolerance(theEdge);
1761   Standard_Real       aRange2d = aL - aF;
1762
1763   if (aCurve.IsNull() == Standard_False && aRange2d > aTol) {
1764     Standard_Real aMin = aF + aRange2d*theMin;
1765     Standard_Real aMax = aF + aRange2d*theMax;
1766
1767     Handle(Standard_Type) aType = aCurve->DynamicType();
1768
1769     // Get the curve of original type
1770     while (aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
1771       Handle(Geom_TrimmedCurve) aTrCurve =
1772         Handle(Geom_TrimmedCurve)::DownCast(aCurve);
1773
1774       aCurve = aTrCurve->BasisCurve();
1775       aType  = aCurve->DynamicType();
1776     }
1777
1778     if (aCurve->IsPeriodic()) {
1779       // The curve is periodic. Check if a new range is less then a period.
1780       if (aMax - aMin > aCurve->Period()) {
1781         aMax = aMin + aCurve->Period();
1782       }
1783     } else {
1784       // The curve is not periodic. Check if aMin and aMax within bounds.
1785       aMin = Max(aMin, aCurve->FirstParameter());
1786       aMax = Min(aMax, aCurve->LastParameter());
1787     }
1788
1789     if (aMax - aMin > aTol) {
1790       // Create a new edge.
1791       BRepBuilderAPI_MakeEdge aME (aCurve, aMin, aMax);
1792
1793       if (aME.IsDone()) {
1794         aResult = aME.Shape();
1795       }
1796     }
1797   }
1798
1799   return aResult;
1800 }
1801
1802 //=============================================================================
1803 /*!
1804  * \brief Returns an extended face.
1805  */
1806 //=============================================================================
1807
1808 TopoDS_Shape GEOMImpl_ShapeDriver::ExtendFace
1809                          (const TopoDS_Face   &theFace,
1810                           const Standard_Real  theUMin,
1811                           const Standard_Real  theUMax,
1812                           const Standard_Real  theVMin,
1813                           const Standard_Real  theVMax) const
1814 {
1815   TopoDS_Shape         aResult;
1816   Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace);
1817   const Standard_Real  aTol     = BRep_Tool::Tolerance(theFace);
1818   Standard_Real        aU1;
1819   Standard_Real        aU2;
1820   Standard_Real        aV1;
1821   Standard_Real        aV2;
1822
1823   // Get U, V bounds of the face.
1824   ShapeAnalysis::GetFaceUVBounds(theFace, aU1, aU2, aV1, aV2);
1825
1826   const Standard_Real aURange = aU2 - aU1;
1827   const Standard_Real aVRange = aV2 - aV1;
1828
1829   if (aSurface.IsNull() == Standard_False &&
1830       aURange > aTol && aURange > aTol) {
1831     Handle(Standard_Type) aType = aSurface->DynamicType();
1832
1833     // Get the surface of original type
1834     while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1835       Handle(Geom_RectangularTrimmedSurface) aTrSurface =
1836         Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
1837
1838       aSurface = aTrSurface->BasisSurface();
1839       aType    = aSurface->DynamicType();
1840     }
1841
1842     Standard_Real aUMin = aU1 + aURange*theUMin;
1843     Standard_Real aUMax = aU1 + aURange*theUMax;
1844     Standard_Real aVMin = aV1 + aVRange*theVMin;
1845     Standard_Real aVMax = aV1 + aVRange*theVMax;
1846
1847     aSurface->Bounds(aU1, aU2, aV1, aV2);
1848
1849     if (aSurface->IsUPeriodic()) {
1850       // The surface is U-periodic. Check if a new U range is less
1851       // then a period.
1852       if (aUMax - aUMin > aSurface->UPeriod()) {
1853         aUMax = aUMin + aSurface->UPeriod();
1854       }
1855     } else {
1856       // The surface is not V-periodic. Check if aUMin and aUMax
1857       // within bounds.
1858       aUMin = Max(aUMin, aU1);
1859       aUMax = Min(aUMax, aU2);
1860     }
1861
1862     if (aSurface->IsVPeriodic()) {
1863       // The surface is V-periodic. Check if a new V range is less
1864       // then a period.
1865       if (aVMax - aVMin > aSurface->VPeriod()) {
1866         aVMax = aVMin + aSurface->VPeriod();
1867       }
1868     } else {
1869       // The surface is not V-periodic. Check if aVMin and aVMax
1870       // within bounds.
1871       aVMin = Max(aVMin, aV1);
1872       aVMax = Min(aVMax, aV2);
1873     }
1874
1875     if (aUMax - aUMin > aTol && aVMax - aVMin > aTol) {
1876       // Create a new edge.
1877       BRepBuilderAPI_MakeFace aMF
1878         (aSurface, aUMin, aUMax, aVMin, aVMax, aTol);
1879     
1880       if (aMF.IsDone()) {
1881         aResult = aMF.Shape();
1882       }
1883     }
1884   }
1885
1886   return aResult;
1887 }
1888
1889 //================================================================================
1890 /*!
1891  * \brief Returns a name of creation operation and names and values of creation parameters
1892  */
1893 //================================================================================
1894
1895 bool GEOMImpl_ShapeDriver::
1896 GetCreationInformation(std::string&             theOperationName,
1897                        std::vector<GEOM_Param>& theParams)
1898 {
1899   if (Label().IsNull()) return 0;
1900   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
1901
1902   GEOMImpl_IShapes aCI( function );
1903   Standard_Integer aType = function->GetType();
1904
1905   switch ( aType ) {
1906   case WIRE_EDGES:
1907     theOperationName = "WIRE";
1908     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1909     AddParam( theParams, "Tolerance", aCI.GetTolerance() );
1910     break;
1911   case FACE_WIRE:
1912     theOperationName = "FACE";
1913     AddParam( theParams, "Wire/edge", aCI.GetBase() );
1914     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1915     break;
1916   case FACE_WIRES:
1917     theOperationName = "FACE";
1918     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1919     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1920     break;
1921   case FACE_FROM_SURFACE:
1922   {
1923     theOperationName = "FACE";
1924
1925     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1926
1927     if (shapes.IsNull() == Standard_False) {
1928       Standard_Integer aNbShapes = shapes->Length();
1929
1930       if (aNbShapes > 0) {
1931         AddParam(theParams, "Face", shapes->Value(1));
1932
1933         if (aNbShapes > 1) {
1934           AddParam(theParams, "Wire", shapes->Value(2));
1935         }
1936       }
1937     }
1938     break;
1939   }
1940   case SHELL_FACES:
1941     theOperationName = "SHELL";
1942     AddParam( theParams, "Objects", aCI.GetShapes() );
1943     break;
1944   case SOLID_SHELLS:
1945     theOperationName = "SOLID";
1946     AddParam( theParams, "Objects", aCI.GetShapes() );
1947     break;
1948   case SOLID_FACES:
1949     theOperationName = "SOLID_FROM_FACES";
1950     AddParam( theParams, "Objects", aCI.GetShapes() );
1951     AddParam( theParams, "Is intersect", aCI.GetIsIntersect() );
1952     break;
1953   case COMPOUND_SHAPES:
1954     theOperationName = "COMPOUND";
1955     AddParam( theParams, "Objects", aCI.GetShapes() );
1956     break;
1957   case EDGE_WIRE:
1958     theOperationName = "EDGE";
1959     AddParam( theParams, "Wire", aCI.GetBase() );
1960     AddParam( theParams, "Linear Tolerance", aCI.GetTolerance() );
1961     AddParam( theParams, "Angular Tolerance", aCI.GetAngularTolerance() );
1962     break;
1963   case EDGE_CURVE_LENGTH:
1964     theOperationName = "EDGE";
1965     {
1966       GEOMImpl_IVector aCI( function );
1967       AddParam( theParams, "Edge", aCI.GetPoint1() );
1968       AddParam( theParams, "Start point", aCI.GetPoint2() );
1969       AddParam( theParams, "Length", aCI.GetParameter() );
1970     }
1971     break;
1972   case SHAPES_ON_SHAPE:
1973   {
1974     theOperationName = "GetShapesOnShapeAsCompound";
1975     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1976     if ( !shapes.IsNull() && shapes->Length() > 0 )
1977       AddParam( theParams, "Check shape", shapes->Value(1) );
1978     if ( !shapes.IsNull() && shapes->Length() > 1 )
1979       AddParam( theParams, "Shape", shapes->Value(2) );
1980     AddParam( theParams, "Shape type", TopAbs_ShapeEnum( aCI.GetSubShapeType() ));
1981     AddParam( theParams, "State" );
1982     GEOMAlgo_State st = GEOMAlgo_State( (int) ( aCI.GetTolerance()+0.1 ) );
1983     const char* stName[] = { "UNKNOWN","IN","OUT","ON","ONIN","ONOUT","INOUT" };
1984     if ( 0 <= st && st <= GEOMAlgo_ST_INOUT )
1985       theParams.back() << stName[ st ];
1986     else
1987       theParams.back() << (int) st;
1988     break;
1989   }
1990   case SHAPE_ISOLINE:
1991   {
1992     GEOMImpl_IIsoline aII (function);
1993
1994     theOperationName = "ISOLINE";
1995     AddParam(theParams, "Face", aII.GetFace());
1996     AddParam(theParams, "Isoline type", (aII.GetIsUIso() ? "U" : "V"));
1997     AddParam(theParams, "Parameter", aII.GetParameter());
1998     break;
1999   }
2000   case EDGE_UV:
2001   {
2002     GEOMImpl_IShapeExtend aSE (function);
2003
2004     theOperationName = "EDGE_EXTEND";
2005     AddParam(theParams, "Edge", aSE.GetShape());
2006     AddParam(theParams, "Min", aSE.GetUMin());
2007     AddParam(theParams, "Max", aSE.GetUMax());
2008     break;
2009   }
2010   case FACE_UV:
2011   {
2012     GEOMImpl_IShapeExtend aSE (function);
2013
2014     theOperationName = "FACE_EXTEND";
2015     AddParam(theParams, "Face", aSE.GetShape());
2016     AddParam(theParams, "UMin", aSE.GetUMin());
2017     AddParam(theParams, "UMax", aSE.GetUMax());
2018     AddParam(theParams, "VMin", aSE.GetVMin());
2019     AddParam(theParams, "VMax", aSE.GetVMax());
2020     break;
2021   }
2022   case SURFACE_FROM_FACE:
2023   {
2024     GEOMImpl_IShapeExtend aSE (function);
2025
2026     theOperationName = "SURFACE_FROM_FACE";
2027     AddParam(theParams, "Face", aSE.GetShape());
2028     break;
2029   }
2030   case EXTRACTION:
2031   {
2032     GEOMImpl_IExtract aCI (function);
2033
2034     theOperationName = "EXTRACTION";
2035     AddParam(theParams, "Main Shape", aCI.GetShape());
2036     AddParam(theParams, "Sub-shape IDs", aCI.GetSubShapeIDs());
2037     break;
2038   }
2039   default:
2040     return false;
2041   }
2042
2043   return true;
2044 }
2045
2046 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ShapeDriver,GEOM_BaseDriver)
2047
2048 //modified by NIZNHY-PKV Wed Dec 28 13:48:31 2011f
2049 #include <TopoDS_Iterator.hxx>
2050 #include <TopTools_HSequenceOfShape.hxx>
2051 #include <ShapeAnalysis_FreeBounds.hxx>
2052 #include <TopTools_MapOfShape.hxx>
2053 #include <TopTools_MapOfOrientedShape.hxx>
2054 #include <BRep_Builder.hxx>
2055 #include <TopoDS_Wire.hxx>
2056
2057 //=======================================================================
2058 //function : KeepEdgesOrder
2059 //purpose  : 
2060 //=======================================================================
2061 /*
2062 void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
2063                     const Handle(TopTools_HSequenceOfShape)& aWires)
2064 {
2065   Standard_Integer aNbWires, aNbEdges;
2066   // 
2067   if (aEdges.IsNull()) {
2068     return;
2069   }
2070   //
2071   if (aWires.IsNull()) {
2072     return;
2073   }
2074   //
2075   aNbEdges=aEdges->Length();
2076   aNbWires=aWires->Length();
2077   if (!aNbEdges || !aNbWires) {
2078     return;
2079   }
2080   //-----
2081   Standard_Boolean bClosed;
2082   Standard_Integer i, j;
2083   TopoDS_Wire aWy;
2084   TopoDS_Iterator aIt;
2085   BRep_Builder aBB;
2086   TopTools_MapOfOrientedShape aMEx;
2087   //
2088   for (i=1; i<=aNbWires; ++i) {
2089     const TopoDS_Shape& aWx=aWires->Value(i);
2090     //
2091     aMEx.Clear();
2092     aIt.Initialize (aWx);
2093     for (; aIt.More(); aIt.Next()) {
2094       const TopoDS_Shape& aEx=aIt.Value();
2095       aMEx.Add(aEx);
2096     }
2097     // aWy
2098     aBB.MakeWire (aWy);
2099     for (j=1; j<=aNbEdges; ++j) {
2100       const TopoDS_Shape& aE=aEdges->Value(j);
2101       if (aMEx.Contains(aE)) {
2102         aBB.Add(aWy, aE);
2103       }
2104     }
2105     //
2106     bClosed=aWx.Closed();
2107     aWy.Closed(bClosed);
2108     //
2109     aWires->Append(aWy);
2110   }// for (i=1; i<=aNbWires; ++i) {
2111   //
2112   aWires->Remove(1, aNbWires);
2113 }
2114 */
2115 //modified by NIZNHY-PKV Wed Dec 28 13:48:34 2011t