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