0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[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
18 #include <Bnd_Box2d.hxx>
19 #include <BndLib_Add2dCurve.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepAdaptor_Curve2d.hxx>
23 #include <BRepLib.hxx>
24 #include <BRepLib_MakeVertex.hxx>
25 #include <BRepTools.hxx>
26 #include <Extrema_ExtCC.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_Plane.hxx>
31 #include <Geom_RectangularTrimmedSurface.hxx>
32 #include <Geom_Surface.hxx>
33 #include <Geom_TrimmedCurve.hxx>
34 #include <GeomAdaptor_Surface.hxx>
35 #include <GeomAPI_ProjectPointOnCurve.hxx>
36 #include <GeomProjLib.hxx>
37 #include <gp_Pnt2d.hxx>
38 #include <gp_Vec.hxx>
39 #include <gp_Vec2d.hxx>
40 #include <LocOpe.hxx>
41 #include <LocOpe_WiresOnShape.hxx>
42 #include <Precision.hxx>
43 #include <Standard_ConstructionError.hxx>
44 #include <Standard_Type.hxx>
45 #include <TopExp.hxx>
46 #include <TopExp_Explorer.hxx>
47 #include <TopoDS.hxx>
48 #include <TopoDS_Compound.hxx>
49 #include <TopoDS_Edge.hxx>
50 #include <TopoDS_Face.hxx>
51 #include <TopoDS_Shape.hxx>
52 #include <TopoDS_Vertex.hxx>
53 #include <TopoDS_Wire.hxx>
54 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
55 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57 #include <TopTools_ListOfShape.hxx>
58 #include <TopTools_MapOfShape.hxx>
59 #include <TopTools_DataMapOfShapeReal.hxx>
60 #include <Extrema_ExtCC2d.hxx>
61 #include <BRepAdaptor_Surface.hxx>
62 #include <ShapeAnalysis_Edge.hxx>
63
64 #include <TopTools_SequenceOfShape.hxx>
65 #include <BRepBndLib.hxx>
66 #include <Bnd_Box.hxx>
67 #include <Bnd_SeqOfBox.hxx>
68 #include <NCollection_Handle.hxx>
69 #include <TColStd_PackedMapOfInteger.hxx>
70 #include <Extrema_ExtPS.hxx>
71
72 #include <BRepTopAdaptor_FClass2d.hxx>
73 #include <ShapeConstruct_ProjectCurveOnSurface.hxx>
74 #include <ShapeAnalysis.hxx>
75
76 IMPLEMENT_STANDARD_RTTIEXT(LocOpe_WiresOnShape,Standard_Transient)
77
78 static Standard_Boolean Project(const TopoDS_Vertex&,
79                                 const gp_Pnt2d&,
80                                 const TopoDS_Face&,
81                                 TopoDS_Edge&,
82                                 Standard_Real&);
83
84 static Standard_Real Project(const TopoDS_Vertex&,
85                              const TopoDS_Edge&);
86
87 static Standard_Real Project(const TopoDS_Vertex&,
88                              const gp_Pnt2d&,
89                              const TopoDS_Edge&,
90                              const TopoDS_Face&);
91
92
93 static void PutPCurve(const TopoDS_Edge&,
94                       const TopoDS_Face&);
95
96
97 static void PutPCurves(const TopoDS_Edge&,
98                        const TopoDS_Edge&,
99                        const TopoDS_Shape&);
100
101 static void FindInternalIntersections(const TopoDS_Edge&,
102                                       const TopoDS_Face&,
103                                       TopTools_IndexedDataMapOfShapeListOfShape&,
104                                       Standard_Boolean&);
105
106 //=======================================================================
107 //function : LocOpe_WiresOnShape
108 //purpose  : 
109 //=======================================================================
110
111 LocOpe_WiresOnShape::LocOpe_WiresOnShape(const TopoDS_Shape& S):
112   myShape(S),myCheckInterior(Standard_True),myDone(Standard_False)
113 {}
114
115 //=======================================================================
116 //function : Init
117 //purpose  : 
118 //=======================================================================
119
120 void LocOpe_WiresOnShape::Init(const TopoDS_Shape& S)
121 {
122    myShape = S;
123    myCheckInterior = Standard_True;
124    myDone = Standard_False;
125    myMap.Clear();
126    myMapEF.Clear();
127 }
128
129 //=======================================================================
130 //function : Bind
131 //purpose  : 
132 //=======================================================================
133
134 void LocOpe_WiresOnShape::Bind(const TopoDS_Wire& W,
135                                const TopoDS_Face& F)
136 {
137   for (TopExp_Explorer exp(W, TopAbs_EDGE); exp.More(); exp.Next()) {
138     Bind(TopoDS::Edge(exp.Current()),F);
139   }
140 }
141
142 //=======================================================================
143 //function : Bind
144 //purpose  : 
145 //=======================================================================
146
147 void LocOpe_WiresOnShape::Bind(const TopoDS_Compound& Comp,
148                                const TopoDS_Face& F)
149 {
150   for (TopExp_Explorer exp(Comp, TopAbs_EDGE); exp.More(); exp.Next()) {
151     Bind(TopoDS::Edge(exp.Current()),F);
152   }
153   myFacesWithSection.Add(F);
154 }
155
156 //=======================================================================
157 //function : Bind
158 //purpose  : 
159 //=======================================================================
160
161 void LocOpe_WiresOnShape::Bind(const TopoDS_Edge& E,
162                                const TopoDS_Face& F)
163 {
164 //  if (!myMapEF.IsBound(E)) {
165   if (!myMapEF.Contains(E)) {
166 //    for (TopExp_Explorer exp(F,TopAbs_EDGE);exp.More();exp.Next()) {
167     TopExp_Explorer exp(F,TopAbs_EDGE) ;
168     for ( ;exp.More();exp.Next()) {
169       if (exp.Current().IsSame(E)) {
170         break;
171       }
172     }
173     if (!exp.More()) {
174 //      myMapEF.Bind(E,F);
175       myMapEF.Add(E,F);
176     }
177   }
178   else {
179     throw Standard_ConstructionError();
180   }
181 }
182
183
184 //=======================================================================
185 //function : Bind
186 //purpose  : 
187 //=======================================================================
188
189 void LocOpe_WiresOnShape::Bind(const TopoDS_Edge& Ewir,
190                                const TopoDS_Edge& Efac)
191 {
192   myMap.Bind(Ewir,Efac);
193 }
194
195
196 //=======================================================================
197 //function : BindAll
198 //purpose  : 
199 //=======================================================================
200
201 void LocOpe_WiresOnShape::BindAll()
202 {
203   if (myDone) {
204     return;
205   }
206   TopTools_MapOfShape theMap;
207
208   // Detection des vertex a projeter ou a "binder" avec des vertex existants
209   TopTools_DataMapOfShapeShape mapV;
210   TopTools_DataMapIteratorOfDataMapOfShapeShape ite(myMap);
211   TopExp_Explorer exp,exp2;
212   for (; ite.More(); ite.Next()) {
213     const TopoDS_Edge& eref = TopoDS::Edge(ite.Key());
214     const TopoDS_Edge& eimg = TopoDS::Edge(ite.Value());
215
216     PutPCurves(eref,eimg,myShape);
217
218     for (exp.Init(eref,TopAbs_VERTEX); exp.More(); exp.Next()) {
219       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
220       if (!theMap.Contains(vtx)) { // pas deja traite
221         for (exp2.Init(eimg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
222           const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current());
223           if (vtx2.IsSame(vtx)) {
224             break;
225           }
226           else if (BRepTools::Compare(vtx,vtx2)) {
227             mapV.Bind(vtx,vtx2);
228             break;
229           }
230         }
231         if (!exp2.More()) {
232           mapV.Bind(vtx,eimg);
233         }
234         theMap.Add(vtx);
235       }
236     }
237   }
238   
239   for (ite.Initialize(mapV); ite.More(); ite.Next()) {
240     myMap.Bind(ite.Key(),ite.Value());
241   }
242
243   TopTools_IndexedDataMapOfShapeListOfShape Splits;
244   Standard_Integer Ind;
245   TopTools_MapOfShape anOverlappedEdges;
246   for (Ind = 1; Ind <= myMapEF.Extent(); Ind++)
247   {
248     const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind));
249     const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind));
250     
251     PutPCurve(edg,fac);
252     Standard_Real pf, pl;
253     Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(edg, fac, pf, pl);
254     if (aPCurve.IsNull())
255       continue;
256
257     if (myCheckInterior)
258     {
259       Standard_Boolean isOverlapped = Standard_False;
260       FindInternalIntersections(edg, fac, Splits, isOverlapped);
261       if(isOverlapped)
262         anOverlappedEdges.Add(edg);
263     }
264   }
265
266   for (Ind = 1; Ind <= Splits.Extent(); Ind++)
267   {
268     TopoDS_Shape anEdge = Splits.FindKey(Ind);
269     if(anOverlappedEdges.Contains(anEdge))
270       continue;
271     TopoDS_Shape aFace  = myMapEF.FindFromKey(anEdge);
272     //Remove "anEdge" from "myMapEF"
273     myMapEF.RemoveKey(anEdge);
274     TopTools_ListIteratorOfListOfShape itl(Splits(Ind));
275     for (; itl.More(); itl.Next())
276       myMapEF.Add(itl.Value(), aFace);
277   }
278
279   TopTools_DataMapOfShapeReal  aVertParam;
280
281   for (Ind = 1; Ind <= myMapEF.Extent(); Ind++) {
282     const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(Ind));
283     const TopoDS_Face& fac = TopoDS::Face(myMapEF(Ind));
284     // JAG 02.02.96 : On verifie les pcurves...
285
286     //PutPCurve(edg,fac);
287
288     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
289       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
290       if (theMap.Contains(vtx)) {
291         continue;
292       }
293       
294       Standard_Real vtx_param = BRep_Tool::Parameter(vtx, edg);
295       BRepAdaptor_Curve2d BAcurve2d(edg, fac);
296             
297       gp_Pnt2d p2d = (!BAcurve2d.Curve().IsNull() ? 
298         BAcurve2d.Value(vtx_param) : gp_Pnt2d(Precision::Infinite(), Precision::Infinite()));
299
300       TopoDS_Edge Epro;
301       Standard_Real prm = Precision::Infinite();
302       Standard_Boolean isProjected = myMap.IsBound(vtx);
303
304       //if vertex was already projected on the current edge on the previous face
305       //it is necessary to check tolerance of the vertex in the 2D space on the current
306       //face without projection and update tolerance of vertex if it is necessary
307       if (isProjected)
308       {
309         TopoDS_Shape aSh = myMap.Find(vtx);
310         if (aSh.ShapeType() != TopAbs_EDGE)
311           continue;
312         Epro = TopoDS::Edge(myMap.Find(vtx));
313         if (aVertParam.IsBound(vtx))
314           prm = aVertParam.Find(vtx);
315       }
316       Standard_Boolean ok = Project(vtx, p2d, fac, Epro, prm);
317       if (ok && !isProjected) {
318
319         for (exp2.Init(Epro, TopAbs_VERTEX); exp2.More(); exp2.Next()) {
320           const TopoDS_Vertex& vtx2 = TopoDS::Vertex(exp2.Current());
321           if (vtx2.IsSame(vtx)) {
322             myMap.Bind(vtx, vtx2);
323             theMap.Add(vtx);
324             break;
325           }
326           else if (BRepTools::Compare(vtx, vtx2)) {
327             Standard_Real aF1, aL1;
328             BRep_Tool::Range(Epro, fac, aF1, aL1);
329             if (!BRep_Tool::Degenerated(Epro) && (
330               Abs(prm - aF1) <= Precision::PConfusion() ||
331               Abs(prm - aL1) <= Precision::PConfusion()))
332             {
333               myMap.Bind(vtx, vtx2);
334               theMap.Add(vtx);
335               break;
336             }
337           }
338         }
339         if (!exp2.More()) {
340           myMap.Bind(vtx,Epro);
341           aVertParam.Bind(vtx, prm);
342         }
343       }
344     }
345   }
346
347 //  Modified by Sergey KHROMOV - Mon Feb 12 16:26:50 2001 Begin
348   for (ite.Initialize(myMap); ite.More(); ite.Next())
349     if ((ite.Key()).ShapeType() == TopAbs_EDGE)
350       myMapEF.Add(ite.Key(),ite.Value());
351 //  Modified by Sergey KHROMOV - Mon Feb 12 16:26:52 2001 End
352
353
354   myDone = Standard_True;
355
356 }
357
358
359 //=======================================================================
360 //function : InitEdgeIterator
361 //purpose  : 
362 //=======================================================================
363
364 void LocOpe_WiresOnShape::InitEdgeIterator()
365 {
366   BindAll();
367 //  myIt.Initialize(myMapEF);
368   myIndex = 1;
369 }
370
371
372 //=======================================================================
373 //function : MoreEdge
374 //purpose  : 
375 //=======================================================================
376
377 Standard_Boolean LocOpe_WiresOnShape::MoreEdge()
378 {
379 //  return myIt.More();
380   return (myIndex <= myMapEF.Extent());
381 }
382
383
384 //=======================================================================
385 //function : Edge
386 //purpose  : 
387 //=======================================================================
388
389 TopoDS_Edge LocOpe_WiresOnShape::Edge()
390 {
391 //  return TopoDS::Edge(myIt.Key());
392   return TopoDS::Edge(myMapEF.FindKey(myIndex));
393 }
394
395
396 //=======================================================================
397 //function : Face
398 //purpose  : 
399 //=======================================================================
400
401 TopoDS_Face LocOpe_WiresOnShape::OnFace()
402 {
403 //  return TopoDS::Face(myIt.Value());
404   return TopoDS::Face(myMapEF(myIndex));
405 }
406
407
408 //=======================================================================
409 //function : OnEdge
410 //purpose  : 
411 //=======================================================================
412
413 Standard_Boolean LocOpe_WiresOnShape::OnEdge(TopoDS_Edge& E)
414 {
415 //  if (myMap.IsBound(myIt.Key())) {
416   if (myMap.IsBound(myMapEF.FindKey(myIndex))) {
417 //    E = TopoDS::Edge(myMap(myIt.Key()));
418     E = TopoDS::Edge(myMap(myMapEF.FindKey(myIndex)));
419     return Standard_True;
420   }
421   return Standard_False;
422 }
423
424
425
426
427 //=======================================================================
428 //function : NextEdge
429 //purpose  : 
430 //=======================================================================
431
432 void LocOpe_WiresOnShape::NextEdge()
433 {
434 //  myIt.Next();
435   myIndex++;
436 }
437
438
439
440 //=======================================================================
441 //function : OnVertex
442 //purpose  : 
443 //=======================================================================
444
445 Standard_Boolean LocOpe_WiresOnShape::OnVertex(const TopoDS_Vertex& Vw,
446                                                TopoDS_Vertex& Vs)
447 {
448   if (myMap.IsBound(Vw)) {
449     if (myMap(Vw).ShapeType() == TopAbs_VERTEX) {
450       Vs = TopoDS::Vertex(myMap(Vw));
451       return Standard_True;
452     }
453     return Standard_False;
454   }
455   return Standard_False;
456 }
457
458
459 //=======================================================================
460 //function : OnEdge
461 //purpose  : 
462 //=======================================================================
463
464 Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
465                                           TopoDS_Edge& Ed,
466                                           Standard_Real& prm)
467 {
468   if (!myMap.IsBound(V) ||
469       myMap(V).ShapeType() == TopAbs_VERTEX) {
470     return Standard_False;
471   }
472   
473   Ed = TopoDS::Edge(myMap(V));
474   prm = Project(V,Ed);
475   return Standard_True;
476 }
477
478 //=======================================================================
479 //function : OnEdge
480 //purpose  : 
481 //=======================================================================
482
483 Standard_Boolean LocOpe_WiresOnShape::OnEdge(const TopoDS_Vertex& V,
484                                              const TopoDS_Edge& EdgeFrom,
485                                              TopoDS_Edge& Ed,
486                                              Standard_Real& prm)
487 {
488   if (!myMap.IsBound(V) ||
489       myMap(V).ShapeType() == TopAbs_VERTEX) {
490     return Standard_False;
491   }
492   
493   Ed = TopoDS::Edge(myMap(V));
494   if(!myMapEF.Contains(EdgeFrom))
495     return Standard_False;
496
497   TopoDS_Shape aShape = myMapEF.FindFromKey(EdgeFrom);
498   Standard_Real aF, aL;
499   Handle(Geom_Curve) aC = BRep_Tool::Curve(Ed, aF, aL);
500   if (aC.IsNull() && aShape.ShapeType() == TopAbs_FACE)
501   {
502
503     TopoDS_Face aFace = TopoDS::Face(aShape);
504     Standard_Real vtx_param = BRep_Tool::Parameter(V, EdgeFrom);
505     BRepAdaptor_Curve2d BAcurve2d(EdgeFrom, aFace);
506     gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
507
508
509     prm = Project(V, p2d, Ed, aFace);
510   }
511   else
512     prm = Project( V, TopoDS::Edge(Ed));
513         
514   return Standard_True;
515 }
516
517
518 //=======================================================================
519 //function : Project
520 //purpose  : 
521 //=======================================================================
522
523 Standard_Boolean Project(const TopoDS_Vertex& V,
524                          const gp_Pnt2d& p2d,
525                          const TopoDS_Face& F,
526                          TopoDS_Edge& theEdge,
527                          Standard_Real& param)
528 {
529   Standard_Real aTolV = BRep_Tool::Tolerance(V);
530   Standard_Real dmin = (theEdge.IsNull() ? RealLast() : aTolV * aTolV);
531  
532   Standard_Boolean valret = Standard_False;
533   
534   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F);
535  
536   if (theEdge.IsNull())
537   {
538     gp_Pnt toproj(BRep_Tool::Pnt(V));
539     for (TopExp_Explorer exp(F.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
540       exp.More(); exp.Next()) {
541       const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
542       Standard_Real f, l;
543       Handle(Geom_Curve) C = BRep_Tool::Curve(edg, f, l);
544       Standard_Real aCurDist = Precision::Infinite();
545       Standard_Real aCurPar = Precision::Infinite();
546       if (!C.IsNull())
547       {
548         aCurPar = Project(V, edg);
549         if (Precision::IsInfinite(aCurPar))
550           continue;
551         gp_Pnt aCurPBound;
552         C->D0(aCurPar, aCurPBound);
553         aCurDist = aCurPBound.SquareDistance(toproj);
554       }
555
556       else if(!Precision::IsInfinite(p2d.X()))
557       {
558         //Geom2dAPI_ProjectPointOnCurve proj;
559         Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(edg,F , f, l);
560         if(aC2d.IsNull())
561           continue;
562
563         aCurPar = Project(V, p2d, edg, F);
564         if (Precision::IsInfinite(aCurPar))
565           continue;
566         Handle(Geom2d_Curve) PC = BRep_Tool::CurveOnSurface(edg, F, f, l);
567         gp_Pnt2d aPProj;
568         PC->D0(aCurPar, aPProj);
569         gp_Pnt aCurPBound;
570         aSurf->D0(aPProj.X(), aPProj.Y(), aCurPBound);
571         aCurDist = aCurPBound.SquareDistance(toproj);
572
573       }
574
575       if (aCurDist < dmin) {
576         theEdge = edg;
577         theEdge.Orientation(edg.Orientation());
578         dmin = aCurDist;
579         param = aCurPar;
580
581       }
582
583     }
584     if (theEdge.IsNull())
585       return Standard_False;
586   }
587   else if (Precision::IsInfinite(param))
588   {
589     Standard_Real f, l;
590     Handle(Geom_Curve) C = BRep_Tool::Curve(theEdge, f, l);
591     param = (!C.IsNull() ? Project(V, theEdge) : Project(V, p2d, theEdge, F));
592
593   }
594
595   Standard_Real ttol = aTolV + BRep_Tool::Tolerance(theEdge);
596   if (dmin <= ttol* ttol) {
597     valret = Standard_True;
598     GeomAdaptor_Surface adSurf(aSurf);
599
600     Standard_Real anUResolution = adSurf.UResolution(1.);
601     Standard_Real aVResolution = adSurf.UResolution(1.);
602
603     Standard_Real f, l;
604     Handle(Geom2d_Curve) aCrvBound = BRep_Tool::CurveOnSurface(theEdge, F, f, l);
605     if (!aCrvBound.IsNull())
606     {
607       gp_Pnt2d aPBound2d;
608       aCrvBound->D0(param, aPBound2d);
609
610       //distance in 2D space recomputed in the 3D space in order to tolerance of vertex
611       //cover gap in 2D space. For consistency with check of the validity in the  BRepCheck_Wire
612       Standard_Real dumax = 0.01 * (adSurf.LastUParameter() - adSurf.FirstUParameter());
613       Standard_Real dvmax = 0.01 * (adSurf.LastVParameter() - adSurf.FirstVParameter());
614       
615       gp_Pnt2d aPcur = p2d;
616       Standard_Real dumin = Abs(aPcur.X() - aPBound2d.X());
617       Standard_Real dvmin = Abs(aPcur.Y() - aPBound2d.Y());
618       if (dumin > dumax && adSurf.IsUPeriodic())
619       {
620         Standard_Real aX1 = aPBound2d.X();
621         Standard_Real aShift = ShapeAnalysis::AdjustToPeriod(aX1, adSurf.FirstUParameter(), adSurf.LastUParameter());
622         aX1 += aShift;
623         aPBound2d.SetX(aX1);
624         Standard_Real aX2 = p2d.X();
625         aShift = ShapeAnalysis::AdjustToPeriod(aX2, adSurf.FirstUParameter(), adSurf.LastUParameter());
626         aX2 += aShift;
627         dumin = Abs(aX2 - aX1);
628         if (dumin > dumax &&  (Abs(dumin - adSurf.UPeriod()) < Precision::PConfusion()) )
629         {
630           aX2 = aX1;
631           dumin = 0.;
632         }
633         aPcur.SetX(aX2);
634
635       }
636
637       if (dvmin > dvmax && adSurf.IsVPeriodic())
638       {
639         Standard_Real aY1 = aPBound2d.Y();
640         Standard_Real aShift = ShapeAnalysis::AdjustToPeriod(aY1, adSurf.FirstVParameter(), adSurf.LastVParameter());
641         aY1 += aShift;
642         aPBound2d.SetY(aY1);
643         Standard_Real aY2 = p2d.Y();
644         aShift = ShapeAnalysis::AdjustToPeriod(aY2, adSurf.FirstVParameter(), adSurf.LastVParameter());
645         aY2 += aShift;
646         dvmin = Abs(aY1 - aY2);
647         if (dvmin > dvmax && ( Abs(dvmin - adSurf.VPeriod()) < Precision::Confusion()) )
648         {
649           aY2 = aY1;
650           dvmin = 0.;
651         }
652         aPcur.SetY(aY2);
653       }
654       Standard_Real aDist3d = aTolV;
655       if ((dumin > dumax) || (dvmin > dvmax))
656       {
657
658         dumax = adSurf.UResolution(aTolV);
659         dvmax = adSurf.VResolution(aTolV);
660         Standard_Real aTol2d = 2. * Max(dumax, dvmax);
661         Standard_Real aDist2d =  Max(dumin, dvmin);
662
663         if (aDist2d > aTol2d)
664         {
665           Standard_Real aDist3d1 = aDist2d / Max(anUResolution, aVResolution);
666           if( aDist3d1 > aDist3d)
667             aDist3d =  aDist3d1;
668         }
669       }
670
671       //added check by 3D the same as in the BRepCheck_Wire::SelfIntersect
672       gp_Pnt aPBound;
673       aSurf->D0(aPBound2d.X(), aPBound2d.Y(), aPBound);
674       gp_Pnt aPV2d;
675       aSurf->D0(p2d.X(), p2d.Y(), aPV2d);
676       Standard_Real aDistPoints_3D = aPV2d.SquareDistance(aPBound);
677             Standard_Real aMaxDist = Max(aDistPoints_3D, aDist3d * aDist3d);
678  
679       BRep_Builder B;
680       if (aTolV * aTolV < aMaxDist)
681       {
682         Standard_Real aNewTol = sqrt(aMaxDist);
683         B.UpdateVertex(V, aNewTol);
684       }
685     }
686   }
687 #ifdef OCCT_DEBUG_MESH
688   else {
689     std::cout <<"LocOpe_WiresOnShape::Project --> le vertex projete est a une "; 
690     std::cout <<"distance / la face = "<<dmin <<" superieure a la tolerance = "<<ttol<<std::endl;
691   }
692 #endif
693   return valret;
694 }
695
696 //=======================================================================
697 //function : Project
698 //purpose  : 
699 //=======================================================================
700
701 Standard_Real Project(const TopoDS_Vertex& V,
702                       const TopoDS_Edge& theEdge)
703 {
704   Handle(Geom_Curve) C;
705   TopLoc_Location Loc;
706   Standard_Real f,l;
707
708   gp_Pnt toproj(BRep_Tool::Pnt(V));
709   GeomAPI_ProjectPointOnCurve proj;
710
711   C = BRep_Tool::Curve(theEdge,Loc,f,l);
712   if (!Loc.IsIdentity()) {
713     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
714     C = Handle(Geom_Curve)::DownCast (GG);
715   }
716   proj.Init(toproj,C,f,l);
717   
718
719
720   return (proj.NbPoints() > 0 ? proj.LowerDistanceParameter() : Precision::Infinite());
721 }
722
723 //=======================================================================
724 //function : Project
725 //purpose  : 
726 //=======================================================================
727
728 Standard_Real Project(const TopoDS_Vertex&,
729                       const gp_Pnt2d&      p2d,
730                       const TopoDS_Edge& theEdge,
731                       const TopoDS_Face& theFace)
732 {
733
734   
735   Handle(Geom2d_Curve) PC;
736  
737   Standard_Real f, l;
738
739   Geom2dAPI_ProjectPointOnCurve proj;
740
741   PC = BRep_Tool::CurveOnSurface(theEdge, theFace, f, l);
742   
743   proj.Init(p2d, PC, f, l);
744
745   return proj.NbPoints() > 0 ? proj.LowerDistanceParameter() : Precision::Infinite();
746 }
747
748
749 //=======================================================================
750 //function : PutPCurve
751 //purpose  : 
752 //=======================================================================
753
754 void PutPCurve(const TopoDS_Edge& Edg,
755                const TopoDS_Face& Fac)
756 {
757   BRep_Builder B;
758   TopLoc_Location LocFac;
759
760   Handle(Geom_Surface) S = BRep_Tool::Surface(Fac, LocFac);
761   Handle(Standard_Type) styp = S->DynamicType();
762
763   if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
764     S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
765     styp = S->DynamicType();
766   }
767
768   if (styp == STANDARD_TYPE(Geom_Plane)) {
769     return;
770   }
771
772   Standard_Real Umin,Umax,Vmin,Vmax;
773   BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
774
775   Standard_Real f,l;
776
777   Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface(Edg,Fac,f,l);
778   if ( !aC2d.IsNull() ) {
779     gp_Pnt2d p2d;
780     aC2d->D0((f + l) *0.5, p2d);
781     Standard_Boolean IsIn = Standard_True;
782     if ( ( p2d.X() < Umin-Precision::PConfusion() ) || 
783          ( p2d.X() > Umax+Precision::PConfusion() ) )
784       IsIn = Standard_False;
785     if ( ( p2d.Y() < Vmin-Precision::PConfusion() ) || 
786          ( p2d.Y() > Vmax+Precision::PConfusion() ) )
787       IsIn = Standard_False;
788  
789     if (IsIn)
790       return;
791   }
792
793   TopLoc_Location Loc;
794   Handle(Geom_Curve) C = BRep_Tool::Curve(Edg,Loc,f,l);
795   if (!Loc.IsIdentity()) {
796     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
797     C = Handle(Geom_Curve)::DownCast (GG);
798   }
799
800   if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
801     C = new Geom_TrimmedCurve(C,f,l);
802   }
803
804   S = BRep_Tool::Surface(Fac);
805
806   Standard_Real TolFirst = -1, TolLast = -1;
807   TopoDS_Vertex V1, V2;
808   TopExp::Vertices(Edg, V1, V2);
809   if (!V1.IsNull())
810     TolFirst = BRep_Tool::Tolerance(V1);
811   if (!V2.IsNull())
812     TolLast = BRep_Tool::Tolerance(V2);
813   
814   Standard_Real tol2d = Precision::Confusion();
815   Handle(Geom2d_Curve) C2d;
816   ShapeConstruct_ProjectCurveOnSurface aToolProj;
817   aToolProj.Init(S, tol2d);
818
819   aToolProj.Perform(C,f,l,C2d,TolFirst,TolLast);
820   if (C2d.IsNull())
821   {
822     return;
823   }
824  
825   gp_Pnt2d pf(C2d->Value(f));
826   gp_Pnt2d pl(C2d->Value(l));
827   gp_Pnt PF,PL;
828   S->D0(pf.X(),pf.Y(),PF);
829   S->D0(pl.X(),pl.Y(),PL);
830   if (Edg.Orientation() == TopAbs_REVERSED) {
831     V1 = TopExp::LastVertex(Edg);
832     V1.Reverse();
833   }
834   else {
835     V1 = TopExp::FirstVertex (Edg);
836   }
837   if (Edg.Orientation() == TopAbs_REVERSED) {
838     V2 = TopExp::FirstVertex(Edg);
839     V2.Reverse();
840   }
841   else {
842     V2 = TopExp::LastVertex (Edg);
843   }
844
845   if(!V1.IsNull() && V2.IsNull()) {
846     //Handling of internal vertices
847     Standard_Real old1 = BRep_Tool::Tolerance (V1);
848     Standard_Real old2 = BRep_Tool::Tolerance (V2);
849     gp_Pnt pnt1 = BRep_Tool::Pnt (V1);
850     gp_Pnt pnt2 = BRep_Tool::Pnt (V2);
851     Standard_Real tol1 = pnt1.Distance(PF);
852     Standard_Real tol2 = pnt2.Distance(PL);
853     B.UpdateVertex(V1,Max(old1,tol1));
854     B.UpdateVertex(V2,Max(old2,tol2));
855   }
856
857   if (S->IsUPeriodic()) {
858     Standard_Real up   = S->UPeriod();
859     Standard_Real tolu = Precision::PConfusion();// Epsilon(up);
860     Standard_Integer nbtra = 0;
861     Standard_Real theUmin = Min(pf.X(),pl.X());
862     Standard_Real theUmax = Max(pf.X(),pl.X());
863
864     if (theUmin < Umin-tolu) {
865       while (theUmin < Umin-tolu) {
866         theUmin += up;
867         nbtra++;
868       }
869     }
870     else if (theUmax > Umax+tolu) {
871       while (theUmax > Umax+tolu) {
872         theUmax -= up;
873         nbtra--;
874       }
875     }
876
877     if (nbtra !=0) {
878       C2d->Translate(gp_Vec2d(nbtra*up,0.));
879     }
880   }    
881
882   if (S->IsVPeriodic()) {
883     Standard_Real vp   = S->VPeriod();
884     Standard_Real tolv = Precision::PConfusion();// Epsilon(vp);
885     Standard_Integer nbtra = 0;
886     Standard_Real theVmin = Min(pf.Y(),pl.Y());
887     Standard_Real theVmax = Max(pf.Y(),pl.Y());
888
889     if (theVmin < Vmin-tolv) {
890       while (theVmin < Vmin-tolv) {
891         theVmin += vp; theVmax += vp;
892         nbtra++;
893       }
894     }
895     else if (theVmax > Vmax+tolv) {
896       while (theVmax > Vmax+tolv) {
897         theVmax -= vp; theVmin -= vp;
898         nbtra--;
899       }
900     }
901
902     if (nbtra !=0) {
903       C2d->Translate(gp_Vec2d(0.,nbtra*vp));
904     }
905   }
906   B.UpdateEdge(Edg,C2d,Fac,BRep_Tool::Tolerance(Edg));
907   
908   B.SameParameter(Edg,Standard_False);
909   BRepLib::SameParameter(Edg,tol2d); 
910 }
911
912
913 //=======================================================================
914 //function : PutPCurves
915 //purpose  : 
916 //=======================================================================
917
918 void PutPCurves(const TopoDS_Edge& Efrom,
919                 const TopoDS_Edge& Eto,
920                 const TopoDS_Shape& myShape)
921 {
922
923   TopTools_ListOfShape Lfaces;
924   TopExp_Explorer exp,exp2;
925
926   for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
927     for (exp2.Init(exp.Current(), TopAbs_EDGE); exp2.More();exp2.Next()) {
928       if (exp2.Current().IsSame(Eto)) {
929         Lfaces.Append(exp.Current());
930       }
931     }
932   }
933
934   if (Lfaces.Extent() != 1 && Lfaces.Extent() !=2) {
935     throw Standard_ConstructionError();
936   }
937
938   // soit bord libre, soit connexite entre 2 faces, eventuellement edge closed
939
940   if (Lfaces.Extent() ==1) {
941     return; // sera fait par PutPCurve.... on l`espere
942   }
943
944   BRep_Builder B;
945   Handle(Geom_Surface) S;
946   Handle(Standard_Type) styp;
947   Handle(Geom_Curve) C;
948   Standard_Real Umin,Umax,Vmin,Vmax;
949   Standard_Real f,l;
950   TopLoc_Location Loc, LocFac;
951
952   if (!Lfaces.First().IsSame(Lfaces.Last())) {
953     TopTools_ListIteratorOfListOfShape itl(Lfaces);
954     for (; itl.More(); itl.Next()) {
955       const TopoDS_Face& Fac = TopoDS::Face(itl.Value());
956
957       if (!BRep_Tool::CurveOnSurface(Efrom,Fac,f,l).IsNull()) {
958         continue;
959       }
960       S = BRep_Tool::Surface(Fac, LocFac);
961       styp = S->DynamicType();
962       if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
963         S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
964         styp = S->DynamicType();
965       }
966       if (styp == STANDARD_TYPE(Geom_Plane)) {
967         continue;
968       }
969
970             
971       BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
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)::DownCast (GG);
976       }
977       
978       if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
979         C = new Geom_TrimmedCurve(C,f,l);
980       }
981     
982       S = BRep_Tool::Surface(Fac);
983
984       // Compute the tol2d
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      if(C2d.IsNull())
995        return;
996
997       gp_Pnt2d pf(C2d->Value(f));
998       gp_Pnt2d pl(C2d->Value(l));
999       
1000       if (S->IsUPeriodic()) {
1001         Standard_Real up   = S->UPeriod();
1002         Standard_Real tolu = Precision::PConfusion();// Epsilon(up);
1003         Standard_Integer nbtra = 0;
1004         Standard_Real theUmin = Min(pf.X(),pl.X());
1005         Standard_Real theUmax = Max(pf.X(),pl.X());
1006
1007         if (theUmin < Umin-tolu) {
1008           while (theUmin < Umin-tolu) {
1009             theUmin += up; theUmax += up;
1010             nbtra++;
1011           }
1012         }
1013         else if (theUmax > Umax+tolu) {
1014           while (theUmax > Umax+tolu) {
1015             theUmax -= up; theUmin -= up;
1016             nbtra--;
1017           }
1018         }
1019 /*
1020         if (theUmin > Umax+tolu) {
1021           while (theUmin > Umax+tolu) {
1022             theUmin -= up;
1023             nbtra--;
1024           }
1025         }
1026         else if (theUmax < Umin-tolu) {
1027           while (theUmax < Umin-tolu) {
1028             theUmax += up;
1029             nbtra++;
1030           }
1031         }
1032 */
1033         if (nbtra !=0) {
1034           C2d->Translate(gp_Vec2d(nbtra*up,0.));
1035         }
1036       }    
1037       
1038       if (S->IsVPeriodic()) {
1039         Standard_Real vp   = S->VPeriod();
1040         Standard_Real tolv = Precision::PConfusion();// Epsilon(vp);
1041         Standard_Integer nbtra = 0;
1042         Standard_Real theVmin = Min(pf.Y(),pl.Y());
1043         Standard_Real theVmax = Max(pf.Y(),pl.Y());
1044
1045         if (theVmin < Vmin-tolv) {
1046           while (theVmin < Vmin-tolv) {
1047             theVmin += vp; theVmax += vp;
1048             nbtra++;
1049           }
1050         }
1051         else if (theVmax > Vmax+tolv) {
1052           while (theVmax > Vmax+tolv) {
1053             theVmax -= vp; theVmin -= vp;
1054             nbtra--;
1055           }
1056         }
1057 /*
1058         if (theVmin > Vmax+tolv) {
1059           while (theVmin > Vmax+tolv) {
1060             theVmin -= vp;
1061             nbtra--;
1062           }
1063         }
1064         else if (theVmax < Vmin-tolv) {
1065           while (theVmax < Vmin-tolv) {
1066             theVmax += vp;
1067             nbtra++;
1068           }
1069         }
1070 */
1071         if (nbtra !=0) {
1072           C2d->Translate(gp_Vec2d(0.,nbtra*vp));
1073         }
1074       }
1075       B.UpdateEdge(Efrom,C2d,Fac,BRep_Tool::Tolerance(Efrom));
1076     }
1077   }
1078
1079   else {
1080     const TopoDS_Face& Fac = TopoDS::Face(Lfaces.First());
1081     if (!BRep_Tool::IsClosed(Eto,Fac)) {
1082       throw Standard_ConstructionError();
1083     }
1084
1085     TopoDS_Shape aLocalE = Efrom.Oriented(TopAbs_FORWARD);
1086     TopoDS_Shape aLocalF = Fac.Oriented(TopAbs_FORWARD);
1087     Handle(Geom2d_Curve) c2dff = 
1088       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
1089                                 TopoDS::Face(aLocalF),
1090                                 f,l);
1091
1092 //    Handle(Geom2d_Curve) c2dff = 
1093 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Efrom.Oriented(TopAbs_FORWARD)),
1094 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
1095 //                              f,l);
1096     
1097     aLocalE = Efrom.Oriented(TopAbs_REVERSED);
1098     aLocalF = Fac.Oriented(TopAbs_FORWARD);
1099     Handle(Geom2d_Curve) c2dfr = 
1100       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
1101                                 TopoDS::Face(aLocalF),
1102                                 f,l);
1103 //    Handle(Geom2d_Curve) c2dfr = 
1104 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Efrom.Oriented(TopAbs_REVERSED)),
1105 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
1106 //                              f,l);
1107     
1108     aLocalE = Eto.Oriented(TopAbs_FORWARD);
1109     aLocalF = Fac.Oriented(TopAbs_FORWARD);
1110     Handle(Geom2d_Curve) c2dtf = 
1111       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
1112                                 TopoDS::Face(aLocalF),
1113                                 f,l);
1114
1115 //    Handle(Geom2d_Curve) c2dtf = 
1116 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Eto.Oriented(TopAbs_FORWARD)),
1117 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
1118 //                              f,l);
1119     aLocalE = Eto.Oriented(TopAbs_REVERSED);
1120     aLocalF = Fac.Oriented(TopAbs_FORWARD);
1121     Handle(Geom2d_Curve) c2dtr = 
1122       BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalE),
1123                                 TopoDS::Face(aLocalF),
1124                                 f,l);
1125 //    Handle(Geom2d_Curve) c2dtr = 
1126 //      BRep_Tool::CurveOnSurface(TopoDS::Edge(Eto.Oriented(TopAbs_REVERSED)),
1127 //                              TopoDS::Face(Fac.Oriented(TopAbs_FORWARD)),
1128 //                              f,l);
1129
1130     gp_Pnt2d ptf(c2dtf->Value(f)); // sur courbe frw
1131     gp_Pnt2d ptr(c2dtr->Value(f)); // sur courbe rev
1132
1133     Standard_Boolean isoU = (Abs(ptf.Y()-ptr.Y())<Epsilon(ptf.X())); // meme V
1134
1135     // Efrom et Eto dans le meme sens???
1136
1137     C = BRep_Tool::Curve(Efrom,Loc,f,l);
1138     if (!Loc.IsIdentity()) {
1139       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
1140       C = Handle(Geom_Curve)::DownCast (GG);
1141     }
1142
1143     gp_Pnt pt;
1144     gp_Vec d1f,d1t;
1145
1146     C->D1(f,pt,d1f);
1147
1148
1149     TopoDS_Vertex FirstVertex = TopExp::FirstVertex(Efrom);
1150     Standard_Real vtx_param = BRep_Tool::Parameter(FirstVertex, Efrom);
1151     BRepAdaptor_Curve2d BAcurve2d(Efrom, Fac);
1152     gp_Pnt2d p2d = BAcurve2d.Value(vtx_param);
1153
1154     Standard_Real prmproj = Project(TopExp::FirstVertex(Efrom),p2d,Eto,Fac);
1155     
1156     C = BRep_Tool::Curve(Eto,Loc,f,l);
1157     if (!Loc.IsIdentity()) {
1158       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
1159       C = Handle(Geom_Curve)::DownCast (GG);
1160     }
1161     
1162     C->D1(prmproj,pt,d1t);
1163
1164     Standard_Real SameOri = (d1t.Dot(d1f)>0.); 
1165
1166
1167     if (c2dff.IsNull() && c2dfr.IsNull()) {
1168       S = BRep_Tool::Surface(Fac);
1169       styp = S->DynamicType();
1170       if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1171         S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
1172         styp = S->DynamicType();
1173       }
1174       
1175       C = BRep_Tool::Curve(Efrom,Loc,f,l);
1176       if (!Loc.IsIdentity()) {
1177         Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
1178         C = Handle(Geom_Curve)::DownCast (GG);
1179       }
1180       
1181       if (C->DynamicType() != STANDARD_TYPE(Geom_TrimmedCurve)) {
1182         C = new Geom_TrimmedCurve(C,f,l);
1183       }
1184
1185       // Compute the tol2d
1186       BRepTools::UVBounds(Fac,Umin,Umax,Vmin,Vmax);
1187
1188       Standard_Real tol3d = Max(BRep_Tool::Tolerance(Efrom),
1189                                 BRep_Tool::Tolerance(Fac));
1190       GeomAdaptor_Surface Gas(S,Umin,Umax,Vmin,Vmax);
1191       Standard_Real TolU  = Gas.UResolution(tol3d);
1192       Standard_Real TolV  = Gas.VResolution(tol3d);
1193       Standard_Real tol2d = Max(TolU,TolV);
1194     
1195       Handle(Geom2d_Curve) C2d = 
1196         GeomProjLib::Curve2d(C,S,Umin,Umax,Vmin,Vmax,tol2d);
1197       c2dff = C2d;
1198       c2dfr = C2d;
1199     }
1200     else if (c2dfr.IsNull()) {
1201       c2dfr = c2dff;
1202
1203     }
1204     else if (c2dff.IsNull()) {
1205       c2dff = c2dfr;
1206     }
1207
1208     BRep_Tool::Range(Efrom,f,l);
1209
1210     gp_Pnt2d p2f = c2dff->Value(f);
1211     gp_Pnt2d p2r = c2dfr->Value(f);
1212
1213     if (isoU) {
1214       if (SameOri) {
1215         if (Abs(ptf.X()-p2f.X()) > Epsilon(ptf.X())) {
1216           c2dff = Handle(Geom2d_Curve)::DownCast
1217             (c2dff->Translated(gp_Vec2d(ptf.X()-p2f.X(),0.)));
1218         }
1219         if (Abs(ptr.X()-p2r.X()) > Epsilon(ptr.X())) {
1220           c2dfr = Handle(Geom2d_Curve)::DownCast
1221             (c2dfr->Translated(gp_Vec2d(ptr.X()-p2r.X(),0.)));
1222         }
1223       }
1224       else {
1225         if (Abs(ptr.X()-p2f.X()) > Epsilon(ptr.X())) {
1226           c2dff = Handle(Geom2d_Curve)::DownCast
1227             (c2dff->Translated(gp_Vec2d(ptr.X()-p2f.X(),0.)));
1228         }
1229         
1230         if (Abs(ptf.X()-p2r.X()) > Epsilon(ptf.X())) {
1231           c2dfr = Handle(Geom2d_Curve)::DownCast
1232             (c2dfr->Translated(gp_Vec2d(ptf.X()-p2r.X(),0.)));
1233         }
1234       }
1235
1236       // on est bien en U, recalage si periodique en V a faire
1237
1238
1239
1240     }
1241     
1242     else { // !isoU soit isoV
1243       if (SameOri) {
1244         if (Abs(ptf.Y()-p2f.Y()) > Epsilon(ptf.Y())) {
1245           c2dff = Handle(Geom2d_Curve)::DownCast
1246             (c2dff->Translated(gp_Vec2d(0.,ptf.Y()-p2f.Y())));
1247         }
1248         if (Abs(ptr.Y()-p2r.Y()) > Epsilon(ptr.Y())) {
1249           c2dfr = Handle(Geom2d_Curve)::DownCast
1250             (c2dfr->Translated(gp_Vec2d(0.,ptr.Y()-p2r.Y())));
1251         }
1252       }
1253       else {
1254         if (Abs(ptr.Y()-p2f.Y()) > Epsilon(ptr.Y())) {
1255           c2dff = Handle(Geom2d_Curve)::DownCast
1256             (c2dff->Translated(gp_Vec2d(0.,ptr.Y()-p2f.Y())));
1257         }
1258         if (Abs(ptf.Y()-p2r.Y()) > Epsilon(ptf.Y())) {
1259           c2dfr = Handle(Geom2d_Curve)::DownCast
1260             (c2dfr->Translated(gp_Vec2d(0.,ptf.Y()-p2r.Y())));
1261         }
1262       }
1263       // on est bien en V, recalage si periodique en U a faire
1264
1265     }
1266     B.UpdateEdge(Efrom,c2dff,c2dfr,Fac,BRep_Tool::Tolerance(Efrom));
1267   }
1268 }
1269
1270 //=======================================================================
1271 //function : FindInternalIntersections
1272 //purpose  : 
1273 //=======================================================================
1274
1275 void FindInternalIntersections(const TopoDS_Edge& theEdge,
1276                                const TopoDS_Face& theFace,
1277                                TopTools_IndexedDataMapOfShapeListOfShape& Splits,
1278                                Standard_Boolean& isOverlapped)
1279 {
1280   Standard_Real TolExt = Precision::PConfusion();
1281   Standard_Integer i, j;
1282
1283   BRepAdaptor_Surface anAdSurf(theFace, Standard_False);
1284   TColStd_SequenceOfReal SplitPars;
1285   
1286   TopoDS_Vertex theVertices [2];
1287   TopExp::Vertices(theEdge, theVertices[0], theVertices[1]);
1288   gp_Pnt thePnt [2];
1289   thePnt[0] = BRep_Tool::Pnt(theVertices[0]);
1290   thePnt[1] = BRep_Tool::Pnt(theVertices[1]);
1291   Standard_Real aTolV[2];
1292   aTolV[0] =BRep_Tool::Tolerance(theVertices[0]);
1293   aTolV[1] =BRep_Tool::Tolerance(theVertices[1]);
1294
1295   BRepAdaptor_Curve2d thePCurve(theEdge, theFace);
1296   Bnd_Box2d theBox;
1297   BndLib_Add2dCurve::Add(thePCurve, BRep_Tool::Tolerance(theEdge), theBox);
1298
1299   Standard_Real thePar [2];
1300   Standard_Real  aFpar, aLpar;
1301   const Handle(Geom_Curve)& theCurve = BRep_Tool::Curve(theEdge, thePar[0], thePar[1]);
1302   GeomAdaptor_Curve theGAcurve(theCurve, thePar[0], thePar[1]);
1303   Standard_Real aDistMax = Precision::Confusion() * Precision::Confusion();
1304   TopExp_Explorer Explo(theFace, TopAbs_EDGE);
1305   for (; Explo.More(); Explo.Next())
1306   {
1307     const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
1308     BRepAdaptor_Curve2d aPCurve(anEdge, theFace);
1309     Bnd_Box2d aBox;
1310     BndLib_Add2dCurve::Add(aPCurve, BRep_Tool::Tolerance(anEdge), aBox);
1311     if (theBox.IsOut(aBox))
1312       continue;
1313
1314     const Handle(Geom_Curve)& aCurve   = BRep_Tool::Curve(anEdge, aFpar, aLpar);
1315     GeomAdaptor_Curve aGAcurve(aCurve, aFpar, aLpar);
1316     Extrema_ExtCC anExtrema(theGAcurve, aGAcurve, TolExt, TolExt);
1317
1318     if (!anExtrema.IsDone() || !anExtrema.NbExt())
1319       continue;
1320    
1321     Standard_Integer aNbExt = anExtrema.NbExt();
1322     Standard_Real MaxTol = BRep_Tool::Tolerance(anEdge);
1323     Standard_Real aMaxTol2 =  MaxTol *  MaxTol;
1324     if (anExtrema.IsParallel() && anExtrema.SquareDistance(1) <= aMaxTol2)
1325     {
1326       isOverlapped = Standard_True;
1327       return;
1328     }
1329     for (i = 1; i <= aNbExt; i++)
1330     {
1331       Standard_Real aDist = anExtrema.SquareDistance(i);
1332       if (aDist > aMaxTol2)
1333         continue;
1334
1335       Extrema_POnCurv aPOnC1, aPOnC2;
1336       anExtrema.Points(i, aPOnC1, aPOnC2);
1337       Standard_Real theIntPar = aPOnC1.Parameter();
1338       Standard_Real anIntPar = aPOnC2.Parameter();
1339       for (j = 0; j < 2; j++) //try to find intersection on an extremity of "theEdge"
1340       {
1341         if (Abs(theIntPar - thePar[j]) <= Precision::PConfusion())
1342           break;
1343       }
1344       //intersection found in the middle of the edge
1345       if (j >= 2) //intersection is inside "theEdge" => split
1346       {
1347         gp_Pnt aPoint = aCurve->Value(anIntPar);
1348         gp_Pnt aPointInt = theCurve->Value(theIntPar);
1349     
1350         if (aPointInt.SquareDistance(thePnt[0]) > aTolV[0] * aTolV[0] &&
1351           aPointInt.SquareDistance(thePnt[1]) > aTolV[1] * aTolV[1] &&
1352           aPoint.SquareDistance(thePnt[0]) > aTolV[0] * aTolV[0] &&
1353           aPoint.SquareDistance(thePnt[1]) > aTolV[1] * aTolV[1])
1354         {
1355           SplitPars.Append(theIntPar);
1356           if( aDist > aDistMax)
1357             aDistMax = aDist;
1358         }
1359       }
1360     }
1361   }
1362
1363   if (SplitPars.IsEmpty())
1364     return;
1365   
1366   //Sort
1367   for (i = 1; i < SplitPars.Length(); i++)
1368     for (j = i+1; j <= SplitPars.Length(); j++)
1369       if (SplitPars(i) > SplitPars(j))
1370       {
1371         Standard_Real Tmp = SplitPars(i);
1372         SplitPars(i) = SplitPars(j);
1373         SplitPars(j) = Tmp;
1374       }
1375   //Remove repeating points
1376   i = 1;
1377   while (i < SplitPars.Length())
1378   {
1379     gp_Pnt Pnt1 = theCurve->Value(SplitPars(i));
1380     gp_Pnt Pnt2 = theCurve->Value(SplitPars(i+1));
1381     if (Pnt1.SquareDistance(Pnt2) <= Precision::Confusion()* Precision::Confusion())
1382       SplitPars.Remove(i+1);
1383     else
1384       i++;
1385   }
1386
1387   //Split
1388   TopTools_ListOfShape NewEdges;
1389   BRep_Builder BB;
1390   
1391   TopoDS_Vertex FirstVertex = theVertices[0], LastVertex;
1392   Standard_Real FirstPar = thePar[0], LastPar;
1393   for (i = 1; i <= SplitPars.Length()+1; i++)
1394   {
1395     FirstVertex.Orientation(TopAbs_FORWARD);
1396     if (i <= SplitPars.Length())
1397     {
1398       LastPar = SplitPars(i);
1399       gp_Pnt LastPoint = theCurve->Value(LastPar);
1400       LastVertex = BRepLib_MakeVertex(LastPoint);
1401       BRep_Builder aB;
1402       aB.UpdateVertex(LastVertex, sqrt(aDistMax));
1403     }
1404     else
1405     {
1406       LastPar = thePar[1];
1407       LastVertex = theVertices[1];
1408     }
1409     LastVertex.Orientation(TopAbs_REVERSED);
1410     
1411     TopoDS_Shape aLocalShape = theEdge.EmptyCopied();
1412     TopAbs_Orientation anOrient = aLocalShape.Orientation();
1413     aLocalShape.Orientation(TopAbs_FORWARD);
1414     TopoDS_Edge NewEdge = TopoDS::Edge(aLocalShape);
1415     BB.Range(NewEdge, FirstPar, LastPar);
1416     BB.Add(NewEdge, FirstVertex);
1417     BB.Add(NewEdge, LastVertex);
1418     NewEdge.Orientation(anOrient);
1419     ShapeAnalysis_Edge aSae;
1420     Standard_Real amaxdev =0.;
1421     if (aSae.CheckSameParameter(NewEdge, theFace, amaxdev))
1422     {
1423       BRep_Builder aB;
1424       aB.UpdateEdge(NewEdge, amaxdev);
1425     }
1426
1427     if (anOrient == TopAbs_FORWARD)
1428       NewEdges.Append(NewEdge);
1429     else
1430       NewEdges.Prepend(NewEdge);
1431     FirstVertex = LastVertex;
1432     FirstPar = LastPar;
1433   }
1434
1435   if (!NewEdges.IsEmpty())
1436     Splits.Add(theEdge, NewEdges);
1437 }
1438
1439 //=======================================================================
1440 //function : AddSplittingEdges
1441 //purpose  : 
1442 //=======================================================================
1443
1444 Standard_Boolean LocOpe_WiresOnShape::Add(const TopTools_SequenceOfShape& theEdges)
1445 {
1446   TopTools_SequenceOfShape anEdges;
1447   Bnd_SeqOfBox anEdgeBoxes;
1448   Standard_Integer i = 1, nb = theEdges.Length();
1449   for (; i <= nb; i++)
1450   {
1451     const TopoDS_Shape& aCurSplit = theEdges(i);
1452     TopExp_Explorer anExpE(aCurSplit, TopAbs_EDGE);
1453     for (; anExpE.More(); anExpE.Next())
1454     {
1455       const TopoDS_Shape& aCurE = anExpE.Current();
1456
1457       Bnd_Box aBoxE;
1458       BRepBndLib::AddClose(aCurE, aBoxE);
1459       if (aBoxE.IsVoid())
1460         continue;
1461       Standard_Real aTolE = BRep_Tool::Tolerance(TopoDS::Edge(aCurE));
1462       aBoxE.SetGap(aTolE);
1463       anEdgeBoxes.Append(aBoxE);
1464       anEdges.Append(aCurE);
1465
1466     }
1467   }
1468   TopExp_Explorer anExpFaces(myShape, TopAbs_FACE);
1469   Standard_Integer numF = 1;
1470   TColStd_PackedMapOfInteger anUsedEdges;
1471   for (; anExpFaces.More(); anExpFaces.Next(), numF++)
1472   {
1473     const TopoDS_Face& aCurF = TopoDS::Face(anExpFaces.Current());
1474     Bnd_Box aBoxF;
1475     BRepBndLib::Add(aCurF, aBoxF);
1476     if (aBoxF.IsVoid())
1477       continue;
1478     BRepAdaptor_Surface anAdF(aCurF, Standard_False);
1479     NCollection_Handle<BRepTopAdaptor_FClass2d> aCheckStateTool;
1480
1481     i = 1;
1482     nb = anEdgeBoxes.Length();
1483     for (; i <= nb; i++)
1484     {
1485       if (anUsedEdges.Contains(i))
1486         continue;
1487
1488       if (aBoxF.IsOut(anEdgeBoxes(i)))
1489         continue;
1490
1491       const TopoDS_Edge& aCurE = TopoDS::Edge(anEdges(i));
1492
1493       Standard_Real aF, aL;
1494       Handle(Geom_Curve) aC = BRep_Tool::Curve(aCurE, aF, aL);
1495       if (aC.IsNull())
1496       {
1497         anUsedEdges.Add(i);
1498         continue;
1499       }
1500       gp_Pnt aP = aC->Value((aF + aL)* 0.5);
1501       Extrema_ExtPS anExtr(aP, anAdF, Precision::Confusion(), Precision::Confusion());
1502      
1503       if (!anExtr.IsDone() || !anExtr.NbExt())
1504         continue;
1505       Standard_Real aTolE = BRep_Tool::Tolerance(TopoDS::Edge(aCurE));
1506       Standard_Real aTol2 = (aTolE + Precision::Confusion()) * (aTolE + Precision::Confusion());
1507       Standard_Integer n = 1;
1508       for (; n <= anExtr.NbExt(); n++)
1509       {
1510         Standard_Real aDist2 = anExtr.SquareDistance(n);
1511         if (aDist2 > aTol2)
1512           continue;
1513         const Extrema_POnSurf& aPS = anExtr.Point(n);
1514         Standard_Real aU, aV;
1515         aPS.Parameter(aU, aV);
1516
1517         if (aCheckStateTool.IsNull())
1518         {
1519           aCheckStateTool = new BRepTopAdaptor_FClass2d(aCurF, Precision::PConfusion());
1520         }
1521         if (aCheckStateTool->Perform(gp_Pnt2d(aU, aV)) == TopAbs_IN)
1522         {
1523           Bind(aCurE, aCurF);
1524           anUsedEdges.Add(i);
1525         }
1526         
1527       }
1528     }
1529
1530   }
1531   return !anUsedEdges.IsEmpty();
1532 }