Salome HOME
0023197: [CEA] Extract and rebuild
[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_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(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     BOPCol_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.ErrorStatus()) 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     // Interprete 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     // Get statistics.
1019     const TopTools_ListOfShape       &aRemoved    = anExtractor.GetRemoved();
1020     const TopTools_ListOfShape       &aModified   = anExtractor.GetModified();
1021     const TopTools_ListOfShape       &aNew        = anExtractor.GetNew();
1022     Handle(TColStd_HArray1OfInteger) aRemovedIDs  =
1023                           GetShapeIDs(aRemoved, anIndices);
1024     Handle(TColStd_HArray1OfInteger) aModifiedIDs =
1025                           GetShapeIDs(aModified, anIndices);
1026     Handle(TColStd_HArray1OfInteger) aNewIDs;
1027
1028     if (!aShape.IsNull()) {
1029       // Get newly created sub-shapes
1030       TopTools_IndexedMapOfShape aNewIndices;
1031
1032       TopExp::MapShapes(aShape, aNewIndices);
1033       aNewIDs = GetShapeIDs(aNew, aNewIndices);
1034     }
1035
1036     if (!aRemovedIDs.IsNull()) {
1037       aCI.SetRemovedIDs(aRemovedIDs);
1038     }
1039
1040     if (!aModifiedIDs.IsNull()) {
1041       aCI.SetModifiedIDs(aModifiedIDs);
1042     }
1043
1044     if (!aNewIDs.IsNull()) {
1045       aCI.SetAddedIDs(aNewIDs);
1046     }
1047   }
1048   else {
1049   }
1050
1051   if (aShape.IsNull()) return 0;
1052
1053   // Check shape validity
1054   BRepCheck_Analyzer ana (aShape, true);
1055   if (!ana.IsValid()) {
1056     //Standard_ConstructionError::Raise("Algorithm have produced an invalid shape result");
1057     // For Mantis issue 0021772: EDF 2336 GEOM: Non valid face created from two circles
1058     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShape);
1059     aSfs->Perform();
1060     aShape = aSfs->Shape();
1061   }
1062
1063   // Check if the result shape is of expected type.
1064   const TopAbs_ShapeEnum aShType = aShape.ShapeType();
1065
1066   bool ok = false;
1067   if ( aShType == TopAbs_COMPOUND || aShType == TopAbs_COMPSOLID ) {
1068     ok = allowCompound && checkCompound( aShape, anExpectedType );
1069   }
1070   else {
1071     ok = ( anExpectedType == TopAbs_SHAPE ) || ( aShType == anExpectedType );
1072   }
1073   if (!ok)
1074     Standard_ConstructionError::Raise("Result type check failed");
1075
1076   aFunction->SetValue(aShape);
1077
1078   log.SetTouched(Label());
1079
1080   if (!aWarning.IsEmpty())
1081     Standard_Failure::Raise(aWarning.ToCString());
1082
1083   return 1;
1084 }
1085
1086 TopoDS_Wire GEOMImpl_ShapeDriver::MakeWireFromEdges(const Handle(TColStd_HSequenceOfTransient)& theEdgesFuncs,
1087                                                     const Standard_Real theTolerance)
1088 {
1089   BRep_Builder B;
1090
1091   TopoDS_Wire aWire;
1092   B.MakeWire(aWire);
1093
1094   // add edges
1095   for (unsigned int ind = 1; ind <= theEdgesFuncs->Length(); ind++) {
1096     Handle(GEOM_Function) aRefShape = Handle(GEOM_Function)::DownCast(theEdgesFuncs->Value(ind));
1097     TopoDS_Shape aShape_i = aRefShape->GetValue();
1098     if (aShape_i.IsNull()) {
1099       Standard_NullObject::Raise("Shape for wire construction is null");
1100     }
1101     if (aShape_i.ShapeType() == TopAbs_EDGE || aShape_i.ShapeType() == TopAbs_WIRE) {
1102       TopExp_Explorer exp (aShape_i, TopAbs_EDGE);
1103       for (; exp.More(); exp.Next())
1104         B.Add(aWire, TopoDS::Edge(exp.Current()));
1105     } else {
1106       Standard_TypeMismatch::Raise
1107         ("Shape for wire construction is neither an edge nor a wire");
1108     }
1109   }
1110
1111   // fix edges order
1112   Handle(ShapeFix_Wire) aFW = new ShapeFix_Wire;
1113   aFW->Load(aWire);
1114   aFW->FixReorder();
1115
1116   if (aFW->StatusReorder(ShapeExtend_FAIL1)) {
1117     Standard_ConstructionError::Raise("Wire construction failed: several loops detected");
1118   }
1119   else if (aFW->StatusReorder(ShapeExtend_FAIL)) {
1120     Standard_ConstructionError::Raise("Wire construction failed");
1121   }
1122   else {
1123   }
1124
1125   // IMP 0019766: Building a Wire from unconnected edges by introducing a tolerance
1126   aFW->ClosedWireMode() = Standard_False;
1127   aFW->FixConnected(theTolerance);
1128   if (aFW->StatusConnected(ShapeExtend_FAIL)) {
1129     Standard_ConstructionError::Raise("Wire construction failed: cannot build connected wire");
1130   }
1131   // IMP 0019766
1132   if (aFW->StatusConnected(ShapeExtend_DONE3)) {
1133     // Confused with <prec> but not Analyzer.Precision(), set the same
1134     aFW->FixGapsByRangesMode() = Standard_True;
1135     if (aFW->FixGaps3d()) {
1136       Handle(ShapeExtend_WireData) sbwd = aFW->WireData();
1137       Handle(ShapeFix_Edge) aFe = new ShapeFix_Edge;
1138       for (Standard_Integer iedge = 1; iedge <= sbwd->NbEdges(); iedge++) {
1139         TopoDS_Edge aEdge = TopoDS::Edge(sbwd->Edge(iedge));
1140         aFe->FixVertexTolerance(aEdge);
1141         aFe->FixSameParameter(aEdge);
1142       }
1143     }
1144     else if (aFW->StatusGaps3d(ShapeExtend_FAIL)) {
1145       Standard_ConstructionError::Raise("Wire construction failed: cannot fix 3d gaps");
1146     }
1147   }
1148   aWire = aFW->WireAPIMake();
1149
1150   return aWire;
1151 }
1152
1153 TopoDS_Edge GEOMImpl_ShapeDriver::MakeEdgeFromWire(const TopoDS_Shape& aWire,
1154                                                    const Standard_Real LinTol,
1155                                                    const Standard_Real AngTol)
1156 {
1157     TopoDS_Edge ResEdge;
1158
1159     BRepLib::BuildCurves3d(aWire);
1160     Handle(ShapeFix_Shape) Fixer = new ShapeFix_Shape(aWire);
1161     Fixer->SetPrecision(LinTol);
1162     Fixer->SetMaxTolerance(LinTol);
1163     Fixer->Perform();
1164     TopoDS_Wire theWire = TopoDS::Wire(Fixer->Shape());
1165
1166     TColGeom_SequenceOfCurve CurveSeq;
1167     TopTools_SequenceOfShape LocSeq;
1168     TColStd_SequenceOfReal FparSeq;
1169     TColStd_SequenceOfReal LparSeq;
1170     TColStd_SequenceOfReal TolSeq;
1171     GeomAbs_CurveType CurType;
1172     TopoDS_Vertex FirstVertex, LastVertex;
1173     Standard_Real aPntShiftDist = 0.;
1174
1175     BRepTools_WireExplorer wexp(theWire) ;
1176     for (; wexp.More(); wexp.Next())
1177     {
1178       TopoDS_Edge anEdge = wexp.Current();
1179       Standard_Real fpar, lpar;
1180       TopLoc_Location aLoc;
1181       Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aLoc, fpar, lpar);
1182       if (aCurve.IsNull())
1183         continue;
1184
1185       BRepAdaptor_Curve BAcurve(anEdge);
1186       GeomAbs_CurveType aType = BAcurve.GetType();
1187
1188       Handle(Geom_Curve) aBasisCurve = BAcurve.Curve().Curve();
1189
1190       if (aBasisCurve->IsPeriodic())
1191         ElCLib::AdjustPeriodic(aBasisCurve->FirstParameter(), aBasisCurve->LastParameter(),
1192                                Precision::PConfusion(), fpar, lpar);
1193
1194       if (CurveSeq.IsEmpty())
1195       {
1196         CurveSeq.Append(aCurve);
1197         TopoDS_Shape aLocShape;
1198         aLocShape.Location(aLoc);
1199         aLocShape.Orientation(wexp.Orientation());
1200         LocSeq.Append(aLocShape);
1201         FparSeq.Append(fpar);
1202         LparSeq.Append(lpar);
1203         CurType = aType;
1204         FirstVertex = wexp.CurrentVertex();
1205       }
1206       else
1207       {
1208         Standard_Boolean Done = Standard_False;
1209         Standard_Real NewFpar, NewLpar;
1210         Handle(Geom_Geometry) aTrsfGeom = CurveSeq.Last()->Transformed
1211                       (LocSeq.Last().Location().Transformation());
1212         GeomAdaptor_Curve GAprevcurve(Handle(Geom_Curve)::DownCast(aTrsfGeom));
1213         TopoDS_Vertex CurVertex = wexp.CurrentVertex();
1214         TopoDS_Vertex CurFirstVer = TopExp::FirstVertex(anEdge);
1215         TopAbs_Orientation ConnectByOrigin = (CurVertex.IsSame(CurFirstVer))? TopAbs_FORWARD : TopAbs_REVERSED;
1216         if (aCurve == CurveSeq.Last() && aLoc.IsEqual(LocSeq.Last().Location()))
1217         {
1218           NewFpar = fpar;
1219           NewLpar = lpar;
1220           if (aBasisCurve->IsPeriodic())
1221           {
1222             if (NewLpar < NewFpar)
1223               NewLpar += aBasisCurve->Period();
1224             if (ConnectByOrigin == TopAbs_FORWARD)
1225               ElCLib::AdjustPeriodic(FparSeq.Last(),
1226                                      FparSeq.Last() + aBasisCurve->Period(),
1227                                      Precision::PConfusion(), NewFpar, NewLpar);
1228             else
1229               ElCLib::AdjustPeriodic(FparSeq.Last() - aBasisCurve->Period(),
1230                                      FparSeq.Last(),
1231                                      Precision::PConfusion(), NewFpar, NewLpar);
1232           }
1233           Done = Standard_True;
1234         }
1235         else if (aType == CurType &&
1236                  aType != GeomAbs_BezierCurve &&
1237                  aType != GeomAbs_BSplineCurve &&
1238                  aType != GeomAbs_OtherCurve)
1239         {
1240           switch (aType)
1241           {
1242           case GeomAbs_Line:
1243             {
1244               gp_Lin aLine    = BAcurve.Line();
1245               gp_Lin PrevLine = GAprevcurve.Line();
1246               if (aLine.Contains(PrevLine.Location(), LinTol) &&
1247                   aLine.Direction().IsParallel(PrevLine.Direction(), AngTol))
1248               {
1249                 gp_Pnt P1 = ElCLib::Value(fpar, aLine);
1250                 gp_Pnt P2 = ElCLib::Value(lpar, aLine);
1251                 NewFpar = ElCLib::Parameter(PrevLine, P1);
1252                 NewLpar = ElCLib::Parameter(PrevLine, P2);
1253
1254                 // Compute shift
1255                 if (ConnectByOrigin == TopAbs_FORWARD) {
1256                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevLine);
1257
1258                   aPntShiftDist += P2.Distance(aNewP2);
1259                 } else {
1260                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevLine);
1261
1262                   aPntShiftDist += P1.Distance(aNewP1);
1263                 }
1264
1265                 if (NewLpar < NewFpar)
1266                 {
1267                   Standard_Real MemNewFpar = NewFpar;
1268                   NewFpar = NewLpar;
1269                   NewLpar = MemNewFpar;
1270                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1271                 }
1272                 Done = Standard_True;
1273               }
1274               break;
1275             }
1276           case GeomAbs_Circle:
1277             {
1278               gp_Circ aCircle    = BAcurve.Circle();
1279               gp_Circ PrevCircle = GAprevcurve.Circle();
1280               if (aCircle.Location().Distance(PrevCircle.Location()) <= LinTol &&
1281                   Abs(aCircle.Radius() - PrevCircle.Radius()) <= LinTol &&
1282                   aCircle.Axis().IsParallel(PrevCircle.Axis(), AngTol))
1283               {
1284                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
1285
1286                 if (aCircle.Axis().Direction() * PrevCircle.Axis().Direction() < 0.)
1287                 {
1288                   Standard_Real memfpar = fpar;
1289                   fpar = lpar;
1290                   lpar = memfpar;
1291                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1292                 }
1293                 gp_Pnt P1 = ElCLib::Value(fpar, aCircle);
1294                 gp_Pnt P2 = ElCLib::Value(lpar, aCircle);
1295                 NewFpar = ElCLib::Parameter(PrevCircle, P1);
1296                 NewLpar = ElCLib::Parameter(PrevCircle, P2);
1297
1298                 // Compute shift
1299                 if (isFwd) {
1300                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevCircle);
1301
1302                   aPntShiftDist += P2.Distance(aNewP2);
1303                 } else {
1304                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevCircle);
1305
1306                   aPntShiftDist += P1.Distance(aNewP1);
1307                 }
1308
1309                 if (NewLpar < NewFpar)
1310                   NewLpar += 2.*M_PI;
1311                 //Standard_Real MemNewFpar = NewFpar, MemNewLpar =  NewLpar;
1312                 if (ConnectByOrigin == TopAbs_FORWARD)
1313                   ElCLib::AdjustPeriodic(FparSeq.Last(),
1314                                          FparSeq.Last() + 2.*M_PI,
1315                                          Precision::PConfusion(), NewFpar, NewLpar);
1316                 else
1317                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
1318                                          FparSeq.Last(),
1319                                          Precision::PConfusion(), NewFpar, NewLpar);
1320                 Done = Standard_True;
1321               }
1322               break;
1323             }
1324           case GeomAbs_Ellipse:
1325             {
1326               gp_Elips anEllipse   = BAcurve.Ellipse();
1327               gp_Elips PrevEllipse = GAprevcurve.Ellipse();
1328               if (anEllipse.Focus1().Distance(PrevEllipse.Focus1()) <= LinTol &&
1329                   anEllipse.Focus2().Distance(PrevEllipse.Focus2()) <= LinTol &&
1330                   Abs(anEllipse.MajorRadius() - PrevEllipse.MajorRadius()) <= LinTol &&
1331                   Abs(anEllipse.MinorRadius() - PrevEllipse.MinorRadius()) <= LinTol &&
1332                   anEllipse.Axis().IsParallel(PrevEllipse.Axis(), AngTol))
1333               {
1334                 const Standard_Boolean isFwd = ConnectByOrigin == TopAbs_FORWARD;
1335
1336                 if (anEllipse.Axis().Direction() * PrevEllipse.Axis().Direction() < 0.)
1337                 {
1338                   Standard_Real memfpar = fpar;
1339                   fpar = lpar;
1340                   lpar = memfpar;
1341                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1342                 }
1343                 gp_Pnt P1 = ElCLib::Value(fpar, anEllipse);
1344                 gp_Pnt P2 = ElCLib::Value(lpar, anEllipse);
1345                 NewFpar = ElCLib::Parameter(PrevEllipse, P1);
1346                 NewLpar = ElCLib::Parameter(PrevEllipse, P2);
1347
1348                 // Compute shift
1349                 if (isFwd) {
1350                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevEllipse);
1351
1352                   aPntShiftDist += P2.Distance(aNewP2);
1353                 } else {
1354                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevEllipse);
1355
1356                   aPntShiftDist += P1.Distance(aNewP1);
1357                 }
1358
1359                 if (NewLpar < NewFpar)
1360                   NewLpar += 2.*M_PI;
1361                 if (ConnectByOrigin == TopAbs_FORWARD)
1362                   ElCLib::AdjustPeriodic(FparSeq.Last(),
1363                                          FparSeq.Last() + 2.*M_PI,
1364                                          Precision::PConfusion(), NewFpar, NewLpar);
1365                 else
1366                   ElCLib::AdjustPeriodic(FparSeq.Last() - 2.*M_PI,
1367                                          FparSeq.Last(),
1368                                          Precision::PConfusion(), NewFpar, NewLpar);
1369                 Done = Standard_True;
1370               }
1371               break;
1372             }
1373           case GeomAbs_Hyperbola:
1374             {
1375               gp_Hypr aHypr    = BAcurve.Hyperbola();
1376               gp_Hypr PrevHypr = GAprevcurve.Hyperbola();
1377               if (aHypr.Focus1().Distance(PrevHypr.Focus1()) <= LinTol &&
1378                   aHypr.Focus2().Distance(PrevHypr.Focus2()) <= LinTol &&
1379                   Abs(aHypr.MajorRadius() - PrevHypr.MajorRadius()) <= LinTol &&
1380                   Abs(aHypr.MinorRadius() - PrevHypr.MinorRadius()) <= LinTol &&
1381                   aHypr.Axis().IsParallel(PrevHypr.Axis(), AngTol))
1382               {
1383                 gp_Pnt P1 = ElCLib::Value(fpar, aHypr);
1384                 gp_Pnt P2 = ElCLib::Value(lpar, aHypr);
1385                 NewFpar = ElCLib::Parameter(PrevHypr, P1);
1386                 NewLpar = ElCLib::Parameter(PrevHypr, P2);
1387
1388                 // Compute shift
1389                 if (ConnectByOrigin == TopAbs_FORWARD) {
1390                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevHypr);
1391
1392                   aPntShiftDist += P2.Distance(aNewP2);
1393                 } else {
1394                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevHypr);
1395
1396                   aPntShiftDist += P1.Distance(aNewP1);
1397                 }
1398
1399                 if (NewLpar < NewFpar)
1400                 {
1401                   Standard_Real MemNewFpar = NewFpar;
1402                   NewFpar = NewLpar;
1403                   NewLpar = MemNewFpar;
1404                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1405                 }
1406                 Done = Standard_True;
1407               }
1408               break;
1409             }
1410           case GeomAbs_Parabola:
1411             {
1412               gp_Parab aParab    = BAcurve.Parabola();
1413               gp_Parab PrevParab = GAprevcurve.Parabola();
1414               if (aParab.Location().Distance(PrevParab.Location()) <= LinTol &&
1415                   aParab.Focus().Distance(PrevParab.Focus()) <= LinTol &&
1416                   Abs(aParab.Focal() - PrevParab.Focal()) <= LinTol &&
1417                   aParab.Axis().IsParallel(PrevParab.Axis(), AngTol))
1418               {
1419                 gp_Pnt P1 = ElCLib::Value(fpar, aParab);
1420                 gp_Pnt P2 = ElCLib::Value(lpar, aParab);
1421                 NewFpar = ElCLib::Parameter(PrevParab, P1);
1422                 NewLpar = ElCLib::Parameter(PrevParab, P2);
1423
1424                 // Compute shift
1425                 if (ConnectByOrigin == TopAbs_FORWARD) {
1426                   gp_Pnt aNewP2 = ElCLib::Value(NewLpar, PrevParab);
1427
1428                   aPntShiftDist += P2.Distance(aNewP2);
1429                 } else {
1430                   gp_Pnt aNewP1 = ElCLib::Value(NewFpar, PrevParab);
1431
1432                   aPntShiftDist += P1.Distance(aNewP1);
1433                 }
1434
1435                 if (NewLpar < NewFpar)
1436                 {
1437                   Standard_Real MemNewFpar = NewFpar;
1438                   NewFpar = NewLpar;
1439                   NewLpar = MemNewFpar;
1440                   ConnectByOrigin = TopAbs::Reverse(ConnectByOrigin);
1441                 }
1442                 Done = Standard_True;
1443               }
1444               break;
1445             }
1446           } //end of switch (aType)
1447         } // end of else if (aType == CurType && ...
1448         if (Done)
1449         {
1450           if (NewFpar < FparSeq.Last())
1451             FparSeq(FparSeq.Length()) = NewFpar;
1452           else
1453             LparSeq(LparSeq.Length()) = NewLpar;
1454         }
1455         else
1456         {
1457           CurveSeq.Append(aCurve);
1458           TopoDS_Shape aLocShape;
1459           aLocShape.Location(aLoc);
1460           aLocShape.Orientation(wexp.Orientation());
1461           LocSeq.Append(aLocShape);
1462           FparSeq.Append(fpar);
1463           LparSeq.Append(lpar);
1464           TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(CurVertex));
1465           aPntShiftDist = 0.;
1466           CurType = aType;
1467         }
1468       } // end of else (CurveSeq.IsEmpty()) -> not first time
1469     } // end for (; wexp.More(); wexp.Next())
1470
1471     LastVertex = wexp.CurrentVertex();
1472     TolSeq.Append(aPntShiftDist + BRep_Tool::Tolerance(LastVertex));
1473
1474     FirstVertex.Orientation(TopAbs_FORWARD);
1475     LastVertex.Orientation(TopAbs_REVERSED);
1476
1477     if (!CurveSeq.IsEmpty())
1478     {
1479       Standard_Integer nb_curve = CurveSeq.Length();   //number of curves
1480       TColGeom_Array1OfBSplineCurve tab(0,nb_curve-1);                    //array of the curves
1481       TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2);  //array of the tolerances
1482
1483       Standard_Integer i;
1484
1485       if (nb_curve > 1)
1486       {
1487         for (i = 1; i <= nb_curve; i++)
1488         {
1489           if (CurveSeq(i)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1490             CurveSeq(i) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(i))))->BasisCurve();
1491
1492           Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(CurveSeq(i), FparSeq(i), LparSeq(i));
1493           tab(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve);
1494           tab(i-1)->Transform(LocSeq(i).Location().Transformation());
1495           GeomConvert::C0BSplineToC1BSplineCurve(tab(i-1), Precision::Confusion());
1496           if (LocSeq(i).Orientation() == TopAbs_REVERSED)
1497             tab(i-1)->Reverse();
1498
1499           //Temporary
1500           //char* name = new char[100];
1501           //sprintf(name, "c%d", i);
1502           //DrawTrSurf::Set(name, tab(i-1));
1503
1504           if (i > 1)
1505             tabtolvertex(i-2) = TolSeq(i-1);
1506         } // end for (i = 1; i <= nb_curve; i++)
1507         tabtolvertex(nb_curve-1) = TolSeq(TolSeq.Length());
1508
1509         Standard_Boolean closed_flag = Standard_False;
1510         Standard_Real closed_tolerance = 0.;
1511         if (FirstVertex.IsSame(LastVertex) &&
1512             GeomLProp::Continuity(tab(0), tab(nb_curve-1),
1513                                   tab(0)->FirstParameter(),
1514                                   tab(nb_curve-1)->LastParameter(),
1515                                   Standard_False, Standard_False, LinTol, AngTol) >= GeomAbs_G1)
1516         {
1517           closed_flag = Standard_True ;
1518           closed_tolerance = BRep_Tool::Tolerance(FirstVertex);
1519         }
1520
1521         Handle(TColGeom_HArray1OfBSplineCurve)  concatcurve;     //array of the concatenated curves
1522         Handle(TColStd_HArray1OfInteger)        ArrayOfIndices;  //array of the remining Vertex
1523         GeomConvert::ConcatC1(tab,
1524                               tabtolvertex,
1525                               ArrayOfIndices,
1526                               concatcurve,
1527                               closed_flag,
1528                               closed_tolerance);   //C1 concatenation
1529
1530         if (concatcurve->Length() > 1)
1531         {
1532           GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower()));
1533
1534           for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++)
1535             Concat.Add( concatcurve->Value(i), LinTol, Standard_True );
1536
1537           concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve());
1538         }
1539         // rnc : prevents the driver from building an edge without C1 continuity
1540         if (concatcurve->Value(concatcurve->Lower())->Continuity()==GeomAbs_C0){
1541           Standard_ConstructionError::Raise("Construction aborted : The given Wire has sharp bends between some Edges, no valid Edge can be built");
1542         }
1543
1544         Standard_Boolean isValidEndVtx = Standard_True;
1545
1546         if (closed_flag) {
1547           // Check if closed curve is reordered.
1548           Handle(Geom_Curve) aCurve  = concatcurve->Value(concatcurve->Lower());
1549           Standard_Real      aFPar   = aCurve->FirstParameter();
1550           gp_Pnt             aPFirst;
1551           gp_Pnt             aPntVtx = BRep_Tool::Pnt(FirstVertex);
1552           Standard_Real      aTolVtx = BRep_Tool::Tolerance(FirstVertex);
1553
1554           aCurve->D0(aFPar, aPFirst);
1555
1556           if (!aPFirst.IsEqual(aPntVtx, aTolVtx)) {
1557             // The curve is reordered. Find the new first and last vertices.
1558             TopTools_IndexedMapOfShape aMapVtx;
1559             TopExp::MapShapes(theWire, TopAbs_VERTEX, aMapVtx);
1560
1561             const Standard_Integer aNbVtx = aMapVtx.Extent();
1562             Standard_Integer       iVtx;
1563
1564             for (iVtx = 1; iVtx <= aNbVtx; iVtx++) {
1565               const TopoDS_Vertex aVtx = TopoDS::Vertex(aMapVtx.FindKey(iVtx));
1566               const gp_Pnt        aPnt = BRep_Tool::Pnt(aVtx);
1567               const Standard_Real aTol = BRep_Tool::Tolerance(aVtx);
1568
1569               if (aPFirst.IsEqual(aPnt, aTol)) {
1570                 // The coinsident vertex is found.
1571                 FirstVertex = aVtx;
1572                 LastVertex  = aVtx;
1573                 FirstVertex.Orientation(TopAbs_FORWARD);
1574                 LastVertex.Orientation(TopAbs_REVERSED);
1575                 break;
1576               }
1577             }
1578
1579             if (iVtx > aNbVtx) {
1580               // It is necessary to create new vertices.
1581               isValidEndVtx = Standard_False;
1582             }
1583           }
1584         }
1585
1586         if (isValidEndVtx) {
1587           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1588                                      FirstVertex, LastVertex,
1589                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1590                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1591         } else {
1592           ResEdge = BRepLib_MakeEdge(concatcurve->Value(concatcurve->Lower()),
1593                                      concatcurve->Value(concatcurve->Lower())->FirstParameter(),
1594                                      concatcurve->Value(concatcurve->Lower())->LastParameter());
1595         }
1596       }
1597       else
1598       {
1599         if (CurveSeq(1)->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1600           CurveSeq(1) = (*((Handle(Geom_TrimmedCurve)*)&(CurveSeq(1))))->BasisCurve();
1601
1602         Handle(Geom_Curve) aNewCurve =
1603           Handle(Geom_Curve)::DownCast(CurveSeq(1)->Copy());
1604
1605         aNewCurve->Transform(LocSeq(1).Location().Transformation());
1606
1607         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1608           const TopoDS_Vertex aVtxTmp = FirstVertex;
1609
1610           FirstVertex = LastVertex;
1611           LastVertex  = aVtxTmp;
1612           FirstVertex.Orientation(TopAbs_FORWARD);
1613           LastVertex.Orientation(TopAbs_REVERSED);
1614         }
1615
1616         ResEdge = BRepLib_MakeEdge(aNewCurve,
1617                                    FirstVertex, LastVertex,
1618                                    FparSeq(1), LparSeq(1));
1619
1620         if (LocSeq(1).Orientation() == TopAbs_REVERSED) {
1621           ResEdge.Reverse();
1622         }
1623       }
1624     }
1625
1626     return ResEdge;
1627 }
1628
1629 //=============================================================================
1630 /*!
1631  * \brief Returns an isoline for a face.
1632  */
1633 //=============================================================================
1634
1635 TopoDS_Shape GEOMImpl_ShapeDriver::MakeIsoline
1636                             (const TopoDS_Face &theFace,
1637                              const bool         IsUIso,
1638                              const double       theParameter) const
1639 {
1640   TopoDS_Shape          aResult;
1641   GEOMUtils::Hatcher    aHatcher(theFace);
1642   const GeomAbs_IsoType aType = (IsUIso ? GeomAbs_IsoU : GeomAbs_IsoV);
1643
1644   aHatcher.Init(aType, theParameter);
1645   aHatcher.Perform();
1646
1647   if (!aHatcher.IsDone()) {
1648     Standard_ConstructionError::Raise("MakeIsoline : Hatcher failure");
1649   }
1650
1651   const Handle(TColStd_HArray1OfInteger) &anIndices =
1652     (IsUIso ? aHatcher.GetUIndices() : aHatcher.GetVIndices());
1653
1654   if (anIndices.IsNull()) {
1655     Standard_ConstructionError::Raise("MakeIsoline : Null hatching indices");
1656   }
1657
1658   const Standard_Integer anIsoInd = anIndices->Lower();
1659   const Standard_Integer aHatchingIndex = anIndices->Value(anIsoInd);
1660
1661   if (aHatchingIndex == 0) {
1662     Standard_ConstructionError::Raise("MakeIsoline : Invalid hatching index");
1663   }
1664
1665   const Standard_Integer aNbDomains =
1666     aHatcher.GetNbDomains(aHatchingIndex);
1667
1668   if (aNbDomains < 0) {
1669     Standard_ConstructionError::Raise("MakeIsoline : Invalid number of domains");
1670   }
1671
1672   // The hatching is performed successfully. Create the 3d Curve.
1673   Handle(Geom_Surface) aSurface   = BRep_Tool::Surface(theFace);
1674   Handle(Geom_Curve)   anIsoCurve = (IsUIso ?
1675     aSurface->UIso(theParameter) : aSurface->VIso(theParameter));
1676   Handle(Geom2d_Curve) aPIsoCurve =
1677     aHatcher.GetHatching(aHatchingIndex);
1678   const Standard_Real  aTol = Precision::Confusion();
1679   Standard_Integer     anIDom = 1;
1680   Standard_Real        aV1;
1681   Standard_Real        aV2;
1682   BRep_Builder         aBuilder;
1683   Standard_Integer     aNbEdges = 0;
1684
1685   for (; anIDom <= aNbDomains; anIDom++) {
1686     if (aHatcher.GetDomain(aHatchingIndex, anIDom, aV1, aV2)) {
1687       // Check first and last parameters.
1688       if (!aHatcher.IsDomainInfinite(aHatchingIndex, anIDom)) {
1689         // Create an edge.
1690         TopoDS_Edge anEdge = BRepBuilderAPI_MakeEdge(anIsoCurve, aV1, aV2);
1691
1692         // Update it with a parametric curve on face.
1693         aBuilder.UpdateEdge(anEdge, aPIsoCurve, theFace, aTol);
1694         aNbEdges++;
1695
1696         if (aNbEdges > 1) {
1697           // Result is a compond.
1698           if (aNbEdges == 2) {
1699             // Create a new compound.
1700             TopoDS_Compound aCompound;
1701
1702             aBuilder.MakeCompound(aCompound);
1703             aBuilder.Add(aCompound, aResult);
1704             aResult = aCompound;
1705           }
1706
1707           // Add an edge to the compound.
1708           aBuilder.Add(aResult, anEdge);
1709         } else {
1710           // Result is the edge.
1711           aResult = anEdge;
1712         }
1713       }
1714     }
1715   }
1716
1717   if (aNbEdges == 0) {
1718     Standard_ConstructionError::Raise("MakeIsoline : Empty result");
1719   }
1720
1721   return aResult;
1722 }
1723
1724 //=============================================================================
1725 /*!
1726  * \brief Returns an extended edge.
1727  */
1728 //=============================================================================
1729
1730 TopoDS_Shape GEOMImpl_ShapeDriver::ExtendEdge
1731                          (const TopoDS_Edge   &theEdge,
1732                           const Standard_Real  theMin,
1733                           const Standard_Real  theMax) const
1734 {
1735   TopoDS_Shape        aResult;
1736   Standard_Real       aF;
1737   Standard_Real       aL;
1738   Handle(Geom_Curve)  aCurve   = BRep_Tool::Curve(theEdge, aF, aL);
1739   const Standard_Real aTol     = BRep_Tool::Tolerance(theEdge);
1740   Standard_Real       aRange2d = aL - aF;
1741
1742   if (aCurve.IsNull() == Standard_False && aRange2d > aTol) {
1743     Standard_Real aMin = aF + aRange2d*theMin;
1744     Standard_Real aMax = aF + aRange2d*theMax;
1745
1746     Handle(Standard_Type) aType = aCurve->DynamicType();
1747
1748     // Get the curve of original type
1749     while (aType == STANDARD_TYPE(Geom_TrimmedCurve)) {
1750       Handle(Geom_TrimmedCurve) aTrCurve =
1751         Handle(Geom_TrimmedCurve)::DownCast(aCurve);
1752
1753       aCurve = aTrCurve->BasisCurve();
1754       aType  = aCurve->DynamicType();
1755     }
1756
1757     if (aCurve->IsPeriodic()) {
1758       // The curve is periodic. Check if a new range is less then a period.
1759       if (aMax - aMin > aCurve->Period()) {
1760         aMax = aMin + aCurve->Period();
1761       }
1762     } else {
1763       // The curve is not periodic. Check if aMin and aMax within bounds.
1764       aMin = Max(aMin, aCurve->FirstParameter());
1765       aMax = Min(aMax, aCurve->LastParameter());
1766     }
1767
1768     if (aMax - aMin > aTol) {
1769       // Create a new edge.
1770       BRepBuilderAPI_MakeEdge aME (aCurve, aMin, aMax);
1771
1772       if (aME.IsDone()) {
1773         aResult = aME.Shape();
1774       }
1775     }
1776   }
1777
1778   return aResult;
1779 }
1780
1781 //=============================================================================
1782 /*!
1783  * \brief Returns an extended face.
1784  */
1785 //=============================================================================
1786
1787 TopoDS_Shape GEOMImpl_ShapeDriver::ExtendFace
1788                          (const TopoDS_Face   &theFace,
1789                           const Standard_Real  theUMin,
1790                           const Standard_Real  theUMax,
1791                           const Standard_Real  theVMin,
1792                           const Standard_Real  theVMax) const
1793 {
1794   TopoDS_Shape         aResult;
1795   Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace);
1796   const Standard_Real  aTol     = BRep_Tool::Tolerance(theFace);
1797   Standard_Real        aU1;
1798   Standard_Real        aU2;
1799   Standard_Real        aV1;
1800   Standard_Real        aV2;
1801
1802   // Get U, V bounds of the face.
1803   ShapeAnalysis::GetFaceUVBounds(theFace, aU1, aU2, aV1, aV2);
1804
1805   const Standard_Real aURange = aU2 - aU1;
1806   const Standard_Real aVRange = aV2 - aV1;
1807
1808   if (aSurface.IsNull() == Standard_False &&
1809       aURange > aTol && aURange > aTol) {
1810     Handle(Standard_Type) aType = aSurface->DynamicType();
1811
1812     // Get the surface of original type
1813     while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1814       Handle(Geom_RectangularTrimmedSurface) aTrSurface =
1815         Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
1816
1817       aSurface = aTrSurface->BasisSurface();
1818       aType    = aSurface->DynamicType();
1819     }
1820
1821     Standard_Real aUMin = aU1 + aURange*theUMin;
1822     Standard_Real aUMax = aU1 + aURange*theUMax;
1823     Standard_Real aVMin = aV1 + aVRange*theVMin;
1824     Standard_Real aVMax = aV1 + aVRange*theVMax;
1825
1826     aSurface->Bounds(aU1, aU2, aV1, aV2);
1827
1828     if (aSurface->IsUPeriodic()) {
1829       // The surface is U-periodic. Check if a new U range is less
1830       // then a period.
1831       if (aUMax - aUMin > aSurface->UPeriod()) {
1832         aUMax = aUMin + aSurface->UPeriod();
1833       }
1834     } else {
1835       // The surface is not V-periodic. Check if aUMin and aUMax
1836       // within bounds.
1837       aUMin = Max(aUMin, aU1);
1838       aUMax = Min(aUMax, aU2);
1839     }
1840
1841     if (aSurface->IsVPeriodic()) {
1842       // The surface is V-periodic. Check if a new V range is less
1843       // then a period.
1844       if (aVMax - aVMin > aSurface->VPeriod()) {
1845         aVMax = aVMin + aSurface->VPeriod();
1846       }
1847     } else {
1848       // The surface is not V-periodic. Check if aVMin and aVMax
1849       // within bounds.
1850       aVMin = Max(aVMin, aV1);
1851       aVMax = Min(aVMax, aV2);
1852     }
1853
1854     if (aUMax - aUMin > aTol && aVMax - aVMin > aTol) {
1855       // Create a new edge.
1856       BRepBuilderAPI_MakeFace aMF
1857         (aSurface, aUMin, aUMax, aVMin, aVMax, aTol);
1858     
1859       if (aMF.IsDone()) {
1860         aResult = aMF.Shape();
1861       }
1862     }
1863   }
1864
1865   return aResult;
1866 }
1867
1868 //================================================================================
1869 /*!
1870  * \brief Returns a name of creation operation and names and values of creation parameters
1871  */
1872 //================================================================================
1873
1874 bool GEOMImpl_ShapeDriver::
1875 GetCreationInformation(std::string&             theOperationName,
1876                        std::vector<GEOM_Param>& theParams)
1877 {
1878   if (Label().IsNull()) return 0;
1879   Handle(GEOM_Function) function = GEOM_Function::GetFunction(Label());
1880
1881   GEOMImpl_IShapes aCI( function );
1882   Standard_Integer aType = function->GetType();
1883
1884   switch ( aType ) {
1885   case WIRE_EDGES:
1886     theOperationName = "WIRE";
1887     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1888     AddParam( theParams, "Tolerance", aCI.GetTolerance() );
1889     break;
1890   case FACE_WIRE:
1891     theOperationName = "FACE";
1892     AddParam( theParams, "Wire/edge", aCI.GetBase() );
1893     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1894     break;
1895   case FACE_WIRES:
1896     theOperationName = "FACE";
1897     AddParam( theParams, "Wires/edges", aCI.GetShapes() );
1898     AddParam( theParams, "Is planar wanted", aCI.GetIsPlanar() );
1899     break;
1900   case FACE_FROM_SURFACE:
1901   {
1902     theOperationName = "FACE";
1903
1904     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1905
1906     if (shapes.IsNull() == Standard_False) {
1907       Standard_Integer aNbShapes = shapes->Length();
1908
1909       if (aNbShapes > 0) {
1910         AddParam(theParams, "Face", shapes->Value(1));
1911
1912         if (aNbShapes > 1) {
1913           AddParam(theParams, "Wire", shapes->Value(2));
1914         }
1915       }
1916     }
1917     break;
1918   }
1919   case SHELL_FACES:
1920     theOperationName = "SHELL";
1921     AddParam( theParams, "Objects", aCI.GetShapes() );
1922     break;
1923   case SOLID_SHELLS:
1924     theOperationName = "SOLID";
1925     AddParam( theParams, "Objects", aCI.GetShapes() );
1926     break;
1927   case SOLID_FACES:
1928     theOperationName = "SOLID_FROM_FACES";
1929     AddParam( theParams, "Objects", aCI.GetShapes() );
1930     AddParam( theParams, "Is intersect", aCI.GetIsIntersect() );
1931     break;
1932   case COMPOUND_SHAPES:
1933     theOperationName = "COMPOUND";
1934     AddParam( theParams, "Objects", aCI.GetShapes() );
1935     break;
1936   case EDGE_WIRE:
1937     theOperationName = "EDGE";
1938     AddParam( theParams, "Wire", aCI.GetBase() );
1939     AddParam( theParams, "Linear Tolerance", aCI.GetTolerance() );
1940     AddParam( theParams, "Angular Tolerance", aCI.GetAngularTolerance() );
1941     break;
1942   case EDGE_CURVE_LENGTH:
1943     theOperationName = "EDGE";
1944     {
1945       GEOMImpl_IVector aCI( function );
1946       AddParam( theParams, "Edge", aCI.GetPoint1() );
1947       AddParam( theParams, "Start point", aCI.GetPoint2() );
1948       AddParam( theParams, "Length", aCI.GetParameter() );
1949     }
1950     break;
1951   case SHAPES_ON_SHAPE:
1952   {
1953     theOperationName = "GetShapesOnShapeAsCompound";
1954     Handle(TColStd_HSequenceOfTransient) shapes = aCI.GetShapes();
1955     if ( !shapes.IsNull() && shapes->Length() > 0 )
1956       AddParam( theParams, "Check shape", shapes->Value(1) );
1957     if ( !shapes.IsNull() && shapes->Length() > 1 )
1958       AddParam( theParams, "Shape", shapes->Value(2) );
1959     AddParam( theParams, "Shape type", TopAbs_ShapeEnum( aCI.GetSubShapeType() ));
1960     AddParam( theParams, "State" );
1961     GEOMAlgo_State st = GEOMAlgo_State( (int) ( aCI.GetTolerance()+0.1 ) );
1962     const char* stName[] = { "UNKNOWN","IN","OUT","ON","ONIN","ONOUT","INOUT" };
1963     if ( 0 <= st && st <= GEOMAlgo_ST_INOUT )
1964       theParams.back() << stName[ st ];
1965     else
1966       theParams.back() << (int) st;
1967     break;
1968   }
1969   case SHAPE_ISOLINE:
1970   {
1971     GEOMImpl_IIsoline aII (function);
1972
1973     theOperationName = "ISOLINE";
1974     AddParam(theParams, "Face", aII.GetFace());
1975     AddParam(theParams, "Isoline type", (aII.GetIsUIso() ? "U" : "V"));
1976     AddParam(theParams, "Parameter", aII.GetParameter());
1977     break;
1978   }
1979   case EDGE_UV:
1980   {
1981     GEOMImpl_IShapeExtend aSE (function);
1982
1983     theOperationName = "EDGE_EXTEND";
1984     AddParam(theParams, "Edge", aSE.GetShape());
1985     AddParam(theParams, "Min", aSE.GetUMin());
1986     AddParam(theParams, "Max", aSE.GetUMax());
1987     break;
1988   }
1989   case FACE_UV:
1990   {
1991     GEOMImpl_IShapeExtend aSE (function);
1992
1993     theOperationName = "FACE_EXTEND";
1994     AddParam(theParams, "Face", aSE.GetShape());
1995     AddParam(theParams, "UMin", aSE.GetUMin());
1996     AddParam(theParams, "UMax", aSE.GetUMax());
1997     AddParam(theParams, "VMin", aSE.GetVMin());
1998     AddParam(theParams, "VMax", aSE.GetVMax());
1999     break;
2000   }
2001   case SURFACE_FROM_FACE:
2002   {
2003     GEOMImpl_IShapeExtend aSE (function);
2004
2005     theOperationName = "SURFACE_FROM_FACE";
2006     AddParam(theParams, "Face", aSE.GetShape());
2007     break;
2008   }
2009   case EXTRACTION:
2010   {
2011     GEOMImpl_IExtract aCI (function);
2012
2013     theOperationName = "EXTRACTION";
2014     AddParam(theParams, "Main Shape", aCI.GetShape());
2015     AddParam(theParams, "Sub-shape IDs", aCI.GetSubShapeIDs());
2016     break;
2017   }
2018   default:
2019     return false;
2020   }
2021
2022   return true;
2023 }
2024
2025 IMPLEMENT_STANDARD_HANDLE (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
2026 IMPLEMENT_STANDARD_RTTIEXT (GEOMImpl_ShapeDriver,GEOM_BaseDriver);
2027
2028 //modified by NIZNHY-PKV Wed Dec 28 13:48:31 2011f
2029 #include <TopoDS_Iterator.hxx>
2030 #include <TopTools_HSequenceOfShape.hxx>
2031 #include <ShapeAnalysis_FreeBounds.hxx>
2032 #include <TopTools_MapOfShape.hxx>
2033 #include <TopTools_MapOfOrientedShape.hxx>
2034 #include <BRep_Builder.hxx>
2035 #include <TopoDS_Wire.hxx>
2036
2037 //=======================================================================
2038 //function : KeepEdgesOrder
2039 //purpose  : 
2040 //=======================================================================
2041 /*
2042 void KeepEdgesOrder(const Handle(TopTools_HSequenceOfShape)& aEdges,
2043                     const Handle(TopTools_HSequenceOfShape)& aWires)
2044 {
2045   Standard_Integer aNbWires, aNbEdges;
2046   // 
2047   if (aEdges.IsNull()) {
2048     return;
2049   }
2050   //
2051   if (aWires.IsNull()) {
2052     return;
2053   }
2054   //
2055   aNbEdges=aEdges->Length();
2056   aNbWires=aWires->Length();
2057   if (!aNbEdges || !aNbWires) {
2058     return;
2059   }
2060   //-----
2061   Standard_Boolean bClosed;
2062   Standard_Integer i, j;
2063   TopoDS_Wire aWy;
2064   TopoDS_Iterator aIt;
2065   BRep_Builder aBB;
2066   TopTools_MapOfOrientedShape aMEx;
2067   //
2068   for (i=1; i<=aNbWires; ++i) {
2069     const TopoDS_Shape& aWx=aWires->Value(i);
2070     //
2071     aMEx.Clear();
2072     aIt.Initialize (aWx);
2073     for (; aIt.More(); aIt.Next()) {
2074       const TopoDS_Shape& aEx=aIt.Value();
2075       aMEx.Add(aEx);
2076     }
2077     // aWy
2078     aBB.MakeWire (aWy);
2079     for (j=1; j<=aNbEdges; ++j) {
2080       const TopoDS_Shape& aE=aEdges->Value(j);
2081       if (aMEx.Contains(aE)) {
2082         aBB.Add(aWy, aE);
2083       }
2084     }
2085     //
2086     bClosed=aWx.Closed();
2087     aWy.Closed(bClosed);
2088     //
2089     aWires->Append(aWy);
2090   }// for (i=1; i<=aNbWires; ++i) {
2091   //
2092   aWires->Remove(1, aNbWires);
2093 }
2094 */
2095 //modified by NIZNHY-PKV Wed Dec 28 13:48:34 2011t