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