Merge pull request #17416 from wwmayer/measure_circle_circle
Measure: When measuring the distance between circles then use the cen…
This commit is contained in:
@@ -27,7 +27,13 @@
|
||||
#include <App/Document.h>
|
||||
#include <App/MeasureManager.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <BRepAdaptor_Curve.hxx>
|
||||
#include <BRepAdaptor_CompCurve.hxx>
|
||||
#include <BRepExtrema_DistShapeShape.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
|
||||
#include "MeasureDistance.h"
|
||||
|
||||
@@ -178,6 +184,44 @@ bool MeasureDistance::getShape(App::PropertyLinkSub* prop, TopoDS_Shape& rShape)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MeasureDistance::distanceCircleCircle(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2)
|
||||
{
|
||||
auto circle1 = asCircle(shape1);
|
||||
auto circle2 = asCircle(shape2);
|
||||
if (!circle1.IsNull() && !circle2.IsNull()) {
|
||||
const gp_Pnt p1 = circle1->Location();
|
||||
const gp_Pnt p2 = circle2->Location();
|
||||
setValues(p1, p2);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MeasureDistance::distanceGeneric(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2)
|
||||
{
|
||||
// Calculate the extrema
|
||||
BRepExtrema_DistShapeShape measure(shape1, shape2);
|
||||
if (!measure.IsDone() || measure.NbSolution() < 1) {
|
||||
throw Base::RuntimeError("Could not get extrema");
|
||||
}
|
||||
|
||||
const gp_Pnt p1 = measure.PointOnShape1(1);
|
||||
const gp_Pnt p2 = measure.PointOnShape2(1);
|
||||
setValues(p1, p2);
|
||||
}
|
||||
|
||||
void MeasureDistance::setValues(const gp_Pnt& p1, const gp_Pnt& p2)
|
||||
{
|
||||
Position1.setValue(p1.X(), p1.Y(), p1.Z());
|
||||
Position2.setValue(p2.X(), p2.Y(), p2.Z());
|
||||
|
||||
const gp_Pnt delta = p2.XYZ() - p1.XYZ();
|
||||
Distance.setValue(p1.Distance(p2));
|
||||
DistanceX.setValue(std::fabs(delta.X()));
|
||||
DistanceY.setValue(std::fabs(delta.Y()));
|
||||
DistanceZ.setValue(std::fabs(delta.Z()));
|
||||
}
|
||||
|
||||
App::DocumentObjectExecReturn* MeasureDistance::execute()
|
||||
{
|
||||
@@ -207,24 +251,11 @@ App::DocumentObjectExecReturn* MeasureDistance::execute()
|
||||
return new App::DocumentObjectExecReturn("Could not get shape");
|
||||
}
|
||||
|
||||
// Calculate the extrema
|
||||
BRepExtrema_DistShapeShape measure(shape1, shape2);
|
||||
if (!measure.IsDone() || measure.NbSolution() < 1) {
|
||||
return new App::DocumentObjectExecReturn("Could not get extrema");
|
||||
if (distanceCircleCircle(shape1, shape2)) {
|
||||
return DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
gp_Pnt p1 = measure.PointOnShape1(1);
|
||||
Position1.setValue(p1.X(), p1.Y(), p1.Z());
|
||||
|
||||
gp_Pnt p2 = measure.PointOnShape2(1);
|
||||
Position2.setValue(p2.X(), p2.Y(), p2.Z());
|
||||
|
||||
gp_Pnt delta = measure.PointOnShape2(1).XYZ() - measure.PointOnShape1(1).XYZ();
|
||||
Distance.setValue(measure.Value());
|
||||
DistanceX.setValue(fabs(delta.X()));
|
||||
DistanceY.setValue(fabs(delta.Y()));
|
||||
DistanceZ.setValue(fabs(delta.Z()));
|
||||
|
||||
distanceGeneric(shape1, shape2);
|
||||
return DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
@@ -240,6 +271,44 @@ void MeasureDistance::onChanged(const App::Property* prop)
|
||||
DocumentObject::onChanged(prop);
|
||||
}
|
||||
|
||||
Handle(Geom_Circle) MeasureDistance::asCircle(const TopoDS_Shape& shape) const
|
||||
{
|
||||
if (shape.IsNull()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (shape.ShapeType() == TopAbs_EDGE) {
|
||||
return asCircle(TopoDS::Edge(shape));
|
||||
}
|
||||
|
||||
if (shape.ShapeType() == TopAbs_WIRE) {
|
||||
return asCircle(TopoDS::Wire(shape));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Handle(Geom_Circle) MeasureDistance::asCircle(const TopoDS_Edge& edge) const
|
||||
{
|
||||
Handle(Geom_Circle) circle;
|
||||
BRepAdaptor_Curve adapt(edge);
|
||||
if (adapt.GetType() == GeomAbs_Circle) {
|
||||
circle = new Geom_Circle(adapt.Circle());
|
||||
}
|
||||
|
||||
return circle;
|
||||
}
|
||||
|
||||
Handle(Geom_Circle) MeasureDistance::asCircle(const TopoDS_Wire& wire) const
|
||||
{
|
||||
Handle(Geom_Circle) circle;
|
||||
BRepAdaptor_CompCurve adapt(wire);
|
||||
if (adapt.GetType() == GeomAbs_Circle) {
|
||||
circle = new Geom_Circle(adapt.Circle());
|
||||
}
|
||||
|
||||
return circle;
|
||||
}
|
||||
|
||||
//! Return the object we are measuring
|
||||
//! used by the viewprovider in determining visibility
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <Mod/Measure/MeasureGlobal.h>
|
||||
|
||||
#include <Geom_Circle.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
|
||||
#include <App/PropertyGeo.h>
|
||||
@@ -35,6 +36,9 @@
|
||||
|
||||
#include "MeasureBase.h"
|
||||
|
||||
class TopoDS_Edge;
|
||||
class TopoDS_Wire;
|
||||
|
||||
namespace Measure
|
||||
{
|
||||
|
||||
@@ -99,7 +103,13 @@ public:
|
||||
|
||||
|
||||
private:
|
||||
bool distanceCircleCircle(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2);
|
||||
void distanceGeneric(const TopoDS_Shape& shape1, const TopoDS_Shape& shape2);
|
||||
void setValues(const gp_Pnt& p1, const gp_Pnt& p2);
|
||||
void onChanged(const App::Property* prop) override;
|
||||
Handle(Geom_Circle) asCircle(const TopoDS_Shape& shape) const;
|
||||
Handle(Geom_Circle) asCircle(const TopoDS_Edge& edge) const;
|
||||
Handle(Geom_Circle) asCircle(const TopoDS_Wire& wire) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -96,6 +96,9 @@ endif(BUILD_ASSEMBLY)
|
||||
if(BUILD_MATERIAL)
|
||||
list (APPEND TestExecutables Material_tests_run)
|
||||
endif(BUILD_MATERIAL)
|
||||
if(BUILD_MEASURE)
|
||||
list (APPEND TestExecutables Measure_tests_run)
|
||||
endif(BUILD_MEASURE)
|
||||
if(BUILD_MESH)
|
||||
list (APPEND TestExecutables Mesh_tests_run)
|
||||
endif(BUILD_MESH)
|
||||
|
||||
@@ -4,6 +4,9 @@ endif(BUILD_ASSEMBLY)
|
||||
if(BUILD_MATERIAL)
|
||||
add_subdirectory(Material)
|
||||
endif(BUILD_MATERIAL)
|
||||
if(BUILD_MEASURE)
|
||||
add_subdirectory(Measure)
|
||||
endif(BUILD_MEASURE)
|
||||
if(BUILD_MESH)
|
||||
add_subdirectory(Mesh)
|
||||
endif(BUILD_MESH)
|
||||
|
||||
11
tests/src/Mod/Measure/App/CMakeLists.txt
Normal file
11
tests/src/Mod/Measure/App/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
target_sources(
|
||||
Measure_tests_run
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/MeasureDistance.cpp
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
Measure_tests_run
|
||||
PUBLIC
|
||||
${CMAKE_BINARY_DIR}
|
||||
)
|
||||
70
tests/src/Mod/Measure/App/MeasureDistance.cpp
Normal file
70
tests/src/Mod/Measure/App/MeasureDistance.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <src/App/InitApplication.h>
|
||||
#include <App/Document.h>
|
||||
#include <Mod/Measure/App/MeasureDistance.h>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Wire.hxx>
|
||||
|
||||
class MeasureDistance: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
static void SetUpTestSuite()
|
||||
{
|
||||
tests::initApplication();
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
document = App::GetApplication().newDocument("Measure");
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
App::GetApplication().closeDocument(document->getName());
|
||||
}
|
||||
|
||||
App::Document* getDocument() const
|
||||
{
|
||||
return document;
|
||||
}
|
||||
|
||||
TopoDS_Edge makeCircle(const gp_Pnt& pnt) const
|
||||
{
|
||||
gp_Circ circle;
|
||||
circle.SetLocation(pnt);
|
||||
circle.SetRadius(1.0);
|
||||
BRepBuilderAPI_MakeEdge mkEdge(circle);
|
||||
return mkEdge.Edge();
|
||||
}
|
||||
|
||||
private:
|
||||
App::Document* document {};
|
||||
};
|
||||
|
||||
// NOLINTBEGIN
|
||||
TEST_F(MeasureDistance, testCircleCircle)
|
||||
{
|
||||
App::Document* doc = getDocument();
|
||||
auto p1 = dynamic_cast<Part::Feature*>(doc->addObject("Part::Feature", "Shape1"));
|
||||
p1->Shape.setValue(makeCircle(gp_Pnt(0.0, 0.0, 0.0)));
|
||||
auto p2 = dynamic_cast<Part::Feature*>(doc->addObject("Part::Feature", "Shape2"));
|
||||
p2->Shape.setValue(makeCircle(gp_Pnt(3.0, 4.0, 0.0)));
|
||||
|
||||
auto md = dynamic_cast<Measure::MeasureDistance*>(
|
||||
doc->addObject("Measure::MeasureDistance", "Distance"));
|
||||
md->Element1.setValue(p1, {"Edge1"});
|
||||
md->Element2.setValue(p2, {"Edge1"});
|
||||
|
||||
doc->recompute();
|
||||
|
||||
EXPECT_DOUBLE_EQ(md->Distance.getValue(), 5.0);
|
||||
EXPECT_DOUBLE_EQ(md->DistanceX.getValue(), 3.0);
|
||||
EXPECT_DOUBLE_EQ(md->DistanceY.getValue(), 4.0);
|
||||
EXPECT_DOUBLE_EQ(md->DistanceZ.getValue(), 0.0);
|
||||
EXPECT_EQ(md->Position1.getValue(), Base::Vector3d(0.0, 0.0, 0.0));
|
||||
EXPECT_EQ(md->Position2.getValue(), Base::Vector3d(3.0, 4.0, 0.0));
|
||||
}
|
||||
// NOLINTEND
|
||||
17
tests/src/Mod/Measure/CMakeLists.txt
Normal file
17
tests/src/Mod/Measure/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
target_include_directories(Measure_tests_run PUBLIC
|
||||
${EIGEN3_INCLUDE_DIR}
|
||||
${OCC_INCLUDE_DIR}
|
||||
${Python3_INCLUDE_DIRS}
|
||||
${SMESH_INCLUDE_DIR}
|
||||
${VTK_INCLUDE_DIRS}
|
||||
${XercesC_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
target_link_libraries(Measure_tests_run
|
||||
gtest_main
|
||||
${Google_Tests_LIBS}
|
||||
Measure
|
||||
)
|
||||
|
||||
add_subdirectory(App)
|
||||
Reference in New Issue
Block a user