0030895: Coding Rules - specify std namespace explicitly for std::cout and streams
[occt.git] / src / LocOpe / LocOpe_BuildShape.cxx
CommitLineData
b311480e 1// Created on: 1996-09-16
2// Created by: Jacques GOUSSARD
3// Copyright (c) 1996-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
7fd59977 17
7fd59977 18#include <BRep_Builder.hxx>
42cf5bc1 19#include <BRep_Tool.hxx>
7fd59977 20#include <BRepClass3d_SolidClassifier.hxx>
42cf5bc1 21#include <gp_Pnt.hxx>
22#include <LocOpe_BuildShape.hxx>
23#include <Precision.hxx>
7fd59977 24#include <Standard_ConstructionError.hxx>
42cf5bc1 25#include <TColStd_MapIteratorOfMapOfInteger.hxx>
26#include <TColStd_MapOfInteger.hxx>
7fd59977 27#include <TopAbs.hxx>
42cf5bc1 28#include <TopExp.hxx>
7fd59977 29#include <TopoDS.hxx>
42cf5bc1 30#include <TopoDS_Compound.hxx>
31#include <TopoDS_Edge.hxx>
32#include <TopoDS_Shape.hxx>
33#include <TopoDS_Shell.hxx>
34#include <TopoDS_Solid.hxx>
35#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
36#include <TopTools_DataMapOfShapeListOfShape.hxx>
37#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
38#include <TopTools_IndexedMapOfShape.hxx>
39#include <TopTools_ListIteratorOfListOfShape.hxx>
7fd59977 40
41static void Add(const Standard_Integer,
42 TColStd_MapOfInteger&,
43 TopTools_IndexedMapOfShape&,
44 const TopTools_IndexedDataMapOfShapeListOfShape&);
45
46static void Propagate(const TopoDS_Shape&, // face
47 TopoDS_Shape&, // shell
48 const TopTools_IndexedMapOfShape&,
49 TColStd_MapOfInteger&);
50
51static Standard_Boolean IsInside(const TopoDS_Shape&,
52 const TopoDS_Shape&);
53
54
55//=======================================================================
56//function : Perform
57//purpose :
58//=======================================================================
59
60void LocOpe_BuildShape::Perform(const TopTools_ListOfShape& L)
61{
62 Standard_Integer i ;
63 Standard_Integer j ;
64 Standard_Integer k ;
65 myRes.Nullify();
66
67 TopoDS_Compound C;
68 BRep_Builder B;
69 B.MakeCompound(C);
70
71 TopTools_IndexedMapOfShape mapF;
72 TopTools_ListIteratorOfListOfShape itl;
73
74 for (itl.Initialize(L); itl.More(); itl.Next()) {
75 if (itl.Value().ShapeType() == TopAbs_FACE &&
76 !mapF.Contains(itl.Value())) {
77 mapF.Add(itl.Value());
78 B.Add(C,itl.Value());
79 }
80 }
81
82 if (mapF.Extent() == 0) {
83 return; // no face
84 }
85
86 TopTools_IndexedDataMapOfShapeListOfShape theMapEF;
87 TopExp::MapShapesAndAncestors(C,TopAbs_EDGE,TopAbs_FACE,theMapEF);
88
89 TopTools_DataMapOfShapeListOfShape mapSh;
90 TColStd_MapOfInteger mapI,mapIf;
91 Standard_Integer Nbedges = theMapEF.Extent();
92
93 TopTools_ListOfShape lshell;
94 TopTools_ListOfShape lresult;
95
96 do {
97 // Recherche du premier edge non traite
98 for ( i = 1; i <= Nbedges; i++) {
99 if (!mapI.Contains(i)) {
100 break;
101 }
102 }
103 if (i <= Nbedges) {
104 mapF.Clear();
105 mapIf.Clear();
106 Add(i,mapI,mapF,theMapEF);
107 Standard_Boolean Manifold = Standard_True;
108 TopoDS_Shape FaceRef;
109 TopAbs_Orientation orient;
110
111 for ( j = 1; j<= mapF.Extent(); j++) {
112 orient = mapF(j).Orientation();
113 if (orient == TopAbs_INTERNAL || orient == TopAbs_EXTERNAL) {
114 Manifold = Standard_False;
115 }
116 else if (FaceRef.IsNull()) {
117 FaceRef = mapF(j);
118 }
119 mapIf.Add(j);
120 }
121
122 TopoDS_Shell newSh;
123 B.MakeShell(newSh);
124 if (!Manifold && FaceRef.IsNull()) {
125 // on a un paquet de faces. pas d'orientation possible ?
126 for (j = 1; j <= mapF.Extent(); j++) {
127 B.Add(newSh,mapF(j));
128 }
129 }
130 else {
131 // orienter ce qu`on peut
132 if (!Manifold) {
133 for (j = 1; j <= mapF.Extent(); j++) {
134 if (mapF(j).Orientation() == TopAbs_INTERNAL ||
135 mapF(j).Orientation() == TopAbs_EXTERNAL) {
136 B.Add(newSh,mapF(j));
137 mapIf.Remove(j);
138 }
139 }
140 }
141
142 B.Add(newSh,FaceRef);
143 Propagate(FaceRef,newSh,mapF,mapIf);
144 }
ab860031 145 newSh.Closed (BRep_Tool::IsClosed (newSh));
7fd59977 146 if (!Manifold) {
147 lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
148 }
149 else {
150 TopTools_IndexedDataMapOfShapeListOfShape theMapEFbis;
151 TopExp::MapShapesAndAncestors(newSh,TopAbs_EDGE,TopAbs_FACE,theMapEFbis);
152 for ( k = 1; k<=theMapEFbis.Extent(); k++) {
153 const TopoDS_Edge& Ed = TopoDS::Edge(theMapEFbis.FindKey(k));
154 TopAbs_Orientation OriEd = Ed.Orientation();
155 if (OriEd != TopAbs_INTERNAL && OriEd != TopAbs_EXTERNAL) {
156 Standard_Integer Nbfac = theMapEFbis(k).Extent();
157 if (Nbfac > 2) { // peu probable
158 break;
159 }
160 else if (Nbfac == 1) {
161 if (!BRep_Tool::Degenerated(Ed)) {
162 break;
163 }
164 }
165 }
166 }
167 if (k > theMapEFbis.Extent()) {
168 TopoDS_Solid newSo;
169 B.MakeSolid(newSo);
170 B.Add(newSo,newSh); // newSh est FORWARD
171 BRepClass3d_SolidClassifier Class(newSo);
172 Class.PerformInfinitePoint(Precision::Confusion());
173 if (Class.State() == TopAbs_IN) {
174 lresult.Append(newSh.Oriented(TopAbs_REVERSED));
175 }
176 else {
177 lresult.Append(newSh);
178 }
179 }
180 else {
181 lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
182 }
183 }
184 }
185 } while (mapI.Extent() < Nbedges);
186
187
188 // on a une list de shells dans lresult. on suppose qu`ils ne s`intersectent pas.
189 // il faut classifier les shells orientes pour en faire des solides...
190 // on n`accepte qu`1 niveau d'imbrication
191
192 TopTools_DataMapOfShapeListOfShape imbSh;
193 TopTools_ListOfShape LIntern;
194
195 for (itl.Initialize(lresult); itl.More(); itl.Next()) {
196 const TopoDS_Shape& sh = itl.Value();
197 TopoDS_Solid tempo;
198 B.MakeSolid(tempo);
199 B.Add(tempo,sh);
200
201 TopTools_ListOfShape thelist;
202 imbSh.Bind(sh, thelist);
203 TopTools_ListIteratorOfListOfShape itl2;
204 for (itl2.Initialize(lresult);
205// for (TopTools_ListIteratorOfListOfShape itl2(lresult);
206 itl2.More(); itl2.Next()) {
207 const TopoDS_Shape& sh2 = itl2.Value();
208 if (!sh2.IsSame(sh)) {
209 if (IsInside(sh2, tempo)) {
210 LIntern.Append(sh2);
211 imbSh(sh).Append(sh2);
212 }
213 }
214 }
215 }
216
217
218 // LPA 07/10/98: on vire les shells imbriques comme
219 // etant aussi des solides a part entiere.
220 for (itl.Initialize(LIntern); itl.More(); itl.Next()) {
221 const TopoDS_Shape& sh = itl.Value();
222 if (imbSh.IsBound(sh)) {
223 imbSh.UnBind(sh);
224 }
225 }
226
227
228
229 TopTools_ListOfShape lsolid;
230 do {
231// for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(imbSh);
232 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(imbSh);
233 for ( ; itdm.More(); itdm.Next()) {
234 if (itdm.Value().Extent() != 0) {
235 break;
236 }
237 }
238 if (itdm.More()) {
239 TopoDS_Solid newSo;
240 B.MakeSolid(newSo);
241 B.Add(newSo,itdm.Key());
242 for (itl.Initialize(itdm.Value()); itl.More(); itl.Next()) {
243 B.Add(newSo,itl.Value().Reversed());
244 }
245 lsolid.Append(newSo);
246 imbSh.UnBind(itdm.Key());
247 }
248 else {
249 for (itdm.Reset(); itdm.More(); itdm.Next()) {
250 TopoDS_Solid newSo;
251 B.MakeSolid(newSo);
252 B.Add(newSo,itdm.Key());
253 lsolid.Append(newSo);
254 }
255 imbSh.Clear();
256 }
c29a9290 257 } while (imbSh.Extent() != 0);
7fd59977 258
259 Standard_Integer nbsol = lsolid.Extent();
260 Standard_Integer nbshl = lshell.Extent();
261
262 if (nbsol == 1 && nbshl == 0) {
263 myRes = lsolid.First();
264 }
265 else if (nbsol == 0 && nbshl == 1) {
266 myRes = lshell.First();
267 }
268 else {
269 B.MakeCompound(TopoDS::Compound(myRes));
270 for (itl.Initialize(lsolid); itl.More(); itl.Next()) {
271 B.Add(myRes,itl.Value());
272 }
273 for (itl.Initialize(lshell); itl.More(); itl.Next()) {
274 B.Add(myRes,itl.Value());
275 }
276 }
277}
278
279
280
281
282
283//=======================================================================
284//function : Add
285//purpose : static function
286//=======================================================================
287
288static void Add(const Standard_Integer ind,
289 TColStd_MapOfInteger& mapI,
290 TopTools_IndexedMapOfShape& mapF,
291 const TopTools_IndexedDataMapOfShapeListOfShape& mapEF)
292
293{
294 if (!mapI.Add(ind)) {
9775fa61 295 throw Standard_ConstructionError();
7fd59977 296 }
297
298 TopTools_ListIteratorOfListOfShape itl(mapEF(ind));
299 for (; itl.More(); itl.Next()) {
300 if (!mapF.Contains(itl.Value())) {
301 mapF.Add(itl.Value());
302 TopExp_Explorer exp;
303 for (exp.Init(itl.Value(),TopAbs_EDGE);
304// for (TopExp_Explorer exp(itl.Value(),TopAbs_EDGE);
305 exp.More(); exp.Next()) {
306 const TopoDS_Shape& edg = exp.Current();
307 Standard_Integer indedg = mapEF.FindIndex(edg);
308 if (indedg == 0) {
9775fa61 309 throw Standard_ConstructionError();
7fd59977 310 }
311 if (!mapI.Contains(indedg)) {
312 Add(indedg,mapI,mapF,mapEF);
313 }
314 }
315 }
316 }
317}
318
319
320//=======================================================================
321//function : Propagate
322//purpose : static function
323//=======================================================================
324
325static void Propagate(const TopoDS_Shape& F,
326 TopoDS_Shape& Sh,
327 const TopTools_IndexedMapOfShape& mapF,
328 TColStd_MapOfInteger& mapIf)
329{
330 BRep_Builder B;
331 Standard_Integer indf = mapF.FindIndex(F);
332 if (!mapIf.Contains(indf)) {
333 return;
334 }
335 mapIf.Remove(indf);
336 if (mapIf.Extent() == 0) {
337 return;
338 }
339
340 TopExp_Explorer exp;
341 for (exp.Init(F,TopAbs_EDGE); exp.More(); exp.Next()) {
342// for (TopExp_Explorer exp(F,TopAbs_EDGE); exp.More(); exp.Next()) {
343 const TopoDS_Shape& edg = exp.Current();
1d47d8d0 344
7fd59977 345 TopAbs_Orientation ored1 = edg.Orientation(),ored2 = TopAbs_FORWARD;
1d47d8d0 346
7fd59977 347 if (ored1 == TopAbs_INTERNAL || ored1 == TopAbs_EXTERNAL) {
348 continue;
349 }
350// for (TColStd_MapIteratorOfMapOfInteger itm(mapIf);
351 TColStd_MapIteratorOfMapOfInteger itm(mapIf);
352 for ( ; itm.More(); itm.Next()) {
353 const TopoDS_Shape& newF = mapF(itm.Key());
354// for (TopExp_Explorer exp2(newF,TopAbs_EDGE);exp2.More(); exp2.Next()) {
355 TopExp_Explorer exp2(newF,TopAbs_EDGE) ;
356 for ( ;exp2.More(); exp2.Next()) {
357 if (exp2.Current().IsSame(edg)) {
358 break;
359 }
360 }
361 if (exp2.More()) {
362 ored2 = exp2.Current().Orientation();
363 break;
364 }
365 }
366 if (itm.More()) {
367 TopoDS_Shape FtoAdd = mapF(itm.Key());
368 Standard_Boolean added = Standard_False;
369 if (ored2 == ored1) {
370 FtoAdd.Reverse();
371 B.Add(Sh,FtoAdd);
372 added = Standard_True;
373 }
374 else if (ored2 == TopAbs::Reverse(ored1)) {
375 B.Add(Sh,FtoAdd);
376 added = Standard_True;
377 }
378 if (added) {
379 Propagate(FtoAdd,Sh,mapF,mapIf);
380 }
381 }
382 }
383}
384
385//=======================================================================
386//function : IsInside
387//purpose : static function
388//=======================================================================
389
390static Standard_Boolean IsInside(const TopoDS_Shape& S1,
391 const TopoDS_Shape& S2)
392{
393 BRepClass3d_SolidClassifier Class(S2);
394 TopExp_Explorer exp;
395 for (exp.Init(S1,TopAbs_VERTEX);exp.More(); exp.Next()) {
396// for (TopExp_Explorer exp(S1,TopAbs_VERTEX);exp.More(); exp.Next()) {
397 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
398 gp_Pnt Pttest = BRep_Tool::Pnt(vtx);
399 Standard_Real Tol = BRep_Tool::Tolerance(vtx);
400 Class.Perform(Pttest,Tol);
401 if (Class.State() == TopAbs_IN) {
402 return Standard_True;
403 }
404 else if (Class.State() == TopAbs_OUT) {
405 return Standard_False;
406 }
407 }
0797d9d3 408#ifdef OCCT_DEBUG
04232180 409 std::cout << "Classification impossible sur vertex " << std::endl;
7fd59977 410#endif
411
412 return Standard_True;
413
414}
415