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