// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static Standard_Boolean IsEqual(const gp_Sphere& aSp1, const gp_Sphere& aSp2, const Standard_Real aTolDst); //======================================================================= //function : FillDetails //purpose : //======================================================================= void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Solid& aSd) { Standard_Boolean bIsStepSphere; Standard_Integer i, aNbF, aNbCyl, aNbCon, aNbPgn, aNbRct, aNbCrc, aNbX; TopoDS_Shape aFCyl, aFCon; TopTools_IndexedMapOfShape aMF; GEOMAlgo_KindOfName aKNF; // GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aSd); aInfo.SetKindOfName(GEOMAlgo_KN_UNKNOWN); // TopExp::MapShapes(aSd, TopAbs_FACE, aMF); // aNbF=aMF.Extent(); if (!aNbF) { return; } // if (aNbF==1) { const TopoDS_Shape& aF=aMF(1); GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aF); aKNF=aInfoF.KindOfName(); // mb: sphere, torus if (aKNF==GEOMAlgo_KN_SPHERE || aKNF==GEOMAlgo_KN_TORUS) { aInfo.SetKindOfName(aKNF); aInfo.SetLocation(aInfoF.Location()); aInfo.SetPosition(aInfoF.Position()); aInfo.SetRadius1(aInfoF.Radius1()); if(aKNF==GEOMAlgo_KN_TORUS) { aInfo.SetRadius2(aInfoF.Radius2()); } return; } } //modified by NIZNHY-PKV Tue Jul 03 13:23:55 2012f else if (aNbF==2) { // specific solid that should be treated as a sphere bIsStepSphere=TreatStepSphere(aSd); if (bIsStepSphere) { return; } } //modified by NIZNHY-PKV Tue Jul 03 13:23:57 2012t // aNbCyl=0; aNbCon=0; aNbPgn=0; aNbRct=0; aNbCrc=0; for (i=1; i<=aNbF; ++i) { const TopoDS_Shape& aF=aMF(i); GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aF); aKNF=aInfoF.KindOfName(); if (aKNF==GEOMAlgo_KN_CYLINDER) { aFCyl=aF; ++aNbCyl; } else if (aKNF==GEOMAlgo_KN_CONE) { aFCon=aF; ++aNbCon; } else if (aKNF==GEOMAlgo_KN_DISKCIRCLE) { ++aNbCrc; } else if (aKNF==GEOMAlgo_KN_POLYGON || aKNF==GEOMAlgo_KN_TRIANGLE || aKNF==GEOMAlgo_KN_QUADRANGLE) { ++aNbPgn; } else if (aKNF==GEOMAlgo_KN_RECTANGLE) { ++aNbPgn; ++aNbRct; } } // aNbX=aNbCyl+aNbCrc; if (aNbCyl==1 && aNbCrc==2 && aNbX==aNbF) { // cylinder (as they understand it) GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aFCyl); aKNF=aInfoF.KindOfName(); aInfo.SetKindOfName(aKNF); aInfo.SetLocation(aInfoF.Location()); aInfo.SetPosition(aInfoF.Position()); aInfo.SetRadius1(aInfoF.Radius1()); aInfo.SetHeight(aInfoF.Height()); return; } // aNbX=aNbCon+aNbCrc; if (aNbCon==1 && (aNbCrc==1 || aNbCrc==2) && aNbX==aNbF) { // cone GEOMAlgo_ShapeInfo& aInfoF=myMapInfo.ChangeFromKey(aFCon); aKNF=aInfoF.KindOfName(); aInfo.SetKindOfName(aKNF); aInfo.SetLocation(aInfoF.Location()); aInfo.SetPosition(aInfoF.Position()); aInfo.SetRadius1(aInfoF.Radius1()); aInfo.SetRadius2(aInfoF.Radius2()); aInfo.SetHeight(aInfoF.Height()); return; } // if (aNbF!=aNbPgn) { return;// -> GEOMAlgo_KN_UNKNOWN } if (aNbPgn!=6) { aInfo.SetKindOfName(GEOMAlgo_KN_POLYHEDRON); return; } // aNbPgn==6 if (aNbPgn!=aNbRct) { aInfo.SetKindOfName(GEOMAlgo_KN_POLYHEDRON); return; } //=================================================== // aNbRct=6; // box Standard_Integer j, aNbFi, aNbV, iMax, iMin, iMid; Standard_Real aDot, aLength, aWidth, aHeight, aDist[3]; Standard_Real aDistMin, aDistMax; gp_Pnt aPi, aPc; gp_Dir aDir[3]; gp_XYZ aXYZc; TColStd_IndexedMapOfInteger aMp; TopTools_IndexedMapOfShape aMV, aMFi; // // barycenter aPc TopExp::MapShapes(aSd, TopAbs_VERTEX, aMV); aNbV=aMV.Extent(); if (aNbV!=8) { return; } // aXYZc.SetCoord(0.,0.,0.); for (i=1; i<=aNbV; ++i) { const TopoDS_Vertex& aVi=TopoDS::Vertex(aMV(i)); aPi=BRep_Tool::Pnt(aVi); const gp_XYZ& aXYZ=aPi.XYZ(); aXYZc=aXYZc+aXYZ; } // aXYZc.Divide(aNbV); aPc.SetXYZ(aXYZc); // // 3 faces for (i=1; i<=aNbF; ++i) { if (aMp.Contains(i)) { continue; } // const TopoDS_Shape& aFi=aMF(i); const GEOMAlgo_ShapeInfo& aIFi=myMapInfo.FindFromKey(aFi); const gp_Dir& aDNi=aIFi.Position().Direction(); // for (j=i+1; j<=aNbF; ++j) { if (aMp.Contains(j)) { continue; } // const TopoDS_Shape& aFj=aMF(j); const GEOMAlgo_ShapeInfo& aIFj=myMapInfo.FindFromKey(aFj); const gp_Dir& aDNj=aIFj.Position().Direction(); // aDot=aDNi*aDNj; //modified by NIZNHY-PKV Tue Jul 03 10:01:56 2012f if (aDot<0.) { aDot=-aDot; } //modified by NIZNHY-PKV Tue Jul 03 10:01:52 2012t if (fabs(1.-aDot)<0.0001) { aMp.Add(i); aMp.Add(j); aMFi.Add(aFi); break; } // } } aNbFi=aMFi.Extent(); if (aNbFi!=3) { return; } // aDistMin=1.e15; aDistMax=-aDistMin; for (i=0; iaDistMax) { aDistMax=aDist[i]; iMax=i; } if (aDist[i] myTolerance) { aInfo.SetKindOfName(GEOMAlgo_KN_QUADRANGLE); return; } } // // rectangle aInfo.SetKindOfName(GEOMAlgo_KN_RECTANGLE); // // shift location to the center and calc. sizes aXYZc.SetCoord(0.,0.,0.); TopExp::MapShapes(aF, TopAbs_VERTEX, aMV); for (i=1; i<=aNbV; ++i) { const TopoDS_Vertex& aV=TopoDS::Vertex(aMV(i)); aP=BRep_Tool::Pnt(aV); const gp_XYZ& aXYZ=aP.XYZ(); aXYZc=aXYZc+aXYZ; } // // Location : aPc in center of rectangle // Position : 0z is plane normal // 0x is along length // aXYZc.Divide(4.); aPc.SetXYZ(aXYZc); // gp_Lin aL0(aPx[0], aDx[0]); gp_Lin aL1(aPx[1], aDx[1]); // aD0=aL0.Distance(aPc); aD1=aL1.Distance(aPc); // aLength=aD0; aWidth =aD1; aDX=aL1.Direction(); if (aD0aR[1]) { aRmin=aR[1]; aRmax=aR[0]; aPc=aPC[0]; gp_Vec aVz(aPC[0], aPC[1]); gp_Vec aVx(aPC[0], aPX[0]); gp_Dir aDz(aVz); gp_Dir aDx(aVx); gp_Ax2 aAx2(aPc, aDz, aDx); aAx2new=aAx2; } else { aRmin=aR[0]; aRmax=aR[1]; aPc=aPC[1]; gp_Vec aVz(aPC[1], aPC[0]); gp_Vec aVx(aPC[1], aPX[1]); gp_Dir aDz(aVz); gp_Dir aDx(aVx); gp_Ax2 aAx2(aPc, aDz, aDx); aAx2new=aAx2; } // gp_Ax3 aAx3(aAx2new); aInfo.SetLocation(aPc); aInfo.SetPosition(aAx3); aInfo.SetRadius1(aRmax); aInfo.SetRadius2(aRmin); aInfo.SetHeight(aHeight); // aInfo.SetKindOfName(GEOMAlgo_KN_CONE); } //======================================================================= //function : FillDetails //purpose : //======================================================================= void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF, const gp_Cylinder& aCyl) { Standard_Integer i, aNbV, aNbE, aNbCE, aNbSE; Standard_Real aT0, aT1, aHeight; gp_Pnt aPC[3], aPc; TopoDS_Edge aE; TopExp_Explorer aExp; TopTools_MapOfShape aM; GEOMAlgo_KindOfShape aKS; GEOMAlgo_KindOfName aKN, aKNE; GEOMAlgo_KindOfClosed aKCE; // GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF); aKN=GEOMAlgo_KN_UNKNOWN; aInfo.SetKindOfName(aKN); // aKS=aInfo.KindOfShape(); if (aKS!=GEOMAlgo_KS_CYLINDER) { return; } // if (aInfo.KindOfBounds()==GEOMAlgo_KB_INFINITE) { return; } // aNbV=aInfo.NbSubShapes(TopAbs_VERTEX); aNbE=aInfo.NbSubShapes(TopAbs_EDGE); if (!(aNbV==2 && aNbE==3)) { return; } // i=0; aNbCE=0; aNbSE=0; aExp.Init(aF, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { aE=TopoDS::Edge(aExp.Current()); if(aM.Add(aE)) { const GEOMAlgo_ShapeInfo& aInfoE=myMapInfo.FindFromKey(aE); aKNE=aInfoE.KindOfName(); aKCE=aInfoE.KindOfClosed(); if (aKNE==GEOMAlgo_KN_CIRCLE && aKCE==GEOMAlgo_KC_CLOSED) { aPC[aNbCE]=aInfoE.Location(); ++aNbCE; } else if (aKNE==GEOMAlgo_KN_SEGMENT) { if (BRep_Tool::IsClosed(aE, aF)) { ++aNbSE; } } } } // if (!(aNbCE==2 && aNbSE==1)) { return; } // const gp_Ax1& aAx1=aCyl.Axis(); const gp_Dir& aDir=aAx1.Direction(); const gp_Pnt& aPLoc=aAx1.Location(); gp_Lin aLin(aPLoc, aDir); // aT0=ElCLib::Parameter(aLin, aPC[0]); aT1=ElCLib::Parameter(aLin, aPC[1]); // aPc=aPC[0];; if (aT0>aT1) { aPc=aPC[1]; } aHeight=aPC[0].Distance(aPC[1]); // gp_Ax3 aAx3=aCyl.Position(); aAx3.SetLocation(aPc); // aInfo.SetKindOfName(GEOMAlgo_KN_CYLINDER); aInfo.SetPosition(aAx3); aInfo.SetLocation(aPc); aInfo.SetHeight(aHeight); } //======================================================================= //function : FillDetails //purpose : //======================================================================= void GEOMAlgo_ShapeInfoFiller::FillDetails(const TopoDS_Face& aF, const gp_Torus& ) { Standard_Integer aNbV, aNbE, aNbSE; TopoDS_Edge aE; TopExp_Explorer aExp; TopTools_MapOfShape aM; GEOMAlgo_KindOfShape aKS; // GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aF); aInfo.SetKindOfName(GEOMAlgo_KN_UNKNOWN); // aKS=aInfo.KindOfShape(); if (aKS!=GEOMAlgo_KS_TORUS) { return; } // aNbV=aInfo.NbSubShapes(TopAbs_VERTEX); aNbE=aInfo.NbSubShapes(TopAbs_EDGE); if (!(aNbV==1 && aNbE==2)) { return; } // aNbSE=0; aExp.Init(aF, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { aE=TopoDS::Edge(aExp.Current()); if (aM.Add(aE)) { if (BRep_Tool::IsClosed(aE, aF)) { ++aNbSE; } } } // if (aNbSE!=2) { return; } aInfo.SetKindOfName(GEOMAlgo_KN_TORUS); } //modified by NIZNHY-PKV Tue Jul 03 13:29:41 2012f //======================================================================= //function : TreatStepSphere //purpose : //======================================================================= Standard_Boolean GEOMAlgo_ShapeInfoFiller::TreatStepSphere(const TopoDS_Solid& aSd) { Standard_Boolean bRet, bIsAllowedType, bOnlyClosed, bIsEqual; Standard_Integer j; Standard_Real aTolAng, aTolLin; Standard_Real aVolume, aVolumeS, dV, aArea, aAreaS, dA; gp_Sphere aSphere[2]; GeomAbs_SurfaceType aST; Handle(Geom_Surface) aS; GeomAdaptor_Surface aGAS; TopExp_Explorer aExp; // bRet=Standard_False; aTolLin=Precision::Confusion(); aTolAng=Precision::Angular(); // aExp.Init(aSd, TopAbs_FACE); for (j=0; aExp.More(); aExp.Next(), ++j) { const TopoDS_Face& aF=*((TopoDS_Face*)&aExp.Current()); aS=BRep_Tool::Surface(aF); aGAS.Load(aS); aST=aGAS.GetType(); bIsAllowedType=GEOMAlgo_ShapeInfoFiller::IsAllowedType(aST); if (!bIsAllowedType) { return bRet; } // if (aST!=GeomAbs_Sphere) { return bRet; } // aSphere[j]=aGAS.Sphere(); } // bIsEqual=IsEqual(aSphere[0], aSphere[1], aTolLin); if (!bIsEqual) { return bRet; } // //-------------------------------- GProp_GProps aGProps; // bOnlyClosed=Standard_False; // aVolume=aSphere[0].Volume(); // BRepGProp::VolumeProperties(aSd, aGProps, bOnlyClosed); aVolumeS=aGProps.Mass(); if (aVolumeS<0.) { aVolumeS=-aVolumeS; } // dV=fabs(aVolumeS-aVolume); if (dV>aTolLin) { return bRet; } //-------------------------------- aArea=aSphere[0].Area(); // BRepGProp::SurfaceProperties(aSd, aGProps); aAreaS=aGProps.Mass(); // dA=fabs(aAreaS-aArea); if (dA>aTolLin) { return bRet; } // //-------------------------------- gp_Pnt aP0; gp_Ax3 aAx3; Standard_Real aR1; // aP0=aSphere[0].Location(); aAx3=aSphere[0].Position(); aR1=aSphere[0].Radius(); // GEOMAlgo_ShapeInfo& aInfo=myMapInfo.ChangeFromKey(aSd); // aInfo.SetKindOfName(GEOMAlgo_KN_SPHERE); aInfo.SetLocation(aP0); aInfo.SetPosition(aAx3); aInfo.SetRadius1(aR1); // return !bRet;// true } //======================================================================= //function : IsEqual //purpose : //======================================================================= Standard_Boolean IsEqual(const gp_Sphere& aSp1, const gp_Sphere& aSp2, const Standard_Real aTolLin) { Standard_Boolean bRet; Standard_Real aR1, aR2, aD2; // bRet=Standard_False; aR1=aSp1.Radius(); aR2=aSp2.Radius(); if (fabs(aR1-aR2)>aTolLin) { return bRet; } // const gp_Pnt& aPC1=aSp1.Position().Location(); const gp_Pnt& aPC2=aSp2.Position().Location(); // aD2=aPC1.SquareDistance(aPC2); bRet=(aD2