X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAPI%2FGeomAPI_Face.cpp;h=c6b76d2bd62a286ac34917d5ee2497afafab7941;hb=a211165b993cec59888b300199b44b525c0daf69;hp=2055bdc6dac6951b35fb2e822c1eb46b5eee628b;hpb=38afbd899a8645c83e17f2c24a17a2b7414911b4;p=modules%2Fshaper.git diff --git a/src/GeomAPI/GeomAPI_Face.cpp b/src/GeomAPI/GeomAPI_Face.cpp index 2055bdc6d..c6b76d2bd 100644 --- a/src/GeomAPI/GeomAPI_Face.cpp +++ b/src/GeomAPI/GeomAPI_Face.cpp @@ -1,21 +1,64 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D +// +// 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, or (at your option) any later version. +// +// 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 +// -// File: GeomAPI_Face.cpp -// Created: 2 Dec 2014 -// Author: Artem ZHIDKOV +#include "GeomAPI_Face.h" -#include -#include -#include -#include +#include "GeomAPI_Dir.h" +#include "GeomAPI_Pln.h" +#include "GeomAPI_Pnt.h" +#include "GeomAPI_Sphere.h" +#include "GeomAPI_Curve.h" +#include "GeomAPI_Cylinder.h" +#include "GeomAPI_Cone.h" +#include "GeomAPI_Torus.h" -#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 + +#include +#include +#include +#include + GeomAPI_Face::GeomAPI_Face() : GeomAPI_Shape() @@ -31,14 +74,20 @@ GeomAPI_Face::GeomAPI_Face(const std::shared_ptr& theShape) bool GeomAPI_Face::isEqual(std::shared_ptr theFace) const { + if (!theFace.get()) + return false; + if (!theFace->isFace()) return false; const TopoDS_Shape& aMyShape = const_cast(this)->impl(); const TopoDS_Shape& aInShape = theFace->impl(); - Handle(Geom_Surface) aMySurf = BRep_Tool::Surface(TopoDS::Face(aMyShape)); - Handle(Geom_Surface) aInSurf = BRep_Tool::Surface(TopoDS::Face(aInShape)); + TopoDS_Face aMyFace = TopoDS::Face(aMyShape); + TopoDS_Face aInFace = TopoDS::Face(aInShape); + + Handle(Geom_Surface) aMySurf = BRep_Tool::Surface(aMyFace); + Handle(Geom_Surface) aInSurf = BRep_Tool::Surface(aInFace); // Check that surfaces a the same type if (aMySurf->DynamicType() != aInSurf->DynamicType()) @@ -57,45 +106,267 @@ bool GeomAPI_Face::isEqual(std::shared_ptr theFace) const fabs(aMyVMax - aInVMax) > Precision::PConfusion()) return false; - return true; + Handle(IntTools_Context) aContext = new IntTools_Context(); + // Double check needed because BOPTools_AlgoTools::AreFacesSameDomain not very smart. + Standard_Boolean aRes = BOPTools_AlgoTools::AreFacesSameDomain(aMyFace, aInFace, aContext) + && BOPTools_AlgoTools::AreFacesSameDomain(aInFace, aMyFace, aContext); + + return aRes == Standard_True; } -bool GeomAPI_Face::isPlanar() const +static Handle(Geom_Surface) baseSurface(const TopoDS_Face& theFace) { - const TopoDS_Shape& aShape = const_cast(this)->impl(); - Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape)); - if (aSurf->IsKind(STANDARD_TYPE(Geom_Plane))) + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(theFace); + while (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { + Handle(Geom_RectangularTrimmedSurface) rts = + Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf); + aSurf = rts->BasisSurface(); + } + return aSurf; +} + +bool GeomAPI_Face::isSameGeometry(const std::shared_ptr theShape) const +{ + if (!theShape->isFace()) + return false; + if (isSame(theShape)) return true; + + GeomFacePtr anOther = theShape->face(); + if (isPlanar() && anOther->isPlanar()) { + GeomPlanePtr anOwnPlane = getPlane(); + GeomPlanePtr anOtherPlane = anOther->getPlane(); + return anOwnPlane->isCoincident(anOtherPlane); + } + + TopoDS_Face anOwnFace = TopoDS::Face(impl()); + TopoDS_Face anOtherFace = TopoDS::Face(theShape->impl()); + + Handle(Geom_Surface) anOwnSurf = baseSurface(anOwnFace); + Handle(Geom_Surface) anOtherSurf = baseSurface(anOtherFace); + + // case of two elementary surfaces + if (anOwnSurf->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) && + anOtherSurf->IsKind(STANDARD_TYPE(Geom_ElementarySurface))) + { + Handle(GeomAdaptor_HSurface) aGA1 = new GeomAdaptor_HSurface(anOwnSurf); + Handle(GeomAdaptor_HSurface) aGA2 = new GeomAdaptor_HSurface(anOtherSurf); + + Handle(BRepTopAdaptor_TopolTool) aTT1 = new BRepTopAdaptor_TopolTool(); + Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool(); + + try { + IntPatch_ImpImpIntersection anIIInt(aGA1, aTT1, aGA2, aTT2, + Precision::Confusion(), + Precision::Confusion()); + if (!anIIInt.IsDone() || anIIInt.IsEmpty()) + return false; + + return anIIInt.TangentFaces(); + } + catch (Standard_Failure const&) { + return false; + } + } + + // case of two cylindrical surfaces, at least one of which is a swept surface + // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution + if ((anOwnSurf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) || + anOwnSurf->IsKind(STANDARD_TYPE(Geom_SweptSurface))) && + (anOtherSurf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) || + anOtherSurf->IsKind(STANDARD_TYPE(Geom_SweptSurface)))) + { + GeomCylinderPtr anOwnCyl = getCylinder(); + GeomCylinderPtr anOtherCyl = anOther->getCylinder(); + if (anOwnCyl && anOtherCyl) + return anOwnCyl->isCoincident(anOtherCyl); + + // compare two swept surfaces of the same type + if ((anOwnSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) && + anOtherSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) || + (anOwnSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)) && + anOtherSurf->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution)))) { + Handle(Geom_SweptSurface) anOwnSwept = Handle(Geom_SweptSurface)::DownCast(anOwnSurf); + Handle(Geom_SweptSurface) anOtherSwept = Handle(Geom_SweptSurface)::DownCast(anOtherSurf); + + const gp_Dir& anOwnDir = anOwnSwept->Direction(); + const gp_Dir& anOtherDir = anOtherSwept->Direction(); + + if (anOwnDir.IsParallel(anOtherDir, Precision::Angular())) { + Handle(Geom_Curve) anOwnCurve = anOwnSwept->BasisCurve(); + Handle(Geom_Curve) anOtherCurve = anOtherSwept->BasisCurve(); + GeomAPI_ExtremaCurveCurve anExtrema(anOwnCurve, anOtherCurve); + return anExtrema.Extrema().IsParallel() && + anExtrema.TotalLowerDistance() < Precision::Confusion(); + } + } + } + return false; } -std::shared_ptr GeomAPI_Face::getPlane() const +bool GeomAPI_Face::isCylindrical() const { const TopoDS_Shape& aShape = const_cast(this)->impl(); - BRepAdaptor_Surface aSurfAdapt(TopoDS::Face(aShape)); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aShape)); + Handle(Geom_RectangularTrimmedSurface) aTrimmed = + Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf); + if (!aTrimmed.IsNull()) + aSurf = aTrimmed->BasisSurface(); + return aSurf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) == Standard_True; +} - if (aSurfAdapt.GetType() != GeomAbs_Plane) - return std::shared_ptr(); +std::shared_ptr GeomAPI_Face::getPlane() const +{ + std::shared_ptr aResult; + TopoDS_Shape aShape = this->impl(); + if (aShape.IsNull()) + return aResult; // null shape + if (aShape.ShapeType() != TopAbs_FACE) + return aResult; // not face + TopoDS_Face aFace = TopoDS::Face(aShape); + if (aFace.IsNull()) + return aResult; // not face + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + if (aSurf.IsNull()) + return aResult; // no surface + GeomLib_IsPlanarSurface isPlanarSurf(aSurf); + gp_Pln aPln; + bool isPlanar = false; + if (isPlanarSurf.IsPlanar()) { + aPln = isPlanarSurf.Plan(); + isPlanar = true; + } + else if (aSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) { + Handle(Geom_OffsetSurface) anOffsetSurf = Handle(Geom_OffsetSurface)::DownCast(aSurf); + Handle(Geom_Surface) aBasisSurf = anOffsetSurf->BasisSurface(); + if (aBasisSurf->IsKind(STANDARD_TYPE(Geom_Plane))) { + aPln = Handle(Geom_Plane)::DownCast(aBasisSurf)->Pln(); + gp_Vec aTranslation(aPln.Axis().Direction().XYZ() * anOffsetSurf->Offset()); + aPln.Translate(aTranslation); + isPlanar = true; + } + } - // Obtain central point - double aUMin, aUMax, aVMin, aVMax; - aUMin = aSurfAdapt.FirstUParameter(); - aUMax = aSurfAdapt.LastUParameter(); - aVMin = aSurfAdapt.FirstVParameter(); - aVMax = aSurfAdapt.LastVParameter(); - gp_Pnt aCentralPnt; - gp_Vec aDU, aDV; - aSurfAdapt.D1((aUMin+aUMax)*0.5, (aVMin+aVMax)*0.5, aCentralPnt, aDU, aDV); - std::shared_ptr aCenter( - new GeomAPI_Pnt(aCentralPnt.X(), aCentralPnt.Y(), aCentralPnt.Z())); - - // Obtain plane direction - gp_XYZ aNormalVec = aDU.XYZ().Crossed(aDV.XYZ()); - if (aNormalVec.SquareModulus() < Precision::Confusion() * Precision::Confusion()) - return std::shared_ptr(); - std::shared_ptr aNormal( - new GeomAPI_Dir(aNormalVec.X(), aNormalVec.Y(), aNormalVec.Z())); - - std::shared_ptr aResult(new GeomAPI_Pln(aCenter, aNormal)); + if (isPlanar) { + double aA, aB, aC, aD; + aPln.Coefficients(aA, aB, aC, aD); + if (aFace.Orientation() == TopAbs_REVERSED) { + aA = -aA; + aB = -aB; + aC = -aC; + aD = -aD; + } + aResult = std::shared_ptr(new GeomAPI_Pln(aA, aB, aC, aD)); + } return aResult; } + +std::shared_ptr GeomAPI_Face::getSphere() const +{ + GeomSpherePtr aSphere; + + const TopoDS_Face& aFace = TopoDS::Face(impl()); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + if (aSurf->IsKind(STANDARD_TYPE(Geom_SphericalSurface))) { + gp_Sphere aSph = Handle(Geom_SphericalSurface)::DownCast(aSurf)->Sphere(); + const gp_Pnt& aCenter = aSph.Location(); + double aRadius = aSph.Radius(); + + GeomPointPtr aCenterPnt(new GeomAPI_Pnt(aCenter.X(), aCenter.Y(), aCenter.Z())); + aSphere = GeomSpherePtr(new GeomAPI_Sphere(aCenterPnt, aRadius)); + } + return aSphere; +} + +std::shared_ptr GeomAPI_Face::getCylinder() const +{ + GeomCylinderPtr aCylinder; + + const TopoDS_Face& aFace = TopoDS::Face(impl()); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + if (aSurf->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) { + gp_Cylinder aCyl = Handle(Geom_CylindricalSurface)::DownCast(aSurf)->Cylinder(); + gp_Pnt aLoc = aCyl.Location(); + const gp_Dir& aDir = aCyl.Position().Direction(); + double aRadius = aCyl.Radius(); + + double aUMin, aUMax, aVMin, aVMax; + BRepTools::UVBounds(aFace, aUMin, aUMax, aVMin, aVMax); + double aHeight = aVMax - aVMin; + + aLoc.ChangeCoord() += aDir.XYZ() * aVMin; + GeomPointPtr aLocation(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z())); + GeomDirPtr aDirection(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z())); + aCylinder = GeomCylinderPtr(new GeomAPI_Cylinder(aLocation, aDirection, aRadius, aHeight)); + } + return aCylinder; +} + +std::shared_ptr GeomAPI_Face::getCone() const +{ + GeomConePtr aCone; + + const TopoDS_Face& aFace = TopoDS::Face(impl()); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + if (aSurf->IsKind(STANDARD_TYPE(Geom_ConicalSurface))) { + gp_Cone aCon = Handle(Geom_ConicalSurface)::DownCast(aSurf)->Cone(); + gp_Pnt aLoc = aCon.Location(); + gp_Dir aDir = aCon.Position().Direction(); + + double aUMin, aUMax, aVMin, aVMax; + BRepTools::UVBounds(aFace, aUMin, aUMax, aVMin, aVMax); + + double aSemiAngle = Abs(aCon.SemiAngle()); + double aRadius1 = Abs(aCon.RefRadius() + aVMin * Sin(aCon.SemiAngle())); + double aRadius2 = Abs(aCon.RefRadius() + aVMax * Sin(aCon.SemiAngle())); + + aLoc.ChangeCoord() += aDir.XYZ() * aVMin * Cos(aCon.SemiAngle()); + + GeomPointPtr aLocation(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z())); + GeomDirPtr aDirection(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z())); + aCone = GeomConePtr(new GeomAPI_Cone(aLocation, aDirection, aSemiAngle, aRadius1, aRadius2)); + } + return aCone; +} + +std::shared_ptr GeomAPI_Face::getTorus() const +{ + GeomTorusPtr aTorus; + + const TopoDS_Face& aFace = TopoDS::Face(impl()); + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + if (aSurf->IsKind(STANDARD_TYPE(Geom_ToroidalSurface))) { + gp_Torus aTor = Handle(Geom_ToroidalSurface)::DownCast(aSurf)->Torus(); + const gp_Pnt& aLoc = aTor.Location(); + const gp_Dir& aDir = aTor.Position().Direction(); + double aMajorRadius = aTor.MajorRadius(); + double aMinorRadius = aTor.MinorRadius(); + + GeomPointPtr aCenter(new GeomAPI_Pnt(aLoc.X(), aLoc.Y(), aLoc.Z())); + GeomDirPtr aDirection(new GeomAPI_Dir(aDir.X(), aDir.Y(), aDir.Z())); + aTorus = GeomTorusPtr(new GeomAPI_Torus(aCenter, aDirection, aMajorRadius, aMinorRadius)); + } + return aTorus; +} + +GeomPointPtr GeomAPI_Face::middlePoint() const +{ + GeomPointPtr anInnerPoint; + + const TopoDS_Face& aFace = impl(); + if (aFace.IsNull()) + return anInnerPoint; + + BRepGProp_Face aProp(aFace); + double aUMin, aUMax, aVMin, aVMax; + aProp.Bounds(aUMin, aUMax, aVMin, aVMax); + + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace); + if (aSurf.IsNull()) + return anInnerPoint; + + gp_Pnt aPnt = aSurf->Value((aUMin + aUMax) * 0.5, (aVMin + aVMax) * 0.5); + anInnerPoint = GeomPointPtr(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z())); + return anInnerPoint; +}