1 // Created on: 1996-01-09
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.
17 // Modified by skv - Mon May 31 12:34:09 2004 OCC5865
19 #include <LocOpe_Spliter.ixx>
21 //#include <LocOpe_ProjectedWires.hxx>
23 #include <TopTools_MapOfShape.hxx>
24 #include <TopTools_DataMapOfShapeShape.hxx>
25 #include <TopTools_IndexedMapOfShape.hxx>
26 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
27 #include <TopTools_SequenceOfShape.hxx>
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>
39 #include <LocOpe_BuildWires.hxx>
41 #include <gp_Vec2d.hxx>
43 #include <Geom_Curve.hxx>
44 #include <GeomAPI_ProjectPointOnCurve.hxx>
45 #include <BRep_Tool.hxx>
47 #include <BRepTools_Substitution.hxx>
48 #include <LocOpe_SplitShape.hxx>
50 #include <BRep_Builder.hxx>
55 #include <Standard_ConstructionError.hxx>
58 // Modified by skv - Mon May 31 13:00:30 2004 OCC5865 Begin
59 // static void RebuildWires(TopTools_ListOfShape&);
60 static void RebuildWires(TopTools_ListOfShape&,
61 const Handle(LocOpe_WiresOnShape)&);
62 // Modified by skv - Mon May 31 13:00:31 2004 OCC5865 End
64 static void Put(const TopoDS_Shape&,
65 TopTools_DataMapOfShapeListOfShape&);
67 static void Select(const TopoDS_Edge&,
68 TopTools_ListOfShape&);
71 //=======================================================================
74 //=======================================================================
76 void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW)
78 if (myShape.IsNull()) {
79 Standard_NullObject::Raise();
81 myDone = Standard_False;
87 TopTools_MapOfShape mapV,mapE;
88 TopTools_DataMapOfShapeShape EdgOnEdg;
89 TopTools_IndexedDataMapOfShapeListOfShape mapFE;
90 TopExp_Explorer exp,exp2;
92 // 1ere etape : substitution des vertex
95 TopTools_ListOfShape lsubs;
96 BRepTools_Substitution theSubs;
99 for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
100 const TopoDS_Edge& edg = PW->Edge();
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)) {
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);
114 theSubs.Substitute(Vb.Oriented(TopAbs_FORWARD),lsubs);
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());
130 if (lsub.Extent() != 1) {
131 Standard_ConstructionError::Raise();
134 myMap(itdesc.Key()).Clear();
135 myMap(itdesc.Key()).Append(lsub.First());
140 myRes = myMap(myShape).First();
141 LocOpe_SplitShape theCFace(myRes);
143 // Adds every vertices lying on an edge of the shape, and prepares
144 // work to rebuild wires on each face
148 TopTools_MapOfShape theFacesWithSection;
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)) {
155 if (PW->OnEdge(vtx,edg,Ed,prm)) {
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);
164 if (PW->OnEdge(Ebis)) {
165 // Ebis = TopoDS::Edge(myMap(Ebis).First());
166 EdgOnEdg.Bind(edg,Ebis);
169 TopoDS_Face fac = PW->OnFace();
170 if(!myMap.IsBound(fac)) continue;
171 Standard_Boolean IsFaceWithSec = PW->IsFaceWithSection(fac);
172 fac = TopoDS::Face(myMap(fac).First());
174 theFacesWithSection.Add(fac);
175 if (!mapFE.Contains(fac)) {
176 TopTools_ListOfShape thelist;
177 mapFE.Add(fac, thelist);
179 mapFE.ChangeFromKey(fac).Append(edg);
183 // Rebuilds wires on each face of the shape
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
193 if (theFacesWithSection.Contains(fac))
194 theCFace.Add(ledges, fac);
196 for (itl.Initialize(ledges); itl.More(); itl.Next())
197 theCFace.Add(TopoDS::Wire(itl.Value()),fac);
201 // Mise a jour des descendants
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);
209 const TopTools_ListOfShape& lres = myMap(myShape);
211 TopAbs_ShapeEnum typS = myShape.ShapeType();
212 if (typS == TopAbs_FACE && lres.Extent() >=2) {
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()));
221 else if (typS == TopAbs_EDGE && lres.Extent() >=2) {
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()));
231 if (lres.Extent() != 1) {
234 myRes = lres.First();
238 for (TopTools_DataMapIteratorOfDataMapOfShapeShape itee(EdgOnEdg);
241 const TopoDS_Edge& e1 = TopoDS::Edge(itee.Key());
242 // on recherche dans les descendants de e2 l`edge qui correspont a e1
244 TopoDS_Vertex vf1,vl1,vf2,vl2;
245 TopExp::Vertices(e1,vf1,vl1);
247 for (itl.Initialize(myMap(itee.Value()));
250 const TopoDS_Edge& e2 = TopoDS::Edge(itl.Value());
251 TopExp::Vertices(e2,vf2,vl2);
253 if (!vl1.IsSame(vf1)) {
254 if (vf1.IsSame(vf2) && vl1.IsSame(vl2)) {
255 lsubs.Append(e2.Oriented(TopAbs_FORWARD));
258 else if (vf1.IsSame(vl2) && vl1.IsSame(vf2)) {
259 lsubs.Append(e2.Oriented(TopAbs_REVERSED));
263 else { // discrimination sur les tangentes
264 if (vf2.IsSame(vl2) && vl2.IsSame(vl1)) { // tout au meme point
269 Handle(Geom_Curve) C = BRep_Tool::Curve(e1,Loc,f,l);
271 v1.Transform(Loc.Transformation());
273 C = BRep_Tool::Curve(e2,Loc,f,l);
275 v2.Transform(Loc.Transformation());
276 if (v1.Dot(v2) >0.) {
277 lsubs.Append(e2.Oriented(TopAbs_FORWARD));
280 lsubs.Append(e2.Oriented(TopAbs_REVERSED));
286 if (lsubs.Extent() >= 2) { // il faut faire un choix
289 if (lsubs.Extent() == 1) {
290 TopoDS_Shape ebase = lsubs.First();
292 lsubs.Append(e1.Oriented(ebase.Orientation()));
293 theSubs.Substitute(ebase.Oriented(TopAbs_FORWARD),lsubs);
297 cout << "Pb pour substitution" << endl;
302 theSubs.Build(myRes);
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());
311 if (lsub.Extent() != 1) {
312 Standard_ConstructionError::Raise();
315 newdesc.Append(lsub.First());
318 newdesc.Append(itl.Value());
321 myMap(itdesc.Key()) = newdesc;
324 if (theSubs.IsCopied(myRes)) {
325 myRes = theSubs.Copy(myRes).First();
328 ////remove superfluous vertices on degenerated edges
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++)
336 const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(i));
337 if (BRep_Tool::Degenerated(anEdge))
338 DegEdges.Append(anEdge);
341 TopTools_SequenceOfShape DegWires;
344 if (DegEdges.IsEmpty())
346 TopoDS_Wire aDegWire;
347 BB.MakeWire(aDegWire);
348 BB.Add(aDegWire, DegEdges(1));
350 TopoDS_Vertex Vfirst, Vlast;
353 TopExp::Vertices(aDegWire, Vfirst, Vlast);
354 Standard_Boolean found = Standard_False;
355 for (i = 1; i <= DegEdges.Length(); i++)
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))
362 BB.Add(aDegWire, anEdge);
364 found = Standard_True;
371 DegWires.Append(aDegWire);
374 for (i = 1; i <= DegWires.Length(); i++)
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++)
382 if (!Vmap(j).IsSame(Vmap(1)))
383 theSubs.Substitute(Vmap(j), LV);
386 theSubs.Build(myRes);
387 if (theSubs.IsCopied(myRes))
388 myRes = theSubs.Copy(myRes).First();
395 TopTools_MapIteratorOfMapOfShape itms;
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()) {
421 /* JAG : Ne peut pas marcher
423 Standard_Boolean full = mapV.IsEmpty();
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())) {
436 full = mapV.IsEmpty();
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());
465 while (Mapebord.Extent() != 0) {
466 itms.Initialize(Mapebord);
467 TopoDS_Shape edg = itms.Key();
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)) {
477 break; // face a gauche
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());
491 Mapebord.Remove(edg);
495 myDone = Standard_True;
499 //=======================================================================
500 //function : DescendantShapes
502 //=======================================================================
504 const TopTools_ListOfShape& LocOpe_Spliter::
505 DescendantShapes(const TopoDS_Shape& F)
507 if (!myDone) {StdFail_NotDone::Raise();}
508 if (myMap.IsBound(F))
511 static TopTools_ListOfShape empty;
517 //=======================================================================
518 //function : DirectLeft
520 //=======================================================================
522 const TopTools_ListOfShape& LocOpe_Spliter::DirectLeft() const
524 if (!myDone) {StdFail_NotDone::Raise();}
530 //=======================================================================
533 //=======================================================================
535 const TopTools_ListOfShape& LocOpe_Spliter::Left() const
537 if (!myDone) {StdFail_NotDone::Raise();}
543 //=======================================================================
544 //function : RebuildWires
546 //=======================================================================
548 // Modified by skv - Mon May 31 12:31:39 2004 OCC5865 Begin
549 //static void RebuildWires(TopTools_ListOfShape& ledge)
550 static void RebuildWires(TopTools_ListOfShape& ledge,
551 const Handle(LocOpe_WiresOnShape)& PW)
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();
558 ledge = theBuild.Result();
565 //=======================================================================
568 //=======================================================================
570 static void Put(const TopoDS_Shape& S,
571 TopTools_DataMapOfShapeListOfShape& theMap)
573 if (theMap.IsBound(S)) {
576 TopTools_ListOfShape thelist;
577 theMap.Bind(S, thelist);
579 for (TopoDS_Iterator it(S); it.More(); it.Next()) {
580 Put(it.Value(),theMap);
585 //=======================================================================
588 //=======================================================================
590 static void Select(const TopoDS_Edge& Ebase,
591 TopTools_ListOfShape& lsubs)
596 Handle(Geom_Curve) C;
598 Standard_Real f,l,dmin = RealLast();
599 Standard_Integer i=0,imin = 0;
601 C = BRep_Tool::Curve(Ebase,Loc,f,l);
603 if (!Loc.IsIdentity()) {
604 Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
605 C = *((Handle(Geom_Curve)*)&GG);
607 gp_Pnt Pt(C->Value((f+l)/2.));
609 GeomAPI_ProjectPointOnCurve proj;
610 // for (TopTools_ListIteratorOfListOfShape itl(lsubs);
611 TopTools_ListIteratorOfListOfShape itl(lsubs);
612 for ( ;itl.More();itl.Next()) {
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);
621 if (proj.NbPoints() > 0) {
622 if (proj.LowerDistance() < dmin) {
624 dmin = proj.LowerDistance();
632 itl.Initialize(lsubs);