7a0f4b9c3a9d2f1f95c407a7979c8ff5f8985ef7
[occt.git] / src / BRepAlgo / BRepAlgo_FaceRestrictor.cxx
1 // Created on: 1995-09-01
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-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 #include <BRepAlgo_FaceRestrictor.ixx>
23
24 #include <BRepTopAdaptor_FClass2d.hxx>
25 #include <TopoDS.hxx>
26 #include <TopoDS_Vertex.hxx>
27 #include <TopoDS_Edge.hxx>
28 #include <TopExp_Explorer.hxx>
29 #include <TopExp.hxx>
30 #include <TopOpeBRepBuild_WireToFace.hxx>
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32 #include <Geom_Surface.hxx>
33 #include <Geom2d_Curve.hxx>
34 #include <Geom_Curve.hxx>
35 #include <Geom_TrimmedCurve.hxx>
36 #include <BRep_Builder.hxx>
37 #include <BRep_Tool.hxx>
38 #include <GeomProjLib.hxx>
39 #include <gp_Pnt2d.hxx>
40
41 #include <Precision.hxx>
42
43 //=======================================================================
44 //function : BRepAlgo_FaceRestrictor
45 //purpose  : 
46 //=======================================================================
47
48 BRepAlgo_FaceRestrictor::BRepAlgo_FaceRestrictor()
49 {}
50
51 //=======================================================================
52 //function : 
53 //purpose  : 
54 //=======================================================================
55
56 void BRepAlgo_FaceRestrictor::Init(const TopoDS_Face&     F,
57                                    const Standard_Boolean Proj,
58                                    const Standard_Boolean CorrectionOrientation)
59 {
60   myFace = F; modeProj = Proj;  myCorrection = CorrectionOrientation;
61 }
62
63
64 //=======================================================================
65 //function : Add
66 //purpose  : 
67 //=======================================================================
68
69 void BRepAlgo_FaceRestrictor::Add(TopoDS_Wire& W)
70 {
71   wires.Append(W);
72 }
73
74
75 //=======================================================================
76 //function : Clear
77 //purpose  : 
78 //=======================================================================
79
80 void BRepAlgo_FaceRestrictor::Clear()
81 {
82   wires.Clear();
83   faces.Clear();
84 }
85
86 //=======================================================================
87 //function : ChangePcurve
88 //purpose  : 
89 //=======================================================================
90
91 static Standard_Boolean  ChangePCurve (TopoDS_Edge&          E,
92                                        const Handle(Geom_Surface)& S,
93                                        TopLoc_Location&      L)
94 {
95   BRep_Builder         BB;
96   Handle(Geom_Surface) SE;
97   Handle(Geom2d_Curve) C2;
98   TopLoc_Location      LE;
99   Standard_Real        f,l;
100
101   BRep_Tool::CurveOnSurface (E,C2,SE,LE,f,l,1);
102   if (!C2.IsNull()) 
103     BB.UpdateEdge(E,C2,S,L,Precision::Confusion());
104   return (C2.IsNull());
105 }
106
107 //=======================================================================
108 //function : ProjCurve3d
109 //purpose  : 
110 //=======================================================================
111
112 static void ProjCurve3d (TopoDS_Edge&          E,
113                          const Handle(Geom_Surface)& S,
114                          TopLoc_Location&      L)
115 {
116   BRep_Builder              BB;
117   TopLoc_Location           LE;
118   Standard_Real             f,l;
119   Handle(Geom_Curve)        C  = BRep_Tool::Curve(E,LE,f,l);
120   Handle(Geom_TrimmedCurve) CT = new Geom_TrimmedCurve(C,f,l);
121   
122   TopLoc_Location LL = L.Inverted().Multiplied(LE);
123   CT->Transform(LL.Transformation());
124   
125   Handle(Geom2d_Curve) C2 = GeomProjLib::Curve2d (CT,S);
126   BB.UpdateEdge(E,C2,S,L,Precision::Confusion());
127 }
128
129 //=======================================================================
130 //function : Perform
131 //purpose  : 
132 //=======================================================================
133
134 void BRepAlgo_FaceRestrictor::Perform()
135 {
136
137   if (myCorrection) {
138     PerformWithCorrection();
139     return;
140   }
141
142   myDone = Standard_False;
143   TopTools_ListIteratorOfListOfShape it(wires);
144
145   //--------------------------------------------------------------------
146   // return geometry of the reference face.
147   //--------------------------------------------------------------------
148   TopLoc_Location L;
149   const Handle(Geom_Surface)& S = BRep_Tool::Surface(myFace,L);
150
151   //-----------------------------------------------------------------------
152   // test if edges are on S. otherwise  add S to the first pcurve.
153   // or projection of the edge on F.
154   //---------------------------------------------------------------------- 
155   TopExp_Explorer Exp;
156 //  BRep_Builder    BB;
157   Standard_Real   f,l;
158
159   TopOpeBRepBuild_WireToFace WTF;
160
161   for ( ; it.More(); it.Next()) {
162     // update the surface on edges.
163     const TopoDS_Wire& W = TopoDS::Wire(it.Value());
164
165     for (Exp.Init(W,TopAbs_EDGE); Exp.More(); Exp.Next()) {
166
167       TopoDS_Edge E = TopoDS::Edge(Exp.Current());
168       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E,S,L,f,l);
169       
170       if (C2.IsNull()) {
171         // no pcurve on the reference surface.
172         if (modeProj) {
173           // Projection of the 3D curve on surface.
174           ProjCurve3d ( E, S, L);
175         }
176         else {
177           // return the first pcurve glued on <S>
178           Standard_Boolean YaPCurve = ChangePCurve (E, S, L);
179           if (!YaPCurve) {
180             ProjCurve3d (E, S, L);
181           }
182         }
183       }
184     }
185     WTF.AddWire(W);
186   }
187
188   WTF.MakeFaces(myFace,faces);
189
190   myDone = Standard_True;
191 }
192
193
194 //=======================================================================
195 //function : IsDone
196 //purpose  : 
197 //=======================================================================
198
199 Standard_Boolean BRepAlgo_FaceRestrictor::IsDone() const 
200 {
201   return myDone;
202 }
203
204
205 //=======================================================================
206 //function : More
207 //purpose  : 
208 //=======================================================================
209
210 Standard_Boolean BRepAlgo_FaceRestrictor::More() const 
211 {
212   return (!faces.IsEmpty());
213 }
214
215
216 //=======================================================================
217 //function : Next
218 //purpose  : 
219 //=======================================================================
220
221 void BRepAlgo_FaceRestrictor::Next()
222 {
223   faces.RemoveFirst();
224 }
225
226
227 //=======================================================================
228 //function : Current
229 //purpose  : 
230 //=======================================================================
231
232 TopoDS_Face BRepAlgo_FaceRestrictor::Current() const 
233 {
234   return (TopoDS::Face(faces.First()));
235 }
236
237 //=======================================================================
238 //function : Standard_Boolean
239 //purpose  : 
240 //=======================================================================
241
242 static Standard_Boolean IsClosed (const TopoDS_Wire& W)
243      
244 {
245   if (W.Closed()) return 1;
246   TopoDS_Vertex V1,V2;
247   TopExp::Vertices (W, V1,V2);
248   return (V1.IsSame(V2));
249 }
250
251
252 //=======================================================================
253 //function : IsInside
254 //purpose  : 
255 //=======================================================================
256
257 static Standard_Boolean IsInside(const TopoDS_Wire&       wir,
258                                  const TopoDS_Face&       F,
259                                  BRepTopAdaptor_FClass2d& /*FClass2d*/)
260 {
261   TopExp_Explorer exp;
262   exp.Init(wir,TopAbs_EDGE);
263   if (exp.More()) {
264     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
265     Standard_Real f,l;
266     Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
267     Standard_Real prm;
268
269     if (!Precision::IsNegativeInfinite(f) && !Precision::IsPositiveInfinite(l)) {
270       prm = (f+l)/2.;
271     }
272     else {
273       if (Precision::IsNegativeInfinite(f) && Precision::IsPositiveInfinite(l)){
274         prm = 0.;
275       }
276       else if (Precision::IsNegativeInfinite(f)) {
277         prm = l-1.;
278       }
279       else {
280         prm = f+1.;
281       }
282     }
283
284     gp_Pnt2d pt2d(C2d->Value(prm));
285     BRepTopAdaptor_FClass2d FClass2d(F,Precision::PConfusion());
286     TopAbs_State st2=FClass2d.Perform(pt2d,Standard_False);
287     return(st2 == TopAbs_IN);     
288   }
289   return Standard_False;
290 }
291 //=======================================================================
292 //function : Store
293 //purpose  : 
294 //=======================================================================
295
296 static void Store (const TopoDS_Wire& W2,
297                    const TopoDS_Wire& W1,
298                    TopTools_DataMapOfShapeListOfShape& keyIsIn,
299                    TopTools_DataMapOfShapeListOfShape& keyContains)
300 {
301   if (!keyIsIn.IsBound(W2)) {
302     TopTools_ListOfShape empty;
303     keyIsIn.Bind(W2,empty);
304   }
305   keyIsIn(W2).Append(W1);
306   if (!keyContains.IsBound(W1)) {
307     TopTools_ListOfShape empty;
308     keyContains.Bind(W1,empty);
309   }
310   keyContains(W1).Append(W2);
311 }
312 //=======================================================================
313 //function : BuildFaceIn
314 //purpose  : 
315 //=======================================================================
316
317 static void BuildFaceIn(  TopoDS_Face& F, 
318                           const TopoDS_Wire& W, 
319                           TopTools_DataMapOfShapeListOfShape& KeyContains, 
320                           TopTools_DataMapOfShapeListOfShape& KeyIsIn,
321                           TopAbs_Orientation                  Orientation,
322                           TopTools_ListOfShape&               Faces)
323 {
324   BRep_Builder B;
325   
326   if (!KeyContains.IsBound(W) || KeyContains(W).IsEmpty()) return;
327
328 // Removal of W in KeyIsIn.
329 //  for (TopTools_ListIteratorOfListOfShape it(KeyContains(W)); it.More(); it.Next()) {
330
331   TopTools_ListIteratorOfListOfShape it;
332   for (it.Initialize(KeyContains(W)); it.More(); it.Next()) {
333     const TopoDS_Wire&    WI = TopoDS::Wire(it.Value());
334     TopTools_ListOfShape& L2 = KeyIsIn(WI);
335     TopTools_ListIteratorOfListOfShape it2;
336     for (it2.Initialize(L2); it2.More(); it2.Next()) {
337       if (it2.Value().IsSame(W)) {
338         L2.Remove(it2);
339         break;
340       }
341     }
342   }
343
344   TopTools_ListOfShape WireExt;
345
346   for (it.Initialize(KeyContains(W)); it.More(); it.Next()) {
347     const TopoDS_Wire&    WI = TopoDS::Wire(it.Value());
348     TopTools_ListOfShape& L2 = KeyIsIn(WI);
349    
350     if (L2.IsEmpty()) {
351       WireExt.Append(WI);
352     }
353   }
354   
355   for (it.Initialize(WireExt); it.More(); it.Next()) {
356     const TopoDS_Wire&    WI = TopoDS::Wire(it.Value());
357     TopTools_ListOfShape& L2 = KeyIsIn(WI);
358     if (L2.IsEmpty()) {
359       if (Orientation == TopAbs_FORWARD) {
360         TopoDS_Wire NWI(WI);
361         NWI.Reverse();
362         // TopoDS_Wire NWI = TopoDS::Wire(WI.Reversed());
363         B.Add(F,NWI);
364         BuildFaceIn (F,WI,KeyContains, KeyIsIn,TopAbs_REVERSED,Faces);
365       }
366       else {
367         TopoDS_Shape aLocalShape  = Faces.First().EmptyCopied();
368         TopoDS_Face NF = TopoDS::Face(aLocalShape);
369         // TopoDS_Face NF = TopoDS::Face(Faces.First().EmptyCopied());;
370         B.Add        (NF,WI);
371         Faces.Append (NF);
372         BuildFaceIn (NF, WI, KeyContains, KeyIsIn, TopAbs_FORWARD,Faces);
373       }
374     }
375   }
376 }
377
378 //=======================================================================
379 //function : Perform
380 //purpose  : 
381 //=======================================================================
382
383 void BRepAlgo_FaceRestrictor::PerformWithCorrection()
384 {
385   BRep_Builder B;
386
387   myDone = Standard_False;
388   TopTools_ListIteratorOfListOfShape it(wires);
389   //---------------------------------------------------------
390   // Reorientation of all closed wires to the left.
391   //---------------------------------------------------------
392   for (; it.More(); it.Next()) {
393     TopoDS_Wire& W  = TopoDS::Wire(it.Value());
394     TopoDS_Shape aLocalShape = myFace.EmptyCopied();
395     TopoDS_Face  NF = TopoDS::Face(aLocalShape);
396 //    TopoDS_Face  NF = TopoDS::Face(myFace.EmptyCopied());
397     NF.Orientation(TopAbs_FORWARD);
398     B.Add(NF,W);
399     
400     if (IsClosed(W)) {  
401       BRepTopAdaptor_FClass2d FClass2d(NF,Precision::PConfusion());
402       if(FClass2d.PerformInfinitePoint() != TopAbs_OUT) { 
403         W.Reverse();
404       }
405     }
406   }
407   //---------------------------------------------------------
408   // Classification of wires ones compared to the others.
409   //---------------------------------------------------------
410   Standard_Integer j,i = 1;
411
412   for (it.Initialize(wires) ; it.More(); it.Next()) {
413     TopoDS_Wire& W1  = TopoDS::Wire(it.Value());
414     TopTools_ListIteratorOfListOfShape it2(wires);  
415     j = 1;    
416
417     if (IsClosed(W1)) {
418       TopoDS_Shape aLocalShape = myFace.EmptyCopied();
419       TopoDS_Face  NF = TopoDS::Face(aLocalShape);
420 //      TopoDS_Face  NF = TopoDS::Face(myFace.EmptyCopied());
421       NF.Orientation(TopAbs_FORWARD);
422       B.Add(NF,W1);
423       
424       BRepTopAdaptor_FClass2d FClass2d(NF,Precision::PConfusion());
425       while (it2.More()) {
426         const TopoDS_Wire& W2 = TopoDS::Wire(it2.Value());
427         if (!W1.IsSame(W2) && IsInside (W2,NF,FClass2d)) {
428           Store (W2,W1,keyIsIn,keyContains);
429         } 
430         it2.Next();
431         j++;
432       }
433     }
434     i++;
435   }
436   TopTools_ListOfShape WireExt;
437   
438   for (it.Initialize(wires) ; it.More(); it.Next()) {
439     const TopoDS_Wire& W = TopoDS::Wire(it.Value());
440     if (!keyIsIn.IsBound(W) || keyIsIn(W).IsEmpty()) {
441       WireExt.Append(W);
442     }
443   }
444   
445   for (it.Initialize(WireExt) ; it.More(); it.Next()) {
446     const TopoDS_Wire& W = TopoDS::Wire(it.Value());
447     if (!keyIsIn.IsBound(W) || keyIsIn(W).IsEmpty()) {
448       TopoDS_Shape aLocalShape = myFace.EmptyCopied();
449       TopoDS_Face NewFace = TopoDS::Face(aLocalShape);
450 //      TopoDS_Face NewFace = TopoDS::Face(myFace.EmptyCopied());
451       NewFace.Orientation(TopAbs_FORWARD);
452       B.Add     (NewFace,W);
453       faces.Append(NewFace); 
454       //--------------------------------------------
455       // Construction of a face by exterior wire.
456       //--------------------------------------------
457       BuildFaceIn(NewFace,W, keyContains, keyIsIn, TopAbs_FORWARD, faces);
458     }
459   }
460   myDone = Standard_True;
461 }
462
463
464
465
466
467
468
469
470
471