1 // Created on: 1995-06-27
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-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 <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepAdaptor_Surface.hxx>
21 #include <BRepClass_FaceExplorer.hxx>
22 #include <BRepLib_MakeFace.hxx>
23 #include <BRepLib_MakeWire.hxx>
24 #include <BRepTools.hxx>
25 #include <BRepTools_WireExplorer.hxx>
26 #include <BRepTopAdaptor_FClass2d.hxx>
27 #include <Geom2d_Curve.hxx>
28 #include <gp_Dir2d.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <gp_Vec2d.hxx>
32 #include <LocOpe_SplitShape.hxx>
33 #include <Precision.hxx>
34 #include <Standard_ConstructionError.hxx>
35 #include <Standard_ErrorHandler.hxx>
36 #include <Standard_NoSuchObject.hxx>
37 #include <StdFail_NotDone.hxx>
39 #include <TopExp_Explorer.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Face.hxx>
43 #include <TopoDS_Iterator.hxx>
44 #include <TopoDS_Shape.hxx>
45 #include <TopoDS_Vertex.hxx>
46 #include <TopoDS_Wire.hxx>
47 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
48 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
49 #include <TopTools_DataMapOfShapeInteger.hxx>
50 #include <TopTools_DataMapOfShapeListOfShape.hxx>
51 #include <TopTools_DataMapOfShapeShape.hxx>
52 #include <TopTools_IndexedMapOfShape.hxx>
53 #include <TopTools_ListIteratorOfListOfShape.hxx>
54 #include <TopTools_ListOfShape.hxx>
55 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
56 #include <TopTools_MapIteratorOfMapOfShape.hxx>
57 #include <TopTools_MapOfOrientedShape.hxx>
58 #include <TopTools_MapOfShape.hxx>
60 static Standard_Boolean IsInside(const TopoDS_Face&,
64 static Standard_Boolean IsInside(const TopoDS_Face&,
67 static void GetDirection(const TopoDS_Edge&,
71 Standard_Boolean isFirstEnd);
73 static Standard_Boolean ChoixUV(const TopoDS_Edge&,
75 const TopTools_IndexedMapOfShape&,
79 const Standard_Real tol);
81 static TopoDS_Shape ChooseDirection(const TopoDS_Shape&,
84 const TopTools_ListOfShape&);
86 inline Standard_Boolean SameUV(const gp_Pnt2d& P1, const gp_Pnt2d& P2,
87 const BRepAdaptor_Surface& theBAS)//const Standard_Real tol)
89 Standard_Boolean isSame = Standard_True;
90 if(theBAS.IsUPeriodic())
91 isSame = (fabs(P1.X() - P2.X()) < theBAS.UPeriod() *0.5);
92 if(theBAS.IsVPeriodic())
93 isSame = (isSame && (fabs(P1.Y() - P2.Y()) < theBAS.VPeriod() *0.5));
95 //return P1.SquareDistance(P2) < tol * tol; //IFV
100 //=======================================================================
103 //=======================================================================
105 void LocOpe_SplitShape::Init(const TopoDS_Shape& S)
107 myDone = Standard_False;
115 //=======================================================================
116 //function : CanSplit
118 //=======================================================================
120 Standard_Boolean LocOpe_SplitShape::CanSplit(const TopoDS_Edge& E) const
123 return Standard_False;
125 if (myMap.IsEmpty()) {
126 return Standard_False;
129 if (!myMap.IsBound(E)) {
130 return Standard_False;
133 // On verifie que l`edge n`appartient pas a un wire deja reconstruit
135 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(myMap);
136 for (; itm.More(); itm.Next()) {
137 if (itm.Key().ShapeType() == TopAbs_WIRE && !itm.Value().IsEmpty()) {
138 for (exp.Init(itm.Key(),TopAbs_EDGE); exp.More(); exp.Next()) {
139 if (exp.Current().IsSame(E)) {
140 return Standard_False;
145 return Standard_True;
149 //=======================================================================
152 //=======================================================================
154 void LocOpe_SplitShape::Add(const TopoDS_Vertex& V,
155 const Standard_Real P,
156 const TopoDS_Edge& E)
163 TopTools_ListOfShape& le = myMap(E);
167 TopTools_ListIteratorOfListOfShape itl(le);
169 TopTools_ListOfShape aNewList;
170 for (; itl.More(); itl.Next()) {
171 const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
172 BRep_Tool::Range(edg,f,l);
173 if (P > f + Precision::PConfusion() && P < l - Precision::PConfusion()) {
177 aNewList.Append(edg);
182 TopoDS_Edge edg = TopoDS::Edge(itl.Value());
184 if (V.Orientation() == TopAbs_FORWARD ||
185 V.Orientation() == TopAbs_REVERSED) {
187 edg.Orientation(TopAbs_FORWARD);
188 TopoDS_Vertex aCurV1, aCurV2;
189 TopExp::Vertices(edg, aCurV1, aCurV2);
190 Standard_Real aPar1 = BRep_Tool::Parameter(aCurV1,edg);
192 Standard_Real aPar2 = BRep_Tool::Parameter(aCurV2,edg);
194 TopoDS_Shape aLocalShape = edg.EmptyCopied();
195 TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
196 aLocalShape = edg.EmptyCopied();
197 TopoDS_Edge E2 = TopoDS::Edge(aLocalShape);
198 // TopoDS_Edge E1 = TopoDS::Edge(edg.EmptyCopied());
199 // TopoDS_Edge E2 = TopoDS::Edge(edg.EmptyCopied());
200 E1.Orientation(TopAbs_FORWARD);
201 E2.Orientation(TopAbs_FORWARD);
202 TopoDS_Vertex newVtx = V;
203 Standard_Real aTolSplitV = BRep_Tool::Tolerance(V);
205 aCurV1.Orientation(TopAbs_FORWARD);
208 //for degenerated edges tolerance of vertices should be set to maximal value
209 //from tolerance of the vertex of the edge and tolerance of splitting vertex
210 Standard_Real aTolV1 = ( BRep_Tool::Degenerated(edg) ?
211 Max(BRep_Tool::Tolerance(aCurV1), aTolSplitV) : BRep_Tool::Tolerance(aCurV1));
213 B.UpdateVertex(aCurV1,aPar1,E1, aTolV1);
214 newVtx.Orientation(TopAbs_REVERSED);
216 B.UpdateVertex(newVtx,P,E1,BRep_Tool::Tolerance(V));
217 newVtx.Orientation(TopAbs_FORWARD);
219 B.UpdateVertex(newVtx,P,E2,BRep_Tool::Tolerance(V));
221 aCurV2.Orientation(TopAbs_REVERSED);
224 //for degenerated edges tolerance of vertices should be set to maximal value
225 //from tolerance of the vertex of the edge and tolerance of splitting vertex
226 Standard_Real aTolV2 = ( BRep_Tool::Degenerated(edg) ? aTolV1 : BRep_Tool::Tolerance(aCurV2));
227 B.UpdateVertex(aCurV2,aPar2,E2,aTolV2);
231 for (; itl.More(); itl.Next())
233 const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
234 aNewList.Append(edg);
237 myMap.Bind(E, aNewList);
241 TopoDS_Shape aLocalShape = edg.EmptyCopied();
242 TopoDS_Edge E1 = TopoDS::Edge(aLocalShape);
245 for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
247 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
248 f = BRep_Tool::Parameter(vtx,edg);
250 B.UpdateVertex(vtx,f,E1,BRep_Tool::Tolerance(vtx));
253 B.UpdateVertex(V,P,E1,BRep_Tool::Tolerance(V));
258 //=======================================================================
260 //purpose : adds the list of wires on the face <F>
261 //=======================================================================
263 Standard_Boolean LocOpe_SplitShape::Add(const TopTools_ListOfShape& Lwires,
264 const TopoDS_Face& F)
268 return Standard_False;
271 TopTools_ListOfShape& lf = myMap(F);
276 // On cherche la face descendante de F qui continent le wire
278 TopTools_ListIteratorOfListOfShape itl(lf);
279 TopoDS_Vertex Vfirst,Vlast;
281 BRepTools::Update(F);
283 TopTools_ListOfShape aLInside;
284 for (; itl.More(); itl.Next())
286 const TopoDS_Face& fac = TopoDS::Face(itl.Value());
287 TopTools_ListIteratorOfListOfShape itwires(Lwires);
288 for (; itwires.More(); itwires.Next())
290 const TopoDS_Wire& aWire = TopoDS::Wire(itwires.Value());
291 if (IsInside(fac, aWire))
293 aLInside.Append(aWire);
297 if(aLInside.Extent())
300 if (!aLInside.Extent() || !itl.More()) {
301 return Standard_False;
304 TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
305 FaceRef.Orientation(TopAbs_FORWARD);
308 TopTools_ListOfShape NewWires;
310 TopTools_DataMapOfShapeInteger SectionsTimes;
311 for (itl.Initialize(aLInside); itl.More(); itl.Next())
312 SectionsTimes.Bind(itl.Value(), 2);
314 TopTools_ListOfShape BreakVertices;
315 TopTools_ListOfShape BreakOnWires;
317 TopTools_DataMapOfShapeShape VerWireMap;
319 TopExp_Explorer ExploF, ExploW;
320 for (itl.Initialize(aLInside); itl.More(); itl.Next())
322 const TopoDS_Wire& aSection = TopoDS::Wire(itl.Value());
323 TopoDS_Vertex Ver [2];
324 TopExp::Vertices(aSection, Ver[0], Ver[1]);
325 for (i = 0; i < 2; i++)
327 if (VerWireMap.IsBound(Ver[i]))
329 for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next())
331 const TopoDS_Shape& aWire = ExploF.Current();
333 for (ExploW.Init(aWire, TopAbs_VERTEX); ExploW.More(); ExploW.Next())
335 aVer = ExploW.Current();
336 if (aVer.IsSame(Ver[i]))
339 if (aVer.IsSame(Ver[i]))
341 VerWireMap.Bind(aVer, aWire);
348 TopTools_DataMapOfShapeListOfShape VerSecMap;
349 for (itl.Initialize(aLInside); itl.More(); itl.Next())
351 const TopoDS_Wire& aWire = TopoDS::Wire(itl.Value());
352 TopoDS_Vertex V1, V2;
353 TopExp::Vertices(aWire, V1, V2);
354 TopTools_ListOfShape LW1, LW2;
355 if (!VerSecMap.IsBound(V1))
356 VerSecMap.Bind(V1, LW1);
357 VerSecMap(V1).Append(aWire);
358 if (!VerSecMap.IsBound(V2))
359 VerSecMap.Bind(V2, LW2);
360 VerSecMap(V2).Append(aWire);
363 //TopTools_IndexedDataMapOfShapeShape InnerTouchingWiresOnVertex;
365 TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef);
366 TopoDS_Wire CurWire = outerW;
367 BRepLib_MakeWire *MW;
368 MW = new BRepLib_MakeWire();
369 BRepTools_WireExplorer wexp(CurWire, FaceRef);
372 TopoDS_Vertex theStartVertex = wexp.CurrentVertex(), CurVertex;
373 TopoDS_Edge CurEdge = wexp.Current();
374 TopoDS_Edge LastEdge = CurEdge;
376 TopoDS_Wire aSectionWire;
377 TopoDS_Vertex aBreakVertex;
380 wexp.Init(CurWire, FaceRef);
383 if (MW->Wire().Closed())
385 CurVertex = wexp.CurrentVertex();
386 if (VerSecMap.IsBound(CurVertex))
388 TopoDS_Shape aLocalWire = ChooseDirection(LastEdge, CurVertex, FaceRef, VerSecMap(CurVertex));
389 aSectionWire = TopoDS::Wire(aLocalWire);
392 CurEdge = wexp.Current();
397 wexp.Init(CurWire, FaceRef);
399 if (MW->Wire().Closed())
401 NewWires.Append(MW->Wire());
402 theStartVertex = TopoDS::Vertex(BreakVertices.First());
403 BreakVertices.RemoveFirst();
404 CurWire = TopoDS::Wire(BreakOnWires.First());
405 BreakOnWires.RemoveFirst();
406 wexp.Init(CurWire, FaceRef);
407 while (!wexp.CurrentVertex().IsSame(theStartVertex))
409 MW = new BRepLib_MakeWire();
412 aBreakVertex = CurVertex;
413 BreakVertices.Append(aBreakVertex);
414 BreakOnWires.Append(CurWire);
417 MW->Add(aSectionWire);
418 (SectionsTimes(aSectionWire))--;
419 if (SectionsTimes(aSectionWire) == 0)
420 SectionsTimes.UnBind(aSectionWire);
421 if (MW->Wire().Closed())
423 NewWires.Append(MW->Wire());
424 if (SectionsTimes.IsEmpty())
426 theStartVertex = TopoDS::Vertex(BreakVertices.First());
427 BreakVertices.RemoveFirst();
428 CurWire = TopoDS::Wire(BreakOnWires.First());
429 BreakOnWires.RemoveFirst();
430 wexp.Init(CurWire, FaceRef);
431 while (!wexp.CurrentVertex().IsSame(theStartVertex))
433 MW = new BRepLib_MakeWire();
438 TopoDS_Vertex V1, V2, aStartVertex;
439 TopExp::Vertices(aSectionWire, V1, V2);
440 aStartVertex = (V1.IsSame(aBreakVertex))? V2 : V1;
441 CurWire = TopoDS::Wire(VerWireMap(aStartVertex));
443 wexp.Init(CurWire, FaceRef);
444 while (!wexp.CurrentVertex().IsSame(aStartVertex))
447 const TopTools_ListOfShape& Lsections = VerSecMap(aStartVertex);
448 if (Lsections.Extent() == 1)
451 //else: choose the way
452 TopoDS_Wire NextSectionWire =
453 TopoDS::Wire((aSectionWire.IsSame(Lsections.First()))? Lsections.Last() : Lsections.First());
455 Standard_Integer Times = 0;
456 TopTools_DataMapIteratorOfDataMapOfShapeShape itVW(VerWireMap);
457 for (; itVW.More(); itVW.Next())
458 if (itVW.Value().IsSame(CurWire))
460 if (Times == 1) //it is inner touching wire
462 //InnerTouchingWiresOnVertex.Bind(aWire, aStartVertex);
466 //we have to choose the direction
467 TopoDS_Edge aStartEdge = wexp.Current();
468 TopTools_ListOfShape Ldirs;
469 Ldirs.Append(aStartEdge);
470 Ldirs.Append(NextSectionWire);
471 TopoDS_Shape theDirection = ChooseDirection(aSectionWire, aStartVertex, FaceRef, Ldirs);
472 if (theDirection.IsSame(aStartEdge))
475 aSectionWire = NextSectionWire;
476 aBreakVertex = aStartVertex;
477 } //end of else (MW is not closed)
478 } //end of for (;;) (loop on section wires)
479 if (SectionsTimes.IsEmpty())
481 } //end of global for (;;)
483 TopTools_ListOfShape NewFaces;
485 for (itl.Initialize(NewWires); itl.More(); itl.Next())
487 TopoDS_Shape aLocalFace = FaceRef.EmptyCopied();
488 TopoDS_Face aNewFace = TopoDS::Face(aLocalFace);
489 aNewFace.Orientation(TopAbs_FORWARD);
490 BB.Add(aNewFace, itl.Value());
491 NewFaces.Append(aNewFace);
495 TopTools_ListOfShape Holes;
496 for (ExploF.Init(FaceRef, TopAbs_WIRE); ExploF.More(); ExploF.Next())
498 const TopoDS_Shape& aWire = ExploF.Current();
499 ExploW.Init(aWire, TopAbs_EDGE);
500 TopoDS_Shape anEdge = ExploW.Current();
501 Standard_Boolean found = Standard_False;
502 for (itl.Initialize(NewWires); itl.More(); itl.Next())
504 const TopoDS_Shape& aNewWire = itl.Value();
505 for (ExploW.Init(aNewWire, TopAbs_EDGE); ExploW.More(); ExploW.Next())
507 if (anEdge.IsSame(ExploW.Current()))
509 found = Standard_True;
519 TopTools_ListIteratorOfListOfShape itlNewF;
520 for (itl.Initialize(Holes); itl.More(); itl.Next())
522 const TopoDS_Wire& aHole = TopoDS::Wire(itl.Value());
523 for (itlNewF.Initialize(NewFaces); itlNewF.More(); itlNewF.Next())
525 TopoDS_Face& aNewFace = TopoDS::Face(itlNewF.Value());
526 if (IsInside(aNewFace, aHole))
528 BB.Add(aNewFace, aHole);
537 //Update of descendants of wires
538 for (ExploF.Init(F, TopAbs_WIRE); ExploF.More(); ExploF.Next())
540 TopTools_ListOfShape& ls = myMap(ExploF.Current());
545 // JAG 10.11.95 Codage des regularites
546 for (itl.Initialize(aLInside); itl.More(); itl.Next())
547 for (ExploW.Init(itl.Value(), TopAbs_EDGE); ExploW.More(); ExploW.Next())
549 const TopoDS_Edge& edg = TopoDS::Edge(ExploW.Current());
550 if (!BRep_Tool::HasContinuity(edg,F,F)) {
551 BB.Continuity(edg,F,F,GeomAbs_CN);
554 return Standard_True;
558 //=======================================================================
561 //=======================================================================
563 Standard_Boolean LocOpe_SplitShape::Add(const TopoDS_Wire& W,
564 const TopoDS_Face& F)
568 return Standard_False;
573 TopTools_ListOfShape& lf = myMap(F);
579 if (!LocOpe::Closed(W,F)) {
580 if(!AddOpenWire(W,F))
581 return Standard_False;
584 if(!AddClosedWire(W,F))
585 return Standard_False;
587 } catch (Standard_Failure ) {
589 cout << "Warning: SpliShape internal problem detected, some faces may be lost. Check input edges/wires" <<endl;
591 return Standard_False;
593 // JAG 10.11.95 Codage des regularites
595 for (exp.Init(W,TopAbs_EDGE); exp.More(); exp.Next()) {
596 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
597 if (!BRep_Tool::HasContinuity(edg,F,F)) {
598 B.Continuity(edg,F,F,GeomAbs_CN);
601 return Standard_True;
606 //=======================================================================
607 //function : AddClosedWire
609 //=======================================================================
611 Standard_Boolean LocOpe_SplitShape::AddClosedWire(const TopoDS_Wire& W,
612 const TopoDS_Face& F)
616 // On cherche la face descendante de F qui continent le wire
617 TopTools_ListOfShape& lf = myMap(F);
618 TopTools_ListIteratorOfListOfShape itl(lf);
620 for (; itl.More(); itl.Next()) {
621 const TopoDS_Face& fac = TopoDS::Face(itl.Value());
623 if (IsInside(fac,W)) {
629 return Standard_False;
634 TopAbs_Orientation orWire = W.Orientation();
635 TopoDS_Shape aLocalFace = F.EmptyCopied();
636 TopoDS_Face newFace = TopoDS::Face(aLocalFace);
637 // TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied());
638 newFace.Orientation(TopAbs_FORWARD);
641 // BRepGProp::SurfaceProperties (newFace,GP);
642 // if (GP.Mass() < 0) {
643 BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
644 if (classif.PerformInfinitePoint() == TopAbs_IN) {
645 //le wire donne defini un trou
646 aLocalFace = F.EmptyCopied();
647 newFace = TopoDS::Face(aLocalFace);
648 // newFace = TopoDS::Face(F.EmptyCopied());
649 newFace.Orientation(TopAbs_FORWARD);
650 orWire = TopAbs::Reverse(orWire);
651 B.Add(newFace,W.Oriented(orWire));
654 TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
655 FaceRef.Orientation(TopAbs_FORWARD);
658 aLocalFace = FaceRef.EmptyCopied();
659 TopoDS_Face newRef = TopoDS::Face(aLocalFace);
660 // TopoDS_Face newRef = TopoDS::Face(FaceRef.EmptyCopied());
661 newRef.Orientation(TopAbs_FORWARD);
663 // On suppose que les edges du wire ont des courbes 2d.
664 // Comme on ne change pas de surface de base, pas besoin d`UpdateEdge.
666 for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
667 exp.More(); exp.Next()) {
668 const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
669 if (IsInside(F,wir,W)) {
676 B.Add(newRef,W.Oriented(TopAbs::Reverse(orWire)));
679 return Standard_True;
683 //=======================================================================
684 //function : AddOpenWire
686 //=======================================================================
688 Standard_Boolean LocOpe_SplitShape::AddOpenWire(const TopoDS_Wire& W,
689 const TopoDS_Face& F)
691 // On cherche la face descendante de F qui continent le wire
692 TopTools_ListOfShape& lf = myMap(F);
693 TopTools_ListIteratorOfListOfShape itl(lf);
694 TopoDS_Vertex Vfirst,Vlast;
696 BRepTools::Update(F);
698 Standard_Real tolf, toll, tol1;
700 TopoDS_Shape aLocalShape = W.Oriented(TopAbs_FORWARD);
701 TopExp::Vertices(TopoDS::Wire(aLocalShape),Vfirst,Vlast);
703 tolf = BRep_Tool::Tolerance(Vfirst);
704 toll = BRep_Tool::Tolerance(Vlast);
705 tol1 = Max(tolf, toll);
708 TopExp_Explorer exp,exp2;
710 TopoDS_Wire wfirst,wlast;
711 for (; itl.More(); itl.Next()) {
712 TopoDS_Face fac = TopoDS::Face(itl.Value());
713 if (!IsInside(fac,W)) {
717 fac.Orientation(TopAbs_FORWARD);
718 Standard_Boolean ffound = Standard_False;
719 Standard_Boolean lfound = Standard_False;
720 for (exp.Init(fac,TopAbs_WIRE); exp.More(); exp.Next()) {
721 const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
722 for (exp2.Init(wir,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
723 if (!ffound && exp2.Current().IsSame(Vfirst)) {
724 ffound = Standard_True;
727 else if (!lfound && exp2.Current().IsSame(Vlast)) {
728 lfound = Standard_True;
731 if (ffound && lfound) {
744 return Standard_False;
747 TopoDS_Face FaceRef = TopoDS::Face(itl.Value());
748 FaceRef.Orientation(TopAbs_FORWARD);
752 BRepAdaptor_Surface BAS(FaceRef, Standard_False);
754 Standard_Boolean IsPeriodic = BAS.IsUPeriodic() || BAS.IsVPeriodic();
756 tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1));
758 if (wfirst.IsSame(wlast)) {
759 // on cree 2 faces en remplacement de itl.Value()
761 TopTools_ListOfShape WiresFirst;
762 for (exp.Init(wfirst,TopAbs_EDGE); exp.More(); exp.Next()) {
763 if (BRep_Tool::IsClosed(TopoDS::Edge(exp.Current()),FaceRef)) {
764 myDblE.Add(exp.Current());
766 WiresFirst.Append(exp.Current());
769 TopAbs_Orientation orient;
770 TopoDS_Wire newW1,newW2;
772 newW1.Orientation(TopAbs_FORWARD);
774 newW2.Orientation(TopAbs_FORWARD);
776 Standard_Integer nbE = 0;
777 for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
778 exp.More(); exp.Next()) {
780 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
781 orient = edg.Orientation();
782 WiresFirst.Append(edg);
783 WiresFirst.Append(edg.Oriented(TopAbs::Reverse(orient)));
787 TopTools_IndexedMapOfShape PossE;
788 TopTools_MapOfOrientedShape MapE;
789 TopoDS_Vertex vdeb,vfin;
790 Standard_Integer nbPoss;
792 // On recherche l`edge contenant Vlast
793 TopoDS_Edge LastEdge;
794 gp_Pnt2d pfirst,plast;
796 Handle(Geom2d_Curve) C2d;
799 for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
800 exp.More(); exp.Next()) {
801 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
802 for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
803 if (exp2.Current().IsSame(Vfirst)) {
809 LastEdge.Orientation(edg.Orientation());
814 TopoDS_Shape aLocalFace = FaceRef.Oriented(wfirst.Orientation());
815 C2d = BRep_Tool::CurveOnSurface(LastEdge, TopoDS::Face(aLocalFace), f, l);
817 if (LastEdge.Orientation() == TopAbs_FORWARD) {
818 pfirst = C2d->Value(f);
821 pfirst = C2d->Value(l);
824 for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
825 exp.More(); exp.Next()) {
826 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
827 if( nbE>1 && edg.IsSame(LastEdge) )
829 for (exp2.Init(edg,TopAbs_VERTEX); exp2.More(); exp2.Next()) {
830 if (exp2.Current().IsSame(Vlast)) {
836 LastEdge.Orientation(edg.Orientation());
840 aLocalFace = FaceRef.Oriented(wfirst.Orientation());
841 GetDirection(LastEdge, TopoDS::Face(aLocalFace),plast , dlast, Standard_False);
843 Standard_Boolean cond;
847 cond = !(Vfirst.IsSame(Vlast) && SameUV(pfirst,plast,BAS));
850 cond = !(Vfirst.IsSame(Vlast));
856 // On enchaine par la fin
857 TopTools_ListIteratorOfListOfShape lexp(WiresFirst);
858 for (; lexp.More(); lexp.Next()) {
859 const TopoDS_Edge& edg = TopoDS::Edge(lexp.Value());
861 orient = edg.Orientation();
862 TopExp::Vertices(edg,vdeb,vfin);
864 if ((orient == TopAbs_FORWARD && Vlast.IsSame(vdeb)) ||
865 (orient == TopAbs_REVERSED && Vlast.IsSame(vfin)))
868 nbPoss = PossE.Extent();
874 TopoDS_Edge aNextEdge;
876 aNextEdge = TopoDS::Edge (PossE.FindKey (1));
877 TopoDS_Shape aLocalFaceTemp = FaceRef.Oriented(wfirst.Orientation());
878 GetDirection(aNextEdge, TopoDS::Face(aLocalFaceTemp),plast , dlast, Standard_False);
881 else if (nbPoss > 1) {
882 // Faire choix en U,V...
883 TopoDS_Shape aLocalFaceTemp = FaceRef.Oriented(wfirst.Orientation());
885 if(!ChoixUV(LastEdge, TopoDS::Face(aLocalFaceTemp), PossE,
886 aNextEdge, plast, dlast, toll))
887 return Standard_False;
892 if (aNextEdge.IsNull())
894 // loop is not closed. Split is not possible
895 return Standard_False;
898 if (MapE.Contains(aNextEdge))
900 B.Add(newW1, aNextEdge);
902 LastEdge = aNextEdge;
904 if (LastEdge.Orientation() == TopAbs_FORWARD) {
905 Vlast = TopExp::LastVertex(LastEdge);
908 Vlast = TopExp::FirstVertex(LastEdge);
911 toll = BRep_Tool::Tolerance(Vlast);
912 tol1 = Max(tolf, toll);
915 //MODIFICATION PIERRE SMEYERS : si pas de possibilite, on sort avec erreur
917 cout<<"erreur Spliter : pas de chainage du wire"<<endl;
918 return Standard_False;
922 tol1 = Max(BAS.UResolution(tol1), BAS.VResolution(tol1));
926 TopTools_ListIteratorOfListOfShape lexp(WiresFirst);
927 for (; lexp.More(); lexp.Next()) {
928 const TopoDS_Edge& edg = TopoDS::Edge(lexp.Value());
929 if (!MapE.Contains(edg)) {
935 TopoDS_Face newF1,newF2;
936 aLocalFace = FaceRef.EmptyCopied();
937 newF1 = TopoDS::Face(aLocalFace);
938 newF1.Orientation(TopAbs_FORWARD);
939 aLocalFace = FaceRef.EmptyCopied();
940 newF2 = TopoDS::Face(aLocalFace);
941 newF2.Orientation(TopAbs_FORWARD);
943 // modifs JAG 97.05.28
947 for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE); exp.More(); exp.Next()) {
948 const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
949 if (!wir.IsSame(wfirst)) {
950 if (IsInside(newF1, wir)) {
953 else if (IsInside(newF2, wir)) {
957 // Ce wire est ni dans newF2 ni dans newF1
958 // Peut etre faut il construire une troisieme face
959 cout << "WARNING: LocOpe_SPlitShape : Ce wire est ni dans newF2 ni dans newF1" << endl;
966 // Mise a jour des descendants des wires
967 for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) {
968 TopTools_ListOfShape& ls = myMap(exp.Current());
970 for (; itl.More(); itl.Next()) {
971 if (itl.Value().IsSame(wfirst)) {
975 if (itl.More()) { // on a trouve le wire
983 // on ne cree qu`une seule face
984 TopoDS_Wire outerW = BRepTools::OuterWire(FaceRef);
988 newWire.Orientation(TopAbs_FORWARD);
989 TopAbs_Orientation orient,orRelat;
991 if (wfirst.Orientation() == wlast.Orientation()) {
992 orRelat = TopAbs_FORWARD;
995 orRelat = TopAbs_REVERSED;
998 if (wlast.IsSame(outerW)) {
1004 for (exp.Init(wfirst.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1005 exp.More(); exp.Next()) {
1006 B.Add(newWire,TopoDS::Edge(exp.Current()));
1010 for (exp.Init(wlast.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1011 exp.More(); exp.Next()) {
1012 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1013 orient = TopAbs::Compose(edg.Orientation(),orRelat);
1014 B.Add(newWire,edg.Oriented(orient));
1018 // Edges du wire ajoute, et dans les 2 sens
1019 for (exp.Init(W.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
1020 exp.More(); exp.Next()) {
1021 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1022 orient = edg.Orientation();
1023 B.Add(newWire,edg.Oriented(orient));
1024 B.Add(newWire,edg.Oriented(TopAbs::Reverse(orient)));
1025 myDblE.Add(edg.Oriented(orient));
1028 // on refait une face
1030 TopoDS_Shape aLocalFace = FaceRef.EmptyCopied();
1031 newFace = TopoDS::Face(aLocalFace);
1032 // newFace = TopoDS::Face(FaceRef.EmptyCopied());
1033 FaceRef.Orientation(TopAbs_FORWARD);
1034 for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
1035 exp.More(); exp.Next()) {
1036 const TopoDS_Wire& wir = TopoDS::Wire(exp.Current());
1037 if (wir.IsSame(wfirst)) {
1038 B.Add(newFace,newWire.Oriented(wir.Orientation()));
1040 else if (!wir.IsSame(wlast)) {
1046 // Mise a jour des descendants des wires
1047 for (exp.Init(F,TopAbs_WIRE); exp.More(); exp.Next()) {
1048 TopTools_ListOfShape& ls = myMap(exp.Current());
1050 Standard_Boolean touch = Standard_False;
1051 while (itl.More()) {
1052 if (itl.Value().IsSame(wfirst) || itl.Value().IsSame(wlast)) {
1054 touch = Standard_True;
1066 return Standard_True;
1070 //=======================================================================
1073 //=======================================================================
1075 const TopTools_ListOfShape& LocOpe_SplitShape::LeftOf(const TopoDS_Wire& W,
1076 const TopoDS_Face& F)
1078 if (myShape.IsNull()) {
1079 Standard_NoSuchObject::Raise();
1082 TopExp_Explorer exp,expw,expf;
1083 exp.Init(myShape,TopAbs_FACE);
1084 for (; exp.More(); exp.Next()) {
1085 if (exp.Current().IsSame(F)) {
1090 Standard_NoSuchObject::Raise();
1094 const TopoDS_Face& theFace = TopoDS::Face(exp.Current());
1095 TopAbs_Orientation orFace = theFace.Orientation();
1096 TopTools_ListIteratorOfListOfShape itl,itl2;
1098 for (expw.Init(W,TopAbs_EDGE); expw.More(); expw.Next()) {
1099 const TopoDS_Edge& edg = TopoDS::Edge(expw.Current());
1100 for (itl.Initialize(myMap(theFace)); itl.More(); itl.Next()) {
1101 TopoDS_Face fac = TopoDS::Face(itl.Value());
1102 fac.Orientation(orFace);
1103 for (expf.Init(fac,TopAbs_EDGE); expf.More(); expf.Next()) {
1104 const TopoDS_Edge& edgbis = TopoDS::Edge(expf.Current());
1105 if (edgbis.IsSame(edg) &&
1106 edgbis.Orientation() == edg.Orientation()) {
1107 for (itl2.Initialize(myLeft); itl2.More(); itl2.Next()) {
1108 if (itl2.Value().IsSame(fac)) {
1112 if (!itl2.More()) { // la face n`est pas deja presente
1118 if (expf.More()) { // face found
1127 //=======================================================================
1128 //function : DescendantShapes
1130 //=======================================================================
1132 const TopTools_ListOfShape& LocOpe_SplitShape::DescendantShapes
1133 (const TopoDS_Shape& S)
1137 myDone = Standard_True;
1140 if (!myDblE.IsEmpty()) {
1141 cout << "Le shape comporte des faces invalides" << endl;
1149 //=======================================================================
1152 //=======================================================================
1154 void LocOpe_SplitShape::Put(const TopoDS_Shape& S)
1156 if (!myMap.IsBound(S)) {
1157 TopTools_ListOfShape thelist;
1158 myMap.Bind(S, thelist);
1159 if (S.ShapeType() != TopAbs_VERTEX) {
1160 for(TopoDS_Iterator theIterator(S);theIterator.More();
1161 theIterator.Next()) {
1162 Put(theIterator.Value());
1172 //=======================================================================
1173 //function : Rebuild
1175 //=======================================================================
1177 Standard_Boolean LocOpe_SplitShape::Rebuild(const TopoDS_Shape& S)
1181 TopTools_ListIteratorOfListOfShape itr(myMap(S));
1183 if (itr.Value().IsSame(S)) {
1184 return Standard_False;
1186 return Standard_True;
1188 Standard_Boolean rebuild = Standard_False;
1190 for(it.Initialize(S); it.More(); it.Next()) {
1191 rebuild = Rebuild(it.Value()) || rebuild;
1196 TopoDS_Shape result = S.EmptyCopied();
1197 TopAbs_Orientation orient;
1198 for(it.Initialize(S); it.More(); it.Next()) {
1199 orient = it.Value().Orientation();
1200 for (itr.Initialize(myMap(it.Value())); itr.More(); itr.Next()) {
1201 B.Add(result,itr.Value().Oriented(orient));
1204 // Assign "Closed" flag for Wires and Shells only
1205 if (result.ShapeType() == TopAbs_WIRE || result.ShapeType() == TopAbs_SHELL)
1206 result.Closed (BRep_Tool::IsClosed(result));
1207 myMap(S).Append(result);
1217 //=======================================================================
1218 //function : IsInside
1220 //=======================================================================
1222 static Standard_Boolean IsInside(const TopoDS_Face& F,
1223 const TopoDS_Wire& W1,
1224 const TopoDS_Wire& W2)
1226 // Attention, c`est tres boeuf !!!!
1228 TopoDS_Shape aLocalShape = F.EmptyCopied();
1229 TopoDS_Face newFace = TopoDS::Face(aLocalShape);
1230 // TopoDS_Face newFace = TopoDS::Face(F.EmptyCopied());
1232 //TopAbs_Orientation orWire = W2.Orientation();
1234 newFace.Orientation(TopAbs_FORWARD);
1237 // BRepGProp::SurfaceProperties(newFace,GP);
1238 // if (GP.Mass() < 0) {
1239 BRepTopAdaptor_FClass2d classif(newFace,Precision::PConfusion());
1240 Standard_Boolean Reversed = Standard_False;
1241 if (classif.PerformInfinitePoint() == TopAbs_IN) {
1242 //le wire donne defini un trou
1243 // newFace = TopoDS::Face(F.EmptyCopied());
1244 // newFace.Orientation(TopAbs_FORWARD);
1245 // orWire = TopAbs::Reverse(orWire);
1246 // B.Add(newFace,W2.Oriented(orWire));
1247 Reversed = Standard_True;
1250 // Standard_Real U,V;
1251 TopExp_Explorer exp(W1,TopAbs_EDGE);
1252 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1253 TopExp_Explorer exp2(edg,TopAbs_VERTEX);
1254 const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
1255 Standard_Real prm = BRep_Tool::Parameter(vtx,edg);
1257 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
1260 cout << "Edge is not on surface" <<endl;
1262 return Standard_False;
1264 gp_Pnt2d pt2d(C2d->Value(prm));
1265 // BRepClass_FaceClassifier classif(newFace,pt2d,Precision::PConfusion());
1266 // return (classif.State() == TopAbs_IN);
1268 return (classif.Perform(pt2d) == TopAbs_IN);
1271 return (classif.Perform(pt2d) == TopAbs_OUT);
1276 //=======================================================================
1277 //function : IsInside
1279 //=======================================================================
1281 static Standard_Boolean IsInside(const TopoDS_Face& F,
1282 const TopoDS_Wire& W)
1284 // Attention, c`est tres boeuf !!!!
1285 TopExp_Explorer exp(W,TopAbs_EDGE);
1286 for( ; exp.More(); exp.Next()) {
1287 const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
1288 // TopExp_Explorer exp2(edg,TopAbs_VERTEX);
1289 // const TopoDS_Vertex& vtx = TopoDS::Vertex(exp2.Current());
1290 // Standard_Real prm = BRep_Tool::Parameter(vtx,edg);
1291 Standard_Real f,l,prm;
1292 Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,F,f,l);
1293 if (!Precision::IsNegativeInfinite(f) &&
1294 !Precision::IsPositiveInfinite(l)) {
1298 if (Precision::IsNegativeInfinite(f) &&
1299 Precision::IsPositiveInfinite(l)){
1302 else if (Precision::IsNegativeInfinite(f)) {
1310 gp_Pnt2d pt2d(C2d->Value(prm));
1311 // BRepClass_FaceClassifier classif(F,pt2d,Precision::PConfusion());
1312 // return (classif.State() != TopAbs_OUT);
1313 BRepTopAdaptor_FClass2d classif(F,Precision::PConfusion());
1314 TopAbs_State stat = classif.Perform(pt2d);
1315 // return (classif.Perform(pt2d) != TopAbs_OUT);
1316 if(stat == TopAbs_OUT) return Standard_False;
1318 if(stat == TopAbs_ON) {
1319 Standard_Integer nbPnt =10;
1320 Standard_Integer nbOut =0,nbIn =0,nbOn=0;
1321 Standard_Integer j =1;
1322 for( ; j<= nbPnt ; j++)
1324 //check neighbouring point
1325 //prm = .66 * prm + .34 * l;
1326 prm = f + (l-f)/nbPnt*(j-1);
1327 pt2d = C2d->Value(prm);
1328 stat = classif.Perform(pt2d);
1329 if(stat == TopAbs_OUT )
1331 else if(stat == TopAbs_IN)
1336 if(nbOut > nbIn + nbOn)
1337 return Standard_False;
1340 return Standard_True;
1343 //=======================================================================
1344 //function : GetDirection
1346 //=======================================================================
1347 static void GetDirection(const TopoDS_Edge& theEdge,
1348 const TopoDS_Face& theFace,
1351 Standard_Boolean isFirstEnd)
1353 Standard_Real aFirst, aLast;
1354 Handle(Geom2d_Curve) aC2d = BRep_Tool::CurveOnSurface (theEdge, theFace, aFirst, aLast);
1356 TopAbs_Orientation anOr = theEdge.Orientation();
1358 Standard_Boolean takeFirst = ((anOr == TopAbs_FORWARD && isFirstEnd) ||
1359 (anOr == TopAbs_REVERSED && !isFirstEnd));
1361 Standard_Real dpar = (aLast - aFirst)*0.01;
1365 aC2d->D0 (aFirst, thePnt);
1366 gp_Pnt2d aNextPnt = aC2d->Value(aFirst + dpar);
1367 theDir = gp_Vec2d(thePnt, aNextPnt);
1372 aC2d->D0 (aLast, thePnt);
1373 gp_Pnt2d aPrevPnt = aC2d->Value(aLast - dpar);
1374 theDir = gp_Vec2d( aPrevPnt, thePnt );
1376 if(anOr == TopAbs_REVERSED)
1380 //=======================================================================
1381 //function : ChoixUV
1383 //=======================================================================
1385 Standard_Boolean ChoixUV(const TopoDS_Edge& Last,
1386 const TopoDS_Face& F,
1387 const TopTools_IndexedMapOfShape& Poss,
1388 TopoDS_Edge& theResEdge,
1391 const Standard_Real toll)
1395 gp_Pnt aPCur, aPlst;
1397 BRepAdaptor_Surface surf(F,Standard_False); // no restriction
1398 surf.D0 (plst.X(), plst.Y(), aPlst);
1402 gp_Dir2d ref2d(dlst);
1404 Handle(Geom2d_Curve) C2d;
1407 Standard_Integer index = 0, imin=0;
1408 Standard_Real angmax = -M_PI, dist, ang;
1410 for (index = 1; index <= Poss.Extent(); index++) {
1411 TopoDS_Edge anEdge = TopoDS::Edge (Poss.FindKey (index));
1413 TopoDS_Vertex aVF = TopExp::FirstVertex(anEdge, Standard_True);
1416 tol = BRep_Tool::Tolerance(aVF);
1417 GetDirection (anEdge, F, p2d, v2d, Standard_True);
1419 surf.D0 (p2d.X(), p2d.Y(), aPCur);
1421 tol = Max(toll, tol); tol *= tol;
1423 dist = aPCur.SquareDistance(aPlst);
1425 if (!Last.IsSame(anEdge)) {
1426 ang = ref2d.Angle(gp_Dir2d(v2d));
1432 if ((dist - tol < Epsilon(1.0)) && (ang > angmax)) {
1440 theResEdge = TopoDS::Edge (Poss.FindKey (imin));
1441 GetDirection (theResEdge, F, plst, dlst, Standard_False);
1447 //=======================================================================
1448 //function : ChooseDirection
1450 //=======================================================================
1452 static TopoDS_Shape ChooseDirection(const TopoDS_Shape& RefDir,
1453 const TopoDS_Vertex& RefVertex,
1454 const TopoDS_Face& theFace,
1455 const TopTools_ListOfShape& Ldirs)
1457 TopExp_Explorer Explo(RefDir, TopAbs_EDGE);
1458 TopoDS_Edge RefEdge;
1459 TopoDS_Vertex V1, V2;
1460 TopAbs_Orientation anOr = TopAbs_FORWARD;
1461 for (; Explo.More(); Explo.Next())
1463 RefEdge = TopoDS::Edge(Explo.Current());
1464 TopExp::Vertices(RefEdge, V1, V2);
1465 if (V1.IsSame(RefVertex))
1467 anOr = TopAbs_REVERSED;
1470 else if (V2.IsSame(RefVertex))
1472 anOr = TopAbs_FORWARD;
1477 Standard_Real RefFirst, RefLast;
1478 Handle(Geom2d_Curve) RefCurve = BRep_Tool::CurveOnSurface(RefEdge, theFace, RefFirst, RefLast);
1482 //Standard_Real RefPar = (RefEdge.Orientation() == TopAbs_FORWARD)? RefLast : RefFirst;
1483 Standard_Real RefPar = (anOr == TopAbs_FORWARD)? RefLast : RefFirst;
1484 RefCurve->D1(RefPar, RefPnt, RefVec);
1485 if (anOr == TopAbs_FORWARD)
1488 Handle(Geom2d_Curve) aCurve;
1489 Standard_Real aFirst, aLast, aPar;
1491 Standard_Real MinAngle = RealLast(), anAngle;
1492 TopoDS_Shape TargetDir;
1493 TopTools_ListIteratorOfListOfShape itl(Ldirs);
1494 for (; itl.More(); itl.Next())
1496 const TopoDS_Shape& aShape = itl.Value();
1498 for (Explo.Init(aShape, TopAbs_EDGE); Explo.More(); Explo.Next())
1500 anEdge = TopoDS::Edge(Explo.Current());
1501 TopExp::Vertices(anEdge, V1, V2);
1502 if (V1.IsSame(RefVertex))
1504 anOr = TopAbs_FORWARD;
1507 else if (V2.IsSame(RefVertex))
1509 anOr = TopAbs_REVERSED;
1513 aCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, aFirst, aLast);
1514 aPar = (anOr == TopAbs_FORWARD)? aFirst : aLast;
1515 aCurve->D1(aPar, RefPnt, aVec);
1516 if (anOr == TopAbs_REVERSED)
1518 anAngle = aVec.Angle(RefVec);
1522 if (anAngle < MinAngle)