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 <BRep_Builder.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepTools_Substitution.hxx>
22 #include <Geom_Curve.hxx>
23 #include <GeomAPI_ProjectPointOnCurve.hxx>
25 #include <gp_Vec2d.hxx>
26 #include <LocOpe_BuildWires.hxx>
27 #include <LocOpe_Spliter.hxx>
28 #include <LocOpe_SplitShape.hxx>
29 #include <LocOpe_WiresOnShape.hxx>
30 #include <Standard_ConstructionError.hxx>
31 #include <Standard_NoSuchObject.hxx>
32 #include <Standard_NullObject.hxx>
33 #include <StdFail_NotDone.hxx>
35 #include <TopExp_Explorer.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <TopoDS_Iterator.hxx>
40 #include <TopoDS_Shape.hxx>
41 #include <TopoDS_Vertex.hxx>
42 #include <TopoDS_Wire.hxx>
43 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
44 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
45 #include <TopTools_DataMapOfShapeShape.hxx>
46 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_IndexedMapOfShape.hxx>
48 #include <TopTools_ListIteratorOfListOfShape.hxx>
49 #include <TopTools_MapIteratorOfMapOfShape.hxx>
50 #include <TopTools_MapOfShape.hxx>
53 //#include <LocOpe_ProjectedWires.hxx>
54 // Modified by skv - Mon May 31 13:00:30 2004 OCC5865 Begin
55 // static void RebuildWires(TopTools_ListOfShape&);
56 static void RebuildWires(TopTools_ListOfShape&,
57 const Handle(LocOpe_WiresOnShape)&);
58 // Modified by skv - Mon May 31 13:00:31 2004 OCC5865 End
60 static void Put(const TopoDS_Shape&,
61 TopTools_DataMapOfShapeListOfShape&);
63 static void Select(const TopoDS_Edge&,
64 TopTools_ListOfShape&);
67 //=======================================================================
70 //=======================================================================
72 void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW)
74 if (myShape.IsNull()) {
75 throw Standard_NullObject();
77 myDone = Standard_False;
83 TopTools_MapOfShape mapV,mapE;
84 TopTools_DataMapOfShapeShape EdgOnEdg;
85 TopTools_IndexedDataMapOfShapeListOfShape mapFE;
86 TopExp_Explorer exp,exp2;
88 // 1ere etape : substitution des vertex
91 TopTools_ListOfShape lsubs;
92 BRepTools_Substitution theSubs;
95 for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
96 const TopoDS_Edge& edg = PW->Edge();
98 for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
99 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
100 if (!mapV.Contains(vtx)) {
101 if (PW->OnVertex(vtx,Vb)) {
106 TopoDS_Vertex vsub = TopoDS::Vertex(vtx.Oriented(TopAbs_FORWARD));
107 gp_Pnt p1 = BRep_Tool::Pnt(vsub), p2 = BRep_Tool::Pnt(Vb);
108 Standard_Real d = p1.Distance(p2);
109 d = d + BRep_Tool::Tolerance(Vb);
110 BB.UpdateVertex(vsub, d);
112 theSubs.Substitute(Vb.Oriented(TopAbs_FORWARD),lsubs);
119 theSubs.Build(myShape);
120 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdesc(myMap);
121 if (theSubs.IsCopied(myShape)) {
122 // on n`a fait que des substitutions de vertex. Donc chaque element
123 // est remplace par lui meme ou par un seul element du meme type.
124 for (; itdesc.More(); itdesc.Next()) {
125 if (theSubs.IsCopied(itdesc.Key())) {
126 const TopTools_ListOfShape& lsub = theSubs.Copy(itdesc.Key());
128 if (lsub.Extent() != 1) {
129 throw Standard_ConstructionError();
132 myMap(itdesc.Key()).Clear();
133 myMap(itdesc.Key()).Append(lsub.First());
138 myRes = myMap(myShape).First();
139 LocOpe_SplitShape theCFace(myRes);
141 // Adds every vertices lying on an edge of the shape, and prepares
142 // work to rebuild wires on each face
146 TopTools_MapOfShape theFacesWithSection;
147 for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
148 TopoDS_Edge edg = PW->Edge();
149 for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
150 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
151 if (!mapV.Contains(vtx)) {
153 if (PW->OnEdge(vtx,edg,Ed,prm)) {
154 // on devrait verifier que le vtx n`existe pas deja sur l`edge
155 if(!myMap.IsBound(Ed)) continue;
156 Ed = TopoDS::Edge(myMap(Ed).First());
157 theCFace.Add(vtx,prm,Ed);
162 if (PW->OnEdge(Ebis)) {
163 // Ebis = TopoDS::Edge(myMap(Ebis).First());
164 EdgOnEdg.Bind(edg,Ebis);
167 TopoDS_Face fac = PW->OnFace();
168 if(!myMap.IsBound(fac)) continue;
169 Standard_Boolean IsFaceWithSec = PW->IsFaceWithSection(fac);
170 fac = TopoDS::Face(myMap(fac).First());
172 theFacesWithSection.Add(fac);
173 if (!mapFE.Contains(fac)) {
174 TopTools_ListOfShape thelist;
175 mapFE.Add(fac, thelist);
177 mapFE.ChangeFromKey(fac).Append(edg);
181 // Rebuilds wires on each face of the shape
183 TopTools_ListIteratorOfListOfShape itl;
184 for (Standard_Integer i=1; i<=mapFE.Extent(); i++) {
185 const TopoDS_Face& fac = TopoDS::Face(mapFE.FindKey(i));
186 TopTools_ListOfShape& ledges = mapFE(i);
187 // Modified by skv - Mon May 31 12:32:54 2004 OCC5865 Begin
188 // RebuildWires(ledges);
189 RebuildWires(ledges, PW);
190 // Modified by skv - Mon May 31 12:32:54 2004 OCC5865 End
191 if (theFacesWithSection.Contains(fac))
192 theCFace.Add(ledges, fac);
194 for (itl.Initialize(ledges); itl.More(); itl.Next())
195 theCFace.Add(TopoDS::Wire(itl.Value()),fac);
199 // Mise a jour des descendants
201 for (itdesc.Reset(); itdesc.More(); itdesc.Next()) {
202 const TopoDS_Shape& sori = itdesc.Key();
203 const TopoDS_Shape& scib = itdesc.Value().First();
204 myMap(sori) = theCFace.DescendantShapes(scib);
207 const TopTools_ListOfShape& lres = myMap(myShape);
209 TopAbs_ShapeEnum typS = myShape.ShapeType();
210 if (typS == TopAbs_FACE && lres.Extent() >=2) {
213 B.MakeShell(TopoDS::Shell(myRes));
214 myRes.Orientation(TopAbs_FORWARD);
215 for (itl.Initialize(lres); itl.More(); itl.Next()) {
216 B.Add(myRes,itl.Value().Oriented(myShape.Orientation()));
219 else if (typS == TopAbs_EDGE && lres.Extent() >=2) {
222 B.MakeWire(TopoDS::Wire(myRes));
223 myRes.Orientation(TopAbs_FORWARD);
224 for (itl.Initialize(lres); itl.More(); itl.Next()) {
225 B.Add(myRes,itl.Value().Oriented(myShape.Orientation()));
229 if (lres.Extent() != 1) {
232 myRes = lres.First();
236 for (TopTools_DataMapIteratorOfDataMapOfShapeShape itee(EdgOnEdg);
239 const TopoDS_Edge& e1 = TopoDS::Edge(itee.Key());
240 // on recherche dans les descendants de e2 l`edge qui correspont a e1
242 TopoDS_Vertex vf1,vl1,vf2,vl2;
243 TopExp::Vertices(e1,vf1,vl1);
245 for (itl.Initialize(myMap(itee.Value()));
248 const TopoDS_Edge& e2 = TopoDS::Edge(itl.Value());
249 TopExp::Vertices(e2,vf2,vl2);
251 if (!vl1.IsSame(vf1)) {
252 if (vf1.IsSame(vf2) && vl1.IsSame(vl2)) {
253 lsubs.Append(e2.Oriented(TopAbs_FORWARD));
256 else if (vf1.IsSame(vl2) && vl1.IsSame(vf2)) {
257 lsubs.Append(e2.Oriented(TopAbs_REVERSED));
261 else { // discrimination sur les tangentes
262 if (vf2.IsSame(vl2) && vl2.IsSame(vl1)) { // tout au meme point
267 Handle(Geom_Curve) C = BRep_Tool::Curve(e1,Loc,f,l);
269 v1.Transform(Loc.Transformation());
271 C = BRep_Tool::Curve(e2,Loc,f,l);
273 v2.Transform(Loc.Transformation());
274 if (v1.Dot(v2) >0.) {
275 lsubs.Append(e2.Oriented(TopAbs_FORWARD));
278 lsubs.Append(e2.Oriented(TopAbs_REVERSED));
284 if (lsubs.Extent() >= 2) { // il faut faire un choix
287 if (lsubs.Extent() == 1) {
288 TopoDS_Shape ebase = lsubs.First();
290 lsubs.Append(e1.Oriented(ebase.Orientation()));
291 theSubs.Substitute(ebase,lsubs);
295 std::cout << "Pb pour substitution" << std::endl;
300 theSubs.Build(myRes);
302 for (itdesc.Reset(); itdesc.More(); itdesc.Next()) {
303 TopTools_ListOfShape& ldesc = myMap(itdesc.Key());
304 TopTools_ListOfShape newdesc;
305 for (itl.Initialize(ldesc); itl.More(); itl.Next()) {
306 if (theSubs.IsCopied(itl.Value())) {
307 const TopTools_ListOfShape& lsub = theSubs.Copy(itl.Value());
309 if (lsub.Extent() != 1) {
310 throw Standard_ConstructionError();
313 newdesc.Append(lsub.First());
316 newdesc.Append(itl.Value());
319 myMap(itdesc.Key()) = newdesc;
322 if (theSubs.IsCopied(myRes)) {
323 myRes = theSubs.Copy(myRes).First();
326 ////remove superfluous vertices on degenerated edges
328 TopTools_IndexedMapOfShape Emap;
329 TopExp::MapShapes(myRes, TopAbs_EDGE, Emap);
330 TopTools_SequenceOfShape DegEdges;
331 Standard_Integer i, j;
332 for (i = 1; i <= Emap.Extent(); i++)
334 const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(i));
335 if (BRep_Tool::Degenerated(anEdge))
336 DegEdges.Append(anEdge);
339 TopTools_SequenceOfShape DegWires;
342 if (DegEdges.IsEmpty())
344 TopoDS_Wire aDegWire;
345 BB.MakeWire(aDegWire);
346 BB.Add(aDegWire, DegEdges(1));
348 TopoDS_Vertex Vfirst, Vlast;
351 TopExp::Vertices(aDegWire, Vfirst, Vlast);
352 Standard_Boolean found = Standard_False;
353 for (i = 1; i <= DegEdges.Length(); i++)
355 const TopoDS_Edge& anEdge = TopoDS::Edge(DegEdges(i));
356 TopoDS_Vertex V1, V2;
357 TopExp::Vertices(anEdge, V1, V2);
358 if (V1.IsSame(Vfirst) || V1.IsSame(Vlast) || V2.IsSame(Vfirst) || V2.IsSame(Vlast))
360 BB.Add(aDegWire, anEdge);
362 found = Standard_True;
369 DegWires.Append(aDegWire);
372 for (i = 1; i <= DegWires.Length(); i++)
374 TopTools_IndexedMapOfShape Vmap;
375 TopExp::MapShapes(DegWires(i), TopAbs_VERTEX, Vmap);
376 TopTools_ListOfShape LV;
377 LV.Append(Vmap(1).Oriented(TopAbs_FORWARD));
378 for (j = 2; j <= Vmap.Extent(); j++)
380 if (!Vmap(j).IsSame(Vmap(1)))
381 theSubs.Substitute(Vmap(j), LV);
384 theSubs.Build(myRes);
385 if (theSubs.IsCopied(myRes))
386 myRes = theSubs.Copy(myRes).First();
393 TopTools_MapIteratorOfMapOfShape itms;
395 for (exp.Init(myRes, TopAbs_FACE); exp.More(); exp.Next()) {
396 const TopoDS_Face& fac = TopoDS::Face(exp.Current());
397 for (exp2.Init(fac,TopAbs_EDGE); exp2.More(); exp2.Next()) {
398 const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
399 for (itms.Initialize(mapE);
400 itms.More(); itms.Next()) {
401 if (itms.Key().IsSame(edg) &&
402 edg.Orientation() == itms.Key().Orientation()) {
419 /* JAG : Ne peut pas marcher
421 Standard_Boolean full = mapV.IsEmpty();
423 full = Standard_True;
424 itms.Initialize(mapV);
425 const TopoDS_Face& fac = TopoDS::Face(itms.Key());
426 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
427 if (!mapE.Contains(exp.Current())) {
428 for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
429 const TopoDS_Face& fac2 = TopoDS::Face(itl.Value());
430 for (exp2.Init(fac2,TopAbs_EDGE); exp2.More(); exp2.Next()) {
431 if (exp2.Current().IsSame(exp.Current())) {
434 full = mapV.IsEmpty();
450 // Map des edges ou les connexions sont possibles
451 TopTools_MapOfShape Mapebord;
452 for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
453 for (exp.Init(itl.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
454 if (!mapE.Contains(exp.Current())) {
455 if (!Mapebord.Add(exp.Current())) {
456 Mapebord.Remove(exp.Current());
463 while (Mapebord.Extent() != 0) {
464 itms.Initialize(Mapebord);
465 TopoDS_Shape edg = itms.Key();
467 for (itms.Initialize(mapV); itms.More(); itms.Next()) {
468 const TopoDS_Shape& fac = itms.Key();
469 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
470 if (exp.Current().IsSame(edg)) {
475 break; // face a gauche
479 TopoDS_Shape fac = itms.Key();
480 for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
481 if (!Mapebord.Add(exp.Current())) {
482 Mapebord.Remove(exp.Current());
489 Mapebord.Remove(edg);
493 myDone = Standard_True;
497 //=======================================================================
498 //function : DescendantShapes
500 //=======================================================================
502 const TopTools_ListOfShape& LocOpe_Spliter::
503 DescendantShapes(const TopoDS_Shape& F)
505 if (!myDone) {throw StdFail_NotDone();}
506 if (myMap.IsBound(F))
509 static TopTools_ListOfShape empty;
515 //=======================================================================
516 //function : DirectLeft
518 //=======================================================================
520 const TopTools_ListOfShape& LocOpe_Spliter::DirectLeft() const
522 if (!myDone) {throw StdFail_NotDone();}
528 //=======================================================================
531 //=======================================================================
533 const TopTools_ListOfShape& LocOpe_Spliter::Left() const
535 if (!myDone) {throw StdFail_NotDone();}
541 //=======================================================================
542 //function : RebuildWires
544 //=======================================================================
546 // Modified by skv - Mon May 31 12:31:39 2004 OCC5865 Begin
547 //static void RebuildWires(TopTools_ListOfShape& ledge)
548 static void RebuildWires(TopTools_ListOfShape& ledge,
549 const Handle(LocOpe_WiresOnShape)& PW)
551 LocOpe_BuildWires theBuild(ledge, PW);
552 // Modified by skv - Mon May 31 12:31:40 2004 OCC5865 End
553 if (!theBuild.IsDone()) {
554 throw Standard_ConstructionError();
556 ledge = theBuild.Result();
563 //=======================================================================
566 //=======================================================================
568 static void Put(const TopoDS_Shape& S,
569 TopTools_DataMapOfShapeListOfShape& theMap)
571 if (theMap.IsBound(S)) {
574 TopTools_ListOfShape thelist;
575 theMap.Bind(S, thelist);
577 for (TopoDS_Iterator it(S); it.More(); it.Next()) {
578 Put(it.Value(),theMap);
583 //=======================================================================
586 //=======================================================================
588 static void Select(const TopoDS_Edge& Ebase,
589 TopTools_ListOfShape& lsubs)
594 Handle(Geom_Curve) C;
596 Standard_Real f,l,dmin = RealLast();
597 Standard_Integer i=0,imin = 0;
599 C = BRep_Tool::Curve(Ebase,Loc,f,l);
601 if (!Loc.IsIdentity()) {
602 Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
603 C = Handle(Geom_Curve)::DownCast (GG);
605 gp_Pnt Pt(C->Value((f+l)/2.));
607 GeomAPI_ProjectPointOnCurve proj;
608 // for (TopTools_ListIteratorOfListOfShape itl(lsubs);
609 TopTools_ListIteratorOfListOfShape itl(lsubs);
610 for ( ;itl.More();itl.Next()) {
612 const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
613 C = BRep_Tool::Curve(edg,Loc,f,l);
614 if (!Loc.IsIdentity()) {
615 Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
616 C = Handle(Geom_Curve)::DownCast (GG);
619 if (proj.NbPoints() > 0) {
620 if (proj.LowerDistance() < dmin) {
622 dmin = proj.LowerDistance();
630 itl.Initialize(lsubs);