1 // Created on: 1994-08-30
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1994-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 <BRepCheck.hxx>
21 #include <BRepCheck_Analyzer.hxx>
22 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
23 #include <BRepCheck_Result.hxx>
24 #include <BRepCheck_Wire.hxx>
26 #include <Standard_NoSuchObject.hxx>
27 #include <TCollection_AsciiString.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <TopoDS_Iterator.hxx>
33 #include <TopoDS_Shape.hxx>
34 #include <TopoDS_Vertex.hxx>
35 #include <TopOpeBRepBuild_Builder.hxx>
36 #include <TopOpeBRepBuild_define.hxx>
37 #include <TopOpeBRepBuild_EdgeBuilder.hxx>
38 #include <TopOpeBRepBuild_FaceBuilder.hxx>
39 #include <TopOpeBRepBuild_GTopo.hxx>
40 #include <TopOpeBRepBuild_HBuilder.hxx>
41 #include <TopOpeBRepBuild_PaveSet.hxx>
42 #include <TopOpeBRepBuild_ShapeSet.hxx>
43 #include <TopOpeBRepBuild_ShellFaceSet.hxx>
44 #include <TopOpeBRepBuild_SolidBuilder.hxx>
45 #include <TopOpeBRepBuild_WireEdgeSet.hxx>
46 #include <TopOpeBRepDS_BuildTool.hxx>
47 #include <TopOpeBRepDS_CurveIterator.hxx>
48 #include <TopOpeBRepDS_HDataStructure.hxx>
49 #include <TopOpeBRepDS_ListOfShapeOn1State.hxx>
50 #include <TopOpeBRepDS_PointIterator.hxx>
51 #include <TopOpeBRepDS_SurfaceIterator.hxx>
52 #include <TopOpeBRepTool_ShapeExplorer.hxx>
53 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
54 #include <TopTools_ListOfShape.hxx>
56 //#include <DBRep.hxx>
58 extern Standard_Boolean TopOpeBRepBuild_GettraceSPS();
61 //static Standard_Integer ifvNbFace = 0;
62 //static char *name = " ";
64 static void CorrectEdgeOrientation(TopoDS_Shape& aWire)
67 TopTools_ListOfShape anEdgeList, anAuxList, aTrueEdgeList;
69 TopoDS_Vertex vf, vl, v1f, v1l;
70 Standard_Boolean append = Standard_True;
72 TopoDS_Iterator tdi(aWire, Standard_False, Standard_False);
73 for(; tdi.More(); tdi.Next()) anEdgeList.Append(tdi.Value());
75 Standard_Integer n = anEdgeList.Extent();
78 TopTools_ListIteratorOfListOfShape anIt(anEdgeList);
80 TopoDS_Shape anCurEdge = anIt.Value();
81 TopExp::Vertices(TopoDS::Edge(anCurEdge), vf, vl, Standard_True);
82 aTrueEdgeList.Append(anCurEdge);
85 while(n > 0 && append) {
87 for(; anIt.More(); anIt.Next()) {
88 append = Standard_False;
89 anCurEdge = anIt.Value();
90 TopExp::Vertices(TopoDS::Edge(anCurEdge), v1f, v1l, Standard_True);
92 aTrueEdgeList.Append(anCurEdge);
94 append = Standard_True;
98 aTrueEdgeList.Append(anCurEdge);
100 append = Standard_True;
105 TopoDS_Shape anRevEdge = anCurEdge.Reversed();
106 aTrueEdgeList.Append(anRevEdge);
108 append = Standard_True;
112 TopoDS_Shape anRevEdge = anCurEdge.Reversed();
113 aTrueEdgeList.Append(anRevEdge);
115 append = Standard_True;
119 anAuxList.Append(anCurEdge);
122 anEdgeList.Assign(anAuxList);
123 anAuxList.Clear(); //something wrong in Assign when list contains 1 element.
124 n = anEdgeList.Extent();
125 anIt.Initialize(anEdgeList);
128 if(n > 0) aTrueEdgeList.Append(anEdgeList);
131 BB.MakeWire(TopoDS::Wire(aWire));
132 anIt.Initialize(aTrueEdgeList);
133 for(; anIt.More(); anIt.Next()) BB.Add(aWire, anIt.Value());
139 static void CorrectUnclosedWire(TopoDS_Shape& aWire)
141 // cout << "-------CorrectUnclosedWire" << endl;
143 TopoDS_Iterator tdi(aWire, Standard_False, Standard_False);
144 Standard_Integer nbe = 0;
145 for(; tdi.More(); tdi.Next()) {
147 const TopoDS_Shape& ed = tdi.Value();
148 Standard_Integer nbv = ed.NbChildren();
149 // cout << "Edge " << nbe << " : " << nbv << endl;
151 // cout << "Remove bad edge" << endl;
152 BB.Remove(aWire, ed);
156 TopTools_IndexedDataMapOfShapeListOfShape VElists;
158 TopExp::MapShapesAndAncestors(aWire, TopAbs_VERTEX, TopAbs_EDGE, VElists);
159 Standard_Integer nbVer = VElists.Extent(), i;
161 for(i = 1; i <= nbVer; i++) {
162 const TopTools_ListOfShape& Elist = VElists.FindFromIndex(i);
163 if(Elist.Extent() == 1) {
164 TopoDS_Shape anEdge = Elist.First();
165 // cout << "Remove redundant edge" << endl;
166 BB.Remove(aWire, anEdge);
171 //=======================================================================
172 //function : MergeShapes
174 //=======================================================================
177 void TopOpeBRepBuild_Builder::MergeShapes(const TopoDS_Shape& S1,const TopAbs_State ToBuild1,const TopoDS_Shape& S2,const TopAbs_State ToBuild2)
179 Standard_Boolean lesmemes = S1.IsEqual(S2);
182 cout<<"TopOpeBRepBuild : S1 == S2"<<endl;
195 Standard_Boolean S1null = S1.IsNull();
196 Standard_Boolean S2null = S2.IsNull();
201 //======================== debut KPart
207 //======================== fin KPart
209 Standard_Boolean RevOri1 = Reverse(ToBuild1,ToBuild2);
210 Standard_Boolean RevOri2 = Reverse(ToBuild2,ToBuild1);
212 // Create a face set <SFS> connected by edges
213 // -----------------------------------------
214 TopOpeBRepBuild_ShellFaceSet SFS;
217 SFS.DEBNumber(GdumpSHASETindex());
220 // NYI : SplitCompound appele par SplitShape
222 TopOpeBRepTool_ShapeExplorer ex1;
224 TopAbs_ShapeEnum t1=TopAbs_COMPOUND,tex1=TopAbs_COMPOUND;
227 t1 = tex1 = TopType(S1);
228 if ( t1 == TopAbs_COMPOUND ) {
229 tex1 = TopAbs_SOLID; ex1.Init(S1,tex1);
230 if ( ! ex1.More() ) {
231 tex1 = TopAbs_SHELL; ex1.Init(S1,tex1);
232 if ( ! ex1.More() ) {
233 tex1 = TopAbs_FACE; ex1.Init(S1,tex1);
235 tex1 = TopAbs_EDGE; ex1.Init(S1,tex1);
240 else if (t1 == TopAbs_WIRE) {
241 tex1 = TopAbs_EDGE; ex1.Init(S1,tex1);
243 else ex1.Init(S1,tex1);
244 SplitShapes(ex1,ToBuild1,ToBuild2,SFS,RevOri1);
247 TopOpeBRepTool_ShapeExplorer ex2;
249 TopAbs_ShapeEnum t2=TopAbs_COMPOUND,tex2=TopAbs_COMPOUND;
252 t2 = tex2 = TopType(S2);
253 if ( t2 == TopAbs_COMPOUND ) {
254 tex2 = TopAbs_SOLID; ex2.Init(S2,tex2);
255 if ( ! ex2.More() ) {
256 tex2 = TopAbs_SHELL; ex2.Init(S2,tex2);
257 if ( ! ex2.More() ) {
258 tex2 = TopAbs_FACE; ex2.Init(S2,tex2);
260 tex2 = TopAbs_EDGE; ex2.Init(S2,tex2);
265 else if (t2 == TopAbs_WIRE) {
266 tex2 = TopAbs_EDGE; ex2.Init(S2,tex2);
268 else ex2.Init(S2,tex2);
269 SplitShapes(ex2,ToBuild2,ToBuild1,SFS,RevOri2);
272 // S1 or S2 = COMPOUND : connect them the list of merged shapes build
273 // on the first subshape.
276 if ( t1 == TopAbs_COMPOUND ) {
277 TopTools_ListOfShape& L1 = ChangeMerged(S1,ToBuild1);
280 const TopoDS_Shape& SS1 = ex1.Current();
281 TopTools_ListOfShape& LSS1 = ChangeMerged(SS1,ToBuild1);
288 if ( t2 == TopAbs_COMPOUND ) {
289 TopTools_ListOfShape& L2 = ChangeMerged(S2,ToBuild2);
292 const TopoDS_Shape& SS2 = ex2.Current();
293 TopTools_ListOfShape& LSS2 = ChangeMerged(SS2,ToBuild2);
304 //=======================================================================
305 //function : Classify
306 //purpose : LocOpe use
307 //=======================================================================
309 Standard_Boolean TopOpeBRepBuild_Builder::Classify() const
311 return myClassifyVal;
314 //=======================================================================
315 //function : ChangeClassify
316 //purpose : LocOpe use
317 //=======================================================================
319 void TopOpeBRepBuild_Builder::ChangeClassify(const Standard_Boolean classify)
321 myClassifyDef = Standard_True;
322 myClassifyVal = classify;
325 //=======================================================================
326 //function : MergeSolids
328 //=======================================================================
330 void TopOpeBRepBuild_Builder::MergeSolids(const TopoDS_Shape& S1,const TopAbs_State ToBuild1,const TopoDS_Shape& S2,const TopAbs_State ToBuild2)
332 MergeShapes(S1,ToBuild1,S2,ToBuild2);
336 //=======================================================================
337 //function : MergeSolid
339 //=======================================================================
341 void TopOpeBRepBuild_Builder::MergeSolid(const TopoDS_Shape& S,const TopAbs_State ToBuild)
344 MergeShapes(S,ToBuild,Snull,ToBuild);
348 //=======================================================================
349 //function : MakeSolids
351 //=======================================================================
353 void TopOpeBRepBuild_Builder::MakeSolids(TopOpeBRepBuild_SolidBuilder& SOBU,TopTools_ListOfShape& L)
355 TopoDS_Shape newSolid;
356 TopoDS_Shape newShell;
357 for (SOBU.InitSolid(); SOBU.MoreSolid(); SOBU.NextSolid()) {
358 myBuildTool.MakeSolid(newSolid);
359 for (SOBU.InitShell(); SOBU.MoreShell(); SOBU.NextShell()) {
360 Standard_Boolean isold = SOBU.IsOldShell();
361 if (isold) newShell = SOBU.OldShell();
363 myBuildTool.MakeShell(newShell);
364 for (SOBU.InitFace(); SOBU.MoreFace(); SOBU.NextFace()) {
365 TopoDS_Shape F = SOBU.Face();
366 myBuildTool.AddShellFace(newShell,F);
369 myBuildTool.Closed(newShell,Standard_True); // NYI : check exact du caractere closed du shell
370 myBuildTool.AddSolidShell(newSolid,newShell);
375 //=======================================================================
376 //function : MakeShells
378 //=======================================================================
380 void TopOpeBRepBuild_Builder::MakeShells(TopOpeBRepBuild_SolidBuilder& SOBU,TopTools_ListOfShape& L)
382 TopoDS_Shape newShell;
383 for (SOBU.InitShell(); SOBU.MoreShell(); SOBU.NextShell()) {
384 Standard_Boolean isold = SOBU.IsOldShell();
385 if (isold) newShell = SOBU.OldShell();
387 myBuildTool.MakeShell(newShell);
388 for (SOBU.InitFace(); SOBU.MoreFace(); SOBU.NextFace()) {
389 TopoDS_Shape F = SOBU.Face();
390 myBuildTool.AddShellFace(newShell,F);
399 //=======================================================================
400 //function : MakeFaces
402 //=======================================================================
404 void TopOpeBRepBuild_Builder::MakeFaces(const TopoDS_Shape& aFace,TopOpeBRepBuild_FaceBuilder& FABU,TopTools_ListOfShape& L)
407 Standard_Integer iF = 0; Standard_Boolean tSPS = GtraceSPS(aFace,iF);
408 if(tSPS){GdumpFABU(FABU);}
410 Standard_Boolean hashds = (!myDataStructure.IsNull());
411 TopoDS_Shape newFace;
412 TopoDS_Shape newWire;
414 for (FABU.InitFace(); FABU.MoreFace(); FABU.NextFace()) {
415 myBuildTool.CopyFace(aFace,newFace);
416 Standard_Boolean hns = Standard_False;
418 const TopOpeBRepDS_DataStructure& BDS = myDataStructure->DS();
419 hns = BDS.HasNewSurface(aFace);
421 const Handle(Geom_Surface)& SU = BDS.NewSurface(aFace);
422 myBuildTool.UpdateSurface(newFace,SU);
427 for (FABU.InitWire(); FABU.MoreWire(); FABU.NextWire()) {
428 Standard_Boolean isold = FABU.IsOldWire();
429 if (isold) newWire = FABU.OldWire();
431 myBuildTool.MakeWire(newWire);
432 for(FABU.InitEdge(); FABU.MoreEdge(); FABU.NextEdge()) {
433 TopoDS_Shape E = FABU.Edge();
434 if (hns) myBuildTool.UpdateSurface(E,aFace,newFace);
435 myBuildTool.AddWireEdge(newWire,E);
440 BRepCheck_Analyzer bca(newWire, Standard_False);
441 if (!bca.IsValid()) {
442 newWire.Free(Standard_True);
443 CorrectUnclosedWire(newWire);
444 const Handle(BRepCheck_Result)& bcr = bca.Result(newWire);
445 BRepCheck_ListIteratorOfListOfStatus itl(bcr->Status());
446 for(; itl.More(); itl.Next() ) {
447 if(itl.Value() == BRepCheck_BadOrientationOfSubshape) {
448 CorrectEdgeOrientation(newWire);
454 myBuildTool.Closed(newWire,Standard_True); // NYI : check exact du caractere closed du wire
455 myBuildTool.AddFaceWire(newFace,newWire);
464 //=======================================================================
465 //function : MakeEdges
467 //=======================================================================
469 void TopOpeBRepBuild_Builder::MakeEdges(const TopoDS_Shape& anEdge,TopOpeBRepBuild_EdgeBuilder& EDBU,TopTools_ListOfShape& L)
472 Standard_Integer iE; Standard_Boolean tSPS = GtraceSPS(anEdge,iE);
473 Standard_Integer ne = 0;
476 Standard_Integer nvertex = 0;
477 for (TopOpeBRepTool_ShapeExplorer ex(anEdge,TopAbs_VERTEX); ex.More(); ex.Next()) nvertex++;
479 TopoDS_Shape newEdge;
480 for (EDBU.InitEdge(); EDBU.MoreEdge(); EDBU.NextEdge()) {
482 // 1 vertex sur edge courante => suppression edge
483 Standard_Integer nloop = 0;
484 for (EDBU.InitVertex(); EDBU.MoreVertex(); EDBU.NextVertex()) nloop++;
485 if ( nloop <= 1 ) continue;
487 myBuildTool.CopyEdge(anEdge,newEdge);
489 Standard_Boolean hasvertex = Standard_False;
490 for (EDBU.InitVertex(); EDBU.MoreVertex(); EDBU.NextVertex()) {
491 TopoDS_Shape V = EDBU.Vertex();
492 TopAbs_Orientation Vori = V.Orientation();
494 Standard_Boolean hassd = myDataStructure->HasSameDomain(V);
496 // on prend le vertex reference de V
497 Standard_Integer iref = myDataStructure->SameDomainReference(V);
498 V = myDataStructure->Shape(iref);
502 TopAbs_Orientation oriV = V.Orientation();
503 if ( oriV != TopAbs_EXTERNAL ) {
505 Standard_Boolean equafound = Standard_False;
506 TopExp_Explorer exE(newEdge,TopAbs_VERTEX);
507 for (; exE.More(); exE.Next() ) {
508 const TopoDS_Shape& VE = exE.Current();
509 TopAbs_Orientation oriVE = VE.Orientation();
510 if ( V.IsEqual(VE) ) {
511 equafound = Standard_True;
514 else if (oriVE == TopAbs_FORWARD || oriVE == TopAbs_REVERSED) {
516 equafound = Standard_True;
520 else if (oriVE == TopAbs_INTERNAL || oriVE == TopAbs_EXTERNAL) {
521 Standard_Real parV = EDBU.Parameter();
522 Standard_Real parVE = BRep_Tool::Parameter(TopoDS::Vertex(VE),
523 TopoDS::Edge(newEdge));
524 if ( parV == parVE ) {
525 equafound = Standard_True;
531 hasvertex = Standard_True;
532 Standard_Real parV = EDBU.Parameter();
533 myBuildTool.AddEdgeVertex(newEdge,V);
534 myBuildTool.Parameter(newEdge,V,parV);
538 } // loop on vertices of new edge newEdge
541 if(tSPS){cout<<endl;}
542 if(tSPS){cout<<"V of new edge "<<++ne<<endl;}
543 if(tSPS){GdumpEDG(newEdge);}
546 if (hasvertex) L.Append(newEdge);
547 } // loop on EDBU edges
551 //=======================================================================
552 //function : IsMerged
554 //=======================================================================
556 Standard_Boolean TopOpeBRepBuild_Builder::IsMerged(const TopoDS_Shape& S,const TopAbs_State ToBuild) const
558 const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State* p = NULL;
559 if ( ToBuild == TopAbs_OUT ) p = &myMergedOUT;
560 else if ( ToBuild == TopAbs_IN ) p = &myMergedIN;
561 else if ( ToBuild == TopAbs_ON ) p = &myMergedON;
562 if ( p == NULL ) return Standard_False;
564 Standard_Boolean notbound = ! (*p).IsBound(S);
566 return Standard_False;
569 const TopTools_ListOfShape& L = Merged(S,ToBuild);
570 Standard_Boolean isempty = L.IsEmpty();
576 //=======================================================================
579 //=======================================================================
581 const TopTools_ListOfShape& TopOpeBRepBuild_Builder::Merged(const TopoDS_Shape& S,const TopAbs_State ToBuild) const
583 const TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State* p = NULL;
584 if ( ToBuild == TopAbs_OUT ) p = &myMergedOUT;
585 else if ( ToBuild == TopAbs_IN ) p = &myMergedIN;
586 else if ( ToBuild == TopAbs_ON ) p = &myMergedON;
587 if ( p == NULL ) return myEmptyShapeList;
589 if ( ! (*p).IsBound(S) ) {
590 return myEmptyShapeList;
593 const TopTools_ListOfShape& L = (*p)(S).ListOnState();
599 //=======================================================================
600 //function : ChangeMerged
602 //=======================================================================
604 TopTools_ListOfShape& TopOpeBRepBuild_Builder::ChangeMerged(const TopoDS_Shape& S, const TopAbs_State ToBuild)
606 TopOpeBRepDS_DataMapOfShapeListOfShapeOn1State* p = NULL;
607 if ( ToBuild == TopAbs_OUT ) p = &myMergedOUT;
608 else if ( ToBuild == TopAbs_IN ) p = &myMergedIN;
609 else if ( ToBuild == TopAbs_ON ) p = &myMergedON;
610 if ( p == NULL ) return myEmptyShapeList;
612 if ( ! (*p).IsBound(S) ) {
613 TopOpeBRepDS_ListOfShapeOn1State thelist;
614 (*p).Bind(S, thelist);
616 TopTools_ListOfShape& L = (*p)(S).ChangeListOnState();
620 //=======================================================================
621 //function : MergeEdges
623 //=======================================================================
625 void TopOpeBRepBuild_Builder::MergeEdges(const TopTools_ListOfShape& ,//L1,
626 const TopAbs_State ,//ToBuild1,
627 const TopTools_ListOfShape& ,//L2,
628 const TopAbs_State ,//ToBuild2,
629 const Standard_Boolean ,//Keepon1,
630 const Standard_Boolean ,//Keepon2,
631 const Standard_Boolean )//Keepon12)
635 //=======================================================================
636 //function : MergeFaces
638 //=======================================================================
640 void TopOpeBRepBuild_Builder::MergeFaces(const TopTools_ListOfShape& , //S1,
641 const TopAbs_State , //ToBuild1,
642 const TopTools_ListOfShape& , //S2,
643 const TopAbs_State , //ToBuild2
644 const Standard_Boolean ,//onA,
645 const Standard_Boolean ,//onB,
646 const Standard_Boolean )//onAB)