0025243: BRepFeat_SplitShape algorithm processes incorrect faces with degenerated...
[occt.git] / src / LocOpe / LocOpe_Spliter.cxx
CommitLineData
b311480e 1// Created on: 1996-01-09
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
17// Modified by skv - Mon May 31 12:34:09 2004 OCC5865
18
19#include <LocOpe_Spliter.ixx>
20
59af51e3 21//#include <LocOpe_ProjectedWires.hxx>
7fd59977 22
23#include <TopTools_MapOfShape.hxx>
24#include <TopTools_DataMapOfShapeShape.hxx>
59af51e3 25#include <TopTools_IndexedMapOfShape.hxx>
7fd59977 26#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
59af51e3 27#include <TopTools_SequenceOfShape.hxx>
7fd59977 28#include <TopTools_ListIteratorOfListOfShape.hxx>
29#include <TopTools_MapIteratorOfMapOfShape.hxx>
30#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
31#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
32#include <TopExp_Explorer.hxx>
33#include <TopoDS_Iterator.hxx>
34#include <TopoDS_Vertex.hxx>
35#include <TopoDS_Edge.hxx>
36#include <TopoDS_Wire.hxx>
37#include <TopoDS_Face.hxx>
38
39#include <LocOpe_BuildWires.hxx>
40
41#include <gp_Vec2d.hxx>
42#include <gp_Vec.hxx>
43#include <Geom_Curve.hxx>
44#include <GeomAPI_ProjectPointOnCurve.hxx>
45#include <BRep_Tool.hxx>
46
47#include <BRepTools_Substitution.hxx>
48#include <LocOpe_SplitShape.hxx>
49
50#include <BRep_Builder.hxx>
51
52#include <TopoDS.hxx>
53#include <TopExp.hxx>
54
55#include <Standard_ConstructionError.hxx>
56
57
58// Modified by skv - Mon May 31 13:00:30 2004 OCC5865 Begin
59// static void RebuildWires(TopTools_ListOfShape&);
60static void RebuildWires(TopTools_ListOfShape&,
59af51e3 61 const Handle(LocOpe_WiresOnShape)&);
7fd59977 62// Modified by skv - Mon May 31 13:00:31 2004 OCC5865 End
63
64static void Put(const TopoDS_Shape&,
65 TopTools_DataMapOfShapeListOfShape&);
66
67static void Select(const TopoDS_Edge&,
68 TopTools_ListOfShape&);
69
70
71//=======================================================================
72//function : Perform
73//purpose :
74//=======================================================================
75
59af51e3 76void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW)
7fd59977 77{
78 if (myShape.IsNull()) {
79 Standard_NullObject::Raise();
80 }
81 myDone = Standard_False;
82 myMap.Clear();
83 myRes.Nullify();
84
85 Put(myShape,myMap);
86
87 TopTools_MapOfShape mapV,mapE;
88 TopTools_DataMapOfShapeShape EdgOnEdg;
89 TopTools_IndexedDataMapOfShapeListOfShape mapFE;
90 TopExp_Explorer exp,exp2;
91
92 // 1ere etape : substitution des vertex
93
94 TopoDS_Vertex Vb;
95 TopTools_ListOfShape lsubs;
96 BRepTools_Substitution theSubs;
97 BRep_Builder BB;
98
99 for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
100 const TopoDS_Edge& edg = PW->Edge();
101 mapE.Add(edg);
102 for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
103 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
104 if (!mapV.Contains(vtx)) {
105 if (PW->OnVertex(vtx,Vb)) {
106 mapV.Add(vtx);
107 lsubs.Clear();
108 TopoDS_Vertex vsub = TopoDS::Vertex(vtx.Oriented(TopAbs_FORWARD));
109 gp_Pnt p1 = BRep_Tool::Pnt(vsub), p2 = BRep_Tool::Pnt(Vb);
110 Standard_Real d = p1.Distance(p2);
111 d = d + BRep_Tool::Tolerance(Vb);
112 BB.UpdateVertex(vsub, d);
113 lsubs.Append(vsub);
114 theSubs.Substitute(Vb.Oriented(TopAbs_FORWARD),lsubs);
115 }
116
117 }
118 }
119 }
120
121 theSubs.Build(myShape);
122 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdesc(myMap);
123 if (theSubs.IsCopied(myShape)) {
124 // on n`a fait que des substitutions de vertex. Donc chaque element
125 // est remplace par lui meme ou par un seul element du meme type.
126 for (; itdesc.More(); itdesc.Next()) {
127 if (theSubs.IsCopied(itdesc.Key())) {
128 const TopTools_ListOfShape& lsub = theSubs.Copy(itdesc.Key());
129#ifdef DEB
130 if (lsub.Extent() != 1) {
131 Standard_ConstructionError::Raise();
132 }
133#endif
134 myMap(itdesc.Key()).Clear();
135 myMap(itdesc.Key()).Append(lsub.First());
136 }
137 }
138 }
139
140 myRes = myMap(myShape).First();
141 LocOpe_SplitShape theCFace(myRes);
142
143 // Adds every vertices lying on an edge of the shape, and prepares
144 // work to rebuild wires on each face
145 TopoDS_Edge Ed;
146 Standard_Real prm;
147
ed60a55e 148 TopTools_MapOfShape theFacesWithSection;
7fd59977 149 for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
150 const TopoDS_Edge& edg = PW->Edge();
151 for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
152 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
153 if (!mapV.Contains(vtx)) {
154 mapV.Add(vtx);
59af51e3 155 if (PW->OnEdge(vtx,edg,Ed,prm)) {
7fd59977 156 // on devrait verifier que le vtx n`existe pas deja sur l`edge
157 if(!myMap.IsBound(Ed)) continue;
158 Ed = TopoDS::Edge(myMap(Ed).First());
159 theCFace.Add(vtx,prm,Ed);
160 }
161 }
162 }
163 TopoDS_Edge Ebis;
164 if (PW->OnEdge(Ebis)) {
165 // Ebis = TopoDS::Edge(myMap(Ebis).First());
166 EdgOnEdg.Bind(edg,Ebis);
167 }
168 else {
169 TopoDS_Face fac = PW->OnFace();
ed60a55e 170 if(!myMap.IsBound(fac)) continue;
171 Standard_Boolean IsFaceWithSec = PW->IsFaceWithSection(fac);
7fd59977 172 fac = TopoDS::Face(myMap(fac).First());
ed60a55e 173 if (IsFaceWithSec)
174 theFacesWithSection.Add(fac);
7fd59977 175 if (!mapFE.Contains(fac)) {
176 TopTools_ListOfShape thelist;
177 mapFE.Add(fac, thelist);
178 }
179 mapFE.ChangeFromKey(fac).Append(edg);
180 }
181 }
182
183 // Rebuilds wires on each face of the shape
184
185 TopTools_ListIteratorOfListOfShape itl;
186 for (Standard_Integer i=1; i<=mapFE.Extent(); i++) {
187 const TopoDS_Face& fac = TopoDS::Face(mapFE.FindKey(i));
188 TopTools_ListOfShape& ledges = mapFE(i);
189// Modified by skv - Mon May 31 12:32:54 2004 OCC5865 Begin
190// RebuildWires(ledges);
191 RebuildWires(ledges, PW);
192// Modified by skv - Mon May 31 12:32:54 2004 OCC5865 End
ed60a55e 193 if (theFacesWithSection.Contains(fac))
194 theCFace.Add(ledges, fac);
195 else
196 for (itl.Initialize(ledges); itl.More(); itl.Next())
197 theCFace.Add(TopoDS::Wire(itl.Value()),fac);
7fd59977 198 }
199
200
201 // Mise a jour des descendants
202
203 for (itdesc.Reset(); itdesc.More(); itdesc.Next()) {
204 const TopoDS_Shape& sori = itdesc.Key();
205 const TopoDS_Shape& scib = itdesc.Value().First();
206 myMap(sori) = theCFace.DescendantShapes(scib);
207 }
208
209 const TopTools_ListOfShape& lres = myMap(myShape);
210
211 TopAbs_ShapeEnum typS = myShape.ShapeType();
212 if (typS == TopAbs_FACE && lres.Extent() >=2) {
213 BRep_Builder B;
214 myRes.Nullify();
215 B.MakeShell(TopoDS::Shell(myRes));
216 myRes.Orientation(TopAbs_FORWARD);
217 for (itl.Initialize(lres); itl.More(); itl.Next()) {
218 B.Add(myRes,itl.Value().Oriented(myShape.Orientation()));
219 }
220 }
221 else if (typS == TopAbs_EDGE && lres.Extent() >=2) {
222 BRep_Builder B;
223 myRes.Nullify();
224 B.MakeWire(TopoDS::Wire(myRes));
225 myRes.Orientation(TopAbs_FORWARD);
226 for (itl.Initialize(lres); itl.More(); itl.Next()) {
227 B.Add(myRes,itl.Value().Oriented(myShape.Orientation()));
228 }
229 }
230 else {
231 if (lres.Extent() != 1) {
232 return;
233 }
234 myRes = lres.First();
235 }
236
237 theSubs.Clear();
238 for (TopTools_DataMapIteratorOfDataMapOfShapeShape itee(EdgOnEdg);
239 itee.More();
240 itee.Next()) {
241 const TopoDS_Edge& e1 = TopoDS::Edge(itee.Key());
242 // on recherche dans les descendants de e2 l`edge qui correspont a e1
243
244 TopoDS_Vertex vf1,vl1,vf2,vl2;
245 TopExp::Vertices(e1,vf1,vl1);
246 lsubs.Clear();
247 for (itl.Initialize(myMap(itee.Value()));
248 itl.More();
249 itl.Next()) {
250 const TopoDS_Edge& e2 = TopoDS::Edge(itl.Value());
251 TopExp::Vertices(e2,vf2,vl2);
252
253 if (!vl1.IsSame(vf1)) {
254 if (vf1.IsSame(vf2) && vl1.IsSame(vl2)) {
255 lsubs.Append(e2.Oriented(TopAbs_FORWARD));
256 // break;
257 }
258 else if (vf1.IsSame(vl2) && vl1.IsSame(vf2)) {
259 lsubs.Append(e2.Oriented(TopAbs_REVERSED));
260 // break;
261 }
262 }
263 else { // discrimination sur les tangentes
264 if (vf2.IsSame(vl2) && vl2.IsSame(vl1)) { // tout au meme point
265 TopLoc_Location Loc;
266 Standard_Real f,l;
267 gp_Pnt pbid;
268 gp_Vec v1,v2;
269 Handle(Geom_Curve) C = BRep_Tool::Curve(e1,Loc,f,l);
270 C->D1(f,pbid,v1);
271 v1.Transform(Loc.Transformation());
272
273 C = BRep_Tool::Curve(e2,Loc,f,l);
274 C->D1(f,pbid,v2);
275 v2.Transform(Loc.Transformation());
276 if (v1.Dot(v2) >0.) {
277 lsubs.Append(e2.Oriented(TopAbs_FORWARD));
278 }
279 else {
280 lsubs.Append(e2.Oriented(TopAbs_REVERSED));
281 }
282 }
283 }
284
285 }
286 if (lsubs.Extent() >= 2) { // il faut faire un choix
287 Select(e1,lsubs);
288 }
289 if (lsubs.Extent() == 1) {
290 TopoDS_Shape ebase = lsubs.First();
291 lsubs.Clear();
292 lsubs.Append(e1.Oriented(ebase.Orientation()));
293 theSubs.Substitute(ebase.Oriented(TopAbs_FORWARD),lsubs);
294 }
295 else {
296#ifdef DEB
297 cout << "Pb pour substitution" << endl;
298#endif
299 }
300 }
301
302 theSubs.Build(myRes);
303
304 for (itdesc.Reset(); itdesc.More(); itdesc.Next()) {
305 TopTools_ListOfShape& ldesc = myMap(itdesc.Key());
306 TopTools_ListOfShape newdesc;
307 for (itl.Initialize(ldesc); itl.More(); itl.Next()) {
308 if (theSubs.IsCopied(itl.Value())) {
309 const TopTools_ListOfShape& lsub = theSubs.Copy(itl.Value());
310#ifdef DEB
311 if (lsub.Extent() != 1) {
312 Standard_ConstructionError::Raise();
313 }
314#endif
315 newdesc.Append(lsub.First());
316 }
317 else {
318 newdesc.Append(itl.Value());
319 }
320 }
321 myMap(itdesc.Key()) = newdesc;
322 }
323
324 if (theSubs.IsCopied(myRes)) {
325 myRes = theSubs.Copy(myRes).First();
326 }
327
59af51e3 328 ////remove superfluous vertices on degenerated edges
329 theSubs.Clear();
330 TopTools_IndexedMapOfShape Emap;
331 TopExp::MapShapes(myRes, TopAbs_EDGE, Emap);
332 TopTools_SequenceOfShape DegEdges;
333 Standard_Integer i, j;
334 for (i = 1; i <= Emap.Extent(); i++)
335 {
336 const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(i));
337 if (BRep_Tool::Degenerated(anEdge))
338 DegEdges.Append(anEdge);
339 }
340
341 TopTools_SequenceOfShape DegWires;
342 for (;;)
343 {
344 if (DegEdges.IsEmpty())
345 break;
346 TopoDS_Wire aDegWire;
347 BB.MakeWire(aDegWire);
348 BB.Add(aDegWire, DegEdges(1));
349 DegEdges.Remove(1);
350 TopoDS_Vertex Vfirst, Vlast;
351 for (;;)
352 {
353 TopExp::Vertices(aDegWire, Vfirst, Vlast);
354 Standard_Boolean found = Standard_False;
355 for (i = 1; i <= DegEdges.Length(); i++)
356 {
357 const TopoDS_Edge& anEdge = TopoDS::Edge(DegEdges(i));
358 TopoDS_Vertex V1, V2;
359 TopExp::Vertices(anEdge, V1, V2);
360 if (V1.IsSame(Vfirst) || V1.IsSame(Vlast) || V2.IsSame(Vfirst) || V2.IsSame(Vlast))
361 {
362 BB.Add(aDegWire, anEdge);
363 DegEdges.Remove(i);
364 found = Standard_True;
365 break;
366 }
367 }
368 if (!found)
369 break;
370 }
371 DegWires.Append(aDegWire);
372 }
373
374 for (i = 1; i <= DegWires.Length(); i++)
375 {
376 TopTools_IndexedMapOfShape Vmap;
377 TopExp::MapShapes(DegWires(i), TopAbs_VERTEX, Vmap);
378 TopTools_ListOfShape LV;
379 LV.Append(Vmap(1).Oriented(TopAbs_FORWARD));
380 for (j = 2; j <= Vmap.Extent(); j++)
381 {
382 if (!Vmap(j).IsSame(Vmap(1)))
383 theSubs.Substitute(Vmap(j), LV);
384 }
385 }
386 theSubs.Build(myRes);
387 if (theSubs.IsCopied(myRes))
388 myRes = theSubs.Copy(myRes).First();
389 ////
390
7fd59977 391 myDLeft.Clear();
392 myLeft.Clear();
393 mapV.Clear();
394
395 TopTools_MapIteratorOfMapOfShape itms;
396
397 for (exp.Init(myRes, TopAbs_FACE); exp.More(); exp.Next()) {
398 const TopoDS_Face& fac = TopoDS::Face(exp.Current());
399 for (exp2.Init(fac,TopAbs_EDGE); exp2.More(); exp2.Next()) {
400 const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
401 for (itms.Initialize(mapE);
402 itms.More(); itms.Next()) {
403 if (itms.Key().IsSame(edg) &&
404 edg.Orientation() == itms.Key().Orientation()) {
405 break;
406 }
407 }
408 if (itms.More()) {
409 break;
410 }
411 }
412 if (exp2.More()) {
413 myDLeft.Append(fac);
414 myLeft.Append(fac);
415 }
416 else {
417 mapV.Add(fac);
418 }
419 }
420
421/* JAG : Ne peut pas marcher
422
423 Standard_Boolean full = mapV.IsEmpty();
424 while (!full) {
425 full = Standard_True;
426 itms.Initialize(mapV);
427 const TopoDS_Face& fac = TopoDS::Face(itms.Key());
428 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
429 if (!mapE.Contains(exp.Current())) {
430 for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
431 const TopoDS_Face& fac2 = TopoDS::Face(itl.Value());
432 for (exp2.Init(fac2,TopAbs_EDGE); exp2.More(); exp2.Next()) {
433 if (exp2.Current().IsSame(exp.Current())) {
434 myLeft.Append(fac);
435 mapV.Remove(fac);
436 full = mapV.IsEmpty();
437 break;
438 }
439 }
440 if (exp2.More()) {
441 break;
442 }
443 }
444 if (itl.More()) {
445 break;
446 }
447 }
448 }
449 }
450*/
451
452 // Map des edges ou les connexions sont possibles
453 TopTools_MapOfShape Mapebord;
454 for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
455 for (exp.Init(itl.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
456 if (!mapE.Contains(exp.Current())) {
457 if (!Mapebord.Add(exp.Current())) {
458 Mapebord.Remove(exp.Current());
459 }
460 }
461 }
462 }
463
464
465 while (Mapebord.Extent() != 0) {
466 itms.Initialize(Mapebord);
467 TopoDS_Shape edg = itms.Key();
468
469 for (itms.Initialize(mapV); itms.More(); itms.Next()) {
470 const TopoDS_Shape& fac = itms.Key();
471 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
472 if (exp.Current().IsSame(edg)) {
473 break;
474 }
475 }
476 if (exp.More()) {
477 break; // face a gauche
478 }
479 }
480 if (itms.More()) {
481 TopoDS_Shape fac = itms.Key();
482 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
483 if (!Mapebord.Add(exp.Current())) {
484 Mapebord.Remove(exp.Current());
485 }
486 }
487 mapV.Remove(fac);
488 myLeft.Append(fac);
489 }
490 else {
491 Mapebord.Remove(edg);
492 }
493 }
494
495 myDone = Standard_True;
496}
497
498
499//=======================================================================
500//function : DescendantShapes
501//purpose :
502//=======================================================================
503
504const TopTools_ListOfShape& LocOpe_Spliter::
505 DescendantShapes(const TopoDS_Shape& F)
506{
507 if (!myDone) {StdFail_NotDone::Raise();}
508 if (myMap.IsBound(F))
509 return myMap(F);
510 else {
511 static TopTools_ListOfShape empty;
512 return empty;
513 }
514}
515
516
517//=======================================================================
518//function : DirectLeft
519//purpose :
520//=======================================================================
521
522const TopTools_ListOfShape& LocOpe_Spliter::DirectLeft() const
523{
524 if (!myDone) {StdFail_NotDone::Raise();}
525 return myDLeft;
526
527}
528
529
530//=======================================================================
531//function : Left
532//purpose :
533//=======================================================================
534
535const TopTools_ListOfShape& LocOpe_Spliter::Left() const
536{
537 if (!myDone) {StdFail_NotDone::Raise();}
538 return myLeft;
539
540}
541
542
543//=======================================================================
544//function : RebuildWires
545//purpose :
546//=======================================================================
547
548// Modified by skv - Mon May 31 12:31:39 2004 OCC5865 Begin
549//static void RebuildWires(TopTools_ListOfShape& ledge)
550static void RebuildWires(TopTools_ListOfShape& ledge,
59af51e3 551 const Handle(LocOpe_WiresOnShape)& PW)
7fd59977 552{
553 LocOpe_BuildWires theBuild(ledge, PW);
554// Modified by skv - Mon May 31 12:31:40 2004 OCC5865 End
555 if (!theBuild.IsDone()) {
556 Standard_ConstructionError::Raise();
557 }
558 ledge = theBuild.Result();
559
560
561}
562
563
564
565//=======================================================================
566//function : Put
567//purpose :
568//=======================================================================
569
570static void Put(const TopoDS_Shape& S,
571 TopTools_DataMapOfShapeListOfShape& theMap)
572{
573 if (theMap.IsBound(S)) {
574 return;
575 }
576 TopTools_ListOfShape thelist;
577 theMap.Bind(S, thelist);
578 theMap(S).Append(S);
579 for (TopoDS_Iterator it(S); it.More(); it.Next()) {
580 Put(it.Value(),theMap);
581 }
582}
583
584
585//=======================================================================
586//function : Select
587//purpose :
588//=======================================================================
589
590static void Select(const TopoDS_Edge& Ebase,
591 TopTools_ListOfShape& lsubs)
592{
593
594 // Choix d`un point
595
596 Handle(Geom_Curve) C;
597 TopLoc_Location Loc;
598 Standard_Real f,l,dmin = RealLast();
599 Standard_Integer i=0,imin = 0;
600
601 C = BRep_Tool::Curve(Ebase,Loc,f,l);
602
603 if (!Loc.IsIdentity()) {
604 Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
605 C = *((Handle(Geom_Curve)*)&GG);
606 }
607 gp_Pnt Pt(C->Value((f+l)/2.));
608
609 GeomAPI_ProjectPointOnCurve proj;
610// for (TopTools_ListIteratorOfListOfShape itl(lsubs);
611 TopTools_ListIteratorOfListOfShape itl(lsubs);
612 for ( ;itl.More();itl.Next()) {
613 i++;
614 const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
615 C = BRep_Tool::Curve(edg,Loc,f,l);
616 if (!Loc.IsIdentity()) {
617 Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
618 C = *((Handle(Geom_Curve)*)&GG);
619 }
620 proj.Init(Pt,C,f,l);
621 if (proj.NbPoints() > 0) {
622 if (proj.LowerDistance() < dmin) {
623 imin = i;
624 dmin = proj.LowerDistance();
625 }
626 }
627 }
628 if (imin == 0) {
629 lsubs.Clear();
630 }
631 else {
632 itl.Initialize(lsubs);
633 i = 1;
634 while (i < imin) {
635 lsubs.Remove(itl);
636 i++;
637 }
638 itl.Next();
639 while (itl.More()) {
640 lsubs.Remove(itl);
641 }
642 }
643}