diff --git a/src/Mod/Sketcher/App/AppSketcher.cpp b/src/Mod/Sketcher/App/AppSketcher.cpp index 4c2410abef..d99b5f5793 100644 --- a/src/Mod/Sketcher/App/AppSketcher.cpp +++ b/src/Mod/Sketcher/App/AppSketcher.cpp @@ -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(); diff --git a/src/Mod/Sketcher/App/CMakeLists.txt b/src/Mod/Sketcher/App/CMakeLists.txt index 54ddd26ac8..2660dd0d4d 100644 --- a/src/Mod/Sketcher/App/CMakeLists.txt +++ b/src/Mod/Sketcher/App/CMakeLists.txt @@ -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 diff --git a/src/Mod/Sketcher/App/SketchGeometry.cpp b/src/Mod/Sketcher/App/SketchGeometry.cpp new file mode 100644 index 0000000000..aecf73c8da --- /dev/null +++ b/src/Mod/Sketcher/App/SketchGeometry.cpp @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2025 Werner Mayer * + * * + * 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 * + * . * + * * + **************************************************************************/ + +#include "PreCompiled.h" + +#include "SketchGeometry.h" +#include + +using namespace Sketcher; + +namespace Sketcher +{ + +template +class SketchGeometryT: public SketchGeometry +{ +public: + using GeomType = GeometryT; + bool supports(const Part::Geometry* geo) const override + { + return geo->is(); + } +}; + +class SketchPoint: public SketchGeometryT +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto geomPoint = dynamic_cast(geo); + if (PosId == PointPos::start || PosId == PointPos::mid || PosId == PointPos::end) { + return geomPoint->getPoint(); + } + + return Base::Vector3d(); + } +}; + +class SketchLineSegment: public SketchGeometryT +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto lineSeg = dynamic_cast(geo); + switch (PosId) { + case PointPos::start: { + return lineSeg->getStartPoint(); + } + case PointPos::end: { + return lineSeg->getEndPoint(); + } + default: + break; + } + return Base::Vector3d(); + } +}; + +class SketchCircle: public SketchGeometryT +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto circle = dynamic_cast(geo); + auto pt = circle->getCenter(); + if (PosId != PointPos::mid) { + pt.x += circle->getRadius(); + } + return pt; + } +}; + +class SketchEllipse: public SketchGeometryT +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto ellipse = dynamic_cast(geo); + auto pt = ellipse->getCenter(); + if (PosId != PointPos::mid) { + pt += ellipse->getMajorAxisDir() * ellipse->getMajorRadius(); + } + return pt; + } +}; + +class SketchArcOfCircle: public SketchGeometryT +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto aoc = dynamic_cast(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 +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto aoe = dynamic_cast(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 +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto aoh = dynamic_cast(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 +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto aop = dynamic_cast(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 +{ +public: + Base::Vector3d getPoint(const Part::Geometry* geo, PointPos PosId) const override + { + auto bsp = dynamic_cast(geo); + switch (PosId) { + case PointPos::start: { + return bsp->getStartPoint(); + } + case PointPos::end: { + return bsp->getEndPoint(); + } + default: + break; + } + return Base::Vector3d(); + } +}; + +} // namespace Sketcher + +std::list SketchGeometryType::sketchGeoms; // NOLINT + +void SketchGeometryType::init() +{ + static bool init = true; + if (init) { + init = false; + addType(std::make_shared()); + addType(std::make_shared()); + addType(std::make_shared()); + addType(std::make_shared()); + addType(std::make_shared()); + addType(std::make_shared()); + addType(std::make_shared()); + addType(std::make_shared()); + addType(std::make_shared()); + } +} + +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(); +} diff --git a/src/Mod/Sketcher/App/SketchGeometry.h b/src/Mod/Sketcher/App/SketchGeometry.h new file mode 100644 index 0000000000..318162ca8f --- /dev/null +++ b/src/Mod/Sketcher/App/SketchGeometry.h @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2025 Werner Mayer * + * * + * 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 * + * . * + * * + **************************************************************************/ + +#ifndef SKETCHER_GEOMETRY_H +#define SKETCHER_GEOMETRY_H + +#include +#include +#include "GeoEnum.h" +#include + +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; + +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 sketchGeoms; // NOLINT +}; + +} // namespace Sketcher + +#endif // SKETCHER_GEOMETRY_H diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 8f33f98556..1519754d7a 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -111,6 +111,7 @@ #include "GeoEnum.h" #include "SketchObject.h" #include "SketchObjectPy.h" +#include "SketchGeometry.h" #include "SolverGeometryExtension.h" #include "ExternalGeometryFacade.h" #include @@ -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(geo)) { - return getPointForGeometry(point, PosId); - } - else if (auto lineSegment = freecad_cast(geo)) { - return getPointForGeometry(lineSegment, PosId); - } - else if (auto circle = freecad_cast(geo)) { - return getPointForGeometry(circle, PosId); - } - else if (auto ellipse = freecad_cast(geo)) { - return getPointForGeometry(ellipse, PosId); - } - else if (auto arcOfCircle = freecad_cast(geo)) { - return getPointForGeometry(arcOfCircle, PosId); - } - else if (auto arcOfEllipse = freecad_cast(geo)) { - return getPointForGeometry(arcOfEllipse, PosId); - } - else if (auto arcOfHyperbola = freecad_cast(geo)) { - return getPointForGeometry(arcOfHyperbola, PosId); - } - else if (auto arcOfParabola = freecad_cast(geo)) { - return getPointForGeometry(arcOfParabola, PosId); - } - else if (auto bSplineCurve = freecad_cast(geo)) { - return getPointForGeometry(bSplineCurve, PosId); - } - return Base::Vector3d(); + return SketchGeometryType::getPoint(geo, PosId); } Base::Vector3d SketchObject::getPoint(int GeoId, PointPos PosId) const diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 87f8f2277e..6744ffc5ea 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -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 - 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);