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