1 // Created on: 1996-01-05
2 // Created by: Jean Yves LEBEY
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.
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <Precision.hxx>
23 #include <Standard_ProgramError.hxx>
24 #include <TopAbs_Orientation.hxx>
27 #include <TopoDS_Compound.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Face.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Vertex.hxx>
32 #include <TopOpeBRepBuild_BlockBuilder.hxx>
33 #include <TopOpeBRepBuild_define.hxx>
34 #include <TopOpeBRepBuild_FaceBuilder.hxx>
35 #include <TopOpeBRepBuild_Loop.hxx>
36 #include <TopOpeBRepBuild_LoopSet.hxx>
37 #include <TopOpeBRepBuild_ShapeSet.hxx>
38 #include <TopOpeBRepBuild_WireEdgeClassifier.hxx>
39 #include <TopOpeBRepBuild_WireEdgeSet.hxx>
40 #include <TopOpeBRepDS_BuildTool.hxx>
41 #include <TopTools_Array1OfShape.hxx>
42 #include <TopTools_DataMapOfShapeInteger.hxx>
43 #include <TopTools_DataMapOfShapeListOfShape.hxx>
44 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
45 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
46 #include <TopTools_IndexedMapOfOrientedShape.hxx>
47 #include <TopTools_IndexedMapOfShape.hxx>
48 #include <TopTools_ListOfShape.hxx>
50 //#include <BRepAdaptor_Curve2d.hxx>
52 // MSV: RM_HANGING behaviour: when state of wire is UNCLOSEDW we do not
53 // remove the whole wire but remove the chains of hanging edges. This would
54 // produce a good result in some cases. But :-( it gives regressions on grid
55 // tests (1cto 021 W4,X4). Therefore I leaved this code not active.
57 #include <TColStd_ListIteratorOfListOfInteger.hxx>
61 extern Standard_Boolean TopOpeBRepBuild_GettracePURGE();
66 #include <TopOpeBRepTool_DRAW.hxx>
69 //=======================================================================
70 //function : TopOpeBRepBuild_FaceBuilder
72 //=======================================================================
73 TopOpeBRepBuild_FaceBuilder::TopOpeBRepBuild_FaceBuilder()
77 //=======================================================================
78 //function : TopOpeBRepBuild_FaceBuilder
80 //=======================================================================
81 TopOpeBRepBuild_FaceBuilder::TopOpeBRepBuild_FaceBuilder(TopOpeBRepBuild_WireEdgeSet& WES,const TopoDS_Shape& F,const Standard_Boolean ForceClass)
83 InitFaceBuilder(WES,F,ForceClass);
86 //=======================================================================
87 //function : InitFaceBuilder
89 //=======================================================================
90 void TopOpeBRepBuild_FaceBuilder::InitFaceBuilder(TopOpeBRepBuild_WireEdgeSet& WES,const TopoDS_Shape& F,const Standard_Boolean ForceClass)
92 myFace = TopoDS::Face(F);
94 TopOpeBRepBuild_BlockBuilder& BB = myBlockBuilder;
95 TopOpeBRepBuild_WireEdgeClassifier WEC(F,BB);
96 TopOpeBRepBuild_LoopSet& LS = myLoopSet;
97 myFaceAreaBuilder.InitFaceAreaBuilder(LS,WEC,ForceClass);
100 //---------------------------------------------------------------
101 void FUN_DetectVerticesOn1Edge(const TopoDS_Shape& W,TopTools_IndexedDataMapOfShapeShape& mapVon1E)
103 // Fills the map <mapVon1edge>,with vertices of <W> of 3d connexity 1.
104 TopTools_IndexedDataMapOfShapeListOfShape mapVedges;
105 TopExp::MapShapesAndAncestors(W,TopAbs_VERTEX,TopAbs_EDGE,mapVedges);
106 Standard_Integer nV = mapVedges.Extent();
108 for (Standard_Integer i = 1;i <= nV;i++) {
109 const TopoDS_Shape& V = mapVedges.FindKey(i);
110 if (V.Orientation() == TopAbs_INTERNAL) continue;
112 const TopTools_ListOfShape& loE = mapVedges.FindFromIndex(i);
113 if (loE.Extent() < 2) {
114 // Keeping INTERNAL or EXTERNAL edges
115 const TopoDS_Shape& E = loE.First();
116 TopAbs_Orientation oriE = E.Orientation();
117 if ((oriE == TopAbs_INTERNAL) || (oriE == TopAbs_EXTERNAL)) continue;
128 Standard_Integer FUN_AnalyzemapVon1E(const TopTools_IndexedDataMapOfShapeShape& mapVon1E,
129 TopTools_IndexedDataMapOfShapeShape& mapVV)
132 Standard_Boolean trc = TopOpeBRepBuild_GettracePURGE();
133 if (trc) cout<<endl<<"* DetectUnclosedWire :"<<endl;
136 Standard_Integer res = ISUNKNOWN;
138 Standard_Integer nV = mapVon1E.Extent();
143 const TopoDS_Shape& E = mapVon1E.FindFromIndex(1);
144 Standard_Boolean Eclosed = BRep_Tool::IsClosed(E);
145 Standard_Boolean dgE = BRep_Tool::Degenerated(TopoDS::Edge(E));
146 if (dgE) res = ISVERTEX;
147 else if (Eclosed) res = CLOSEDW;
148 else res = UNCLOSEDW;
151 // Finding among all vertices,couple of vertices falling on same
153 // Filling up map <mapVV>,with (vi,vj),vi and vj are on same point.
154 Standard_Real tol = Precision::Confusion();
155 for (Standard_Integer i = 1;i <= nV;i++) {
156 const TopoDS_Vertex& vi = TopoDS::Vertex(mapVon1E.FindKey(i));
157 gp_Pnt pi = BRep_Tool::Pnt(vi);
158 for (Standard_Integer j = i+1;j <= nV;j++) {
159 const TopoDS_Vertex& vj = TopoDS::Vertex(mapVon1E.FindKey(j));
160 gp_Pnt pj = BRep_Tool::Pnt(vj);
161 Standard_Boolean same = pi.IsEqual(pj,tol);
169 Standard_Integer nVV = mapVV.Extent();
171 // MSV Oct 4, 2001: consider GCLOSEDW even if not all vertices from mapVon1E
172 // hit into mapVV; reason is the left vertices may start
173 // useless chains of hanging edges that can be removed to
174 // achieve a closed wire.
175 if (nVV > 0) res = GCLOSEDW;
177 if (nVV == nV) res = GCLOSEDW;
179 else res = UNCLOSEDW;
182 } // FUN_AnalyzemapVon1E
185 void FUN_AnalyzemapVon1EDRAW(const Standard_Integer res,
186 const TopTools_IndexedDataMapOfShapeShape& mapVon1E,
187 const TopTools_IndexedDataMapOfShapeShape& mapVV,
188 const TopoDS_Shape& W,const Standard_Integer iiwi,
189 TopTools_IndexedDataMapOfShapeShape& mapVon1EdgeDRAW,
190 TopTools_IndexedDataMapOfShapeShape& mapVVsameGDRAW)
192 Standard_Boolean trc = TopOpeBRepBuild_GettracePURGE();
195 if (res == ISVERTEX) {
196 cout<<" is vertex"<<endl;
198 else if (res == CLOSEDW) {
199 cout<<" is closed"<<endl;
201 else if (res == GCLOSEDW) {
202 cout<<" is Gclosed :"<<endl;
203 TCollection_AsciiString aa("w_");FUN_tool_draw(aa,W,iiwi);
205 for ( i = 1;i <= mapVV.Extent();i++) {
206 Standard_Integer iV = mapVVsameGDRAW.Add(mapVV.FindKey(i),mapVV.FindFromIndex(i));
207 cout<<" on vve_"<<iV; aa = "vve_";
208 FUN_tool_draw(aa,mapVVsameGDRAW.FindKey(iV),iV);
210 for (i = 1;i <= mapVon1E.Extent();i++) {
211 Standard_Integer iE = mapVon1EdgeDRAW.Add(mapVon1E.FindKey(i),mapVon1E.FindFromIndex(i));
212 cout<<" on eed_"<<iE; aa = "eed_";
213 FUN_tool_draw(aa,mapVon1EdgeDRAW.FindFromIndex(iE),iE);
217 else if (res == UNCLOSEDW) {
218 cout<<" is unclosed "<<endl;
219 TCollection_AsciiString aa("w_");FUN_tool_draw(aa,W,iiwi);
222 } // FUN_AnalyzemapVon1EDRAW
225 //=======================================================================
226 //function : DetectUnclosedWire
228 //=======================================================================
229 void TopOpeBRepBuild_FaceBuilder::DetectUnclosedWire(TopTools_IndexedDataMapOfShapeShape& mapVVsameG,
230 TopTools_IndexedDataMapOfShapeShape& mapVon1Edge)
232 // wire unclosed : has vertices of connexity == 1
233 // exception : a wire of one closed edge with only one vertex describing
234 // a face or a degenerated edge.
239 // During the wire processing,
240 // * IF THE WIRE IS G-CLOSED,we fill up the maps :
241 // - <mapVVsameG> with vertices falling on same geometry
242 // - <mapVon1Edge> with (key = vertex,item = edge),
243 // the vertex is connected to only one unclosed,undegenerated edge.
244 // * Else,if it is unclosed,we delete it (or it`s hanging edges).
247 TopTools_IndexedDataMapOfShapeShape mapVon1EdgeDRAW,mapVVsameGDRAW;
248 Standard_Boolean trc = TopOpeBRepBuild_GettracePURGE();
249 if (trc) cout<<endl<<"* DetectUnclosedWire :"<<endl<<endl;
252 Standard_Integer iiwi = 0; // DEB
255 for (;MoreFace();NextFace()) {
257 for (;MoreWire();NextWire()) {
259 Standard_Boolean isold = IsOldWire();
261 if ( trc && isold ) cout<<"wire "<<iiwi<<" is old wire => closed"<<endl;
265 TopoDS_Compound cmp;BRep_Builder BB;BB.MakeCompound(cmp);
267 for(;MoreEdge();NextEdge()) AddEdgeWire(Edge(),cmp);
268 TopoDS_Shape W = cmp;
270 // <mapVon1E> binds vertices of connexity 1 attached to one non-closed,non-degenerated edge.
271 TopTools_IndexedDataMapOfShapeShape mapVon1E;
272 FUN_DetectVerticesOn1Edge(W,mapVon1E);
274 TopTools_IndexedDataMapOfShapeShape mapVV;
275 Standard_Integer res = FUN_AnalyzemapVon1E(mapVon1E,mapVV);
277 FUN_AnalyzemapVon1EDRAW(res,mapVon1E,mapVV,W,iiwi,mapVon1EdgeDRAW,mapVVsameGDRAW);
280 if (res == ISVERTEX) {
283 else if (res == CLOSEDW) {
286 else if (res == GCLOSEDW) {
288 for (i = 1;i <= mapVV.Extent();i++) {
289 mapVVsameG.Add(mapVV.FindKey(i),mapVV.FindFromIndex(i));
291 for (i = 1;i <= mapVon1E.Extent();i++) {
292 mapVon1Edge.Add(mapVon1E.FindKey(i),mapVon1E.FindFromIndex(i));
295 else if (res == UNCLOSEDW) {
297 // MSV Oct 4, 2001: remove hanging edges
298 TopTools_IndexedDataMapOfShapeListOfShape mapVE;
299 TopExp::MapShapesAndAncestors (W, TopAbs_VERTEX, TopAbs_EDGE, mapVE);
300 Standard_Integer nV = mapVon1E.Extent();
301 for (Standard_Integer i = 1; i <= nV; i++)
303 TopoDS_Vertex V = TopoDS::Vertex (mapVon1E.FindKey(i));
304 if (mapVV.Contains(V)) continue; // V is in same geometry pair
307 const TopTools_ListOfShape &LE = mapVE.FindFromKey(V);
309 // get not yet processed edge, count the number of such edges
310 Standard_Integer nEdges = 0;
312 TColStd_ListOfInteger LOI;
313 TopTools_ListIteratorOfListOfShape itE (LE);
314 for (; itE.More() && nEdges <= 1; itE.Next())
316 const TopoDS_Edge &E = TopoDS::Edge (itE.Value());
317 Standard_Integer I = myBlockBuilder.Element(E);
318 if (!BRep_Tool::IsClosed(E) && myBlockBuilder.ElementIsValid(I))
321 TopExp::Vertices (E, Vf, Vl);
323 // consider not small edges only
331 if (nEdges != 1) break; // stop this chain
333 // remove edges from Block Builder
334 TColStd_ListIteratorOfListOfInteger itLOI (LOI);
335 for (; itLOI.More(); itLOI.Next())
336 myBlockBuilder.SetValid (itLOI.Value(), Standard_False);
339 TopoDS_Vertex aV1, aV2, otherV;
340 TopExp::Vertices (Edge, aV1, aV2);
343 else if (aV2.IsSame (V))
345 if (otherV.IsNull()) break;
351 for (ex.Init(W,TopAbs_EDGE);ex.More();ex.Next()) {
352 // for (TopExp_Explorer ex(W,TopAbs_EDGE);ex.More();ex.Next()) {
353 Standard_Integer I = myBlockBuilder.Element(ex.Current());
354 myBlockBuilder.SetValid(I,Standard_False);
360 } // DetectUnclosedWire
362 //=======================================================================
363 //function : CorrectGclosedWire
365 //=======================================================================
366 void TopOpeBRepBuild_FaceBuilder::CorrectGclosedWire(const TopTools_IndexedDataMapOfShapeShape& mapVVref,
367 const TopTools_IndexedDataMapOfShapeShape& mapVon1Edge)
369 // prequesitory : edges described by <mapVon1Edge> are not closed,not degenerated
371 if (TopOpeBRepBuild_GettracePURGE()) {
372 cout<<endl<<"* CorrectGclosedWire :"<<endl<<endl;
376 Standard_Integer nVV = mapVVref.Extent();
377 for (Standard_Integer i = 1;i <= nVV;i++) {
378 const TopoDS_Vertex& V = TopoDS::Vertex(mapVVref.FindKey(i));
379 const TopoDS_Vertex& Vref = TopoDS::Vertex(mapVVref.FindFromIndex(i));
381 if (V.IsSame(Vref)) continue;
383 TopoDS_Edge E = TopoDS::Edge(mapVon1Edge.FindFromKey(V));
384 Standard_Real paronE = BRep_Tool::Parameter(V,E);
386 BRep_Builder BB;E.Free(Standard_True);
388 TopoDS_Shape aLocalShape = Vref.Oriented(V.Orientation());
389 TopoDS_Vertex newVref = TopoDS::Vertex(aLocalShape);
390 // TopoDS_Vertex newVref = TopoDS::Vertex(Vref.Oriented(V.Orientation()));
392 TopOpeBRepDS_BuildTool BT;
393 BT.Parameter(E,newVref,paronE);
397 //=======================================================================
398 //function : DetectPseudoInternalEdge
400 //=======================================================================
401 void TopOpeBRepBuild_FaceBuilder::DetectPseudoInternalEdge(TopTools_IndexedMapOfShape& MapE)
403 TopoDS_Compound cmp;BRep_Builder BB;BB.MakeCompound(cmp);
405 for (;MoreFace();NextFace()) {
407 for (;MoreWire();NextWire()) {
408 Standard_Boolean isold = IsOldWire(); if (isold) continue;
410 for(;MoreEdge();NextEdge()) AddEdgeWire(Edge(),cmp);
414 TopTools_IndexedDataMapOfShapeListOfShape mapVOE;
415 TopExp::MapShapesAndAncestors(cmp,TopAbs_VERTEX,TopAbs_EDGE,mapVOE);
416 Standard_Integer nv = mapVOE.Extent();
419 for (Standard_Integer i = 1; i <= nv; i++) {
420 const TopTools_ListOfShape& le = mapVOE.FindFromIndex(i);
421 Standard_Integer ne = le.Extent();
423 TopTools_ListIteratorOfListOfShape ile(le); const TopoDS_Shape& e1 = ile.Value();
424 ile.Next(); const TopoDS_Shape& e2 = ile.Value();
425 Standard_Boolean same = e1.IsSame(e2);
426 TopAbs_Orientation o1 = e1.Orientation();
427 TopAbs_Orientation o2 = e2.Orientation();
428 Standard_Boolean o1co2 = (o1 == TopAbs::Complement(o2));
430 if ( same && o1co2 ) {
433 Standard_Integer ie1 = myBlockBuilder.Element(e1);
434 myBlockBuilder.SetValid(ie1,Standard_False);
436 Standard_Integer ie2 = myBlockBuilder.Element(e2);
437 myBlockBuilder.SetValid(ie2,Standard_False);
444 //=======================================================================
447 //=======================================================================
448 const TopoDS_Shape& TopOpeBRepBuild_FaceBuilder::Face() const
453 //=======================================================================
454 //function : InitFace
456 //=======================================================================
457 Standard_Integer TopOpeBRepBuild_FaceBuilder::InitFace()
459 Standard_Integer n = myFaceAreaBuilder.InitArea();
463 //=======================================================================
464 //function : MoreFace
466 //=======================================================================
467 Standard_Boolean TopOpeBRepBuild_FaceBuilder::MoreFace() const
469 Standard_Boolean b = myFaceAreaBuilder.MoreArea();
473 //=======================================================================
474 //function : NextFace
476 //=======================================================================
477 void TopOpeBRepBuild_FaceBuilder::NextFace()
479 myFaceAreaBuilder.NextArea();
482 //=======================================================================
483 //function : InitWire
485 //=======================================================================
486 Standard_Integer TopOpeBRepBuild_FaceBuilder::InitWire()
488 Standard_Integer n = myFaceAreaBuilder.InitLoop();
492 //=======================================================================
493 //function : MoreWire
495 //=======================================================================
496 Standard_Boolean TopOpeBRepBuild_FaceBuilder::MoreWire() const
498 Standard_Boolean b = myFaceAreaBuilder.MoreLoop();
502 //=======================================================================
503 //function : NextWire
505 //=======================================================================
506 void TopOpeBRepBuild_FaceBuilder::NextWire()
508 myFaceAreaBuilder.NextLoop();
511 //=======================================================================
512 //function : IsOldWire
514 //=======================================================================
515 Standard_Boolean TopOpeBRepBuild_FaceBuilder::IsOldWire() const
517 const Handle(TopOpeBRepBuild_Loop)& L = myFaceAreaBuilder.Loop();
518 Standard_Boolean b = L->IsShape();
522 //=======================================================================
525 //=======================================================================
526 const TopoDS_Shape& TopOpeBRepBuild_FaceBuilder::OldWire() const
528 const Handle(TopOpeBRepBuild_Loop)& L = myFaceAreaBuilder.Loop();
529 const TopoDS_Shape& B = L->Shape();
533 //=======================================================================
534 //function : FindNextValidElement
536 //=======================================================================
537 void TopOpeBRepBuild_FaceBuilder::FindNextValidElement()
539 // prerequisites : myBlockIterator.Initialize
540 myFaceAreaBuilder.Loop();
541 Standard_Boolean found = Standard_False;
543 while ( myBlockIterator.More()) {
544 const Standard_Integer i = myBlockIterator.Value();
545 found = myBlockBuilder.ElementIsValid(i);
547 else myBlockIterator.Next();
551 //=======================================================================
552 //function : InitEdge
554 //=======================================================================
555 Standard_Integer TopOpeBRepBuild_FaceBuilder::InitEdge()
557 const Handle(TopOpeBRepBuild_Loop)& L = myFaceAreaBuilder.Loop();
559 throw Standard_DomainError("TopOpeBRepBuild_FaceBuilder:InitEdge");
561 myBlockIterator = L->BlockIterator();
562 myBlockIterator.Initialize();
563 FindNextValidElement();
565 Standard_Integer n = myBlockIterator.Extent();
569 //=======================================================================
570 //function : MoreEdge
572 //=======================================================================
573 Standard_Boolean TopOpeBRepBuild_FaceBuilder::MoreEdge() const
575 Standard_Boolean b = myBlockIterator.More();
579 //=======================================================================
580 //function : NextEdge
582 //=======================================================================
583 void TopOpeBRepBuild_FaceBuilder::NextEdge()
585 myBlockIterator.Next();
586 FindNextValidElement();
589 //=======================================================================
592 //=======================================================================
593 const TopoDS_Shape& TopOpeBRepBuild_FaceBuilder::Edge() const
595 if (!myBlockIterator.More()) throw Standard_Failure("OutOfRange");
597 const Standard_Integer i = myBlockIterator.Value();
598 Standard_Boolean isvalid = myBlockBuilder.ElementIsValid(i);
599 if (!isvalid) throw Standard_Failure("Edge not Valid");
601 const TopoDS_Shape& E = myBlockBuilder.Element(i);
605 //=======================================================================
606 //function : EdgeConnexity
608 //=======================================================================
609 Standard_Integer TopOpeBRepBuild_FaceBuilder::EdgeConnexity(const TopoDS_Shape& /*E*/) const
612 throw Standard_ProgramError("FaceBuilder::EdgeConnexity management disactivated");
616 // Standard_Boolean inmosi = myMOSI.IsBound(E);
617 // Standard_Integer nmosi = (inmosi) ? myMOSI.Find(E) : 0;
621 //=======================================================================
622 //function : AddEdgeWire
624 //=======================================================================
625 Standard_Integer TopOpeBRepBuild_FaceBuilder::AddEdgeWire(const TopoDS_Shape& E,TopoDS_Shape& W) const
627 Standard_Integer nadd = 0;
630 // Standard_Integer nmosi = EdgeConnexity(E);
631 // Standard_Boolean addEC = (nmosi == 1);
633 // TopAbs_Orientation oe = E.Orientation();
634 // TopAbs_Orientation oc = TopAbs::Complement(oe);
635 // TopoDS_Shape EC = E.Oriented(oc);
636 // BB.Add(W,EC);nadd++;
641 //=======================================================================
642 //function : MakeLoops
644 //=======================================================================
645 void TopOpeBRepBuild_FaceBuilder::MakeLoops(TopOpeBRepBuild_ShapeSet& SS)
647 TopOpeBRepBuild_BlockBuilder& BB = myBlockBuilder;
648 TopOpeBRepBuild_ListOfLoop& LL = myLoopSet.ChangeListOfLoop();
650 // Build blocks on elements of SS
653 // make list of loop (LL) of the LoopSet
654 // - on shapes of the ShapeSet (SS)
655 // - on blocks of the BlockBuilder (BB)
657 // Add shapes of SS as shape loops
659 for(SS.InitShapes();SS.MoreShapes();SS.NextShape()) {
660 const TopoDS_Shape& S = SS.Shape();
661 Handle(TopOpeBRepBuild_Loop) ShapeLoop = new TopOpeBRepBuild_Loop(S);
662 LL.Append(ShapeLoop);
665 // Add blocks of BB as block loops
666 for (BB.InitBlock();BB.MoreBlock();BB.NextBlock()) {
667 TopOpeBRepBuild_BlockIterator BI = BB.BlockIterator();
668 Handle(TopOpeBRepBuild_Loop) BlockLoop = new TopOpeBRepBuild_Loop(BI);
669 LL.Append(BlockLoop);