X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FGeomAlgoAPI%2FGeomAlgoAPI_EdgeBuilder.cpp;h=86fe03d7b30a640cba5b53ce8f00af2c8848c396;hb=f64e1300ed35bb1e9a2486cdb5713355e832dd39;hp=c8419fe376853ab416221be403e4441779c9a379;hpb=d4572a0253007ff9fc263253720e37bf896f8d0d;p=modules%2Fshaper.git diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp index c8419fe37..86fe03d7b 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_EdgeBuilder.cpp @@ -1,23 +1,304 @@ -// File: GeomAlgoAPI_EdgeBuilder.cpp -// Created: 23 Apr 2014 -// Author: Mikhail PONIKAROV +// Copyright (C) 2014-2023 CEA, EDF +// +// 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 +// #include + +#include +#include +#include +#include +#include + #include #include #include +#include #include #include +#include #include +#include +#include +#include + +#include +#include +#include +#include +#include -boost::shared_ptr GeomAlgoAPI_EdgeBuilder::line( - boost::shared_ptr theStart, boost::shared_ptr theEnd) +static GeomEdgePtr createLine(const gp_Pnt& theStart, const gp_Pnt& theEnd) +{ + GeomEdgePtr aRes; + if (!theStart.IsEqual(theEnd, Precision::Confusion()) && + Abs(theStart.SquareDistance(theEnd)) < 1.e+100) { + BRepBuilderAPI_MakeEdge anEdgeBuilder(theStart, theEnd); + TopoDS_Edge anEdge = anEdgeBuilder.Edge(); + aRes = GeomEdgePtr(new GeomAPI_Edge); + aRes->setImpl(new TopoDS_Shape(anEdge)); + } + return aRes; +} + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::line( + std::shared_ptr theStart, std::shared_ptr theEnd) { const gp_Pnt& aStart = theStart->impl(); const gp_Pnt& anEnd = theEnd->impl(); + return createLine(aStart, anEnd); +} +std::shared_ptr GeomAlgoAPI_EdgeBuilder::line( + double theDX, double theDY, double theDZ) +{ + const gp_Pnt& aStart = gp_Pnt(0, 0, 0); + const gp_Pnt& anEnd = gp_Pnt(theDX, theDY, theDZ); + return createLine(aStart, anEnd); +} + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::line( + const std::shared_ptr theLin) +{ + GeomEdgePtr aRes; + if (theLin.get()) { + const gp_Lin& aLin = theLin->impl(); + BRepBuilderAPI_MakeEdge anEdgeBuilder(aLin); + TopoDS_Edge anEdge = anEdgeBuilder.Edge(); + aRes = GeomEdgePtr(new GeomAPI_Edge); + aRes->setImpl(new TopoDS_Shape(anEdge)); + } + return aRes; +} + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::cylinderAxis( + std::shared_ptr theCylindricalFace) +{ + std::shared_ptr aResult; + const TopoDS_Shape& aShape = theCylindricalFace->impl(); + if (aShape.IsNull()) + return aResult; + TopoDS_Face aFace = TopoDS::Face(aShape); + if (aFace.IsNull()) + return aResult; + TopLoc_Location aLoc; + Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc); + if (aSurf.IsNull()) + return aResult; + Handle(Geom_RectangularTrimmedSurface) aTrimmed = + Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf); + if (!aTrimmed.IsNull()) + aSurf = aTrimmed->BasisSurface(); + Handle(Geom_CylindricalSurface) aCyl = Handle(Geom_CylindricalSurface)::DownCast(aSurf); + if (aCyl.IsNull()) + return aResult; + gp_Ax1 anAxis = aCyl->Axis(); + // compute the start and the end points of the resulting edge by the bounding box of the face + // (vertices projected to the axis) plus 10% + Bnd_Box aFaceBnd; + BRepBndLib::Add(aFace, aFaceBnd); + gp_Pnt aBoxMin(aFaceBnd.CornerMin()), aBoxMax(aFaceBnd.CornerMax()); + bool isFirst = true; + double aParamMin = 0, aParamMax = 0; + for(int aX = 0; aX < 2; aX++) { + for(int aY = 0; aY < 2; aY++) { + for(int aZ = 0; aZ < 2; aZ++) { + gp_XYZ aBoxVertex(aX == 0 ? aBoxMin.X() : aBoxMax.X(), + aY == 0 ? aBoxMin.Y() : aBoxMax.Y(), aZ == 0 ? aBoxMin.Z() : aBoxMax.Z()); + gp_XYZ aVec(aBoxVertex - anAxis.Location().XYZ()); + double aProjParam = aVec.Dot(anAxis.Direction().XYZ()); + if (isFirst) { + isFirst = false; + aParamMin = aProjParam; + aParamMax = aProjParam; + } else { + if (aParamMin > aProjParam) + aParamMin = aProjParam; + else if (aParamMax < aProjParam) + aParamMax = aProjParam; + } + } + } + } + // add 10% + double aDelta = aParamMax - aParamMin; + if (aDelta < 1.e-4) aDelta = 1.e-4; + aParamMin -= aDelta * 0.1; + aParamMax += aDelta * 0.1; + + gp_Pnt aStart(aParamMin * anAxis.Direction().XYZ() + anAxis.Location().XYZ()); + aStart.Transform(aLoc.Transformation()); + gp_Pnt anEnd(aParamMax * anAxis.Direction().XYZ() + anAxis.Location().XYZ()); + anEnd.Transform(aLoc.Transformation()); + /* + gp_Pnt aStart(anAxis.Location().Transformed(aLoc.Transformation())); + // edge length is 100, "-" because cylinder of extrusion has negative direction with the cylinder + gp_Pnt anEnd(anAxis.Location().XYZ() - anAxis.Direction().XYZ() * 100.); + anEnd.Transform(aLoc.Transformation()); + */ BRepBuilderAPI_MakeEdge anEdgeBuilder(aStart, anEnd); - boost::shared_ptr aRes(new GeomAPI_Shape); + std::shared_ptr aRes(new GeomAPI_Edge); + TopoDS_Edge anEdge = anEdgeBuilder.Edge(); + // an axis is an infinite object + anEdge.Infinite(Standard_True); + aRes->setImpl(new TopoDS_Shape(anEdge)); + return aRes; +} + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircle( + std::shared_ptr theCenter, std::shared_ptr theNormal, + double theRadius, double theRotationAngle) +{ + const gp_Pnt& aCenter = theCenter->impl(); + const gp_Dir& aDir = theNormal->impl(); + + gp_Ax1 anAx(aCenter, aDir); + + gp_Circ aCircle(gp_Ax2(aCenter, aDir), theRadius); + if (Abs(theRotationAngle) > 1.e-7) // Tolerance + aCircle.Rotate(anAx, theRotationAngle); + + BRepBuilderAPI_MakeEdge anEdgeBuilder(aCircle); + std::shared_ptr aRes(new GeomAPI_Edge); + TopoDS_Edge anEdge = anEdgeBuilder.Edge(); + aRes->setImpl(new TopoDS_Shape(anEdge)); + return aRes; +} + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircle( + std::shared_ptr theCircle) +{ + GeomEdgePtr aRes; + if (theCircle.get()) { + const gp_Circ& aCirc = theCircle->impl(); + BRepBuilderAPI_MakeEdge anEdgeBuilder(aCirc); + TopoDS_Edge anEdge = anEdgeBuilder.Edge(); + aRes = GeomEdgePtr(new GeomAPI_Edge); + aRes->setImpl(new TopoDS_Shape(anEdge)); + } + return aRes; +} + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::lineCircleArc( + std::shared_ptr theCenter, std::shared_ptr theStartPoint, + std::shared_ptr theEndPoint, std::shared_ptr theNormal) +{ + std::shared_ptr aRes; + + const gp_Pnt& aCenter = theCenter->impl(); + const gp_Dir& aDir = theNormal->impl(); + + /// OCCT creates an edge on a circle with empty radius, but visualization + /// is not able to process it + if (theCenter->isEqual(theStartPoint) || theCenter->isEqual(theEndPoint)) + return aRes; + + double aRadius = theCenter->distance(theStartPoint); + gp_Circ aCircle(gp_Ax2(aCenter, aDir), aRadius); + + const gp_Pnt& aStart = theStartPoint->impl(); + const gp_Pnt& anEndInter = theEndPoint->impl(); + + // project end point to a circle + gp_XYZ aEndDir = anEndInter.XYZ() - aCenter.XYZ(); + gp_Pnt anEnd(aCenter.XYZ() + aEndDir.Normalized() * aRadius); + + BRepBuilderAPI_MakeEdge anEdgeBuilder; + anEdgeBuilder = BRepBuilderAPI_MakeEdge(aCircle, aStart, anEnd); + + anEdgeBuilder.Build(); + + if (anEdgeBuilder.IsDone()) { + aRes = std::shared_ptr(new GeomAPI_Edge); + aRes->setImpl(new TopoDS_Shape(anEdgeBuilder.Edge())); + } + return aRes; +} + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::ellipse( + const std::shared_ptr& theCenter, + const std::shared_ptr& theNormal, + const std::shared_ptr& theMajorAxis, + const double theMajorRadius, + const double theMinorRadius) +{ + const gp_Pnt& aCenter = theCenter->impl(); + const gp_Dir& aNormal = theNormal->impl(); + const gp_Dir& aMajorAxis = theMajorAxis->impl(); + + gp_Elips anEllipse(gp_Ax2(aCenter, aNormal, aMajorAxis), theMajorRadius, theMinorRadius); + + BRepBuilderAPI_MakeEdge anEdgeBuilder(anEllipse); + std::shared_ptr aRes(new GeomAPI_Edge); + TopoDS_Edge anEdge = anEdgeBuilder.Edge(); + aRes->setImpl(new TopoDS_Shape(anEdge)); + return aRes; +} + +std::shared_ptr GeomAlgoAPI_EdgeBuilder::ellipticArc( + const std::shared_ptr& theCenter, + const std::shared_ptr& theNormal, + const std::shared_ptr& theMajorAxis, + const double theMajorRadius, + const double theMinorRadius, + const std::shared_ptr& theStart, + const std::shared_ptr& theEnd) +{ + std::shared_ptr anAx2(new GeomAPI_Ax2(theCenter, theNormal, theMajorAxis)); + GeomAPI_Ellipse anEllipse(anAx2, theMajorRadius, theMinorRadius); + + GeomPointPtr aStartPnt = anEllipse.project(theStart); + GeomPointPtr aEndPnt = anEllipse.project(theEnd); + + double aStartParam, aEndParam; + anEllipse.parameter(aStartPnt, Precision::Confusion(), aStartParam); + anEllipse.parameter(aEndPnt, Precision::Confusion(), aEndParam); + + BRepBuilderAPI_MakeEdge anEdgeBuilder(anEllipse.impl(), aStartParam, aEndParam); + GeomEdgePtr aRes(new GeomAPI_Edge); + TopoDS_Edge anEdge = anEdgeBuilder.Edge(); + aRes->setImpl(new TopoDS_Shape(anEdge)); + return aRes; +} + +GeomEdgePtr GeomAlgoAPI_EdgeBuilder::bsplineOnPlane( + const std::shared_ptr& thePlane, + const std::list& thePoles, + const std::list& theWeights, + const std::list& theKnots, + const std::list& theMults, + const int theDegree, + const bool thePeriodic) +{ + std::shared_ptr aBSplineCurve( + new GeomAPI_BSpline2d(theDegree, thePoles, theWeights, theKnots, theMults, thePeriodic)); + return bsplineOnPlane(thePlane, aBSplineCurve); +} + +GeomEdgePtr GeomAlgoAPI_EdgeBuilder::bsplineOnPlane( + const std::shared_ptr& thePlane, + const std::shared_ptr& theCurve) +{ + Handle(Geom_Curve) aCurve3D = GeomLib::To3d(thePlane->impl().Ax2(), + theCurve->impl()); + + BRepBuilderAPI_MakeEdge anEdgeBuilder(aCurve3D); + GeomEdgePtr aRes(new GeomAPI_Edge); TopoDS_Edge anEdge = anEdgeBuilder.Edge(); aRes->setImpl(new TopoDS_Shape(anEdge)); return aRes;