1 // Created on: 1996-09-16
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepClass3d_SolidClassifier.hxx>
22 #include <LocOpe_BuildShape.hxx>
23 #include <Precision.hxx>
24 #include <Standard_ConstructionError.hxx>
25 #include <TColStd_MapOfInteger.hxx>
29 #include <TopoDS_Compound.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Shape.hxx>
32 #include <TopoDS_Shell.hxx>
33 #include <TopoDS_Solid.hxx>
34 #include <TopTools_DataMapOfShapeListOfShape.hxx>
35 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
36 #include <TopTools_IndexedMapOfShape.hxx>
38 static void Add(const Standard_Integer,
39 TColStd_MapOfInteger&,
40 TopTools_IndexedMapOfShape&,
41 const TopTools_IndexedDataMapOfShapeListOfShape&);
43 static void Propagate(const TopoDS_Shape&, // face
44 TopoDS_Shape&, // shell
45 const TopTools_IndexedMapOfShape&,
46 TColStd_MapOfInteger&);
48 static Standard_Boolean IsInside(const TopoDS_Shape&,
52 //=======================================================================
55 //=======================================================================
57 void LocOpe_BuildShape::Perform(const TopTools_ListOfShape& L)
68 TopTools_IndexedMapOfShape mapF;
69 TopTools_ListIteratorOfListOfShape itl;
71 for (itl.Initialize(L); itl.More(); itl.Next()) {
72 if (itl.Value().ShapeType() == TopAbs_FACE &&
73 !mapF.Contains(itl.Value())) {
74 mapF.Add(itl.Value());
79 if (mapF.Extent() == 0) {
83 TopTools_IndexedDataMapOfShapeListOfShape theMapEF;
84 TopExp::MapShapesAndAncestors(C,TopAbs_EDGE,TopAbs_FACE,theMapEF);
86 TopTools_DataMapOfShapeListOfShape mapSh;
87 TColStd_MapOfInteger mapI,mapIf;
88 Standard_Integer Nbedges = theMapEF.Extent();
90 TopTools_ListOfShape lshell;
91 TopTools_ListOfShape lresult;
94 // Recherche du premier edge non traite
95 for ( i = 1; i <= Nbedges; i++) {
96 if (!mapI.Contains(i)) {
103 Add(i,mapI,mapF,theMapEF);
104 Standard_Boolean Manifold = Standard_True;
105 TopoDS_Shape FaceRef;
106 TopAbs_Orientation orient;
108 for ( j = 1; j<= mapF.Extent(); j++) {
109 orient = mapF(j).Orientation();
110 if (orient == TopAbs_INTERNAL || orient == TopAbs_EXTERNAL) {
111 Manifold = Standard_False;
113 else if (FaceRef.IsNull()) {
121 if (!Manifold && FaceRef.IsNull()) {
122 // on a un paquet de faces. pas d'orientation possible ?
123 for (j = 1; j <= mapF.Extent(); j++) {
124 B.Add(newSh,mapF(j));
128 // orienter ce qu`on peut
130 for (j = 1; j <= mapF.Extent(); j++) {
131 if (mapF(j).Orientation() == TopAbs_INTERNAL ||
132 mapF(j).Orientation() == TopAbs_EXTERNAL) {
133 B.Add(newSh,mapF(j));
139 B.Add(newSh,FaceRef);
140 Propagate(FaceRef,newSh,mapF,mapIf);
142 newSh.Closed (BRep_Tool::IsClosed (newSh));
144 lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
147 TopTools_IndexedDataMapOfShapeListOfShape theMapEFbis;
148 TopExp::MapShapesAndAncestors(newSh,TopAbs_EDGE,TopAbs_FACE,theMapEFbis);
149 for ( k = 1; k<=theMapEFbis.Extent(); k++) {
150 const TopoDS_Edge& Ed = TopoDS::Edge(theMapEFbis.FindKey(k));
151 TopAbs_Orientation OriEd = Ed.Orientation();
152 if (OriEd != TopAbs_INTERNAL && OriEd != TopAbs_EXTERNAL) {
153 Standard_Integer Nbfac = theMapEFbis(k).Extent();
154 if (Nbfac > 2) { // peu probable
157 else if (Nbfac == 1) {
158 if (!BRep_Tool::Degenerated(Ed)) {
164 if (k > theMapEFbis.Extent()) {
167 B.Add(newSo,newSh); // newSh est FORWARD
168 BRepClass3d_SolidClassifier Class(newSo);
169 Class.PerformInfinitePoint(Precision::Confusion());
170 if (Class.State() == TopAbs_IN) {
171 lresult.Append(newSh.Oriented(TopAbs_REVERSED));
174 lresult.Append(newSh);
178 lshell.Append(newSh.Oriented(TopAbs_INTERNAL));
182 } while (mapI.Extent() < Nbedges);
185 // on a une list de shells dans lresult. on suppose qu`ils ne s`intersectent pas.
186 // il faut classifier les shells orientes pour en faire des solides...
187 // on n`accepte qu`1 niveau d'imbrication
189 TopTools_DataMapOfShapeListOfShape imbSh;
190 TopTools_ListOfShape LIntern;
192 for (itl.Initialize(lresult); itl.More(); itl.Next()) {
193 const TopoDS_Shape& sh = itl.Value();
198 TopTools_ListOfShape thelist;
199 imbSh.Bind(sh, thelist);
200 TopTools_ListIteratorOfListOfShape itl2;
201 for (itl2.Initialize(lresult);
202 // for (TopTools_ListIteratorOfListOfShape itl2(lresult);
203 itl2.More(); itl2.Next()) {
204 const TopoDS_Shape& sh2 = itl2.Value();
205 if (!sh2.IsSame(sh)) {
206 if (IsInside(sh2, tempo)) {
208 imbSh(sh).Append(sh2);
215 // LPA 07/10/98: on vire les shells imbriques comme
216 // etant aussi des solides a part entiere.
217 for (itl.Initialize(LIntern); itl.More(); itl.Next()) {
218 const TopoDS_Shape& sh = itl.Value();
219 if (imbSh.IsBound(sh)) {
226 TopTools_ListOfShape lsolid;
228 // for (TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(imbSh);
229 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm(imbSh);
230 for ( ; itdm.More(); itdm.Next()) {
231 if (itdm.Value().Extent() != 0) {
238 B.Add(newSo,itdm.Key());
239 for (itl.Initialize(itdm.Value()); itl.More(); itl.Next()) {
240 B.Add(newSo,itl.Value().Reversed());
242 lsolid.Append(newSo);
243 imbSh.UnBind(itdm.Key());
246 for (itdm.Reset(); itdm.More(); itdm.Next()) {
249 B.Add(newSo,itdm.Key());
250 lsolid.Append(newSo);
254 } while (imbSh.Extent() != 0);
256 Standard_Integer nbsol = lsolid.Extent();
257 Standard_Integer nbshl = lshell.Extent();
259 if (nbsol == 1 && nbshl == 0) {
260 myRes = lsolid.First();
262 else if (nbsol == 0 && nbshl == 1) {
263 myRes = lshell.First();
266 B.MakeCompound(TopoDS::Compound(myRes));
267 for (itl.Initialize(lsolid); itl.More(); itl.Next()) {
268 B.Add(myRes,itl.Value());
270 for (itl.Initialize(lshell); itl.More(); itl.Next()) {
271 B.Add(myRes,itl.Value());
280 //=======================================================================
282 //purpose : static function
283 //=======================================================================
285 static void Add(const Standard_Integer ind,
286 TColStd_MapOfInteger& mapI,
287 TopTools_IndexedMapOfShape& mapF,
288 const TopTools_IndexedDataMapOfShapeListOfShape& mapEF)
291 if (!mapI.Add(ind)) {
292 throw Standard_ConstructionError();
295 TopTools_ListIteratorOfListOfShape itl(mapEF(ind));
296 for (; itl.More(); itl.Next()) {
297 if (!mapF.Contains(itl.Value())) {
298 mapF.Add(itl.Value());
300 for (exp.Init(itl.Value(),TopAbs_EDGE);
301 // for (TopExp_Explorer exp(itl.Value(),TopAbs_EDGE);
302 exp.More(); exp.Next()) {
303 const TopoDS_Shape& edg = exp.Current();
304 Standard_Integer indedg = mapEF.FindIndex(edg);
306 throw Standard_ConstructionError();
308 if (!mapI.Contains(indedg)) {
309 Add(indedg,mapI,mapF,mapEF);
317 //=======================================================================
318 //function : Propagate
319 //purpose : static function
320 //=======================================================================
322 static void Propagate(const TopoDS_Shape& F,
324 const TopTools_IndexedMapOfShape& mapF,
325 TColStd_MapOfInteger& mapIf)
328 Standard_Integer indf = mapF.FindIndex(F);
329 if (!mapIf.Contains(indf)) {
333 if (mapIf.Extent() == 0) {
338 for (exp.Init(F,TopAbs_EDGE); exp.More(); exp.Next()) {
339 // for (TopExp_Explorer exp(F,TopAbs_EDGE); exp.More(); exp.Next()) {
340 const TopoDS_Shape& edg = exp.Current();
342 TopAbs_Orientation ored1 = edg.Orientation(),ored2 = TopAbs_FORWARD;
344 if (ored1 == TopAbs_INTERNAL || ored1 == TopAbs_EXTERNAL) {
347 // for (TColStd_MapIteratorOfMapOfInteger itm(mapIf);
348 TColStd_MapIteratorOfMapOfInteger itm(mapIf);
349 for ( ; itm.More(); itm.Next()) {
350 const TopoDS_Shape& newF = mapF(itm.Key());
351 // for (TopExp_Explorer exp2(newF,TopAbs_EDGE);exp2.More(); exp2.Next()) {
352 TopExp_Explorer exp2(newF,TopAbs_EDGE) ;
353 for ( ;exp2.More(); exp2.Next()) {
354 if (exp2.Current().IsSame(edg)) {
359 ored2 = exp2.Current().Orientation();
364 TopoDS_Shape FtoAdd = mapF(itm.Key());
365 Standard_Boolean added = Standard_False;
366 if (ored2 == ored1) {
369 added = Standard_True;
371 else if (ored2 == TopAbs::Reverse(ored1)) {
373 added = Standard_True;
376 Propagate(FtoAdd,Sh,mapF,mapIf);
382 //=======================================================================
383 //function : IsInside
384 //purpose : static function
385 //=======================================================================
387 static Standard_Boolean IsInside(const TopoDS_Shape& S1,
388 const TopoDS_Shape& S2)
390 BRepClass3d_SolidClassifier Class(S2);
392 for (exp.Init(S1,TopAbs_VERTEX);exp.More(); exp.Next()) {
393 // for (TopExp_Explorer exp(S1,TopAbs_VERTEX);exp.More(); exp.Next()) {
394 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
395 gp_Pnt Pttest = BRep_Tool::Pnt(vtx);
396 Standard_Real Tol = BRep_Tool::Tolerance(vtx);
397 Class.Perform(Pttest,Tol);
398 if (Class.State() == TopAbs_IN) {
399 return Standard_True;
401 else if (Class.State() == TopAbs_OUT) {
402 return Standard_False;
406 std::cout << "Classification impossible sur vertex " << std::endl;
409 return Standard_True;