b311480e |
1 | // Created on: 1996-01-30 |
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 | |
42cf5bc1 |
18 | #include <BRep_Builder.hxx> |
19 | #include <BRep_Tool.hxx> |
20 | #include <BRepExtrema_ExtPF.hxx> |
21 | #include <Extrema_ExtPS.hxx> |
22 | #include <Geom2d_Curve.hxx> |
23 | #include <Geom_Surface.hxx> |
24 | #include <GeomAdaptor_Surface.hxx> |
25 | #include <gp_Pnt2d.hxx> |
26 | #include <gp_Vec.hxx> |
27 | #include <LocOpe.hxx> |
28 | #include <LocOpe_Generator.hxx> |
7fd59977 |
29 | #include <LocOpe_GluedShape.hxx> |
42cf5bc1 |
30 | #include <LocOpe_Gluer.hxx> |
31 | #include <LocOpe_Spliter.hxx> |
7fd59977 |
32 | #include <LocOpe_WiresOnShape.hxx> |
42cf5bc1 |
33 | #include <Precision.hxx> |
34 | #include <Standard_ConstructionError.hxx> |
35 | #include <Standard_NoSuchObject.hxx> |
36 | #include <StdFail_NotDone.hxx> |
7fd59977 |
37 | #include <TopExp.hxx> |
42cf5bc1 |
38 | #include <TopExp_Explorer.hxx> |
39 | #include <TopoDS.hxx> |
40 | #include <TopoDS_Edge.hxx> |
41 | #include <TopoDS_Face.hxx> |
42 | #include <TopoDS_Shape.hxx> |
43 | #include <TopoDS_Vertex.hxx> |
7fd59977 |
44 | #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx> |
45 | #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx> |
7fd59977 |
46 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
47 | #include <TopTools_IndexedMapOfShape.hxx> |
42cf5bc1 |
48 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
7fd59977 |
49 | |
50 | static TopAbs_Orientation GetOrientation(const TopoDS_Face&, |
51 | const TopoDS_Face&); |
52 | |
53 | |
54 | static Standard_Boolean Contains(const TopTools_ListOfShape&, |
55 | const TopoDS_Shape&); |
56 | |
57 | |
58 | //======================================================================= |
59 | //function : Init |
60 | //purpose : |
61 | //======================================================================= |
62 | |
63 | void LocOpe_Gluer::Init(const TopoDS_Shape& Sbase, |
64 | const TopoDS_Shape& Snew) |
65 | { |
66 | mySb = Sbase; |
67 | mySn = Snew; |
68 | myMapEF.Clear(); |
69 | myMapEE.Clear(); |
70 | myDescF.Clear(); |
71 | myDone = Standard_False; |
72 | myOri = TopAbs_INTERNAL; |
73 | myOpe = LocOpe_INVALID; |
74 | } |
75 | |
76 | |
77 | //======================================================================= |
78 | //function : Bind |
79 | //purpose : |
80 | //======================================================================= |
81 | |
82 | void LocOpe_Gluer::Bind(const TopoDS_Face& Fnew, |
83 | const TopoDS_Face& Fbase) |
84 | { |
85 | TopExp_Explorer exp(mySn,TopAbs_FACE); |
86 | |
87 | for (; exp.More(); exp.Next()) { |
88 | if (exp.Current().IsSame(Fnew)) { |
89 | break; |
90 | } |
91 | } |
92 | if (!exp.More()) { |
9775fa61 |
93 | throw Standard_ConstructionError(); |
7fd59977 |
94 | } |
95 | |
96 | TopoDS_Shape aLocalFace = Fnew.Oriented(exp.Current().Orientation()); |
97 | TopoDS_Face Fnor = TopoDS::Face(aLocalFace); |
98 | // TopoDS_Face Fnor = TopoDS::Face(Fnew.Oriented(exp.Current().Orientation())); |
99 | |
100 | for (exp.Init(mySb,TopAbs_FACE); exp.More(); exp.Next()) { |
101 | if (exp.Current().IsSame(Fbase)) { |
102 | break; |
103 | } |
104 | } |
105 | if (!exp.More()) { |
9775fa61 |
106 | throw Standard_ConstructionError(); |
7fd59977 |
107 | } |
108 | |
109 | aLocalFace = Fbase.Oriented(exp.Current().Orientation()); |
110 | TopoDS_Face Fbor = TopoDS::Face(aLocalFace); |
111 | // TopoDS_Face Fbor = TopoDS::Face(Fbase.Oriented(exp.Current().Orientation())); |
112 | TopAbs_Orientation Ori = GetOrientation(Fnor,Fbor); |
113 | |
114 | if (myOri == TopAbs_INTERNAL) { |
115 | myOri = Ori; |
116 | if (myOri == TopAbs_REVERSED) { |
117 | mySn.Reverse(); |
118 | myOpe = LocOpe_CUT; |
119 | } |
120 | else { |
121 | myOpe = LocOpe_FUSE; |
122 | } |
123 | } |
124 | else if (Ori != TopAbs_FORWARD) { |
125 | myOpe = LocOpe_INVALID; |
126 | } |
127 | |
128 | for (exp.Init(Fnor, TopAbs_EDGE); exp.More(); exp.Next()) { |
129 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
130 | // if (!myMapEF.IsBound(edg)) { |
131 | // myMapEF.Bind(edg,Fbor); |
132 | if (!myMapEF.Contains(edg)) { |
133 | myMapEF.Add(edg,Fbor); |
134 | } |
135 | // else if (!myMapEF(edg).IsSame(Fbor)) { |
136 | else if (!myMapEF.FindFromKey(edg).IsSame(Fbor)) { |
137 | // myMapEF.UnBind(edg); // edg sur 2 face. a binder avec l`edge commun |
138 | myMapEF.ChangeFromKey(edg).Nullify(); |
139 | // edg sur 2 face. a binder avec l`edge commun |
140 | } |
141 | } |
142 | // myMapEF.Bind(Fnor,Fbor); |
143 | myMapEF.Add(Fnor,Fbor); |
144 | } |
145 | |
146 | |
147 | //======================================================================= |
148 | //function : Bind |
149 | //purpose : |
150 | //======================================================================= |
151 | |
152 | void LocOpe_Gluer::Bind(const TopoDS_Edge& Enew, |
153 | const TopoDS_Edge& Ebase) |
154 | { |
155 | if (myMapEE.IsBound(Enew) && !myMapEE(Enew).IsSame(Ebase)) { |
9775fa61 |
156 | throw Standard_ConstructionError(); |
7fd59977 |
157 | } |
158 | myMapEE.Bind(Enew,Ebase); |
159 | } |
160 | |
161 | |
162 | //======================================================================= |
163 | //function : Perform |
164 | //purpose : |
165 | //======================================================================= |
166 | |
167 | void LocOpe_Gluer::Perform() |
168 | { |
169 | Standard_Integer ind ; |
170 | if (myDone) { |
171 | return; |
172 | } |
173 | if (mySb.IsNull() || mySn.IsNull() || |
174 | myMapEF.IsEmpty() || myOpe ==LocOpe_INVALID) { |
9775fa61 |
175 | throw Standard_ConstructionError(); |
7fd59977 |
176 | } |
177 | |
178 | Handle(LocOpe_WiresOnShape) theWOnS = new LocOpe_WiresOnShape(mySb); |
179 | Handle(LocOpe_GluedShape) theGS = new LocOpe_GluedShape(mySn); |
180 | |
181 | Standard_Integer lmap = myMapEF.Extent(); |
182 | |
183 | for ( ind = 1; ind <= lmap; ind++) { |
184 | TopoDS_Shape S = myMapEF.FindKey(ind); |
185 | if (S.ShapeType() == TopAbs_EDGE) { |
186 | TopoDS_Shape S2 = myMapEF(ind); |
187 | if (!S2.IsNull()) { |
188 | theWOnS->Bind(TopoDS::Edge(S), TopoDS::Face(S2)); |
189 | } |
190 | } |
191 | else { // TopAbs_FACE |
192 | theGS->GlueOnFace(TopoDS::Face(S)); |
193 | } |
194 | } |
195 | |
196 | TopTools_DataMapIteratorOfDataMapOfShapeShape itm(myMapEE); |
197 | for (; itm.More(); itm.Next()) { |
198 | theWOnS->Bind(TopoDS::Edge(itm.Key()), TopoDS::Edge(itm.Value())); |
199 | } |
200 | |
201 | theWOnS->BindAll(); |
202 | |
203 | if (!theWOnS->IsDone()) { |
204 | return; |
205 | } |
206 | |
207 | LocOpe_Spliter theSplit(mySb); |
208 | theSplit.Perform(theWOnS); |
209 | if (!theSplit.IsDone()) { |
210 | return; |
211 | } |
212 | // Mise a jour des descendants |
213 | // for (TopExp_Explorer exp(mySb,TopAbs_FACE); exp.More(); exp.Next()) { |
214 | TopExp_Explorer exp(mySb,TopAbs_FACE) ; |
215 | for ( ; exp.More(); exp.Next()) { |
216 | myDescF.Bind(exp.Current(),theSplit.DescendantShapes(exp.Current())); |
217 | } |
218 | |
219 | for (exp.Init(mySn,TopAbs_FACE); exp.More(); exp.Next()) { |
220 | TopTools_ListOfShape thelist; |
221 | myDescF.Bind(exp.Current(), thelist); |
222 | if (Contains(theGS->OrientedFaces(),exp.Current())) { |
223 | myDescF(exp.Current()).Append(exp.Current()); |
224 | } |
225 | } |
226 | |
227 | LocOpe_Generator theGen(theSplit.ResultingShape()); |
228 | theGen.Perform(theGS); |
229 | |
230 | myDone = theGen.IsDone(); |
231 | if (myDone) { |
232 | myRes = theGen.ResultingShape(); |
233 | |
234 | AddEdges(); |
235 | |
236 | // Mise a jour des descendants |
237 | TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itd; |
238 | for (itd.Initialize(myDescF); |
239 | itd.More(); |
240 | itd.Next()) { |
241 | TopTools_ListOfShape newDesc; |
242 | TopTools_ListIteratorOfListOfShape itl; |
243 | for (itl.Initialize(itd.Value()); |
244 | itl.More(); |
245 | itl.Next()) { |
246 | TopTools_ListIteratorOfListOfShape itl2 |
247 | (theGen.DescendantFace(TopoDS::Face(itl.Value()))); |
248 | for (; itl2.More(); itl2.Next()) { |
249 | const TopoDS_Face& descface =TopoDS::Face(itl2.Value()); |
250 | if (!descface.IsNull()) { // sinon la face a disparu |
251 | newDesc.Append(descface); |
252 | } |
253 | } |
254 | } |
255 | myDescF(itd.Key()) = newDesc; |
256 | } |
257 | } |
258 | |
259 | // recodage des regularites |
260 | TopTools_IndexedDataMapOfShapeListOfShape theMapEF1, theMapEF2; |
261 | TopExp::MapShapesAndAncestors(mySn,TopAbs_EDGE,TopAbs_FACE,theMapEF1); |
262 | TopExp::MapShapesAndAncestors(myRes,TopAbs_EDGE,TopAbs_FACE,theMapEF2); |
263 | |
264 | for (ind = 1; ind <= theMapEF1.Extent(); ind++) { |
265 | const TopoDS_Edge& edg = TopoDS::Edge(theMapEF1.FindKey(ind)); |
266 | const TopTools_ListOfShape& LL = theMapEF1(ind); |
267 | if (LL.Extent() == 2) { |
268 | const TopoDS_Face& fac1 = TopoDS::Face(LL.First()); |
269 | const TopoDS_Face& fac2 = TopoDS::Face(LL.Last()); |
270 | GeomAbs_Shape thecont = BRep_Tool::Continuity(edg,fac1,fac2); |
271 | if (thecont >= GeomAbs_G1) { |
272 | // on essaie de recoder |
273 | Standard_Integer ind2 = theMapEF2.FindIndex(edg); |
274 | if (ind2 != 0) { |
275 | const TopTools_ListOfShape& LL2 = theMapEF2(ind2); |
276 | if (LL2.Extent() == 2) { |
277 | const TopoDS_Face& ff1 = TopoDS::Face(LL2.First()); |
278 | const TopoDS_Face& ff2 = TopoDS::Face(LL2.Last()); |
279 | if ((ff1.IsSame(fac1) && ff2.IsSame(fac2)) || |
280 | (ff1.IsSame(fac2) && ff2.IsSame(fac1))) { |
281 | |
282 | } |
283 | else { |
284 | BRep_Builder B; |
285 | B.Continuity(edg, ff1,ff2,thecont); |
286 | } |
287 | } |
288 | } |
289 | } |
290 | } |
291 | } |
292 | //creation de la liste d`edge |
293 | theWOnS->InitEdgeIterator(); |
294 | while(theWOnS->MoreEdge()) { |
295 | TopoDS_Edge edg = theWOnS->Edge(); |
296 | for (ind = 1; ind <= theMapEF2.Extent(); ind++) { |
297 | const TopoDS_Edge& edg1 = TopoDS::Edge(theMapEF2.FindKey(ind)); |
298 | if(edg1.IsSame(edg)) { |
299 | myEdges.Append(edg); |
300 | // recodage eventuel des regularites sur cet edge |
301 | const TopTools_ListOfShape& L = theMapEF2(ind); |
302 | if (L.Extent() == 2) { |
303 | const TopoDS_Face& fac1 = TopoDS::Face(L.First()); |
304 | const TopoDS_Face& fac2 = TopoDS::Face(L.Last()); |
305 | if(LocOpe::TgtFaces(edg, fac1, fac2)) { |
306 | myTgtEdges.Append(edg); |
307 | GeomAbs_Shape thecont = BRep_Tool::Continuity(edg,fac1,fac2); |
308 | if (thecont < GeomAbs_G1) { |
309 | BRep_Builder B; |
310 | B.Continuity(edg, fac1,fac2,GeomAbs_G1); |
311 | } |
312 | } |
313 | } |
314 | } |
315 | } |
316 | theWOnS->NextEdge(); |
317 | } |
318 | |
319 | // recodage eventuel des regularites sur cet edge |
320 | } |
321 | |
322 | |
323 | |
324 | |
325 | //======================================================================= |
326 | //function : DescendantFaces |
327 | //purpose : |
328 | //======================================================================= |
329 | |
330 | const TopTools_ListOfShape& LocOpe_Gluer::DescendantFaces |
331 | (const TopoDS_Face& F) const |
332 | { |
9775fa61 |
333 | if (!myDone) {throw StdFail_NotDone();} |
7fd59977 |
334 | if (myDescF.IsBound(F)) |
335 | return myDescF(F); |
336 | static TopTools_ListOfShape nullList; |
337 | return nullList; |
338 | } |
339 | |
340 | |
341 | |
342 | //======================================================================= |
343 | //function : GetOrientation |
344 | //purpose : |
345 | //======================================================================= |
346 | |
347 | static TopAbs_Orientation GetOrientation(const TopoDS_Face& Fn, |
348 | const TopoDS_Face& Fb) |
349 | { |
350 | |
351 | Handle(Geom_Surface) Sn,Sb; |
352 | Sn = BRep_Tool::Surface(Fn); |
353 | Sb = BRep_Tool::Surface(Fb); |
354 | |
355 | |
356 | // Find a point on Sb |
357 | TopExp_Explorer exp; |
358 | Standard_Real f,l; |
359 | gp_Pnt2d ptvtx; |
360 | gp_Pnt pvt; |
361 | gp_Vec d1u,d1v, n1,n2; |
362 | |
363 | |
364 | for (exp.Init(Fn,TopAbs_EDGE); exp.More(); exp.Next()) { |
365 | const TopoDS_Edge& edg = TopoDS::Edge(exp.Current()); |
366 | Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,Fn,f,l); |
367 | if (Precision::IsNegativeInfinite(f) && |
368 | Precision::IsPositiveInfinite(l)) { |
369 | f = -100.; |
370 | l = 100.; |
371 | } |
372 | else if (Precision::IsNegativeInfinite(f)) { |
373 | f = l-200.; |
374 | } |
375 | else if (Precision::IsPositiveInfinite(l)) { |
376 | l = f+200.; |
377 | } |
378 | Standard_Real deltau = (l-f)/20.; |
379 | for (Standard_Integer i=1; i<=21; i++) { |
380 | C2d->D0(f+(i-1)*deltau,ptvtx); |
381 | Sn->D1(ptvtx.X(),ptvtx.Y(),pvt,d1u,d1v); |
382 | n1 = d1u.Crossed(d1v); |
383 | if (n1.Magnitude() > Precision::Confusion() ) { |
384 | n1.Normalize(); |
385 | if (Fn.Orientation() == TopAbs_REVERSED) { |
386 | n1.Reverse(); |
387 | } |
388 | |
389 | // Projection sur Sb |
390 | GeomAdaptor_Surface GAS(Sb); |
391 | Standard_Real TolU = GAS.UResolution(Precision::Confusion()); |
392 | Standard_Real TolV = GAS.VResolution(Precision::Confusion()); |
393 | Extrema_ExtPS dist(pvt,GAS,TolU,TolV); |
394 | if (dist.IsDone()) { |
395 | Standard_Real dist2min = RealLast(); |
396 | Standard_Integer jmin = 0; |
397 | for (Standard_Integer j=1; j<=dist.NbExt(); j++) { |
398 | if (dist.SquareDistance(j)<dist2min) { |
399 | jmin = j; |
400 | dist2min = dist.SquareDistance(j); |
401 | } |
402 | } |
403 | if (jmin != 0) { |
404 | Standard_Real uu,vv; |
405 | dist.Point(jmin).Parameter(uu,vv); |
406 | Sb->D1(uu,vv,pvt,d1u,d1v); |
407 | n2 = d1u.Crossed(d1v); |
408 | if (n2.Magnitude() > Precision::Confusion()) { |
409 | n2.Normalize(); |
410 | if (Fb.Orientation() == TopAbs_REVERSED) { |
411 | n2.Reverse(); |
412 | } |
413 | if (n1.Dot(n2) > 0.) { |
414 | return TopAbs_REVERSED; |
415 | } |
416 | return TopAbs_FORWARD; |
417 | } |
418 | } |
419 | } |
420 | } |
421 | } |
422 | } |
423 | return TopAbs_INTERNAL; |
424 | } |
425 | |
426 | |
427 | //======================================================================= |
428 | //function : GetOrientation |
429 | //purpose : |
430 | //======================================================================= |
431 | |
432 | static Standard_Boolean Contains(const TopTools_ListOfShape& L, |
433 | const TopoDS_Shape& S) |
434 | { |
435 | TopTools_ListIteratorOfListOfShape it; |
436 | for (it.Initialize(L); |
437 | it.More(); |
438 | it.Next()) { |
439 | if (it.Value().IsSame(S)) { |
440 | return Standard_True; |
441 | } |
442 | } |
443 | return Standard_False; |
444 | } |
445 | |
446 | |
447 | |
448 | |
449 | |
450 | //======================================================================= |
451 | //function : AddEdges |
452 | //purpose : |
453 | //======================================================================= |
454 | |
455 | void LocOpe_Gluer::AddEdges() |
456 | { |
457 | TopExp_Explorer exp, expsb; |
458 | exp.Init(mySn, TopAbs_EDGE); |
459 | |
460 | TopLoc_Location Loc; |
461 | // Standard_Real l, f; |
462 | TopTools_IndexedMapOfShape MapV, MapFPrism, MapE; |
463 | TopExp_Explorer vexp; |
464 | Standard_Integer flag, i; |
465 | |
466 | TopExp::MapShapes(mySn, TopAbs_FACE, MapFPrism); |
467 | |
468 | for (expsb.Init(myRes, TopAbs_FACE); expsb.More(); expsb.Next()) { |
469 | if (!MapFPrism.Contains(expsb.Current())) { |
470 | MapV.Clear(); |
471 | TopExp::MapShapes(expsb.Current(), TopAbs_VERTEX, MapV); |
472 | TopExp::MapShapes(expsb.Current(), TopAbs_EDGE, MapE); |
473 | for(exp.Init(mySn, TopAbs_EDGE); exp.More(); exp.Next()) { |
474 | TopoDS_Edge e = TopoDS::Edge(exp.Current()); |
475 | if (MapE.Contains(e)) continue; |
476 | flag = 0; |
477 | vexp.Init(e, TopAbs_VERTEX); |
478 | for(; vexp.More(); vexp.Next()) { |
479 | TopoDS_Vertex v = TopoDS::Vertex(vexp.Current()); |
480 | if (MapV.Contains(v)) { |
481 | flag = 1; |
482 | } |
483 | } |
484 | if (flag == 1) { |
485 | |
486 | vexp.Init(e, TopAbs_VERTEX); |
487 | BRepExtrema_ExtPF ext; |
488 | ext.Initialize(TopoDS::Face(expsb.Current())); |
489 | flag = 0; |
490 | for(; vexp.More(); vexp.Next()) { |
491 | TopoDS_Vertex v = TopoDS::Vertex(vexp.Current()); |
492 | if (!MapV.Contains(v)) { |
493 | ext.Perform(v, TopoDS::Face(expsb.Current())); |
494 | if (!ext.IsDone() || ext.NbExt() == 0) { flag = 0; break;} |
495 | else { |
496 | Standard_Real dist2min = ext.SquareDistance(1); |
497 | for (i = 2; i <= ext.NbExt(); i++) { |
498 | dist2min = Min(dist2min, ext.SquareDistance(i)); |
499 | } |
500 | if (dist2min >= BRep_Tool::Tolerance(v) * BRep_Tool::Tolerance(v)) { |
501 | flag = 0; |
502 | break; |
503 | } |
504 | else flag = 1; |
505 | } |
506 | } |
507 | else flag = 1; |
508 | } |
509 | if (flag == 1) { |
510 | |
511 | } |
512 | } |
513 | } |
514 | } |
515 | } |
516 | |
517 | |
518 | } |
519 | |