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