1 // Created on: 1999-01-13
2 // Created by: Xuan PHAM PHU
3 // Copyright (c) 1999-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 <Bnd_Array1OfBox2d.hxx>
19 #include <Bnd_Box2d.hxx>
20 #include <BndLib_Add2dCurve.hxx>
21 #include <BRep_Tool.hxx>
22 #include <BRepAdaptor_Curve2d.hxx>
23 #include <BRepClass3d_SolidExplorer.hxx>
24 #include <BRepClass_FaceClassifier.hxx>
25 #include <TColStd_Array2OfReal.hxx>
26 #include <TopExp_Explorer.hxx>
28 #include <TopoDS_Face.hxx>
29 #include <TopoDS_Shape.hxx>
30 #include <TopOpeBRepTool_2d.hxx>
31 #include <TopOpeBRepTool_CLASSI.hxx>
32 #include <TopOpeBRepTool_define.hxx>
33 #include <TopOpeBRepTool_EXPORT.hxx>
34 #include <TopOpeBRepTool_face.hxx>
35 #include <TopOpeBRepTool_TOOL.hxx>
43 #define M_IN(st ) (st == TopAbs_IN )
44 #define M_OUT(st) (st == TopAbs_OUT)
46 //=======================================================================
47 //function : TopOpeBRepTool_CLASSI
49 //=======================================================================
51 TopOpeBRepTool_CLASSI::TopOpeBRepTool_CLASSI()
55 //=======================================================================
58 //=======================================================================
60 void TopOpeBRepTool_CLASSI::Init2d(const TopoDS_Face& Fref)
65 //=======================================================================
66 //function : HasInit2d
68 //=======================================================================
70 Standard_Boolean TopOpeBRepTool_CLASSI::HasInit2d() const
72 return (!myFref.IsNull());
77 //=======================================================================
80 //=======================================================================
82 Standard_Boolean TopOpeBRepTool_CLASSI::Add2d(const TopoDS_Shape& S)
84 if (!HasInit2d()) return Standard_False;
86 Standard_Boolean isb = mymapsbox2d.Contains(S);
87 if (isb) return Standard_True;
90 TopExp_Explorer exe(S, TopAbs_EDGE);
91 for (; exe.More(); exe.Next()){
92 const TopoDS_Edge& E = TopoDS::Edge(exe.Current());
93 Standard_Real tolE = BRep_Tool::Tolerance(E);
95 Standard_Boolean haspc = FC2D_HasCurveOnSurface(E,myFref);
96 if (!haspc) return Standard_False;
97 BRepAdaptor_Curve2d BC2d(E,myFref);
98 Standard_Real tol2d = BC2d.Resolution(tolE);
99 BndLib_Add2dCurve::Add(BC2d,tol2d,B2d);
101 mymapsbox2d.Add(S,B2d);
102 return Standard_True;
105 //=======================================================================
106 //function : GetBox2d
108 //=======================================================================
110 Standard_Boolean TopOpeBRepTool_CLASSI::GetBox2d(const TopoDS_Shape& S, Bnd_Box2d& B2d)
112 Standard_Boolean isb = mymapsbox2d.Contains(S);
113 if (!isb) isb = Add2d(S);
114 if (!isb) return Standard_False;
115 B2d = mymapsbox2d.FindFromKey(S);
116 return Standard_True;
119 //=======================================================================
120 //function : ClassiBnd2d
122 //=======================================================================
124 Standard_Integer TopOpeBRepTool_CLASSI::ClassiBnd2d(const TopoDS_Shape& S1,const TopoDS_Shape& S2,
125 const Standard_Real tol,const Standard_Boolean chklarge)
127 Bnd_Array1OfBox2d B(1,2);
128 Standard_Boolean isb = mymapsbox2d.Contains(S1);
129 if (!isb) isb = Add2d(S1);
130 if (!isb) return Standard_False;
131 B(1) = mymapsbox2d.FindFromKey(S1);
132 isb = mymapsbox2d.Contains(S2);
133 if (!isb) isb = Add2d(S2);
134 if (!isb) return Standard_False;
135 B(2) = mymapsbox2d.FindFromKey(S2);
137 TColStd_Array2OfReal UV(1,2, 1,4);
138 // for (Standard_Integer i = 1; i <= 2; i++)
140 for ( i = 1; i <= 2; i++)
141 // (Umin(i), Vmin(i), Umax(i), Vmax(i))
142 B(i).Get(UV(i,1), UV(i,3), UV(i,2), UV(i,4));
145 Standard_Boolean trc = Standard_False;
147 for (Standard_Integer j = 1; j <= 2; j++)
148 std::cout<<"B("<<j<<") = ("<<UV(j,1)<<" "<<UV(j,3)<<" "<<UV(j,2)<<" "<<UV(j,4)<<")"<<std::endl;
152 for (Standard_Integer k = 1; k <= 3; k+=2) {
153 for (i = 1; i <= 2; i++) {
154 Standard_Integer ii = i, jj = (i == 1) ? 2 : 1;
155 // diff = Umin<ii> - Umax<jj> : k = 1
156 // diff = Vmin<ii> - Vmax<jj> : k = 3
157 Standard_Real diff = UV(ii,k) - UV(jj,k+1);
158 // IMPORTANT : for splitted faces sharing same edge, use
160 Standard_Boolean disjoint = chklarge ? (diff >= -tol) : (diff > 0.);
161 if (disjoint) return DIFF;
165 for (i = 1; i <= 2; i++) {
166 // comparing Bnd2d(ii) with Bnd2d(jj)
167 Standard_Integer ii = i, jj = (i == 1) ? 2 : 1;
168 Standard_Boolean smaller=Standard_True, same=Standard_True;
170 // for (Standard_Integer k = 1; k <= 3; k += 2){
172 for ( k = 1; k <= 3; k += 2){
173 // diff = Umin<ii> - Umin<jj> : k = 1
174 // diff = Vmin<ii> - Vmin<jj> : k = 3
175 Standard_Real diff = UV(ii,k) - UV(jj,k);
176 smaller = chklarge ? (smaller && (diff > -tol)) : (smaller && (diff > 0.));
177 same = same && (Abs(diff) <= tol);
179 for (k = 2; k <= 4; k +=2){
180 // diff = Umax<ii> - Umax<jj> : k = 2
181 // diff = Vmax<ii> - Vmax<jj> : k = 4
182 Standard_Real diff = UV(ii,k) - UV(jj,k);
183 smaller = chklarge ? (smaller && (diff < tol)) : (smaller && (diff < 0.));
184 same = same && (Abs(diff) <= tol);
187 if (same) return SAME;
189 Standard_Integer sta = (ii==1) ? oneINtwo : twoINone;
196 static Standard_Integer FUN_thegreatest(const TopoDS_Face& F1, BRepClass_FaceClassifier& class2)
197 // prequesitory : p2d1 IN f2, p2d2 IN f1
199 // returns oneINtwo || twoINone || UNKNOWN
201 TopExp_Explorer ex1(F1, TopAbs_EDGE);
202 Standard_Real tolf1 = BRep_Tool::Tolerance(F1);
203 for (; ex1.More(); ex1.Next()){
204 const TopoDS_Edge& e1 = TopoDS::Edge(ex1.Current());
205 Standard_Real f1,l1; FUN_tool_bounds(e1,f1,l1);
206 Standard_Real x= 0.45678; Standard_Real p1 = (1-x)*f1+x+l1;
207 gp_Pnt2d uv1; Standard_Boolean ok1 = FUN_tool_paronEF(e1,p1,F1,uv1,tolf1);
209 TopAbs_State sta12 = class2.State();
210 if (M_IN(sta12) ) return oneINtwo;
211 else if (M_OUT(sta12)) return twoINone;
216 //=======================================================================
217 //function : Classip2d
219 //=======================================================================
221 Standard_Integer TopOpeBRepTool_CLASSI::Classip2d(const TopoDS_Shape& S1, const TopoDS_Shape& S2,
222 const Standard_Integer stabnd2d12)
224 if (!HasInit2d()) return UNKNOWN;
225 Standard_Boolean bnd2dUNK = (stabnd2d12 == UNKNOWN)||(stabnd2d12 == SAME);
227 // fa1,ffi1,finite1 :
228 TopOpeBRepTool_face fa1;
229 Standard_Boolean isb1 = mymapsface.IsBound(S1);
230 if (isb1) fa1 = mymapsface.Find(S1);
232 Standard_Boolean ok1 = fa1.Init(TopoDS::Wire(S1), myFref);
233 if (!ok1) return UNKNOWN;
234 mymapsface.Bind(S1,fa1);
236 const TopoDS_Face& ffi1 = fa1.Ffinite();
237 Standard_Boolean finite1 = fa1.Finite();
239 // fa2,ffi2,finite2 :
240 TopOpeBRepTool_face fa2;
241 Standard_Boolean isb2 = mymapsface.IsBound(S2);
242 if (isb2) fa2 = mymapsface.Find(S2);
244 Standard_Boolean ok2 = fa2.Init(TopoDS::Wire(S2), myFref);
245 if (!ok2) return UNKNOWN;
246 mymapsface.Bind(S2,fa2);
248 const TopoDS_Face& ffi2 = fa2.Ffinite();
249 Standard_Boolean finite2 = fa2.Finite();
252 Standard_Real u1,v1; Standard_Boolean ok1 = BRepClass3d_SolidExplorer::FindAPointInTheFace(ffi1,u1,v1);
253 if (!ok1) return UNKNOWN;
254 gp_Pnt2d p2d1(u1,v1);
256 // sta12 = status(p2d1 / ffi2) :
257 // recall : ffi1 and ffi2 are built on same face
258 // => ffi1(u1,v1) = ffi2(u1,v1)
259 // ----------------------------
260 Standard_Real tol2d2 = TopOpeBRepTool_TOOL::TolUV(ffi2,BRep_Tool::Tolerance(ffi2));
261 BRepClass_FaceClassifier class2(ffi2,p2d1,tol2d2);
262 TopAbs_State sta12 = class2.State();
264 // staffi12 : only if !bnd2dUNK and stabnd2d12!=DIFF
265 // PREQUESITORY : the only possible situations are
268 // - ffi1 and ffi2 are distinct
269 Standard_Integer staffi12 = UNKNOWN;
271 Standard_Boolean try21 = Standard_False;
273 try21 = Standard_True;
275 else if (stabnd2d12 == DIFF) {
279 if (sta12 == TopAbs_IN) {// 2 possible states : oneINtwo || twoINone
280 if (stabnd2d12 == oneINtwo) staffi12 = oneINtwo; //Bnd2d(S1) IN Bnd2d(S2)
281 else if (stabnd2d12 == twoINone) staffi12 = twoINone; //Bnd2d(S2) IN Bnd2d(S1)
282 else try21 = Standard_True;
284 else if (sta12 == TopAbs_OUT) {// 2 possible states : twoINone || DIFF
285 if (stabnd2d12 == twoINone) staffi12 = twoINone;
286 // else if (stabnd2d12 == DIFF) staffi12 = DIFF;
287 else try21 = Standard_True;
289 else return UNKNOWN; // NYIxpu140199
294 Standard_Real u2,v2; Standard_Boolean ok2 = BRepClass3d_SolidExplorer::FindAPointInTheFace(ffi2,u2,v2);
295 if (!ok2) return UNKNOWN;
296 gp_Pnt2d p2d2(u2,v2);
299 Standard_Real tol2d1 = TopOpeBRepTool_TOOL::TolUV(ffi1,BRep_Tool::Tolerance(ffi1));
300 BRepClass_FaceClassifier class1(ffi1,p2d2,tol2d1);
301 TopAbs_State sta21 = class1.State();
304 if (M_OUT(sta12)&& M_OUT(sta21)) staffi12 = DIFF;
305 else if (M_IN(sta12) && M_OUT(sta21)) staffi12 = oneINtwo;
306 else if (M_OUT(sta12)&& M_IN(sta21) ) staffi12 = twoINone;
307 else if (M_IN(sta12) && M_IN(sta21) ) staffi12 = ::FUN_thegreatest(ffi1,class2);
310 if (sta12 == TopAbs_IN) {// 2 possible states : oneINtwo || twoINone
311 if (sta21 == TopAbs_OUT) staffi12 = oneINtwo;
313 else if (sta12 == TopAbs_OUT) {// 2 possible states : twoINone || DIFF
314 if (sta21 == TopAbs_OUT) staffi12 = DIFF;
315 else if (sta21 == TopAbs_IN) staffi12 = twoINone;
317 else return UNKNOWN; // NYIxpu140199
322 // classif(S1,S2) knowing staffi12, finite, finite2 :
323 if (staffi12 == DIFF) {
324 if (finite1 && finite2) return DIFF;
325 if (finite1 && !finite2) return twoINone;
326 if (!finite1 && finite2) return oneINtwo;
327 return oneINtwo; // !!!!!!! or twoINone
329 else if (staffi12 == oneINtwo) {
330 if (!finite1 && !finite2) return twoINone;
333 else if (staffi12 == twoINone) {
334 if (!finite1 && !finite2) return oneINtwo;
340 //=======================================================================
343 //=======================================================================
345 Standard_Boolean TopOpeBRepTool_CLASSI::Getface(const TopoDS_Shape& S, TopOpeBRepTool_face& fa) const
347 Standard_Boolean isb = mymapsface.IsBound(S);
348 if (!isb) return Standard_False;
349 fa = mymapsface.Find(S);
350 return Standard_True;
354 //=======================================================================
355 //function : Classilist
357 //=======================================================================
359 Standard_EXPORT void FUN_addOwlw(const TopoDS_Shape& Ow, const TopTools_ListOfShape& lw, TopTools_ListOfShape& lresu)
361 Standard_Integer nw = lw.Extent();
362 if (nw == 0) lresu.Append(Ow);
364 TopTools_ListIteratorOfListOfShape it(lw);
365 for (; it.More(); it.Next()) lresu.Append(it.Value());
369 Standard_Boolean TopOpeBRepTool_CLASSI::Classilist(const TopTools_ListOfShape& lS, TopTools_DataMapOfShapeListOfShape& mapgreasma)
371 Standard_Real tolref = BRep_Tool::Tolerance(myFref);
372 Standard_Real toluv = TopOpeBRepTool_TOOL::TolUV(myFref,tolref);//nyixpu : cdliser??
373 TopTools_ListOfShape null;
375 TopTools_ListOfShape lw; lw.Assign(lS);
377 TopTools_ListIteratorOfListOfShape anIterW(lS);
378 for (; anIterW.More(); anIterW.Next()) mapgreasma.Bind(anIterW.Value(),null);
380 Standard_Integer nw = lw.Extent();
381 if (nw <= 1) return Standard_True;
383 Standard_Integer nite = 0, nitemax = Standard_Integer(nw*(nw-1)/2);
384 while (nite <= nitemax){
390 TopTools_ListIteratorOfListOfShape itw(lw);
391 for (; itw.More(); itw.Next()){
393 Standard_Boolean isb1 = mapgreasma.IsBound(wi1);
394 if (!isb1) continue; // wi1 stored as smaller shape
398 while (itw.More()) {// compare wi1 with all wi(k) (k>1)
399 Standard_Boolean isb1 = mapgreasma.IsBound(wi1);
403 if (!itw.More()) break;
406 Standard_Integer sta12 = UNKNOWN;
407 Standard_Boolean OUTall = Standard_False;
409 for (; itw.More(); itw.Next()){
411 Standard_Boolean isb2 = mapgreasma.IsBound(wi2);
414 Standard_Integer stabnd2d12 = ClassiBnd2d(wi1,wi2,toluv,Standard_True);
415 sta12 = Classip2d(wi1,wi2, stabnd2d12);
416 if (sta12 == DIFF) {OUTall = Standard_True; continue;}
421 if (sta12 == oneINtwo) {//greater = shape two
422 TopTools_ListOfShape& lwgre = mapgreasma.ChangeFind(wi2);
423 TopTools_ListOfShape lsma; FUN_addOwlw(wi1,mapgreasma.Find(wi1),lsma);
424 mapgreasma.UnBind(wi1);
427 else if (sta12 == twoINone) {//greater = shape one
428 TopTools_ListOfShape& lwgre = mapgreasma.ChangeFind(wi1);
429 TopTools_ListOfShape lsma; FUN_addOwlw(wi2,mapgreasma.Find(wi2),lsma);
430 mapgreasma.UnBind(wi2);
436 else return Standard_False;
441 return Standard_True;