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