mirror of
https://github.com/Open-Cascade-SAS/OCCT.git
synced 2026-09-04 19:57:55 +08:00
Modeling Data - Prevent exception in BRep_Tool::CurveOnPlane (#1402)
Validate the edge range against the effective curve basis before constructing Geom_TrimmedCurve. Preserve valid periodic ranges and return a null pcurve for inconsistent bounded ranges.
This commit is contained in:
@@ -65,6 +65,40 @@
|
||||
// modified by NIZNHY-PKV Fri Oct 17 14:13:29 2008f
|
||||
static bool IsPlane(const occ::handle<Geom_Surface>& aS);
|
||||
|
||||
namespace
|
||||
{
|
||||
//=================================================================================================
|
||||
|
||||
//! Checks trim range against the effective basis curve.
|
||||
//! @param[in] theCurve curve to check
|
||||
//! @param[in] theFirst first trim parameter
|
||||
//! @param[in] theLast last trim parameter
|
||||
//! @return true if the trim range is valid
|
||||
bool isValidTrimRange(const occ::handle<Geom_Curve>& theCurve,
|
||||
const double theFirst,
|
||||
const double theLast)
|
||||
{
|
||||
const double aTrimFirst = std::min(theFirst, theLast);
|
||||
const double aTrimLast = std::max(theFirst, theLast);
|
||||
if (!(aTrimFirst < aTrimLast))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unwrap nested trims.
|
||||
occ::handle<Geom_Curve> aBasisCurve = theCurve;
|
||||
for (occ::handle<Geom_TrimmedCurve> aTrim = occ::down_cast<Geom_TrimmedCurve>(aBasisCurve);
|
||||
!aTrim.IsNull();
|
||||
aTrim = occ::down_cast<Geom_TrimmedCurve>(aBasisCurve))
|
||||
{
|
||||
aBasisCurve = aTrim->BasisCurve();
|
||||
}
|
||||
return aBasisCurve->IsPeriodic()
|
||||
|| (aBasisCurve->FirstParameter() - aTrimFirst <= Precision::PConfusion()
|
||||
&& aTrimLast - aBasisCurve->LastParameter() <= Precision::PConfusion());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// modified by NIZNHY-PKV Fri Oct 17 14:13:33 2008t
|
||||
//
|
||||
//=================================================================================================
|
||||
@@ -427,12 +461,16 @@ occ::handle<Geom2d_Curve> BRep_Tool::CurveOnPlane(const TopoDS_Edge&
|
||||
l = C3D->TransformedParameter(l, aTrsf);
|
||||
}
|
||||
|
||||
if (!isValidTrimRange(C3D, f, l))
|
||||
{
|
||||
return nullPCurve;
|
||||
}
|
||||
|
||||
occ::handle<Geom_TrimmedCurve> aTrimmedCurve = new Geom_TrimmedCurve(C3D, f, l, true, false);
|
||||
|
||||
// Perform projection
|
||||
occ::handle<Geom_Curve> ProjOnPlane =
|
||||
GeomProjLib::ProjectOnPlane(new Geom_TrimmedCurve(C3D, f, l, true, false),
|
||||
GP,
|
||||
GP->Position().Direction(),
|
||||
true);
|
||||
GeomProjLib::ProjectOnPlane(aTrimmedCurve, GP, GP->Position().Direction(), true);
|
||||
|
||||
occ::handle<GeomAdaptor_Surface> HS = new GeomAdaptor_Surface(GP);
|
||||
occ::handle<GeomAdaptor_Curve> HC = new GeomAdaptor_Curve(ProjOnPlane);
|
||||
|
||||
@@ -11,15 +11,20 @@
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepPrimAPI_MakeBox.hxx>
|
||||
#include <Geom2d_Curve.hxx>
|
||||
#include <Geom_BezierCurve.hxx>
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <Geom_Curve.hxx>
|
||||
#include <Geom_Plane.hxx>
|
||||
#include <Geom_Surface.hxx>
|
||||
#include <gp.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <NCollection_Array1.hxx>
|
||||
#include <Precision.hxx>
|
||||
#include <TopAbs_ShapeEnum.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
@@ -158,3 +163,101 @@ TEST(BRep_Tool_Test, Degenerated)
|
||||
const TopoDS_Edge& anEdge = TopoDS::Edge(anExp.Current());
|
||||
EXPECT_FALSE(BRep_Tool::Degenerated(anEdge)) << "Box edges should not be degenerated";
|
||||
}
|
||||
|
||||
TEST(BRep_Tool_Test, CurveOnPlane_RejectsEdgeRangeOutsideBoundedCurve)
|
||||
{
|
||||
NCollection_Array1<gp_Pnt> aPoles(1, 3);
|
||||
aPoles.SetValue(1, gp_Pnt(0.0, 0.0, 0.0));
|
||||
aPoles.SetValue(2, gp_Pnt(0.5, 0.25, 0.0));
|
||||
aPoles.SetValue(3, gp_Pnt(1.0, 0.0, 0.0));
|
||||
occ::handle<Geom_BezierCurve> aCurve = new Geom_BezierCurve(aPoles);
|
||||
|
||||
BRepBuilderAPI_MakeEdge anEdgeMaker(aCurve);
|
||||
ASSERT_TRUE(anEdgeMaker.IsDone());
|
||||
const TopoDS_Edge& anEdge = anEdgeMaker.Edge();
|
||||
|
||||
constexpr double THE_EDGE_FIRST = -0.000002673149646;
|
||||
constexpr double THE_EDGE_LAST = 0.999997326850354;
|
||||
BRep_Builder().Range(anEdge, THE_EDGE_FIRST, THE_EDGE_LAST, true);
|
||||
|
||||
occ::handle<Geom_Plane> aPlane = new Geom_Plane(gp::XOY());
|
||||
occ::handle<Geom2d_Curve> aPCurve;
|
||||
double aFirst = 0.0;
|
||||
double aLast = 0.0;
|
||||
bool isStored = true;
|
||||
EXPECT_NO_THROW(
|
||||
aPCurve =
|
||||
BRep_Tool::CurveOnSurface(anEdge, aPlane, TopLoc_Location(), aFirst, aLast, &isStored));
|
||||
|
||||
EXPECT_TRUE(aPCurve.IsNull());
|
||||
EXPECT_FALSE(isStored);
|
||||
EXPECT_DOUBLE_EQ(aFirst, THE_EDGE_FIRST);
|
||||
EXPECT_DOUBLE_EQ(aLast, THE_EDGE_LAST);
|
||||
}
|
||||
|
||||
TEST(BRep_Tool_Test, CurveOnPlane_ProjectsShiftedPeriodicRange)
|
||||
{
|
||||
occ::handle<Geom_Circle> aCircle = new Geom_Circle(gp_Ax2(gp::Origin(), gp::DZ()), 1.0);
|
||||
BRepBuilderAPI_MakeEdge anEdgeMaker(aCircle);
|
||||
ASSERT_TRUE(anEdgeMaker.IsDone());
|
||||
const TopoDS_Edge& anEdge = anEdgeMaker.Edge();
|
||||
|
||||
const double aRangeFirst = aCircle->Period();
|
||||
const double aRangeLast = 2.0 * aCircle->Period();
|
||||
BRep_Builder().Range(anEdge, aRangeFirst, aRangeLast, true);
|
||||
|
||||
occ::handle<Geom_Plane> aPlane = new Geom_Plane(gp::XOY());
|
||||
occ::handle<Geom2d_Curve> aPCurve;
|
||||
double aFirst = 0.0;
|
||||
double aLast = 0.0;
|
||||
EXPECT_NO_THROW(aPCurve =
|
||||
BRep_Tool::CurveOnPlane(anEdge, aPlane, TopLoc_Location(), aFirst, aLast));
|
||||
|
||||
EXPECT_FALSE(aPCurve.IsNull());
|
||||
EXPECT_DOUBLE_EQ(aFirst, aRangeFirst);
|
||||
EXPECT_DOUBLE_EQ(aLast, aRangeLast);
|
||||
}
|
||||
|
||||
TEST(BRep_Tool_Test, CurveOnPlane_ProjectsPeriodicEdgeBuiltFromEqualParameters)
|
||||
{
|
||||
occ::handle<Geom_Circle> aCircle = new Geom_Circle(gp_Ax2(gp::Origin(), gp::DZ()), 1.0);
|
||||
BRepBuilderAPI_MakeEdge anEdgeMaker(aCircle, 0.0, 0.0);
|
||||
ASSERT_TRUE(anEdgeMaker.IsDone());
|
||||
const TopoDS_Edge& anEdge = anEdgeMaker.Edge();
|
||||
|
||||
double aEdgeFirst = 0.0;
|
||||
double aEdgeLast = 0.0;
|
||||
BRep_Tool::Range(anEdge, aEdgeFirst, aEdgeLast);
|
||||
EXPECT_NEAR(aEdgeLast - aEdgeFirst, aCircle->Period(), Precision::PConfusion());
|
||||
|
||||
occ::handle<Geom_Plane> aPlane = new Geom_Plane(gp::XOY());
|
||||
occ::handle<Geom2d_Curve> aPCurve;
|
||||
double aFirst = 0.0;
|
||||
double aLast = 0.0;
|
||||
EXPECT_NO_THROW(aPCurve =
|
||||
BRep_Tool::CurveOnPlane(anEdge, aPlane, TopLoc_Location(), aFirst, aLast));
|
||||
|
||||
EXPECT_FALSE(aPCurve.IsNull());
|
||||
EXPECT_DOUBLE_EQ(aFirst, aEdgeFirst);
|
||||
EXPECT_DOUBLE_EQ(aLast, aEdgeLast);
|
||||
}
|
||||
|
||||
TEST(BRep_Tool_Test, CurveOnPlane_RejectsEqualPeriodicRange)
|
||||
{
|
||||
occ::handle<Geom_Circle> aCircle = new Geom_Circle(gp_Ax2(gp::Origin(), gp::DZ()), 1.0);
|
||||
BRepBuilderAPI_MakeEdge anEdgeMaker(aCircle);
|
||||
ASSERT_TRUE(anEdgeMaker.IsDone());
|
||||
const TopoDS_Edge& anEdge = anEdgeMaker.Edge();
|
||||
BRep_Builder().Range(anEdge, 0.0, 0.0, true);
|
||||
|
||||
occ::handle<Geom_Plane> aPlane = new Geom_Plane(gp::XOY());
|
||||
occ::handle<Geom2d_Curve> aPCurve;
|
||||
double aFirst = 1.0;
|
||||
double aLast = 1.0;
|
||||
EXPECT_NO_THROW(aPCurve =
|
||||
BRep_Tool::CurveOnPlane(anEdge, aPlane, TopLoc_Location(), aFirst, aLast));
|
||||
|
||||
EXPECT_TRUE(aPCurve.IsNull());
|
||||
EXPECT_DOUBLE_EQ(aFirst, 0.0);
|
||||
EXPECT_DOUBLE_EQ(aLast, 0.0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user