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