Sketch: Refactor SketchObject::getPoint

Add the helper class SketchGeometryType and the interface SketchGeometry with the needed sub-classes to
remove the cascaded if-else construct
This commit is contained in:
wmayer
2025-03-19 19:54:15 +01:00
committed by pjcreath
parent 51b37da53e
commit baa47bd606
6 changed files with 331 additions and 169 deletions
+2
View File
@@ -36,6 +36,7 @@
#include "GeometryFacadePy.h"
#include "PropertyConstraintList.h"
#include "Sketch.h"
#include "SketchGeometry.h"
#include "SketchGeometryExtension.h"
#include "SketchGeometryExtensionPy.h"
#include "SketchObject.h"
@@ -88,6 +89,7 @@ PyMOD_INIT_FUNC(Sketcher)
// call PyType_Ready, otherwise we run into a segmentation fault, later on.
// This function is responsible for adding inherited slots from a type's base class.
Sketcher::SketchGeometryType::init();
Sketcher::SketchGeometryExtension ::init();
Sketcher::ExternalGeometryExtension ::init();
Sketcher::SolverGeometryExtension ::init();
+2
View File
@@ -58,6 +58,8 @@ SOURCE_GROUP("Properties" FILES ${Properties_SRCS})
SET(Features_SRCS
SketchObjectSF.cpp
SketchObjectSF.h
SketchGeometry.cpp
SketchGeometry.h
SketchGeometryExtension.cpp
SketchGeometryExtension.h
ExternalGeometryExtension.cpp
+256
View File
@@ -0,0 +1,256 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2025 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD 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. *
* *
* FreeCAD 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 FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#include "PreCompiled.h"
#include "SketchGeometry.h"
#include <Mod/Part/App/Geometry.h>
using namespace Sketcher;
namespace Sketcher
{
template<typename GeometryT>
class SketchGeometryT: public SketchGeometry
{
public:
using GeomType = GeometryT;
bool supports(const Part::Geometry* geo) const override
{
return geo->is<GeomType>();
}
};
class SketchPoint: public SketchGeometryT<Part::GeomPoint>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto geomPoint = dynamic_cast<const GeomType*>(geo);
if (PosId == PointPos::start || PosId == PointPos::mid || PosId == PointPos::end) {
return geomPoint->getPoint();
}
return Base::Vector3d();
}
};
class SketchLineSegment: public SketchGeometryT<Part::GeomLineSegment>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto lineSeg = dynamic_cast<const GeomType*>(geo);
switch (PosId) {
case PointPos::start: {
return lineSeg->getStartPoint();
}
case PointPos::end: {
return lineSeg->getEndPoint();
}
default:
break;
}
return Base::Vector3d();
}
};
class SketchCircle: public SketchGeometryT<Part::GeomCircle>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto circle = dynamic_cast<const GeomType*>(geo);
auto pt = circle->getCenter();
if (PosId != PointPos::mid) {
pt.x += circle->getRadius();
}
return pt;
}
};
class SketchEllipse: public SketchGeometryT<Part::GeomEllipse>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto ellipse = dynamic_cast<const GeomType*>(geo);
auto pt = ellipse->getCenter();
if (PosId != PointPos::mid) {
pt += ellipse->getMajorAxisDir() * ellipse->getMajorRadius();
}
return pt;
}
};
class SketchArcOfCircle: public SketchGeometryT<Part::GeomArcOfCircle>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto aoc = dynamic_cast<const GeomType*>(geo);
const bool emulateCCW = true;
switch (PosId) {
case PointPos::start: {
return aoc->getStartPoint(emulateCCW);
}
case PointPos::end: {
return aoc->getEndPoint(emulateCCW);
}
case PointPos::mid: {
return aoc->getCenter();
}
default:
break;
}
return Base::Vector3d();
}
};
class SketchArcOfEllipse: public SketchGeometryT<Part::GeomArcOfEllipse>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto aoe = dynamic_cast<const GeomType*>(geo);
const bool emulateCCW = true;
switch (PosId) {
case PointPos::start: {
return aoe->getStartPoint(emulateCCW);
}
case PointPos::end: {
return aoe->getEndPoint(emulateCCW);
}
case PointPos::mid: {
return aoe->getCenter();
}
default:
break;
}
return Base::Vector3d();
}
};
class SketchArcOfHyperbola: public SketchGeometryT<Part::GeomArcOfHyperbola>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto aoh = dynamic_cast<const GeomType*>(geo);
switch (PosId) {
case PointPos::start: {
return aoh->getStartPoint();
}
case PointPos::end: {
return aoh->getEndPoint();
}
case PointPos::mid: {
return aoh->getCenter();
}
default:
break;
}
return Base::Vector3d();
}
};
class SketchArcOfParabola: public SketchGeometryT<Part::GeomArcOfParabola>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto aop = dynamic_cast<const GeomType*>(geo);
switch (PosId) {
case PointPos::start: {
return aop->getStartPoint();
}
case PointPos::end: {
return aop->getEndPoint();
}
case PointPos::mid: {
return aop->getCenter();
}
default:
break;
}
return Base::Vector3d();
}
};
class SketchBSplineCurve: public SketchGeometryT<Part::GeomBSplineCurve>
{
public:
Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override
{
auto bsp = dynamic_cast<const GeomType*>(geo);
switch (PosId) {
case PointPos::start: {
return bsp->getStartPoint();
}
case PointPos::end: {
return bsp->getEndPoint();
}
default:
break;
}
return Base::Vector3d();
}
};
} // namespace Sketcher
std::list<SketchGeometryPtr> SketchGeometryType::sketchGeoms; // NOLINT
void SketchGeometryType::init()
{
static bool init = true;
if (init) {
init = false;
addType(std::make_shared<SketchPoint>());
addType(std::make_shared<SketchLineSegment>());
addType(std::make_shared<SketchCircle>());
addType(std::make_shared<SketchEllipse>());
addType(std::make_shared<SketchArcOfCircle>());
addType(std::make_shared<SketchArcOfEllipse>());
addType(std::make_shared<SketchArcOfHyperbola>());
addType(std::make_shared<SketchArcOfParabola>());
addType(std::make_shared<SketchBSplineCurve>());
}
}
void SketchGeometryType::addType(const SketchGeometryPtr& type)
{
sketchGeoms.emplace_back(type);
}
Base::Vector3d SketchGeometryType::getPoint(const Part::Geometry* geo, PointPos PosId)
{
for (const auto& it : sketchGeoms) {
if (it->supports(geo)) {
return it->getPoint(geo, PosId);
}
}
return Base::Vector3d();
}
+69
View File
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/***************************************************************************
* Copyright (c) 2025 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD 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. *
* *
* FreeCAD 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 FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
**************************************************************************/
#ifndef SKETCHER_GEOMETRY_H
#define SKETCHER_GEOMETRY_H
#include <memory>
#include <list>
#include "GeoEnum.h"
#include <Base/Vector3D.h>
namespace Part
{
class Geometry;
}
namespace Sketcher
{
class SketcherExport SketchGeometry
{
public:
SketchGeometry() = default;
SketchGeometry(const SketchGeometry&) = default;
SketchGeometry(SketchGeometry&&) = default;
SketchGeometry& operator=(const SketchGeometry&) = default;
SketchGeometry& operator=(SketchGeometry&&) = default;
virtual ~SketchGeometry() = default;
virtual bool supports(const Part::Geometry* geo) const = 0;
virtual Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const = 0;
};
using SketchGeometryPtr = std::shared_ptr<SketchGeometry>;
class SketchGeometryType
{
public:
static void init();
static void addType(const SketchGeometryPtr& type);
static Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId);
private:
static std::list<SketchGeometryPtr> sketchGeoms; // NOLINT
};
} // namespace Sketcher
#endif // SKETCHER_GEOMETRY_H
+2 -162
View File
@@ -111,6 +111,7 @@
#include "GeoEnum.h"
#include "SketchObject.h"
#include "SketchObjectPy.h"
#include "SketchGeometry.h"
#include "SolverGeometryExtension.h"
#include "ExternalGeometryFacade.h"
#include <Mod/Part/App/Datums.h>
@@ -1644,170 +1645,9 @@ int SketchObject::moveGeometry(int geoId, PointPos pos, const Base::Vector3d& to
return moveGeometries(geoEltIds, toPoint, relative, updateGeoBeforeMoving);
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomPoint *geomPoint, PointPos PosId)
{
if (PosId == PointPos::start || PosId == PointPos::mid || PosId == PointPos::end)
return geomPoint->getPoint();
return Base::Vector3d();
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomLineSegment *lineSeg, PointPos PosId)
{
switch (PosId) {
case PointPos::start: {
return lineSeg->getStartPoint();
}
case PointPos::end: {
return lineSeg->getEndPoint();
}
default:
break;
}
return Base::Vector3d();
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomCircle *circle, PointPos PosId)
{
auto pt = circle->getCenter();
if(PosId != PointPos::mid)
pt.x += circle->getRadius();
return pt;
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomEllipse *ellipse, PointPos PosId)
{
auto pt = ellipse->getCenter();
if(PosId != PointPos::mid)
pt += ellipse->getMajorAxisDir()*ellipse->getMajorRadius();
return pt;
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomArcOfCircle *aoc, PointPos PosId)
{
switch (PosId) {
case PointPos::start: {
return aoc->getStartPoint(/*emulateCCW=*/true);
}
case PointPos::end: {
return aoc->getEndPoint(/*emulateCCW=*/true);
}
case PointPos::mid: {
return aoc->getCenter();
}
default:
break;
}
return Base::Vector3d();
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomArcOfEllipse *aoe, PointPos PosId)
{
switch (PosId) {
case PointPos::start: {
return aoe->getStartPoint(/*emulateCCW=*/true);
}
case PointPos::end: {
return aoe->getEndPoint(/*emulateCCW=*/true);
}
case PointPos::mid: {
return aoe->getCenter();
}
default:
break;
}
return Base::Vector3d();
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomArcOfHyperbola *aoh, PointPos PosId)
{
switch (PosId) {
case PointPos::start: {
return aoh->getStartPoint();
}
case PointPos::end: {
return aoh->getEndPoint();
}
case PointPos::mid: {
return aoh->getCenter();
}
default:
break;
}
return Base::Vector3d();
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomArcOfParabola *aop, PointPos PosId)
{
switch (PosId) {
case PointPos::start: {
return aop->getStartPoint();
}
case PointPos::end: {
return aop->getEndPoint();
}
case PointPos::mid: {
return aop->getCenter();
}
default:
break;
}
return Base::Vector3d();
}
template <>
Base::Vector3d SketchObject::getPointForGeometry<>(const Part::GeomBSplineCurve *bsp, PointPos PosId)
{
switch (PosId) {
case PointPos::start: {
return bsp->getStartPoint();
}
case PointPos::end: {
return bsp->getEndPoint();
}
default:
break;
}
return Base::Vector3d();
}
Base::Vector3d SketchObject::getPoint(const Part::Geometry *geo, PointPos PosId)
{
if (auto point = freecad_cast<Part::GeomPoint*>(geo)) {
return getPointForGeometry<Part::GeomPoint>(point, PosId);
}
else if (auto lineSegment = freecad_cast<Part::GeomLineSegment*>(geo)) {
return getPointForGeometry<Part::GeomLineSegment>(lineSegment, PosId);
}
else if (auto circle = freecad_cast<Part::GeomCircle*>(geo)) {
return getPointForGeometry<Part::GeomCircle>(circle, PosId);
}
else if (auto ellipse = freecad_cast<Part::GeomEllipse*>(geo)) {
return getPointForGeometry<Part::GeomEllipse>(ellipse, PosId);
}
else if (auto arcOfCircle = freecad_cast<Part::GeomArcOfCircle*>(geo)) {
return getPointForGeometry<Part::GeomArcOfCircle>(arcOfCircle, PosId);
}
else if (auto arcOfEllipse = freecad_cast<Part::GeomArcOfEllipse*>(geo)) {
return getPointForGeometry<Part::GeomArcOfEllipse>(arcOfEllipse, PosId);
}
else if (auto arcOfHyperbola = freecad_cast<Part::GeomArcOfHyperbola*>(geo)) {
return getPointForGeometry<Part::GeomArcOfHyperbola>(arcOfHyperbola, PosId);
}
else if (auto arcOfParabola = freecad_cast<Part::GeomArcOfParabola*>(geo)) {
return getPointForGeometry<Part::GeomArcOfParabola>(arcOfParabola, PosId);
}
else if (auto bSplineCurve = freecad_cast<Part::GeomBSplineCurve*>(geo)) {
return getPointForGeometry<Part::GeomBSplineCurve>(bSplineCurve, PosId);
}
return Base::Vector3d();
return SketchGeometryType::getPoint(geo, PosId);
}
Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const
-7
View File
@@ -437,13 +437,6 @@ public:
/// retrieves the coordinates of a point
static Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId);
Base::Vector3d getPoint(int GeoId, PointPos PosId) const;
template<class GeomType>
static Base::Vector3d getPointForGeometry(const GeomType* geo, PointPos PosId)
{
(void)geo;
(void)PosId;
return Base::Vector3d();
}
/// toggle geometry to draft line
int toggleConstruction(int GeoId);