e1a5648a54c4281e85f0ce5e13b4e2faf05a7a24
[occt.git] / src / LocOpe / LocOpe_WiresOnShape.cxx
1 // Created on: 1996-01-11
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Bnd_Box2d.hxx>
19 #include <BndLib_Add2dCurve.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepAdaptor_Curve2d.hxx>
23 #include <BRepLib.hxx>
24 #include <BRepLib_MakeVertex.hxx>
25 #include <BRepTools.hxx>
26 #include <Extrema_ExtCC.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_Plane.hxx>
31 #include <Geom_RectangularTrimmedSurface.hxx>
32 #include <Geom_Surface.hxx>
33 #include <Geom_TrimmedCurve.hxx>
34 #include <GeomAdaptor_Surface.hxx>
35 #include <GeomAPI_ProjectPointOnCurve.hxx>
36 #include <GeomProjLib.hxx>
37 #include <gp_Pnt2d.hxx>
38 #include <gp_Vec.hxx>
39 #include <gp_Vec2d.hxx>
40 #include <LocOpe.hxx>
41 #include <LocOpe_WiresOnShape.hxx>
42 #include <Precision.hxx>
43 #include <Standard_ConstructionError.hxx>
44 #include <Standard_Type.hxx>
45 #include <TopExp.hxx>
46 #include <TopExp_Explorer.hxx>
47 #include <TopoDS.hxx>
48 #include <TopoDS_Compound.hxx>
49 #include <TopoDS_Edge.hxx>
50 #include <TopoDS_Face.hxx>
51 #include <TopoDS_Shape.hxx>
52 #include <TopoDS_Vertex.hxx>
53 #include <TopoDS_Wire.hxx>
54 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
55 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57 #include <TopTools_ListOfShape.hxx>
58 #include <TopTools_MapOfShape.hxx>
59
60 IMPLEMENT_STANDARD_RTTIEXT(LocOpe_WiresOnShape,MMgt_TShared)
61
62 static Standard_Boolean Project(const TopoDS_Vertex&,
63                                 const gp_Pnt2d&,
64                                 const TopoDS_Face&,
65                                 TopoDS_Edge&,
66                                 Standard_Real&);
67
68 static Standard_Real Project(const TopoDS_Vertex&,
69                              const TopoDS_Edge&);
70
71 static Standard_Real Project(const TopoDS_Vertex&,
72                              const gp_Pnt2d&,
73                              const TopoDS_Edge&,
74                              const TopoDS_Face&);
75
76
77 static void PutPCurve(const TopoDS_Edge&,
78                       const TopoDS_Face&);
79
80
81 static void PutPCurves(const TopoDS_Edge&,
82                        const TopoDS_Edge&,
83                        const TopoDS_Shape&);
84
85 static void FindInternalIntersections(const TopoDS_Edge&,
86                                       const TopoDS_Face&,
87                                       TopTools_IndexedDataMapOfShapeListOfShape&);
88
89 //=======================================================================
90 //function : LocOpe_WiresOnShape
91 //purpose  : 
92 //=======================================================================
93
94 LocOpe_WiresOnShape::LocOpe_WiresOnShape(const TopoDS_Shape& S):
95   myShape(S),myCheckInterior(Standard_True),myDone(Standard_False)
96 {}
97
98
99
100 //=======================================================================
101 //function : Init
102 //purpose  : 
103 //=======================================================================
104
105 void LocOpe_WiresOnShape::Init(const TopoDS_Shape& S)
106 {
107    myShape = S;
108    myCheckInterior = Standard_True;
109    myDone = Standard_False;
110    myMap.Clear();
111    myMapEF.Clear();
112 }
113
114
115
116 //=======================================================================
117 //function : Bind
118 //purpose  : 
119 //=======================================================================
120
121 void LocOpe_WiresOnShape::Bind(const TopoDS_Wire& W,
122                                const TopoDS_Face& F)
123 {
124   for (TopExp_Explorer exp(W, TopAbs_EDGE); exp.More(); exp.Next()) {
125     Bind(TopoDS::Edge(exp.Current()),F);
126   }
127 }
128
129 //=======================================================================
130 //function : Bind
131 //purpose  : 
132 //=======================================================================
133
134 void LocOpe_WiresOnShape::Bind(const TopoDS_Compound& Comp,
135                                const TopoDS_Face& F)
136 {
137   for (TopExp_Explorer exp(Comp, TopAbs_EDGE); exp.More(); exp.Next()) {
138     Bind(TopoDS::Edge(exp.Current()),F);
139   }
140   myFacesWithSection.Add(F);
141 }
142
143 //=======================================================================
144 //function : Bind
145 //purpose  : 
146 //=======================================================================
147
148 void LocOpe_WiresOnShape::Bind(const TopoDS_Edge& E,
149                                const TopoDS_Face& F)
150 {
151 //  if (!myMapEF.IsBound(E)) {
152   if (!myMapEF.Contains(E)) {
153 //    for (TopExp_Explorer exp(F,TopAbs_EDGE);exp.More();exp.Next()) {
154     TopExp_Explorer exp(F,TopAbs_EDGE) ;
155     for ( ;exp.More();exp.Next()) {
156       if (exp.Current().IsSame(E)) {
157         break;
158       }
159     }
160     if (!exp.More()) {
161 //      myMapEF.Bind(E,F);
162       myMapEF.Add(E,F);
163     }
164   }
165   else {
166     Standard_ConstructionError::Raise();
167   }
168 }
169
170
171 //=======================================================================
172 //function : Bind
173 //purpose  : 
174 //=======================================================================
175
176 void LocOpe_WiresOnShape::Bind(const TopoDS_Edge& Ewir,
177                                const TopoDS_Edge& Efac)
178 {
179   myMap.Bind(Ewir,Efac);
180 }
181
182
183 //=======================================================================
184 //function : BindAll
185 //purpose  : 
186 //=======================================================================
187
188 void LocOpe_WiresOnShape::BindAll()
189 {
190   if (myDone) {
191     return;
192   }
193   TopTools_MapOfShape theMap;
194
195   // Detection des vertex a projeter ou a "binder" avec des vertex existants
196   TopTools_DataMapOfShapeShape mapV;
197   TopTools_DataMapIteratorOfDataMapOfShapeShape ite(myMap);
198   TopExp_Explorer exp,exp2;
199   for (; ite.More(); ite.Next()) {
200     const TopoDS_Edge& eref = TopoDS::Edge(ite.Key());
201     const TopoDS_Edge& eimg = TopoDS::Edge(ite.Value());
202
203     PutPCurves(eref,eimg,myShape);
204
205     for (exp.Init(eref,TopAbs_VERTEX); exp.More(); exp.Next()) {
206       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
207       if (!theMap.Contains(vtx)) { // pas deja traite
208         for (exp2.Init(eimg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
209           const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current());
210           if (vtx2.IsSame(vtx)) {
211             break;
212           }
213           else if (BRepTools::Compare(vtx,vtx2)) {
214             mapV.Bind(vtx,vtx2);
215             break;
216           }
217         }
218         if (!exp2.More()) {
219           mapV.Bind(vtx,eimg);
220         }
221         theMap.Add(vtx);
222       }
223     }
224   }
225   
226   for (ite.Initialize(mapV); ite.More(); ite.Next()) {
227     myMap.Bind(ite.Key(),ite.Value());
228   }
229
230   TopTools_IndexedDataMapOfShapeListOfShape Splits;
231   Standard_Integer Ind;
232   for (Ind = 1; Ind <= myMapEF.Extent(); Ind++)
233   {
234     const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind));
235     const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind));
236     
237     PutPCurve(edg,fac);
238     Standard_Real pf, pl;
239     Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(edg, fac, pf, pl);
240     if (aPCurve.IsNull())
241       continue;
242
243     if (myCheckInterior)
244       FindInternalIntersections(edg, fac, Splits);
245   }
246
247   for (Ind = 1; Ind <= Splits.Extent(); Ind++)
248   {
249     TopoDS_Shape anEdge = Splits.FindKey(Ind);
250     TopoDS_Shape aFace  = myMapEF.FindFromKey(anEdge);
251     //Remove "anEdge" from "myMapEF"
252     TopoDS_Shape LastEdge = myMapEF.FindKey(myMapEF.Extent());
253     TopoDS_Shape LastFace = myMapEF(myMapEF.Extent());
254     myMapEF.RemoveLast();
255     if (myMapEF.FindIndex(anEdge) != 0)
256       myMapEF.Substitute(myMapEF.FindIndex(anEdge), LastEdge, LastFace);
257     ////////////////////////////////
258     TopTools_ListIteratorOfListOfShape itl(Splits(Ind));
259     for (; itl.More(); itl.Next())
260       myMapEF.Add(itl.Value(), aFace);
261   }
262   
263  
264   for (Ind = 1; Ind <= myMapEF.Extent(); Ind++) {
265     const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind));
266     const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind));
267     // JAG 02.02.96 : On verifie les pcurves...
268
269     //PutPCurve(edg,fac);
270
271     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
272       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
273       if (theMap.Contains(vtx)) {
274         continue;
275       }
276       
277       Standard_Real vtx_param = BRep_Tool::Parameter(vtx, edg);
278       BRepAdaptor_Curve2d BAcurve2d(edg, fac);
279       gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
280
281       TopoDS_Edge Epro;
282       Standard_Real prm = 0.;
283       Standard_Boolean ok = Project(vtx, p2d, fac, Epro, prm);
284       if (ok) {
285        
286         for (exp2.Init(Epro,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
287           const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current());
288           if (vtx2.IsSame(vtx)) {
289             break;
290           }
291           else if (BRepTools::Compare(vtx,vtx2)) {
292             Standard_Real aF1, aL1;
293             BRep_Tool::Range(Epro, fac, aF1, aL1);
294             if (!BRep_Tool::Degenerated(Epro) ||
295                 Abs(prm-aF1) <= Precision::PConfusion() ||
296                 Abs(prm-aL1)  <= Precision::PConfusion())
297             {
298               myMap.Bind(vtx,vtx2);
299               break;
300             }
301           }
302         }
303         if (!exp2.More()) {
304           myMap.Bind(vtx,Epro);
305         }
306         theMap.Add(vtx);
307       }
308     }
309   }
310
311 //  Modified by Sergey KHROMOV - Mon Feb 12 16:26:50 2001 Begin
312   for (ite.Initialize(myMap); ite.More(); ite.Next())
313     if ((ite.Key()).ShapeType() == TopAbs_EDGE)
314       myMapEF.Add(ite.Key(),ite.Value());
315 //  Modified by Sergey KHROMOV - Mon Feb 12 16:26:52 2001 End
316
317
318   myDone = Standard_True;
319
320 }
321
322
323 //=======================================================================
324 //function : InitEdgeIterator
325 //purpose  : 
326 //=======================================================================
327
328 void LocOpe_WiresOnShape::InitEdgeIterator()
329 {
330   BindAll();
331 //  myIt.Initialize(myMapEF);
332   myIndex = 1;
333 }
334
335
336 //=======================================================================
337 //function : MoreEdge
338 //purpose  : 
339 //=======================================================================
340
341 Standard_Boolean LocOpe_WiresOnShape::MoreEdge()
342 {
343 //  return myIt.More();
344   return (myIndex <= myMapEF.Extent());
345 }
346
347
348 //=======================================================================
349 //function : Edge
350 //purpose  : 
351 //=======================================================================
352
353 TopoDS_Edge LocOpe_WiresOnShape::Edge()
354 {
355 //  return TopoDS::Edge(myIt.Key());
356   return TopoDS::Edge(myMapEF.FindKey(myIndex));
357 }
358
359
360 //=======================================================================
361 //function : Face
362 //purpose  : 
363 //=======================================================================
364
365 TopoDS_Face LocOpe_WiresOnShape::OnFace()
366 {
367 //  return TopoDS::Face(myIt.Value());
368   return TopoDS::Face(myMapEF(myIndex));
369 }
370
371
372 //=======================================================================
373 //function : OnEdge
374 //purpose  : 
375 //=======================================================================
376
377 Standard_Boolean LocOpe_WiresOnShape::OnEdge(TopoDS_Edge& E)
378 {
379 //  if (myMap.IsBound(myIt.Key())) {
380   if (myMap.IsBound(myMapEF.FindKey(myIndex))) {
381 //    E = TopoDS::Edge(myMap(myIt.Key()));
382     E = TopoDS::Edge(myMap(myMapEF.FindKey(myIndex)));
383     return Standard_True;
384   }
385   return Standard_False;
386 }
387
388
389
390
391 //=======================================================================
392 //function : NextEdge
393 //purpose  : 
394 //=======================================================================
395
396 void LocOpe_WiresOnShape::NextEdge()
397 {
398 //  myIt.Next();
399   myIndex++;
400 }
401
402
403
404 //=======================================================================
405 //function : OnVertex
406 //purpose  : 
407 //=======================================================================
408
409 Standard_Boolean LocOpe_WiresOnShape::OnVertex(const TopoDS_Vertex& Vw,
410                                                TopoDS_Vertex& Vs)
411 {
412   if (myMap.IsBound(Vw)) {
413     if (myMap(Vw).ShapeType() == TopAbs_VERTEX) {
414       Vs = TopoDS::Vertex(myMap(Vw));
415       return Standard_True;
416     }
417     return Standard_False;
418   }
419   return Standard_False;
420 }
421
422
423 //=======================================================================
424 //function : OnEdge
425 //purpose  : 
426 //=======================================================================
427
428 Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
429                                           TopoDS_Edge& Ed,
430                                           Standard_Real& prm)
431 {
432   if (!myMap.IsBound(V) ||
433       myMap(V).ShapeType() == TopAbs_VERTEX) {
434     return Standard_False;
435   }
436   
437   Ed = TopoDS::Edge(myMap(V));
438   prm = Project(V,Ed);
439   return Standard_True;
440 }
441
442 //=======================================================================
443 //function : OnEdge
444 //purpose  : 
445 //=======================================================================
446
447 Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
448                                              const TopoDS_Edge& EdgeFrom,
449                                              TopoDS_Edge& Ed,
450                                              Standard_Real& prm)
451 {
452   if (!myMap.IsBound(V) ||
453       myMap(V).ShapeType() == TopAbs_VERTEX) {
454     return Standard_False;
455   }
456   
457   Ed = TopoDS::Edge(myMap(V));
458   if(!myMapEF.Contains(EdgeFrom))
459     return Standard_False;
460
461   TopoDS_Shape aShape = myMapEF.FindFromKey(EdgeFrom);
462   if(  aShape.ShapeType() == TopAbs_FACE)
463   {
464
465     TopoDS_Face aFace = TopoDS::Face(aShape);
466     Standard_Real vtx_param = BRep_Tool::Parameter(V, EdgeFrom);
467     BRepAdaptor_Curve2d BAcurve2d(EdgeFrom, aFace);
468     gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
469
470
471     prm = Project(V, p2d, Ed, aFace);
472   }
473   else
474     prm = Project( V, TopoDS::Edge(Ed));
475         
476   return Standard_True;
477 }
478
479
480 //=======================================================================
481 //function : Project
482 //purpose  : 
483 //=======================================================================
484
485 Standard_Boolean Project(const TopoDS_Vertex& V,
486                          const gp_Pnt2d& p2d,
487                          const TopoDS_Face& F,
488                          TopoDS_Edge& theEdge,
489                          Standard_Real& param)
490 {
491   Handle(Geom2d_Curve) PC;
492   //TopLoc_Location Loc;
493   Standard_Real f,l;
494
495   Standard_Real dmin = RealLast();
496   //gp_Pnt toproj(BRep_Tool::Pnt(V));
497   Standard_Boolean valret = Standard_False;
498   Geom2dAPI_ProjectPointOnCurve proj;
499
500   for (TopExp_Explorer exp(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE); 
501        exp.More(); exp.Next()) {
502     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
503     //C = BRep_Tool::Curve(edg,Loc,f,l);
504     PC = BRep_Tool::CurveOnSurface(edg, F, f, l);
505     proj.Init(p2d, PC, f, l);
506     if (proj.NbPoints() > 0) {
507       if (proj.LowerDistance() < dmin) {
508         theEdge = edg;
509         theEdge.Orientation(edg.Orientation());
510         dmin = proj.LowerDistance();
511         param = proj.LowerDistanceParameter();
512       }
513     }
514   }
515
516   if(theEdge.IsNull())
517     return Standard_False;
518   //compute distance in 3D space
519
520   Handle(Geom2d_Curve) aCrvBound = BRep_Tool::CurveOnSurface(theEdge, F, f, l);
521   gp_Pnt2d aPBound2d;
522   aCrvBound->D0(param,aPBound2d);
523   gp_Pnt aPBound;
524   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
525   aSurf->D0(aPBound2d.X(), aPBound2d.Y(), aPBound);
526   
527   //point of vertex computed by pcurve of the splitting edge
528   gp_Pnt aPV2d;
529   aSurf->D0(p2d.X(), p2d.Y(), aPV2d);
530   //point of vertex in 3D splace
531   gp_Pnt aP3dV = BRep_Tool::Pnt(V);
532
533   Standard_Real aDist3d2 = Max( aPV2d.SquareDistance(aPBound), aP3dV.SquareDistance(aPBound));
534   Standard_Real aTolV = BRep_Tool::Tolerance(V);
535   Standard_Real ttol = aTolV + BRep_Tool::Tolerance(theEdge);
536   if (aDist3d2 <= ttol* ttol) {
537     valret = Standard_True;
538
539     BRep_Builder B;
540     if( aTolV * aTolV < aDist3d2)
541     {
542       Standard_Real aNewTol = sqrt(aDist3d2) + Precision::Confusion();
543       B.UpdateVertex(V, aNewTol);
544     }
545   }
546 #ifdef OCCT_DEBUG_MESH
547   else {
548     cout <<"LocOpe_WiresOnShape::Project --> le vertex projete est a une "; 
549     cout <<"distance / la face = "<<dmin <<" superieure a la tolerance = "<<ttol<<endl;
550   }
551 #endif
552   return valret;
553 }
554
555 //=======================================================================
556 //function : Project
557 //purpose  : 
558 //=======================================================================
559
560 Standard_Real Project(const TopoDS_Vertex& V,
561                       const TopoDS_Edge& theEdge)
562 {
563   Handle(Geom_Curve) C;
564   TopLoc_Location Loc;
565   Standard_Real f,l;
566
567   gp_Pnt toproj(BRep_Tool::Pnt(V));
568   GeomAPI_ProjectPointOnCurve proj;
569
570   C = BRep_Tool::Curve(theEdge,Loc,f,l);
571   if (!Loc.IsIdentity()) {
572     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
573     C = Handle(Geom_Curve)::DownCast (GG);
574   }
575   proj.Init(toproj,C,f,l);
576   
577
578   return proj.LowerDistanceParameter();
579 }
580
581 //=======================================================================
582 //function : Project
583 //purpose  : 
584 //=======================================================================
585
586 Standard_Real Project(const TopoDS_Vertex&,
587                       const gp_Pnt2d&      p2d,
588                       const TopoDS_Edge& theEdge,
589                       const TopoDS_Face& theFace)
590 {
591   //Handle(Geom_Curve) C;
592   Handle(Geom2d_Curve) PC;
593   //TopLoc_Location Loc;
594   Standard_Real f,l;
595
596   Geom2dAPI_ProjectPointOnCurve proj;
597
598   PC = BRep_Tool::CurveOnSurface(theEdge, theFace, f, l);
599   /*
600   if (!Loc.IsIdentity()) {
601     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
602     C = Handle(Geom_Curve)::DownCast (GG);
603   }
604   */
605   proj.Init(p2d, PC, f, l);
606
607   return proj.LowerDistanceParameter();
608 }
609
610
611 //=======================================================================
612 //function : PutPCurve
613 //purpose  : 
614 //=======================================================================
615
616 void PutPCurve(const TopoDS_Edge& Edg,
617                const TopoDS_Face& Fac)
618 {
619   BRep_Builder B;
620   TopLoc_Location LocFac;
621
622   Handle(Geom_Surface) S = BRep_Tool::Surface(Fac, LocFac);
623   Handle(Standard_Type) styp = S->DynamicType();
624
625   if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
626     S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
627     styp = S->DynamicType();
628   }
629
630   if (styp == STANDARD_TYPE(Geom_Plane)) {
631     return;
632   }
633
634   Standard_Real Umin,Umax,Vmin,Vmax;
635   BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
636
637   Standard_Real f,l;
638
639   Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(Edg,Fac,f,l);
640   if ( !aC2d.IsNull() ) {
641     gp_Pnt2d p2d;
642     aC2d->D0(f,p2d);
643     Standard_Boolean IsIn = Standard_True;
644     if ( ( p2d.X() < Umin-Precision::PConfusion() ) || 
645          ( p2d.X() > Umax+Precision::PConfusion() ) )
646       IsIn = Standard_False;
647     if ( ( p2d.Y() < Vmin-Precision::PConfusion() ) || 
648          ( p2d.Y() > Vmax+Precision::PConfusion() ) )
649       IsIn = Standard_False;
650     aC2d->D0(l,p2d);
651     if ( ( p2d.X() < Umin-Precision::PConfusion() ) || 
652          ( p2d.X() > Umax+Precision::PConfusion() ) )
653       IsIn = Standard_False;
654     if ( ( p2d.Y() < Vmin-Precision::PConfusion() ) || 
655          ( p2d.Y() > Vmax+Precision::PConfusion() ) )
656       IsIn = Standard_False;
657     if (IsIn)
658       return;
659   }
660
661   TopLoc_Location Loc;
662   Handle(Geom_Curve) C = BRep_Tool::Curve(Edg,Loc,f,l);
663   if (!Loc.IsIdentity()) {
664     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
665     C = Handle(Geom_Curve)::DownCast (GG);
666   }
667
668   if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
669     C = new Geom_TrimmedCurve(C,f,l);
670   }
671
672   S = BRep_Tool::Surface(Fac);
673
674   // Compute the tol2d
675   Standard_Real tol3d = Max(BRep_Tool::Tolerance(Edg),
676                             BRep_Tool::Tolerance(Fac));
677   GeomAdaptor_Surface Gas(S,Umin,Umax,Vmin,Vmax);
678   Standard_Real TolU  = Gas.UResolution(tol3d);
679   Standard_Real TolV  = Gas.VResolution(tol3d);
680   Standard_Real tol2d = Max(TolU,TolV);
681
682   Handle(Geom2d_Curve) C2d = 
683     GeomProjLib::Curve2d(C,S,Umin,Umax,Vmin,Vmax,tol2d);
684  if(C2d.IsNull()) 
685        return;
686   gp_Pnt2d pf(C2d->Value(f));
687   gp_Pnt2d pl(C2d->Value(l));
688   gp_Pnt PF,PL;
689   S->D0(pf.X(),pf.Y(),PF);
690   S->D0(pl.X(),pl.Y(),PL);
691   TopoDS_Vertex V1,V2;
692   if (Edg.Orientation() == TopAbs_REVERSED) {
693     V1 = TopExp::LastVertex(Edg);
694     V1.Reverse();
695   }
696   else {
697     V1 = TopExp::FirstVertex (Edg);
698   }
699   if (Edg.Orientation() == TopAbs_REVERSED) {
700     V2 = TopExp::FirstVertex(Edg);
701     V2.Reverse();
702   }
703   else {
704     V2 = TopExp::LastVertex (Edg);
705   }
706
707   if(!V1.IsNull() && V2.IsNull()) {
708     //Handling of internal vertices
709     Standard_Real old1 = BRep_Tool::Tolerance (V1);
710     Standard_Real old2 = BRep_Tool::Tolerance (V2);
711     gp_Pnt pnt1 = BRep_Tool::Pnt (V1);
712     gp_Pnt pnt2 = BRep_Tool::Pnt (V2);
713     Standard_Real tol1 = pnt1.Distance(PF);
714     Standard_Real tol2 = pnt2.Distance(PL);
715     B.UpdateVertex(V1,Max(old1,tol1));
716     B.UpdateVertex(V2,Max(old2,tol2));
717   }
718
719   if (S->IsUPeriodic()) {
720     Standard_Real up   = S->UPeriod();
721     Standard_Real tolu = Precision::PConfusion();// Epsilon(up);
722     Standard_Integer nbtra = 0;
723     Standard_Real theUmin = Min(pf.X(),pl.X());
724     Standard_Real theUmax = Max(pf.X(),pl.X());
725
726     if (theUmin < Umin-tolu) {
727       while (theUmin < Umin-tolu) {
728         theUmin += up;
729         nbtra++;
730       }
731     }
732     else if (theUmax > Umax+tolu) {
733       while (theUmax > Umax+tolu) {
734         theUmax -= up;
735         nbtra--;
736       }
737     }
738
739     if (nbtra !=0) {
740       C2d->Translate(gp_Vec2d(nbtra*up,0.));
741     }
742   }    
743
744   if (S->IsVPeriodic()) {
745     Standard_Real vp   = S->VPeriod();
746     Standard_Real tolv = Precision::PConfusion();// Epsilon(vp);
747     Standard_Integer nbtra = 0;
748     Standard_Real theVmin = Min(pf.Y(),pl.Y());
749     Standard_Real theVmax = Max(pf.Y(),pl.Y());
750
751     if (theVmin < Vmin-tolv) {
752       while (theVmin < Vmin-tolv) {
753         theVmin += vp; theVmax += vp;
754         nbtra++;
755       }
756     }
757     else if (theVmax > Vmax+tolv) {
758       while (theVmax > Vmax+tolv) {
759         theVmax -= vp; theVmin -= vp;
760         nbtra--;
761       }
762     }
763 /*
764     if (theVmin > Vmax-tolv) {
765       while (theVmin > Vmax-tolv) {
766         theVmin -= vp;
767         nbtra--;
768       }
769     }
770     else if (theVmax < Vmin+tolv) {
771       while (theVmax < Vmin+tolv) {
772         theVmax += vp;
773         nbtra++;
774       }
775     }
776 */
777     if (nbtra !=0) {
778       C2d->Translate(gp_Vec2d(0.,nbtra*vp));
779     }
780   }
781   B.UpdateEdge(Edg,C2d,Fac,BRep_Tool::Tolerance(Edg));
782   
783   B.SameParameter(Edg,Standard_False);
784   BRepLib::SameParameter(Edg,tol2d); 
785 }
786
787
788 //=======================================================================
789 //function : PutPCurves
790 //purpose  : 
791 //=======================================================================
792
793 void PutPCurves(const TopoDS_Edge& Efrom,
794                 const TopoDS_Edge& Eto,
795                 const TopoDS_Shape& myShape)
796 {
797
798   TopTools_ListOfShape Lfaces;
799   TopExp_Explorer exp,exp2;
800
801   for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
802     for (exp2.Init(exp.Current(), TopAbs_EDGE); exp2.More();exp2.Next()) {
803       if (exp2.Current().IsSame(Eto)) {
804         Lfaces.Append(exp.Current());
805       }
806     }
807   }
808
809   if (Lfaces.Extent() != 1 && Lfaces.Extent() !=2) {
810     Standard_ConstructionError::Raise();
811   }
812
813   // soit bord libre, soit connexite entre 2 faces, eventuellement edge closed
814
815   if (Lfaces.Extent() ==1) {
816     return; // sera fait par PutPCurve.... on l`espere
817   }
818
819   BRep_Builder B;
820   Handle(Geom_Surface) S;
821   Handle(Standard_Type) styp;
822   Handle(Geom_Curve) C;
823   Standard_Real Umin,Umax,Vmin,Vmax;
824   Standard_Real f,l;
825   TopLoc_Location Loc, LocFac;
826
827   if (!Lfaces.First().IsSame(Lfaces.Last())) {
828     TopTools_ListIteratorOfListOfShape itl(Lfaces);
829     for (; itl.More(); itl.Next()) {
830       const TopoDS_Face& Fac = TopoDS::Face(itl.Value());
831
832       if (!BRep_Tool::CurveOnSurface(Efrom,Fac,f,l).IsNull()) {
833         continue;
834       }
835       S = BRep_Tool::Surface(Fac, LocFac);
836       styp = S->DynamicType();
837       if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
838         S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
839         styp = S->DynamicType();
840       }
841       if (styp == STANDARD_TYPE(Geom_Plane)) {
842         continue;
843       }
844
845             
846       BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
847       C = BRep_Tool::Curve(Efrom,Loc,f,l);
848       if (!Loc.IsIdentity()) {
849         Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
850         C = Handle(Geom_Curve)::DownCast (GG);
851       }
852       
853       if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
854         C = new Geom_TrimmedCurve(C,f,l);
855       }
856     
857       S = BRep_Tool::Surface(Fac);
858
859       // Compute the tol2d
860       Standard_Real tol3d = Max(BRep_Tool::Tolerance(Efrom),
861                                 BRep_Tool::Tolerance(Fac));
862       GeomAdaptor_Surface Gas(S,Umin,Umax,Vmin,Vmax);
863       Standard_Real TolU  = Gas.UResolution(tol3d);
864       Standard_Real TolV  = Gas.VResolution(tol3d);
865       Standard_Real tol2d = Max(TolU,TolV);
866
867       Handle(Geom2d_Curve) C2d = 
868         GeomProjLib::Curve2d(C,S,Umin,Umax,Vmin,Vmax,tol2d);
869      if(C2d.IsNull())
870        return;
871
872       gp_Pnt2d pf(C2d->Value(f));
873       gp_Pnt2d pl(C2d->Value(l));
874       
875       if (S->IsUPeriodic()) {
876         Standard_Real up   = S->UPeriod();
877         Standard_Real tolu = Precision::PConfusion();// Epsilon(up);
878         Standard_Integer nbtra = 0;
879         Standard_Real theUmin = Min(pf.X(),pl.X());
880         Standard_Real theUmax = Max(pf.X(),pl.X());
881
882         if (theUmin < Umin-tolu) {
883           while (theUmin < Umin-tolu) {
884             theUmin += up; theUmax += up;
885             nbtra++;
886           }
887         }
888         else if (theUmax > Umax+tolu) {
889           while (theUmax > Umax+tolu) {
890             theUmax -= up; theUmin -= up;
891             nbtra--;
892           }
893         }
894 /*
895         if (theUmin > Umax+tolu) {
896           while (theUmin > Umax+tolu) {
897             theUmin -= up;
898             nbtra--;
899           }
900         }
901         else if (theUmax < Umin-tolu) {
902           while (theUmax < Umin-tolu) {
903             theUmax += up;
904             nbtra++;
905           }
906         }
907 */
908         if (nbtra !=0) {
909           C2d->Translate(gp_Vec2d(nbtra*up,0.));
910         }
911       }    
912       
913       if (S->IsVPeriodic()) {
914         Standard_Real vp   = S->VPeriod();
915         Standard_Real tolv = Precision::PConfusion();// Epsilon(vp);
916         Standard_Integer nbtra = 0;
917         Standard_Real theVmin = Min(pf.Y(),pl.Y());
918         Standard_Real theVmax = Max(pf.Y(),pl.Y());
919
920         if (theVmin < Vmin-tolv) {
921           while (theVmin < Vmin-tolv) {
922             theVmin += vp; theVmax += vp;
923             nbtra++;
924           }
925         }
926         else if (theVmax > Vmax+tolv) {
927           while (theVmax > Vmax+tolv) {
928             theVmax -= vp; theVmin -= vp;
929             nbtra--;
930           }
931         }
932 /*
933         if (theVmin > Vmax+tolv) {
934           while (theVmin > Vmax+tolv) {
935             theVmin -= vp;
936             nbtra--;
937           }
938         }
939         else if (theVmax < Vmin-tolv) {
940           while (theVmax < Vmin-tolv) {
941             theVmax += vp;
942             nbtra++;
943           }
944         }
945 */
946         if (nbtra !=0) {
947           C2d->Translate(gp_Vec2d(0.,nbtra*vp));
948         }
949       }
950       B.UpdateEdge(Efrom,C2d,Fac,BRep_Tool::Tolerance(Efrom));
951     }
952   }
953
954   else {
955     const TopoDS_Face& Fac = TopoDS::Face(Lfaces.First());
956     if (!BRep_Tool::IsClosed(Eto,Fac)) {
957       Standard_ConstructionError::Raise();
958     }
959
960     TopoDS_Shape aLocalE = Efrom.Oriented(TopAbs_FORWARD);
961     TopoDS_Shape aLocalF = Fac.Oriented(TopAbs_FORWARD);
962     Handle(Geom2d_Curve) c2dff = 
963       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
964                                 TopoDS::Face(aLocalF),
965                                 f,l);
966
967 //    Handle(Geom2d_Curve) c2dff = 
968 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Efrom.Oriented(TopAbs_FORWARD)),
969 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
970 //                              f,l);
971     
972     aLocalE = Efrom.Oriented(TopAbs_REVERSED);
973     aLocalF = Fac.Oriented(TopAbs_FORWARD);
974     Handle(Geom2d_Curve) c2dfr = 
975       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
976                                 TopoDS::Face(aLocalF),
977                                 f,l);
978 //    Handle(Geom2d_Curve) c2dfr = 
979 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Efrom.Oriented(TopAbs_REVERSED)),
980 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
981 //                              f,l);
982     
983     aLocalE = Eto.Oriented(TopAbs_FORWARD);
984     aLocalF = Fac.Oriented(TopAbs_FORWARD);
985     Handle(Geom2d_Curve) c2dtf = 
986       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
987                                 TopoDS::Face(aLocalF),
988                                 f,l);
989
990 //    Handle(Geom2d_Curve) c2dtf = 
991 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Eto.Oriented(TopAbs_FORWARD)),
992 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
993 //                              f,l);
994     aLocalE = Eto.Oriented(TopAbs_REVERSED);
995     aLocalF = Fac.Oriented(TopAbs_FORWARD);
996     Handle(Geom2d_Curve) c2dtr = 
997       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
998                                 TopoDS::Face(aLocalF),
999                                 f,l);
1000 //    Handle(Geom2d_Curve) c2dtr = 
1001 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Eto.Oriented(TopAbs_REVERSED)),
1002 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
1003 //                              f,l);
1004
1005     gp_Pnt2d ptf(c2dtf->Value(f)); // sur courbe frw
1006     gp_Pnt2d ptr(c2dtr->Value(f)); // sur courbe rev
1007
1008     Standard_Boolean isoU = (Abs(ptf.Y()-ptr.Y())<Epsilon(ptf.X())); // meme V
1009
1010     // Efrom et Eto dans le meme sens???
1011
1012     C = BRep_Tool::Curve(Efrom,Loc,f,l);
1013     if (!Loc.IsIdentity()) {
1014       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
1015       C = Handle(Geom_Curve)::DownCast (GG);
1016     }
1017
1018     gp_Pnt pt;
1019     gp_Vec d1f,d1t;
1020
1021     C->D1(f,pt,d1f);
1022
1023
1024     TopoDS_Vertex FirstVertex = TopExp::FirstVertex(Efrom);
1025     Standard_Real vtx_param = BRep_Tool::Parameter(FirstVertex, Efrom);
1026     BRepAdaptor_Curve2d BAcurve2d(Efrom, Fac);
1027     gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
1028
1029     Standard_Real prmproj = Project(TopExp::FirstVertex(Efrom),p2d,Eto,Fac);
1030     
1031     C = BRep_Tool::Curve(Eto,Loc,f,l);
1032     if (!Loc.IsIdentity()) {
1033       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
1034       C = Handle(Geom_Curve)::DownCast (GG);
1035     }
1036     
1037     C->D1(prmproj,pt,d1t);
1038
1039     Standard_Real SameOri = (d1t.Dot(d1f)>0.); 
1040
1041
1042     if (c2dff.IsNull() && c2dfr.IsNull()) {
1043       S = BRep_Tool::Surface(Fac);
1044       styp = S->DynamicType();
1045       if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1046         S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
1047         styp = S->DynamicType();
1048       }
1049       
1050       C = BRep_Tool::Curve(Efrom,Loc,f,l);
1051       if (!Loc.IsIdentity()) {
1052         Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
1053         C = Handle(Geom_Curve)::DownCast (GG);
1054       }
1055       
1056       if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
1057         C = new Geom_TrimmedCurve(C,f,l);
1058       }
1059
1060       // Compute the tol2d
1061       BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
1062
1063       Standard_Real tol3d = Max(BRep_Tool::Tolerance(Efrom),
1064                                 BRep_Tool::Tolerance(Fac));
1065       GeomAdaptor_Surface Gas(S,Umin,Umax,Vmin,Vmax);
1066       Standard_Real TolU  = Gas.UResolution(tol3d);
1067       Standard_Real TolV  = Gas.VResolution(tol3d);
1068       Standard_Real tol2d = Max(TolU,TolV);
1069     
1070       Handle(Geom2d_Curve) C2d = 
1071         GeomProjLib::Curve2d(C,S,Umin,Umax,Vmin,Vmax,tol2d);
1072       c2dff = C2d;
1073       c2dfr = C2d;
1074     }
1075     else if (c2dfr.IsNull()) {
1076       c2dfr = c2dff;
1077
1078     }
1079     else if (c2dff.IsNull()) {
1080       c2dff = c2dfr;
1081     }
1082
1083     BRep_Tool::Range(Efrom,f,l);
1084
1085     gp_Pnt2d p2f = c2dff->Value(f);
1086     gp_Pnt2d p2r = c2dfr->Value(f);
1087
1088     if (isoU) {
1089       if (SameOri) {
1090         if (Abs(ptf.X()-p2f.X()) > Epsilon(ptf.X())) {
1091           c2dff = Handle(Geom2d_Curve)::DownCast
1092             (c2dff->Translated(gp_Vec2d(ptf.X()-p2f.X(),0.)));
1093         }
1094         if (Abs(ptr.X()-p2r.X()) > Epsilon(ptr.X())) {
1095           c2dfr = Handle(Geom2d_Curve)::DownCast
1096             (c2dfr->Translated(gp_Vec2d(ptr.X()-p2r.X(),0.)));
1097         }
1098       }
1099       else {
1100         if (Abs(ptr.X()-p2f.X()) > Epsilon(ptr.X())) {
1101           c2dff = Handle(Geom2d_Curve)::DownCast
1102             (c2dff->Translated(gp_Vec2d(ptr.X()-p2f.X(),0.)));
1103         }
1104         
1105         if (Abs(ptf.X()-p2r.X()) > Epsilon(ptf.X())) {
1106           c2dfr = Handle(Geom2d_Curve)::DownCast
1107             (c2dfr->Translated(gp_Vec2d(ptf.X()-p2r.X(),0.)));
1108         }
1109       }
1110
1111       // on est bien en U, recalage si periodique en V a faire
1112
1113
1114
1115     }
1116     
1117     else { // !isoU soit isoV
1118       if (SameOri) {
1119         if (Abs(ptf.Y()-p2f.Y()) > Epsilon(ptf.Y())) {
1120           c2dff = Handle(Geom2d_Curve)::DownCast
1121             (c2dff->Translated(gp_Vec2d(0.,ptf.Y()-p2f.Y())));
1122         }
1123         if (Abs(ptr.Y()-p2r.Y()) > Epsilon(ptr.Y())) {
1124           c2dfr = Handle(Geom2d_Curve)::DownCast
1125             (c2dfr->Translated(gp_Vec2d(0.,ptr.Y()-p2r.Y())));
1126         }
1127       }
1128       else {
1129         if (Abs(ptr.Y()-p2f.Y()) > Epsilon(ptr.Y())) {
1130           c2dff = Handle(Geom2d_Curve)::DownCast
1131             (c2dff->Translated(gp_Vec2d(0.,ptr.Y()-p2f.Y())));
1132         }
1133         if (Abs(ptf.Y()-p2r.Y()) > Epsilon(ptf.Y())) {
1134           c2dfr = Handle(Geom2d_Curve)::DownCast
1135             (c2dfr->Translated(gp_Vec2d(0.,ptf.Y()-p2r.Y())));
1136         }
1137       }
1138       // on est bien en V, recalage si periodique en U a faire
1139
1140     }
1141     B.UpdateEdge(Efrom,c2dff,c2dfr,Fac,BRep_Tool::Tolerance(Efrom));
1142   }
1143 }
1144
1145 //=======================================================================
1146 //function : FindInternalIntersections
1147 //purpose  : 
1148 //=======================================================================
1149
1150 void FindInternalIntersections(const TopoDS_Edge& theEdge,
1151                                const TopoDS_Face& theFace,
1152                                TopTools_IndexedDataMapOfShapeListOfShape& Splits)
1153 {
1154   Standard_Real TolExt = Precision::PConfusion();
1155   Standard_Integer i, j, aNbExt;
1156
1157   TColStd_SequenceOfReal SplitPars;
1158   
1159   TopoDS_Vertex theVertices [2];
1160   TopExp::Vertices(theEdge, theVertices[0], theVertices[1]);
1161   gp_Pnt thePnt [2];
1162   thePnt[0] = BRep_Tool::Pnt(theVertices[0]);
1163   thePnt[1] = BRep_Tool::Pnt(theVertices[1]);
1164   Standard_Real aTolV[2];
1165   aTolV[0] =BRep_Tool::Tolerance(theVertices[0]);
1166   aTolV[1] =BRep_Tool::Tolerance(theVertices[1]);
1167
1168   BRepAdaptor_Curve2d thePCurve(theEdge, theFace);
1169   Bnd_Box2d theBox;
1170   BndLib_Add2dCurve::Add(thePCurve, BRep_Tool::Tolerance(theEdge), theBox);
1171
1172   Standard_Real thePar [2];
1173   Standard_Real  aFpar, aLpar;
1174   const Handle(Geom_Curve)& theCurve = BRep_Tool::Curve(theEdge, thePar[0], thePar[1]);
1175   GeomAdaptor_Curve theGAcurve(theCurve, thePar[0], thePar[1]);
1176   Standard_Real aDistMax = Precision::Confusion() * Precision::Confusion();
1177   TopExp_Explorer Explo(theFace, TopAbs_EDGE);
1178   for (; Explo.More(); Explo.Next())
1179   {
1180     const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
1181     BRepAdaptor_Curve2d aPCurve(anEdge, theFace);
1182     Bnd_Box2d aBox;
1183     BndLib_Add2dCurve::Add(aPCurve, BRep_Tool::Tolerance(anEdge), aBox);
1184     if (theBox.IsOut(aBox))
1185       continue;
1186
1187     const Handle(Geom_Curve)& aCurve   = BRep_Tool::Curve(anEdge, aFpar, aLpar);
1188     GeomAdaptor_Curve aGAcurve(aCurve, aFpar, aLpar);
1189     Extrema_ExtCC anExtrema(theGAcurve, aGAcurve, TolExt, TolExt);
1190
1191     if (!anExtrema.IsDone())
1192       continue;
1193     if (anExtrema.IsParallel())
1194       continue;
1195
1196     aNbExt = anExtrema.NbExt();
1197     Standard_Real MaxTol = Max(BRep_Tool::Tolerance(theEdge), BRep_Tool::Tolerance(anEdge));
1198     Standard_Real aMaxTol2 =  MaxTol *  MaxTol;
1199     for (i = 1; i <= aNbExt; i++)
1200     {
1201       Standard_Real aDist = anExtrema.SquareDistance(i);
1202       if (aDist > aMaxTol2)
1203         continue;
1204
1205       Extrema_POnCurv aPOnC1, aPOnC2;
1206       anExtrema.Points(i, aPOnC1, aPOnC2);
1207       Standard_Real theIntPar = aPOnC1.Parameter();
1208       Standard_Real anIntPar = aPOnC2.Parameter();
1209       for (j = 0; j < 2; j++) //try to find intersection on an extremity of "theEdge"
1210       {
1211         if (Abs(theIntPar - thePar[j]) <= Precision::PConfusion())
1212           break;
1213       }
1214       //intersection found in the middle of the edge
1215       if (j >= 2) //intersection is inside "theEdge" => split
1216       {
1217         gp_Pnt aPoint = aCurve->Value(anIntPar);
1218         if (aPoint.SquareDistance(thePnt[0]) > aTolV[0] * aTolV[0] &&
1219             aPoint.SquareDistance(thePnt[1]) > aTolV[1] * aTolV[1])
1220         {
1221           SplitPars.Append(theIntPar);
1222           if( aDist > aDistMax)
1223             aDistMax = aDist;
1224         }
1225       }
1226     }
1227   }
1228
1229   if (SplitPars.IsEmpty())
1230     return;
1231   
1232   //Sort
1233   for (i = 1; i < SplitPars.Length(); i++)
1234     for (j = i+1; j <= SplitPars.Length(); j++)
1235       if (SplitPars(i) > SplitPars(j))
1236       {
1237         Standard_Real Tmp = SplitPars(i);
1238         SplitPars(i) = SplitPars(j);
1239         SplitPars(j) = Tmp;
1240       }
1241   //Remove repeating points
1242   i = 1;
1243   while (i < SplitPars.Length())
1244   {
1245     gp_Pnt Pnt1 = theCurve->Value(SplitPars(i));
1246     gp_Pnt Pnt2 = theCurve->Value(SplitPars(i+1));
1247     if (Pnt1.SquareDistance(Pnt2) <= Precision::Confusion()* Precision::Confusion())
1248       SplitPars.Remove(i+1);
1249     else
1250       i++;
1251   }
1252
1253   //Split
1254   TopTools_ListOfShape NewEdges;
1255   BRep_Builder BB;
1256   
1257   TopoDS_Vertex FirstVertex = theVertices[0], LastVertex;
1258   Standard_Real FirstPar = thePar[0], LastPar;
1259   for (i = 1; i <= SplitPars.Length()+1; i++)
1260   {
1261     FirstVertex.Orientation(TopAbs_FORWARD);
1262     if (i <= SplitPars.Length())
1263     {
1264       LastPar = SplitPars(i);
1265       gp_Pnt LastPoint = theCurve->Value(LastPar);
1266       LastVertex = BRepLib_MakeVertex(LastPoint);
1267       BRep_Builder aB;
1268       aB.UpdateVertex(LastVertex, sqrt(aDistMax));
1269     }
1270     else
1271     {
1272       LastPar = thePar[1];
1273       LastVertex = theVertices[1];
1274     }
1275     LastVertex.Orientation(TopAbs_REVERSED);
1276     
1277     TopoDS_Shape aLocalShape = theEdge.EmptyCopied();
1278     TopAbs_Orientation anOrient = aLocalShape.Orientation();
1279     aLocalShape.Orientation(TopAbs_FORWARD);
1280     TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
1281     BB.Range(NewEdge, FirstPar, LastPar);
1282     BB.Add(NewEdge, FirstVertex);
1283     BB.Add(NewEdge, LastVertex);
1284     NewEdge.Orientation(anOrient);
1285     NewEdges.Append(NewEdge);
1286     FirstVertex = LastVertex;
1287     FirstPar = LastPar;
1288   }
1289
1290   if (!NewEdges.IsEmpty())
1291     Splits.Add(theEdge, NewEdges);
1292 }