Skip to content

Commit

Permalink
[TD]Long and link dim refs (fix #13375) (#18641)
Browse files Browse the repository at this point in the history
* [Meas]Changes for TD dimension refs for links

* [TD]App changes for dim refs to links

* [TD]Gui changes for dim refs to links

* [TD]fix 2 lint messages

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
WandererFan and pre-commit-ci[bot] authored Dec 23, 2024
1 parent 0d12851 commit abb50a4
Show file tree
Hide file tree
Showing 16 changed files with 1,091 additions and 197 deletions.
170 changes: 170 additions & 0 deletions src/Mod/Measure/App/AppMeasurePy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/****************************************************************************
* *
* Copyright (c) 2024 wandererfan <wandererfan@gmail.com> *
* *
* 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"
#ifndef _PreComp_

#endif
#include <Mod/Measure/MeasureGlobal.h>

#include <algorithm> // clears "include what you use" lint message, but creates "included header not used"
#include <string>

#include <Python.h>

#include <App/DocumentObject.h>
#include <App/DocumentObjectPy.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Interpreter.h>
#include <Base/MatrixPy.h>
#include <Base/PlacementPy.h>
#include <Base/PyWrapParseTupleAndKeywords.h>

#include <Mod/Part/App/TopoShapePy.h>
#include "Mod/Part/App/OCCError.h"

#include "ShapeFinder.h"


namespace Measure
{
// module level static C++ functions go here
}

namespace Measure
{
/** Copies a Python dictionary of Python strings to a C++ container.
*
* After the function call, the key-value pairs of the Python
* dictionary are copied into the target buffer as C++ pairs
* (pair<string, string>).
*
* @param sourceRange is a Python dictionary (Py::Dict). Both, the
* keys and the values must be Python strings.
*
* @param targetIt refers to where the data should be inserted. Must
* be of concept output iterator.
*/
template<typename OutputIt>
void copy(Py::Dict sourceRange, OutputIt targetIt)
{
std::string key;
std::string value;

for (const auto& keyPy : sourceRange.keys()) {
key = Py::String(keyPy);
value = Py::String(sourceRange[keyPy]);
*targetIt = {key, value};
++targetIt;
}
}


class Module: public Py::ExtensionModule<Module>

Check warning on line 85 in src/Mod/Measure/App/AppMeasurePy.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

class 'Module' defines a non-default destructor but does not define a copy constructor, a copy assignment operator, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions]
{
public:
Module()
: Py::ExtensionModule<Module>("Measure")
{
add_varargs_method(
"getLocatedTopoShape",
&Module::getLocatedTopoShape,
"Part.TopoShape = Measure.getLocatedTopoShape(DocumentObject, longSubElement) Resolves "
"the net placement of DocumentObject and returns the object's shape/subshape with the "
"net placement applied. Link scaling operations along the path are also applied.");
initialize("This is a module for measuring"); // register with Python
}
~Module() override

Check warning on line 99 in src/Mod/Measure/App/AppMeasurePy.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

use '= default' to define a trivial destructor [modernize-use-equals-default]
{}

private:
Py::Object invoke_method_varargs(void* method_def, const Py::Tuple& args) override
{
try {
return Py::ExtensionModule<Module>::invoke_method_varargs(method_def, args);
}
catch (const Standard_Failure& e) {
std::string str;
Standard_CString msg = e.GetMessageString();
str += typeid(e).name();
str += " ";
if (msg) {
str += msg;
}
else {
str += "No OCCT Exception Message";
}
Base::Console().Error("%s\n", str.c_str());
throw Py::Exception(Part::PartExceptionOCCError, str);
}
catch (const Base::Exception& e) {
std::string str;
str += "FreeCAD exception thrown (";
str += e.what();
str += ")";
e.ReportException();
throw Py::RuntimeError(str);
}
catch (const std::exception& e) {
std::string str;
str += "C++ exception thrown (";
str += e.what();
str += ")";
Base::Console().Error("%s\n", str.c_str());
throw Py::RuntimeError(str);
}
}

Py::Object getLocatedTopoShape(const Py::Tuple& args)
{
PyObject* pyRootObject {nullptr};
PyObject* pyLeafSubName {nullptr};
App::DocumentObject* rootObject {nullptr};
std::string leafSub;
if (!PyArg_ParseTuple(args.ptr(), "OO", &pyRootObject, &pyLeafSubName)) {

Check warning on line 146 in src/Mod/Measure/App/AppMeasurePy.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

do not call c-style vararg functions [cppcoreguidelines-pro-type-vararg]

Check warning on line 146 in src/Mod/Measure/App/AppMeasurePy.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

implicit conversion 'int' -> 'bool' [readability-implicit-bool-conversion]
throw Py::TypeError("expected (rootObject, subname");
}

if (PyObject_TypeCheck(pyRootObject, &(App::DocumentObjectPy::Type))) {
rootObject = static_cast<App::DocumentObjectPy*>(pyRootObject)->getDocumentObjectPtr();
}

if (PyUnicode_Check(pyLeafSubName)) {
leafSub = PyUnicode_AsUTF8(pyLeafSubName);
}

if (!rootObject) {
return Py::None();
}

// this is on the stack
auto temp = ShapeFinder::getLocatedShape(*rootObject, leafSub);
// need new in here to make the twin object on the heap
auto topoShapePy = new Part::TopoShapePy(new Part::TopoShape(temp));
return Py::asObject(topoShapePy);
}
};

} // namespace Measure
6 changes: 6 additions & 0 deletions src/Mod/Measure/App/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ SET(MeasureModule_SRCS
PreCompiled.cpp
PreCompiled.h
AppMeasure.cpp
AppMeasurePy.cpp

# original service routines
Measurement.cpp
Expand All @@ -54,6 +55,11 @@ SET(MeasureModule_SRCS

Preferences.cpp
Preferences.h

ShapeFinder.cpp
ShapeFinder.h
SubnameHelper.cpp
SubnameHelper.h
)

SOURCE_GROUP("Module" FILES ${MeasureModule_SRCS})
Expand Down
38 changes: 4 additions & 34 deletions src/Mod/Measure/App/Measurement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

#include "Measurement.h"
#include "MeasurementPy.h"
#include "ShapeFinder.h"


using namespace Measure;

Check warning on line 54 in src/Mod/Measure/App/Measurement.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

Do not use namespace using-directives. Use using-declarations instead. [build/namespaces] [5]
Expand Down Expand Up @@ -278,43 +279,12 @@ MeasureType Measurement::getType()
return measureType;
}

TopoDS_Shape Measurement::getShape(App::DocumentObject* rootObj, const char* subName) const
TopoDS_Shape Measurement::getShape(App::DocumentObject* obj, const char* subName) const
{
std::vector<std::string> names = Base::Tools::splitSubName(subName);

if (names.empty()) {
TopoDS_Shape shape = Part::Feature::getShape(rootObj);
if (shape.IsNull()) {
throw Part::NullShapeException("null shape in measurement");
}
return shape;
}

try {
App::DocumentObject* obj = rootObj->getSubObject(subName);

Part::TopoShape partShape = Part::Feature::getTopoShape(obj);

partShape.setPlacement(App::GeoFeature::getGlobalPlacement(obj, rootObj, subName));

TopoDS_Shape shape = partShape.getSubShape(names.back().c_str());
if (shape.IsNull()) {
throw Part::NullShapeException("null shape in measurement");
}
return shape;
}
catch (const Base::Exception&) {
// re-throw original exception
throw;
}
catch (Standard_Failure& e) {
throw Base::CADKernelError(e.GetMessageString());
}
catch (...) {
throw Base::RuntimeError("Measurement: Unknown error retrieving shape");
}
return ShapeFinder::getLocatedShape(*obj, subName);
}


// TODO:: add lengthX, lengthY (and lengthZ??) support

Check warning on line 288 in src/Mod/Measure/App/Measurement.cpp

View workflow job for this annotation

GitHub Actions / Lint / Lint

Missing username in TODO; it should look like "// TODO(my_username): Stuff." [readability/todo] [2]
// Methods for distances (edge length, two points, edge and a point
double Measurement::length() const
Expand Down
Loading

0 comments on commit abb50a4

Please sign in to comment.