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