0024060: Wrong result done by general fuse algorithm.
[occt.git] / src / BRepAlgo / BRepAlgo_FaceRestrictor.cxx
CommitLineData
b311480e 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
7fd59977 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
48BRepAlgo_FaceRestrictor::BRepAlgo_FaceRestrictor()
49{}
50
51//=======================================================================
52//function :
53//purpose :
54//=======================================================================
55
56void 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
69void BRepAlgo_FaceRestrictor::Add(TopoDS_Wire& W)
70{
71 wires.Append(W);
72}
73
74
75//=======================================================================
76//function : Clear
77//purpose :
78//=======================================================================
79
80void BRepAlgo_FaceRestrictor::Clear()
81{
82 wires.Clear();
83 faces.Clear();
84}
85
86//=======================================================================
87//function : ChangePcurve
88//purpose :
89//=======================================================================
90
91static 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
112static 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
134void 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 //--------------------------------------------------------------------
0d969553 146 // return geometry of the reference face.
7fd59977 147 //--------------------------------------------------------------------
148 TopLoc_Location L;
149 const Handle(Geom_Surface)& S = BRep_Tool::Surface(myFace,L);
150
151 //-----------------------------------------------------------------------
0d969553
Y
152 // test if edges are on S. otherwise add S to the first pcurve.
153 // or projection of the edge on F.
7fd59977 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()) {
0d969553 162 // update the surface on edges.
7fd59977 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()) {
0d969553 171 // no pcurve on the reference surface.
7fd59977 172 if (modeProj) {
0d969553 173 // Projection of the 3D curve on surface.
7fd59977 174 ProjCurve3d ( E, S, L);
175 }
176 else {
0d969553 177 // return the first pcurve glued on <S>
7fd59977 178 Standard_Boolean YaPCurve = ChangePCurve (E, S, L);
179 if (!YaPCurve) {
180 ProjCurve3d (E, S, L);
181 }
182
183 }
184 }
185 }
186 WTF.AddWire(W);
187 }
188
189 WTF.MakeFaces(myFace,faces);
190
191 myDone = Standard_True;
192}
193
194
195//=======================================================================
196//function : IsDone
197//purpose :
198//=======================================================================
199
200Standard_Boolean BRepAlgo_FaceRestrictor::IsDone() const
201{
202 return myDone;
203}
204
205
206//=======================================================================
207//function : More
208//purpose :
209//=======================================================================
210
211Standard_Boolean BRepAlgo_FaceRestrictor::More() const
212{
213 return (!faces.IsEmpty());
214}
215
216
217//=======================================================================
218//function : Next
219//purpose :
220//=======================================================================
221
222void BRepAlgo_FaceRestrictor::Next()
223{
224 faces.RemoveFirst();
225}
226
227
228//=======================================================================
229//function : Current
230//purpose :
231//=======================================================================
232
233TopoDS_Face BRepAlgo_FaceRestrictor::Current() const
234{
235 return (TopoDS::Face(faces.First()));
236}
237
238//=======================================================================
239//function : Standard_Boolean
240//purpose :
241//=======================================================================
242
243static Standard_Boolean IsClosed (const TopoDS_Wire& W)
244
245{
246 if (W.Closed()) return 1;
247 TopoDS_Vertex V1,V2;
248 TopExp::Vertices (W, V1,V2);
249 return (V1.IsSame(V2));
250}
251
252
253//=======================================================================
254//function : IsInside
255//purpose :
256//=======================================================================
257
258static Standard_Boolean IsInside(const TopoDS_Wire& wir,
259 const TopoDS_Face& F,
260 BRepTopAdaptor_FClass2d& /*FClass2d*/)
261{
262
263//Standard_Real U,V;
264 TopExp_Explorer exp;
265 for (exp.Init(wir,TopAbs_EDGE);
266 exp.More();
267 exp.Next()) {
268 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
269 Standard_Real f,l;
270 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
271 Standard_Real prm;
272
273 if (!Precision::IsNegativeInfinite(f) &&
274 !Precision::IsPositiveInfinite(l)) {
275 prm = (f+l)/2.;
276 }
277 else {
278 if (Precision::IsNegativeInfinite(f) &&
279 Precision::IsPositiveInfinite(l)){
280 prm = 0.;
281 }
282 else if (Precision::IsNegativeInfinite(f)) {
283 prm = l-1.;
284 }
285 else {
286 prm = f+1.;
287 }
288 }
289
290 gp_Pnt2d pt2d(C2d->Value(prm));
291 BRepTopAdaptor_FClass2d FClass2d(F,Precision::PConfusion());
292 TopAbs_State st2=FClass2d.Perform(pt2d,Standard_False);
293 return(st2 == TopAbs_IN);
294 }
295 return Standard_False;
296}
297//=======================================================================
298//function : Store
299//purpose :
300//=======================================================================
301
302static void Store (const TopoDS_Wire& W2,
303 const TopoDS_Wire& W1,
304 TopTools_DataMapOfShapeListOfShape& keyIsIn,
305 TopTools_DataMapOfShapeListOfShape& keyContains)
306{
307 if (!keyIsIn.IsBound(W2)) {
308 TopTools_ListOfShape empty;
309 keyIsIn.Bind(W2,empty);
310 }
311 keyIsIn(W2).Append(W1);
312 if (!keyContains.IsBound(W1)) {
313 TopTools_ListOfShape empty;
314 keyContains.Bind(W1,empty);
315 }
316 keyContains(W1).Append(W2);
317}
318//=======================================================================
319//function : BuildFaceIn
320//purpose :
321//=======================================================================
322
323static void BuildFaceIn( TopoDS_Face& F,
324 const TopoDS_Wire& W,
325 TopTools_DataMapOfShapeListOfShape& KeyContains,
326 TopTools_DataMapOfShapeListOfShape& KeyIsIn,
327 TopAbs_Orientation Orientation,
328 TopTools_ListOfShape& Faces)
329{
330 BRep_Builder B;
331
332 if (!KeyContains.IsBound(W) || KeyContains(W).IsEmpty()) return;
333
0d969553 334// Removal of W in KeyIsIn.
7fd59977 335// for (TopTools_ListIteratorOfListOfShape it(KeyContains(W)); it.More(); it.Next()) {
336
337 TopTools_ListIteratorOfListOfShape it;
338 for (it.Initialize(KeyContains(W)); it.More(); it.Next()) {
339 const TopoDS_Wire& WI = TopoDS::Wire(it.Value());
340 TopTools_ListOfShape& L2 = KeyIsIn(WI);
341 TopTools_ListIteratorOfListOfShape it2;
342 for (it2.Initialize(L2); it2.More(); it2.Next()) {
343 if (it2.Value().IsSame(W)) {
344 L2.Remove(it2);
345 break;
346 }
347 }
348 }
349
350 TopTools_ListOfShape WireExt;
351
352 for (it.Initialize(KeyContains(W)); it.More(); it.Next()) {
353 const TopoDS_Wire& WI = TopoDS::Wire(it.Value());
354 TopTools_ListOfShape& L2 = KeyIsIn(WI);
355
356 if (L2.IsEmpty()) {
357 WireExt.Append(WI);
358 }
359 }
360
361 for (it.Initialize(WireExt); it.More(); it.Next()) {
362 const TopoDS_Wire& WI = TopoDS::Wire(it.Value());
363 TopTools_ListOfShape& L2 = KeyIsIn(WI);
364 if (L2.IsEmpty()) {
365 if (Orientation == TopAbs_FORWARD) {
366 TopoDS_Wire NWI(WI);
367 NWI.Reverse();
368// TopoDS_Wire NWI = TopoDS::Wire(WI.Reversed());
369 B.Add(F,NWI);
370 BuildFaceIn (F,WI,KeyContains, KeyIsIn,TopAbs_REVERSED,Faces);
371 }
372 else {
373 TopoDS_Shape aLocalShape = Faces.First().EmptyCopied();
374 TopoDS_Face NF = TopoDS::Face(aLocalShape);
375// TopoDS_Face NF = TopoDS::Face(Faces.First().EmptyCopied());;
376 B.Add (NF,WI);
377 Faces.Append (NF);
378 BuildFaceIn (NF, WI, KeyContains, KeyIsIn, TopAbs_FORWARD,Faces);
379 }
380 }
381 }
382}
383
384//=======================================================================
385//function : Perform
386//purpose :
387//=======================================================================
388
389void BRepAlgo_FaceRestrictor::PerformWithCorrection()
390{
391 BRep_Builder B;
392
393 myDone = Standard_False;
394 TopTools_ListIteratorOfListOfShape it(wires);
395 //---------------------------------------------------------
0d969553 396 // Reorientation of all closed wires to the left.
7fd59977 397 //---------------------------------------------------------
398 for (; it.More(); it.Next()) {
399 TopoDS_Wire& W = TopoDS::Wire(it.Value());
400 TopoDS_Shape aLocalShape = myFace.EmptyCopied();
401 TopoDS_Face NF = TopoDS::Face(aLocalShape);
402// TopoDS_Face NF = TopoDS::Face(myFace.EmptyCopied());
403 NF.Orientation(TopAbs_FORWARD);
404 B.Add(NF,W);
405
406 if (IsClosed(W)) {
407 BRepTopAdaptor_FClass2d FClass2d(NF,Precision::PConfusion());
408 if(FClass2d.PerformInfinitePoint() != TopAbs_OUT) {
409 W.Reverse();
410 }
411 }
412 }
413 //---------------------------------------------------------
0d969553 414 // Classification of wires ones compared to the others.
7fd59977 415 //---------------------------------------------------------
416 Standard_Integer j,i = 1;
417
418 for (it.Initialize(wires) ; it.More(); it.Next()) {
419 TopoDS_Wire& W1 = TopoDS::Wire(it.Value());
420 TopTools_ListIteratorOfListOfShape it2(wires);
421 j = 1;
422
423 if (IsClosed(W1)) {
424 TopoDS_Shape aLocalShape = myFace.EmptyCopied();
425 TopoDS_Face NF = TopoDS::Face(aLocalShape);
426// TopoDS_Face NF = TopoDS::Face(myFace.EmptyCopied());
427 NF.Orientation(TopAbs_FORWARD);
428 B.Add(NF,W1);
429
430 BRepTopAdaptor_FClass2d FClass2d(NF,Precision::PConfusion());
431 while (it2.More()) {
432 const TopoDS_Wire& W2 = TopoDS::Wire(it2.Value());
433 if (!W1.IsSame(W2) && IsInside (W2,NF,FClass2d)) {
434 Store (W2,W1,keyIsIn,keyContains);
435 }
436 it2.Next();
437 j++;
438 }
439 }
440 i++;
441 }
442 TopTools_ListOfShape WireExt;
443
444 for (it.Initialize(wires) ; it.More(); it.Next()) {
445 const TopoDS_Wire& W = TopoDS::Wire(it.Value());
446 if (!keyIsIn.IsBound(W) || keyIsIn(W).IsEmpty()) {
447 WireExt.Append(W);
448 }
449 }
450
451 for (it.Initialize(WireExt) ; it.More(); it.Next()) {
452 const TopoDS_Wire& W = TopoDS::Wire(it.Value());
453 if (!keyIsIn.IsBound(W) || keyIsIn(W).IsEmpty()) {
454 TopoDS_Shape aLocalShape = myFace.EmptyCopied();
455 TopoDS_Face NewFace = TopoDS::Face(aLocalShape);
456// TopoDS_Face NewFace = TopoDS::Face(myFace.EmptyCopied());
457 NewFace.Orientation(TopAbs_FORWARD);
458 B.Add (NewFace,W);
459 faces.Append(NewFace);
460 //--------------------------------------------
0d969553 461 // Construction of a face by exterior wire.
7fd59977 462 //--------------------------------------------
463 BuildFaceIn(NewFace,W, keyContains, keyIsIn, TopAbs_FORWARD, faces);
464 }
465 }
466 myDone = Standard_True;
467}
468
469
470
471
472
473
474
475
476
477