1 // File: GEOMAlgo_Gluer.cxx
2 // Created: Sat Dec 04 12:45:53 2004
3 // Author: Peter KURNEV
7 #include <GEOMAlgo_Gluer.ixx>
9 #include <TColStd_ListOfInteger.hxx>
10 #include <TColStd_ListIteratorOfListOfInteger.hxx>
16 #include <Geom_Curve.hxx>
17 #include <Geom_Surface.hxx>
19 #include <Bnd_Box.hxx>
20 #include <Bnd_HArray1OfBox.hxx>
21 #include <Bnd_BoundSortBox.hxx>
23 #include <TopLoc_Location.hxx>
24 #include <TopAbs_ShapeEnum.hxx>
25 #include <TopAbs_Orientation.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Vertex.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Compound.hxx>
32 #include <TopoDS_Wire.hxx>
33 #include <TopoDS_Shell.hxx>
34 #include <TopoDS_Solid.hxx>
36 #include <TopTools_IndexedMapOfShape.hxx>
37 #include <TopTools_ListOfShape.hxx>
38 #include <TopTools_ListIteratorOfListOfShape.hxx>
39 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
40 #include <TopTools_MapOfShape.hxx>
41 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
44 #include <TopExp_Explorer.hxx>
46 #include <BRep_Tool.hxx>
47 #include <BRep_Builder.hxx>
48 #include <BRepLib.hxx>
49 #include <BRepTools.hxx>
50 #include <BRepBndLib.hxx>
52 #include <IntTools_Context.hxx>
53 #include <BOPTools_Tools.hxx>
54 #include <BOPTools_Tools3D.hxx>
55 #include <BOPTools_Tools2D.hxx>
56 #include <BOP_CorrectTolerances.hxx>
58 #include <GEOMAlgo_IndexedDataMapOfIntegerShape.hxx>
59 #include <GEOMAlgo_IndexedDataMapOfShapeBox.hxx>
60 #include <GEOMAlgo_IndexedDataMapOfPassKeyListOfShape.hxx>
61 #include <GEOMAlgo_PassKey.hxx>
62 #include <GEOMAlgo_Tools.hxx>
64 //=======================================================================
65 //function : GEOMAlgo_Gluer
67 //=======================================================================
68 GEOMAlgo_Gluer::GEOMAlgo_Gluer()
74 myCheckGeometry=Standard_True;
77 //=======================================================================
78 //function : ~GEOMAlgo_Gluer
80 //=======================================================================
81 GEOMAlgo_Gluer::~GEOMAlgo_Gluer()
84 //=======================================================================
85 //function : SetCheckGeometry
87 //=======================================================================
88 void GEOMAlgo_Gluer::SetCheckGeometry(const Standard_Boolean aFlag)
90 myCheckGeometry=aFlag;
92 //=======================================================================
93 //function : CheckGeometry
95 //=======================================================================
96 Standard_Boolean GEOMAlgo_Gluer::CheckGeometry() const
98 return myCheckGeometry;
100 //=======================================================================
101 //function : AloneShapes
103 //=======================================================================
104 Standard_Integer GEOMAlgo_Gluer::AloneShapes()const
108 //=======================================================================
111 //=======================================================================
112 const TopTools_DataMapOfShapeListOfShape& GEOMAlgo_Gluer::Images()const
116 //=======================================================================
119 //=======================================================================
120 const TopTools_DataMapOfShapeShape& GEOMAlgo_Gluer::Origins()const
124 //=======================================================================
127 //=======================================================================
128 void GEOMAlgo_Gluer::Perform()
134 const Standard_Integer aNb=8;
135 void (GEOMAlgo_Gluer::* pF[aNb])()={
136 &GEOMAlgo_Gluer::CheckData, &GEOMAlgo_Gluer::InnerTolerance,
137 &GEOMAlgo_Gluer::MakeVertices, &GEOMAlgo_Gluer::MakeEdges,
138 &GEOMAlgo_Gluer::MakeFaces, &GEOMAlgo_Gluer::MakeShells,
139 &GEOMAlgo_Gluer::MakeSolids, &GEOMAlgo_Gluer::CheckResult
142 for (i=0; i<aNb; ++i) {
149 //=======================================================================
150 //function : MakeVertices
152 //=======================================================================
153 void GEOMAlgo_Gluer::MakeVertices()
157 Standard_Integer j, i, aNbV, aIndex, aNbVSD;
158 TColStd_ListIteratorOfListOfInteger aIt;
159 Handle(Bnd_HArray1OfBox) aHAB;
160 Bnd_BoundSortBox aBSB;
161 TopoDS_Shape aSTmp, aVF;
163 TopTools_IndexedMapOfShape aMV, aMVProcessed;
164 TopTools_ListIteratorOfListOfShape aItS;
165 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
166 TopTools_DataMapOfShapeListOfShape aMVV;
167 GEOMAlgo_IndexedDataMapOfIntegerShape aMIS;
168 GEOMAlgo_IndexedDataMapOfShapeBox aMSB;
170 TopExp::MapShapes(myShape, TopAbs_VERTEX, aMV);
173 myErrorStatus=2; // no vertices in source shape
177 aHAB=new Bnd_HArray1OfBox(1, aNbV);
179 for (i=1; i<=aNbV; ++i) {
180 const TopoDS_Shape& aV=aMV(i);
184 BRepBndLib::Add(aV, aBox);
185 aHAB->SetValue(i, aBox);
190 aBSB.Initialize(aHAB);
192 for (i=1; i<=aNbV; ++i) {
193 const TopoDS_Shape& aV=aMV(i);
195 if (aMVProcessed.Contains(aV)) {
199 const Bnd_Box& aBoxV=aMSB.FindFromKey(aV);
200 const TColStd_ListOfInteger& aLI=aBSB.Compare(aBoxV);
203 myErrorStatus=3; // it must not be
209 TopTools_ListOfShape aLVSD;
212 for (j=0; aIt.More(); aIt.Next(), ++j) {
214 const TopoDS_Shape& aVx=aMIS.FindFromKey(aIndex);
219 aMVProcessed.Add(aVx);
222 myImages.Bind(aVF, aLVSD);
227 aItIm.Initialize(myImages);
228 for (; aItIm.More(); aItIm.Next()) {
229 const TopoDS_Shape& aV=aItIm.Key();
230 const TopTools_ListOfShape& aLVSD=aItIm.Value();
231 aNbVSD=aLVSD.Extent();
234 MakeVertex(aLVSD, aVnew);
235 aMVV.Bind(aVnew, aLVSD);
239 // UnBind old vertices
241 for (i=1; i<=aNbV; ++i) {
242 const TopoDS_Shape& aV=aMV(i);
247 aItIm.Initialize(aMVV);
248 for (; aItIm.More(); aItIm.Next()) {
249 const TopoDS_Shape& aV=aItIm.Key();
250 const TopTools_ListOfShape& aLVSD=aItIm.Value();
251 myImages.Bind(aV, aLVSD);
255 aItIm.Initialize(myImages);
256 for (; aItIm.More(); aItIm.Next()) {
257 const TopoDS_Shape& aV=aItIm.Key();
258 const TopTools_ListOfShape& aLVSD=aItIm.Value();
260 aItS.Initialize(aLVSD);
261 for (; aItS.More(); aItS.Next()) {
262 const TopoDS_Shape& aVSD=aItS.Value();
263 if (!myOrigins.IsBound(aVSD)) {
264 myOrigins.Bind(aVSD, aV);
269 //=======================================================================
270 //function : MakeSolids
272 //=======================================================================
273 void GEOMAlgo_Gluer::MakeSolids()
277 Standard_Integer aNbS;
278 TopAbs_Orientation anOr;
279 TopoDS_Compound aCmp;
280 TopoDS_Solid aNewSolid;
281 TopTools_IndexedMapOfShape aMS;
282 TopExp_Explorer aExpS, aExp;
285 aBB.MakeCompound(aCmp);
288 aExpS.Init(myShape, TopAbs_SOLID);
289 for (; aExpS.More(); aExpS.Next()) {
290 const TopoDS_Solid& aSolid=TopoDS::Solid(aExpS.Current());
291 if (aMS.Contains(aSolid)) {
296 anOr=aSolid.Orientation();
298 aBB.MakeSolid(aNewSolid);
299 aNewSolid.Orientation(anOr);
301 aExp.Init(aSolid, TopAbs_SHELL);
302 for (; aExp.More(); aExp.Next()) {
303 const TopoDS_Shape& aShell=aExp.Current();
304 const TopoDS_Shape& aShellR=myOrigins.Find(aShell);
305 aBB.Add(aNewSolid, aShellR);
308 TopTools_ListOfShape aLS;
311 myImages.Bind(aNewSolid, aLS);
312 myOrigins.Bind(aSolid, aNewSolid);
314 aBB.Add(aCmp, aNewSolid);
321 Standard_Real aTol=1.e-7;
322 BOP_CorrectTolerances::CorrectCurveOnSurface(myResult);
325 //=======================================================================
326 //function : MakeShells
328 //=======================================================================
329 void GEOMAlgo_Gluer::MakeShells()
333 Standard_Boolean bIsToReverse;
334 Standard_Integer i, aNbS;
335 TopAbs_Orientation anOr;
336 TopoDS_Shell aNewShell;
338 TopTools_IndexedMapOfShape aMS;
339 TopExp_Explorer aExp;
342 TopExp::MapShapes(myShape, TopAbs_SHELL, aMS);
345 for (i=1; i<=aNbS; ++i) {
346 const TopoDS_Shell& aShell=TopoDS::Shell(aMS(i));
347 anOr=aShell.Orientation();
349 aBB.MakeShell(aNewShell);
350 aNewShell.Orientation(anOr);
351 aExp.Init(aShell, TopAbs_FACE);
352 for (; aExp.More(); aExp.Next()) {
353 const TopoDS_Face& aF=TopoDS::Face(aExp.Current());
354 aFR=TopoDS::Face(myOrigins.Find(aF));
355 if (aFR.IsSame(aF)) {
356 aBB.Add(aNewShell, aF);
359 bIsToReverse=IsToReverse(aFR, aF);
363 aBB.Add(aNewShell, aFR);
366 TopTools_ListOfShape aLS;
369 myImages.Bind(aNewShell, aLS);
370 myOrigins.Bind(aShell, aNewShell);
373 //=======================================================================
374 //function : MakeFaces
376 //=======================================================================
377 void GEOMAlgo_Gluer::MakeFaces()
379 MakeShapes(TopAbs_FACE);
381 //=======================================================================
382 //function : MakeEdges
384 //=======================================================================
385 void GEOMAlgo_Gluer::MakeEdges()
387 MakeShapes(TopAbs_EDGE);
389 //=======================================================================
390 //function : MakeShapes
392 //=======================================================================
393 void GEOMAlgo_Gluer::MakeShapes(const TopAbs_ShapeEnum aType)
397 Standard_Integer i, aNbF, aNbSDF, iErr;
398 TopoDS_Shape aNewShape;
399 TopTools_IndexedMapOfShape aMF;
400 TopTools_ListIteratorOfListOfShape aItS;
401 GEOMAlgo_PassKey aPKF;
402 GEOMAlgo_IndexedDataMapOfPassKeyListOfShape aMPKLF;
404 TopExp::MapShapes(myShape, aType, aMF);
407 for (i=1; i<=aNbF; ++i) {
408 const TopoDS_Shape& aS=aMF(i);
411 if (aType==TopAbs_FACE) {
412 const TopoDS_Face& aF=TopoDS::Face(aS);
413 FacePassKey(aF, aPKF);
415 else if (aType==TopAbs_EDGE) {
416 const TopoDS_Edge& aE=TopoDS::Edge(aS);
417 EdgePassKey(aE, aPKF);
424 if (aMPKLF.Contains(aPKF)) {
425 TopTools_ListOfShape& aLSDF=aMPKLF.ChangeFromKey(aPKF);
429 TopTools_ListOfShape aLSDF;
432 aMPKLF.Add(aPKF, aLSDF);
435 // check geometric coincidence
436 if (myCheckGeometry) {
437 iErr=GEOMAlgo_Tools::RefineSDShapes(aMPKLF, myTol, myContext);
445 aNbF=aMPKLF.Extent();
446 for (i=1; i<=aNbF; ++i) {
447 const TopTools_ListOfShape& aLSDF=aMPKLF(i);
448 aNbSDF=aLSDF.Extent();
450 myErrorStatus=4; // it must not be
453 const TopoDS_Shape& aS1=aLSDF.First();
454 if (aType==TopAbs_FACE) {
455 TopoDS_Face aNewFace;
457 const TopoDS_Face& aF1=TopoDS::Face(aS1);
458 MakeFace(aF1, aNewFace);
461 else if (aType==TopAbs_EDGE) {
462 TopoDS_Edge aNewEdge;
464 const TopoDS_Edge& aE1=TopoDS::Edge(aS1);
465 MakeEdge(aE1, aNewEdge);
469 myImages.Bind(aNewShape, aLSDF);
471 aItS.Initialize(aLSDF);
472 for (; aItS.More(); aItS.Next()) {
473 const TopoDS_Shape& aFSD=aItS.Value();
474 if (!myOrigins.IsBound(aFSD)) {
475 myOrigins.Bind(aFSD, aNewShape);
480 //=======================================================================
481 //function : CheckResult
483 //=======================================================================
484 void GEOMAlgo_Gluer::CheckResult()
488 if (myResult.IsNull()) {
493 Standard_Boolean bFound;
494 Standard_Integer i, j, aNbS, aNbFS, aNbSx;
495 TopTools_IndexedMapOfShape aMS, aMFS;
496 TopTools_IndexedDataMapOfShapeListOfShape aMFR;
498 TopExp::MapShapesAndAncestors(myResult, TopAbs_FACE, TopAbs_SOLID, aMFR);
499 TopExp::MapShapes(myResult, TopAbs_SOLID, aMS);
504 for (i=1; i<=aNbS; ++i) {
505 const TopoDS_Shape& aSolid=aMS(i);
508 TopExp::MapShapes(aSolid, TopAbs_FACE, aMFS);
510 bFound=Standard_False;
512 for (j=1; j<=aNbFS; ++j) {
513 const TopoDS_Shape& aFS=aMFS(j);
514 if (aMFR.Contains(aFS)) {
515 const TopTools_ListOfShape& aLSx=aMFR.FindFromKey(aFS);
531 //=======================================================================
532 //function : CheckData
534 //=======================================================================
535 void GEOMAlgo_Gluer::CheckData()
539 if (myShape.IsNull()) {
544 //=======================================================================
545 //function : InnerTolerance
547 //=======================================================================
548 void GEOMAlgo_Gluer::InnerTolerance()
554 Standard_Real aX[3][2], dH, dHmin, aCoef, aTolTresh;
557 BRepBndLib::Add(myShape, aBox);
558 aBox.Get(aX[0][0], aX[1][0], aX[2][0], aX[0][1], aX[1][1], aX[2][1]);
560 dHmin=aX[0][1]-aX[0][0];
561 for (i=1; i<3; ++i) {
562 dH=aX[i][1]-aX[i][0];
570 aTolTresh=aCoef*dHmin;
571 if (myTol>aTolTresh) {
577 //=======================================================================
578 //function : FacePassKey
580 //=======================================================================
581 void GEOMAlgo_Gluer::FacePassKey(const TopoDS_Face& aF,
582 GEOMAlgo_PassKey& aPK)
584 Standard_Integer i, aNbE, aNbMax;
585 TopTools_ListOfShape aLE;
586 TopTools_IndexedMapOfShape aME;
588 TopExp::MapShapes(aF, TopAbs_EDGE, aME);
591 if (!aNbE || aNbE>aNbMax) {
592 myErrorStatus=101; // temprorary
596 for (i=1; i<=aNbE; ++i) {
597 const TopoDS_Shape& aE=aME(i);
598 if (!myOrigins.IsBound(aE)) {
602 const TopoDS_Shape& aER=myOrigins.Find(aE);
607 //=======================================================================
608 //function : EdgePassKey
610 //=======================================================================
611 void GEOMAlgo_Gluer::EdgePassKey(const TopoDS_Edge& aE,
612 GEOMAlgo_PassKey& aPK)
614 TopoDS_Vertex aV1, aV2;
616 TopExp::Vertices(aE, aV1, aV2);
618 if (!myOrigins.IsBound(aV1) || !myOrigins.IsBound(aV2) ) {
622 const TopoDS_Shape& aVR1=myOrigins.Find(aV1);
623 const TopoDS_Shape& aVR2=myOrigins.Find(aV2);
624 aPK.SetIds(aVR1, aVR2);
626 //=======================================================================
627 //function : MakeVertex
629 //=======================================================================
630 void GEOMAlgo_Gluer::MakeVertex(const TopTools_ListOfShape& aLV,
631 TopoDS_Vertex& aNewVertex)
633 Standard_Integer aNbV;
634 Standard_Real aTolV, aD, aDmax;
639 TopTools_ListIteratorOfListOfShape aIt;
647 aGC.SetCoord(0.,0.,0.);
649 for (; aIt.More(); aIt.Next()) {
650 aVx=TopoDS::Vertex(aIt.Value());
651 aP3D=BRep_Tool::Pnt(aVx);
654 aGC/=(Standard_Real)aNbV;
660 for (; aIt.More(); aIt.Next()) {
661 aVx=TopoDS::Vertex(aIt.Value());
662 aP3D=BRep_Tool::Pnt(aVx);
663 aTolV=BRep_Tool::Tolerance(aVx);
664 aD=aPGC.Distance(aP3D)+aTolV;
670 aBB.MakeVertex (aNewVertex, aPGC, aDmax);
672 //=======================================================================
673 //function : MakeEdge
675 //=======================================================================
676 void GEOMAlgo_Gluer::MakeEdge(const TopoDS_Edge& aE,
677 TopoDS_Edge& aNewEdge)
679 //modified by NIZNHY-PKV Thu Dec 30 11:15:23 2004 f
682 Standard_Boolean bIsDE;
683 Standard_Real aT1, aT2;
684 TopoDS_Vertex aV1, aV2, aVR1, aVR2;
687 bIsDE=BRep_Tool::Degenerated(aE);
690 aEx.Orientation(TopAbs_FORWARD);
692 TopExp::Vertices(aEx, aV1, aV2);
694 aT1=BRep_Tool::Parameter(aV1, aEx);
695 aT2=BRep_Tool::Parameter(aV2, aEx);
697 aVR1=TopoDS::Vertex(myOrigins.Find(aV1));
698 aVR1.Orientation(TopAbs_FORWARD);
699 aVR2=TopoDS::Vertex(myOrigins.Find(aV2));
700 aVR2.Orientation(TopAbs_REVERSED);
706 TopAbs_Orientation anOrE;
708 anOrE=aE.Orientation();
709 aTol=BRep_Tool::Tolerance(aE);
716 aBB.Range(E, aT1, aT2);
717 aBB.Degenerated(E, Standard_True);
718 aBB.UpdateEdge(E, aTol);
724 BOPTools_Tools::MakeSplitEdge(aEx, aVR1, aT1, aVR2, aT2, aNewEdge);
726 //modified by NIZNHY-PKV Thu Dec 30 11:15:28 2004 t
729 //=======================================================================
730 //function : MakeFace
732 //=======================================================================
733 void GEOMAlgo_Gluer::MakeFace(const TopoDS_Face& aF,
734 TopoDS_Face& aNewFace)
738 Standard_Boolean bIsToReverse, bIsUPeriodic;
739 Standard_Real aTol, aUMin, aUMax, aVMin, aVMax;
742 TopoDS_Face aFFWD, newFace;
743 TopLoc_Location aLoc;
744 Handle(Geom_Surface) aS;
745 Handle(Geom2d_Curve) aC2D;
746 TopExp_Explorer aExpW, aExpE;
750 aFFWD.Orientation(TopAbs_FORWARD);
752 aS=BRep_Tool::Surface(aFFWD, aLoc);
753 bIsUPeriodic=GEOMAlgo_Tools::IsUPeriodic(aS);
754 aTol=BRep_Tool::Tolerance(aFFWD);
755 BRepTools::UVBounds(aF, aUMin, aUMax, aVMin, aVMax);
757 aBB.MakeFace (newFace, aS, aLoc, aTol);
759 aExpW.Init(aFFWD, TopAbs_WIRE);
760 for (; aExpW.More(); aExpW.Next()) {
761 aBB.MakeWire(newWire);
762 const TopoDS_Wire& aW=TopoDS::Wire(aExpW.Current());
763 aExpE.Init(aW, TopAbs_EDGE);
764 for (; aExpE.More(); aExpE.Next()) {
765 const TopoDS_Edge& aE=TopoDS::Edge(aExpE.Current());
766 aER=TopoDS::Edge(myOrigins.Find(aE));
768 aER.Orientation(TopAbs_FORWARD);
769 if (!BRep_Tool::Degenerated(aER)) {//modified by NIZNHY-PKV Thu Dec 30 11:31:37 2004 ft
772 GEOMAlgo_Tools::RefinePCurveForEdgeOnFace(aER, aFFWD, aUMin, aUMax);
774 BOPTools_Tools2D::BuildPCurveForEdgeOnFace(aER, aFFWD);
777 bIsToReverse=BOPTools_Tools3D::IsSplitToReverse1(aER, aE, myContext);
783 aER.Orientation(aE.Orientation());
786 aBB.Add(newWire, aER);
788 aBB.Add(newFace, newWire);
792 //=======================================================================
793 //function : IsToReverse
795 //=======================================================================
796 Standard_Boolean GEOMAlgo_Gluer::IsToReverse(const TopoDS_Face& aFR,
797 const TopoDS_Face& aF)
799 Standard_Boolean bRet;
800 Standard_Real aT, aT1, aT2, aTR, aScPr;
801 TopExp_Explorer aExp;
802 Handle(Geom_Curve)aC3D;
808 aExp.Init(aF, TopAbs_EDGE);
809 for (; aExp.More(); aExp.Next()) {
810 const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
811 //modified by NIZNHY-PKV Thu Dec 30 11:38:05 2004 f
812 if (BRep_Tool::Degenerated(aE)) {
815 //modified by NIZNHY-PKV Thu Dec 30 11:38:08 2004 t
816 const TopoDS_Edge& aER=TopoDS::Edge(myOrigins.Find(aE));
818 aC3D=BRep_Tool::Curve(aE, aT1, aT2);
819 aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
821 myContext.ProjectPointOnEdge(aP, aER, aTR);
823 BOPTools_Tools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF);
824 if (aF.Orientation()==TopAbs_REVERSED) {
828 BOPTools_Tools3D::GetNormalToFaceOnEdge (aER, aFR, aTR, aDNFR);
829 if (aFR.Orientation()==TopAbs_REVERSED) {
843 // 1 - the object is just initialized
844 // 2 - no vertices found in source shape
845 // 3 - nb same domain vertices for the vertex Vi =0
846 // 4 - nb same domain edges(faces) for the edge Ei(face Fi) =0
847 // 5 - source shape is Null
848 // 6 - result shape is Null
849 // 101 - nb edges > PassKey.NbMax() in FacesPassKey()
850 // 102 - the edge Ei can not be found in myOrigins Map
851 // 100 - the vertex Vi can not be found in myOrigins Map
855 // 1 - some shapes can not be glued by faces
858 //=======================================================================
859 //function : BuildResult
861 //=======================================================================
862 void GEOMAlgo_Gluer::BuildResult()
864 Standard_Boolean bAdded;
865 TopoDS_Compound aCmp;
867 TopAbs_ShapeEnum aType;
868 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm;
870 aBB.MakeCompound(aCmp);
872 bAdded=Standard_False;
873 aItIm.Initialize(myImages);
874 for (; aItIm.More(); aItIm.Next()) {
875 const TopoDS_Shape& aIm=aItIm.Key();
876 aType=aIm.ShapeType();
877 if(aType==TopAbs_SOLID) {
878 bAdded=Standard_True;
885 Standard_Real aTol=1.e-7;
886 BOP_CorrectTolerances::CorrectCurveOnSurface(myResult);
887 //BRepLib::SameParameter(myResult, aTol, bAdded);