Add /Mod/Measure for TechDraw
This commit is contained in:
parent
40a9403eef
commit
96ba139f70
74
src/Mod/Measure/App/AppMeasure.cpp
Normal file
74
src/Mod/Measure/App/AppMeasure.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <Python.h>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Interpreter.h>
|
||||
|
||||
#include "Measurement.h"
|
||||
#include "MeasurementPy.h"
|
||||
|
||||
struct PyMethodDef Measure_methods[] = {
|
||||
// {"read" , read, 1},
|
||||
{NULL, NULL} /* end of table marker */
|
||||
};
|
||||
|
||||
|
||||
PyDoc_STRVAR(module_Measure_doc,
|
||||
"This module is the Measure module.");
|
||||
|
||||
|
||||
/* Python entry */
|
||||
extern "C" {
|
||||
void MeasureExport initMeasure()
|
||||
{
|
||||
// load dependent module
|
||||
try {
|
||||
Base::Interpreter().runString("import Part");
|
||||
}
|
||||
catch(const Base::Exception& e) {
|
||||
PyErr_SetString(PyExc_ImportError, e.what());
|
||||
return;
|
||||
}
|
||||
PyObject* measureModule = Py_InitModule3("Measure", Measure_methods, module_Measure_doc); /* mod name, table ptr */
|
||||
|
||||
// Add Types to module
|
||||
Base::Interpreter().addType(&Measure::MeasurementPy ::Type,measureModule,"Measurement");
|
||||
|
||||
Base::Console().Log("Loading Measure module... done\n");
|
||||
|
||||
Measure::Measurement ::init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // extern "C"
|
||||
|
||||
// debug print for sketchsolv
|
||||
void debugprint(std::string s)
|
||||
{
|
||||
Base::Console().Log(s.c_str());
|
||||
}
|
31
src/Mod/Measure/App/AppMeasurePy.cpp
Normal file
31
src/Mod/Measure/App/AppMeasurePy.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <Python.h>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/VectorPy.h>
|
||||
|
||||
|
93
src/Mod/Measure/App/CMakeLists.txt
Normal file
93
src/Mod/Measure/App/CMakeLists.txt
Normal file
|
@ -0,0 +1,93 @@
|
|||
if(MSVC)
|
||||
add_definitions(-DFCAppMeasure -DHAVE_ACOSH -DHAVE_ASINH -DHAVE_ATANH)
|
||||
else(MSVC)
|
||||
add_definitions(-DHAVE_LIMITS_H -DHAVE_CONFIG_H -DHAVE_ACOSH -DHAVE_ATANH -DHAVE_ASINH)
|
||||
endif(MSVC)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_BINARY_DIR}
|
||||
${CMAKE_BINARY_DIR}/src
|
||||
${CMAKE_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${OCC_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${PYTHON_INCLUDE_PATH}
|
||||
${XERCESC_INCLUDE_DIR}
|
||||
)
|
||||
link_directories(${OCC_LIBRARY_DIR})
|
||||
|
||||
set(Measure_LIBS
|
||||
Part
|
||||
FreeCADApp
|
||||
)
|
||||
|
||||
generate_from_xml(MeasurementPy)
|
||||
|
||||
SET(Python_SRCS
|
||||
MeasurementPy.xml
|
||||
MeasurementPyImp.cpp
|
||||
)
|
||||
SOURCE_GROUP("Python" FILES ${Python_SRCS})
|
||||
|
||||
SET(MeasureModule_SRCS
|
||||
AppMeasure.cpp
|
||||
AppMeasurePy.cpp
|
||||
Measurement.cpp
|
||||
Measurement.h
|
||||
PreCompiled.cpp
|
||||
PreCompiled.h
|
||||
)
|
||||
|
||||
SOURCE_GROUP("Module" FILES ${MeasureModule_SRCS})
|
||||
|
||||
|
||||
SET(Measure_SRCS
|
||||
${MeasureModule_SRCS}
|
||||
${Python_SRCS}
|
||||
)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-D_PreComp_)
|
||||
GET_MSVC_PRECOMPILED_SOURCE("PreCompiled.cpp" Measure_CPP_SRCS ${Measure_SRCS})
|
||||
ADD_MSVC_PRECOMPILED_HEADER(Measure PreCompiled.h PreCompiled.cpp Measure_CPP_SRCS)
|
||||
endif(MSVC)
|
||||
|
||||
# Set special compiler flag to convert a SIGSEV into an exception
|
||||
# to handle issue #0000478.
|
||||
IF(MSVC)
|
||||
ENDIF(MSVC)
|
||||
|
||||
add_library(Measure SHARED ${Measure_SRCS} )
|
||||
target_link_libraries(Measure ${Measure_LIBS})
|
||||
|
||||
SET(Measure_Scripts
|
||||
Init.py
|
||||
)
|
||||
|
||||
fc_target_copy_resource(Measure
|
||||
${CMAKE_SOURCE_DIR}/src/Mod/Measure
|
||||
${CMAKE_BINARY_DIR}/Mod/Measure
|
||||
${Measure_Scripts})
|
||||
|
||||
#if(MSVC)
|
||||
# set_target_properties(Measure PROPERTIES SUFFIX ".pyd")
|
||||
# set_target_properties(Measure PROPERTIES DEBUG_OUTPUT_NAME "Measure_d")
|
||||
# set_target_properties(Measure PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Measure)
|
||||
# set_target_properties(Measure PROPERTIES PREFIX "../")
|
||||
#elseif(MINGW)
|
||||
# set_target_properties(Measure PROPERTIES SUFFIX ".pyd")
|
||||
# set_target_properties(Measure PROPERTIES DEBUG_OUTPUT_NAME "Measure_d")
|
||||
# set_target_properties(Measure PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Measure)
|
||||
# set_target_properties(Measure PROPERTIES PREFIX "")
|
||||
#else(MSVC)
|
||||
# set_target_properties(Measure PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/Mod/Measure)
|
||||
# set_target_properties(Measure PROPERTIES PREFIX "")
|
||||
# set_target_properties(Measure PROPERTIES INSTALL_RPATH ${INSTALL_RPATH})
|
||||
#endif(MSVC)
|
||||
|
||||
SET_BIN_DIR(Measure Measure /Mod/Measure)
|
||||
SET_PYTHON_PREFIX_SUFFIX(Measure)
|
||||
|
||||
|
||||
INSTALL(TARGETS Measure DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
486
src/Mod/Measure/App/Measurement.cpp
Normal file
486
src/Mod/Measure/App/Measurement.cpp
Normal file
|
@ -0,0 +1,486 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
# include <TopoDS_Shape.hxx>
|
||||
# include <TopoDS_Face.hxx>
|
||||
# include <TopoDS.hxx>
|
||||
# include <TopExp_Explorer.hxx>
|
||||
# include <gp_Pln.hxx>
|
||||
# include <gp_Ax3.hxx>
|
||||
# include <gp_Circ.hxx>
|
||||
# include <gp_Elips.hxx>
|
||||
# include <GCPnts_AbscissaPoint.hxx>
|
||||
# include <BRepAdaptor_Surface.hxx>
|
||||
# include <BRepAdaptor_Curve.hxx>
|
||||
# include <BRepExtrema_DistShapeShape.hxx>
|
||||
# include <GProp_GProps.hxx>
|
||||
# include <GeomAPI_ExtremaCurveCurve.hxx>
|
||||
# include <BRepGProp.hxx>
|
||||
#endif
|
||||
|
||||
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Console.h>
|
||||
#include <Base/VectorPy.h>
|
||||
|
||||
#include <Mod/Part/App/Geometry.h>
|
||||
#include <Mod/Part/App/PartFeature.h>
|
||||
#include <Mod/Part/App/TopoShape.h>
|
||||
|
||||
#include "Measurement.h"
|
||||
#include "MeasurementPy.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#endif
|
||||
using namespace Measure;
|
||||
using namespace Base;
|
||||
using namespace Part;
|
||||
|
||||
TYPESYSTEM_SOURCE(Measure::Measurement, Base::BaseClass)
|
||||
|
||||
Measurement::Measurement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Measurement::~Measurement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Measurement::clear()
|
||||
{
|
||||
std::vector<App::DocumentObject*> Objects;
|
||||
std::vector<std::string> SubElements;
|
||||
References.setValues(Objects, SubElements);
|
||||
measureType = Invalid;
|
||||
}
|
||||
|
||||
bool Measurement::hasReferences()
|
||||
{
|
||||
return (References.getSize() > 0);
|
||||
}
|
||||
|
||||
/// Convenience Methods for adding points
|
||||
int Measurement::addReference(App::DocumentObject *obj, const char* subName)
|
||||
{
|
||||
std::vector<App::DocumentObject*> objects = References.getValues();
|
||||
std::vector<std::string> subElements = References.getSubValues();
|
||||
|
||||
objects.push_back(obj);
|
||||
subElements.push_back(subName);
|
||||
|
||||
References.setValues(objects, subElements);
|
||||
|
||||
measureType = getType();
|
||||
return References.getSize();
|
||||
}
|
||||
|
||||
MeasureType Measurement::getType()
|
||||
{
|
||||
const std::vector<App::DocumentObject*> &objects = References.getValues();
|
||||
const std::vector<std::string> &subElements = References.getSubValues();
|
||||
|
||||
std::vector<App::DocumentObject*>::const_iterator obj = objects.begin();
|
||||
std::vector<std::string>::const_iterator subEl = subElements.begin();
|
||||
|
||||
//
|
||||
int dims = -1;
|
||||
MeasureType mode;
|
||||
|
||||
// Type of References
|
||||
int verts = 0;
|
||||
int edges = 0;
|
||||
int faces = 0;
|
||||
int vols = 0;
|
||||
|
||||
for (;obj != objects.end(); ++obj, ++subEl) {
|
||||
|
||||
const Part::Feature *refObj = static_cast<const Part::Feature*>((*obj));
|
||||
const Part::TopoShape& refShape = refObj->Shape.getShape();
|
||||
|
||||
// Check if solid object
|
||||
if(strcmp((*subEl).c_str(), "") == 0) {
|
||||
vols++;
|
||||
} else {
|
||||
|
||||
TopoDS_Shape refSubShape;
|
||||
try {
|
||||
refSubShape = refShape.getSubShape((*subEl).c_str());
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
std::stringstream errorMsg;
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
errorMsg << "Measurement - getType - " << e->GetMessageString() << std::endl;
|
||||
throw Base::Exception(e->GetMessageString());
|
||||
}
|
||||
|
||||
switch (refSubShape.ShapeType()) {
|
||||
case TopAbs_VERTEX:
|
||||
{
|
||||
verts++;
|
||||
}
|
||||
break;
|
||||
case TopAbs_EDGE:
|
||||
{
|
||||
edges++;
|
||||
}
|
||||
break;
|
||||
case TopAbs_FACE:
|
||||
{
|
||||
faces++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(vols > 0) {
|
||||
if(verts > 0 || edges > 0 || faces > 0) {
|
||||
mode = Invalid;
|
||||
} else {
|
||||
mode = Volumes;
|
||||
}
|
||||
} else if(faces > 0) {
|
||||
if(verts > 0 || edges > 0) {
|
||||
if(faces > 1 && verts > 1 && edges > 0) {
|
||||
mode = Invalid;
|
||||
} else {
|
||||
// One Surface and One Point
|
||||
mode = PointToSurface;
|
||||
}
|
||||
} else {
|
||||
mode = Surfaces;
|
||||
}
|
||||
} else if(edges > 0) {
|
||||
if(verts > 0) {
|
||||
if(verts > 1 && edges > 0) {
|
||||
mode = Invalid;
|
||||
} else {
|
||||
mode = PointToEdge;
|
||||
}
|
||||
} else {
|
||||
// if(edges == 2) {
|
||||
// mode = EdgeToEdge;
|
||||
// } else {
|
||||
mode = Edges;
|
||||
// }
|
||||
}
|
||||
} else if (verts > 0) {
|
||||
mode = Points;
|
||||
} else {
|
||||
mode = Invalid;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
TopoDS_Shape Measurement::getShape(App::DocumentObject *obj , const char *subName) const
|
||||
{
|
||||
const Part::Feature *refObj = static_cast<const Part::Feature*>(obj);
|
||||
const Part::TopoShape& refShape = refObj->Shape.getShape();
|
||||
|
||||
// Check if selecting whol object
|
||||
if(strcmp(subName, "") == 0) {
|
||||
return refShape._Shape;
|
||||
} else {
|
||||
|
||||
TopoDS_Shape refSubShape;
|
||||
try {
|
||||
refSubShape = refShape.getSubShape(subName);
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
throw Base::Exception(e->GetMessageString());
|
||||
}
|
||||
return refSubShape;
|
||||
}
|
||||
}
|
||||
|
||||
// Methods for distances (edge length, two points, edge and a point
|
||||
double Measurement::length() const
|
||||
{
|
||||
int numRefs = References.getSize();
|
||||
if(!numRefs || measureType == Invalid) {
|
||||
throw Base::Exception("Measurement - length - Invalid References Provided");
|
||||
}
|
||||
|
||||
const std::vector<App::DocumentObject*> &objects = References.getValues();
|
||||
const std::vector<std::string> &subElements = References.getSubValues();
|
||||
|
||||
if(measureType == Points ||
|
||||
measureType == PointToEdge ||
|
||||
measureType == PointToSurface) {
|
||||
|
||||
Base::Vector3d diff = this->delta();
|
||||
return diff.Length();
|
||||
|
||||
} else if(measureType == Edges) {
|
||||
|
||||
double length = 0.f;
|
||||
// Iterate through edges and calculate each length
|
||||
std::vector<App::DocumentObject*>::const_iterator obj = objects.begin();
|
||||
std::vector<std::string>::const_iterator subEl = subElements.begin();
|
||||
|
||||
for (;obj != objects.end(); ++obj, ++subEl) {
|
||||
const Part::Feature *refObj = static_cast<const Part::Feature*>((*obj));
|
||||
const Part::TopoShape& refShape = refObj->Shape.getShape();
|
||||
// Get the length of one edge
|
||||
TopoDS_Shape shape = getShape(*obj, (*subEl).c_str());
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(shape);
|
||||
BRepAdaptor_Curve curve(edge);
|
||||
|
||||
switch(curve.GetType()) {
|
||||
case GeomAbs_Line : {
|
||||
gp_Pnt P1 = curve.Value(curve.FirstParameter());
|
||||
gp_Pnt P2 = curve.Value(curve.LastParameter());
|
||||
gp_XYZ diff = P2.XYZ() - P1.XYZ();
|
||||
length += diff.Modulus();
|
||||
} break;
|
||||
case GeomAbs_Circle : {
|
||||
double u = curve.FirstParameter();
|
||||
double v = curve.LastParameter();
|
||||
double radius = curve.Circle().Radius();
|
||||
if (u > v) // if arc is reversed
|
||||
std::swap(u, v);
|
||||
|
||||
double range = v-u;
|
||||
length += radius * range;
|
||||
} break;
|
||||
case GeomAbs_Ellipse:
|
||||
case GeomAbs_BSplineCurve:
|
||||
case GeomAbs_Hyperbola:
|
||||
case GeomAbs_BezierCurve: {
|
||||
length += GCPnts_AbscissaPoint::Length(curve);
|
||||
} break;
|
||||
default: {
|
||||
throw Base::Exception("Measurement - length - Curve type not currently handled");
|
||||
}
|
||||
}
|
||||
}
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
double Measurement::angle(const Base::Vector3d ¶m) const
|
||||
{
|
||||
int numRefs = References.getSize();
|
||||
if(!numRefs)
|
||||
throw Base::Exception("Measurement - angle - No references provided");
|
||||
|
||||
if(measureType == Edges) {
|
||||
// Only case that is supported is edge to edge
|
||||
if(numRefs == 2) {
|
||||
const std::vector<App::DocumentObject*> &objects = References.getValues();
|
||||
const std::vector<std::string> &subElements = References.getSubValues();
|
||||
|
||||
TopoDS_Shape shape1 = getShape(objects.at(0), subElements.at(0).c_str());
|
||||
TopoDS_Shape shape2 = getShape(objects.at(1), subElements.at(1).c_str());
|
||||
|
||||
BRepAdaptor_Curve curve1(TopoDS::Edge(shape1));
|
||||
BRepAdaptor_Curve curve2(TopoDS::Edge(shape2));
|
||||
|
||||
if(curve1.GetType() == GeomAbs_Line &&
|
||||
curve2.GetType() == GeomAbs_Line) {
|
||||
|
||||
gp_Pnt pnt1 = curve1.Value(curve1.FirstParameter());
|
||||
gp_Pnt pnt2 = curve1.Value(curve1.LastParameter());
|
||||
gp_Dir dir1 = curve1.Line().Direction();
|
||||
gp_Dir dir2 = curve2.Line().Direction();
|
||||
|
||||
gp_Lin l1 = gp_Lin(pnt1,dir1);
|
||||
gp_Lin l2 = gp_Lin(pnt2,dir2);
|
||||
Standard_Real aRad = l1.Angle(l2);
|
||||
return aRad * 180 / M_PI;
|
||||
} else {
|
||||
throw Base::Exception("Objects must both be lines");
|
||||
}
|
||||
} else {
|
||||
throw Base::Exception("Can not compute angle. Too many references");
|
||||
}
|
||||
}
|
||||
throw Base::Exception("References are not Edges");
|
||||
}
|
||||
|
||||
double Measurement::radius() const
|
||||
{
|
||||
int numRefs = References.getSize();
|
||||
if(!numRefs) {
|
||||
throw Base::Exception("Measurement - radius - No references provided");
|
||||
}
|
||||
|
||||
if(numRefs == 1 || measureType == Edges) {
|
||||
const std::vector<App::DocumentObject*> &objects = References.getValues();
|
||||
const std::vector<std::string> &subElements = References.getSubValues();
|
||||
|
||||
TopoDS_Shape shape = getShape(objects.at(0), subElements.at(0).c_str());
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(shape);
|
||||
|
||||
BRepAdaptor_Curve curve(edge);
|
||||
if(curve.GetType() == GeomAbs_Circle) {
|
||||
return (double) curve.Circle().Radius();
|
||||
}
|
||||
}
|
||||
throw Base::Exception("Measurement - radius - Invalid References Provided");
|
||||
}
|
||||
|
||||
Base::Vector3d Measurement::delta() const
|
||||
{
|
||||
int numRefs = References.getSize();
|
||||
if(!numRefs || measureType == Invalid)
|
||||
throw Base::Exception("Measurement - delta - Invalid References Provided");
|
||||
|
||||
const std::vector<App::DocumentObject*> &objects = References.getValues();
|
||||
const std::vector<std::string> &subElements = References.getSubValues();
|
||||
|
||||
if(measureType == Points) {
|
||||
if(numRefs == 2) {
|
||||
// Keep Seperate case for two points to reduce need for complex algorithm
|
||||
TopoDS_Shape shape1 = getShape(objects.at(0), subElements.at(0).c_str());
|
||||
TopoDS_Shape shape2 = getShape(objects.at(1), subElements.at(1).c_str());
|
||||
|
||||
const TopoDS_Vertex& vert1 = TopoDS::Vertex(shape1);
|
||||
const TopoDS_Vertex& vert2 = TopoDS::Vertex(shape2);
|
||||
|
||||
gp_Pnt P1 = BRep_Tool::Pnt(vert1);
|
||||
gp_Pnt P2 = BRep_Tool::Pnt(vert2);
|
||||
gp_XYZ diff = P2.XYZ() - P1.XYZ();
|
||||
return Base::Vector3d(diff.X(), diff.Y(), diff.Z());
|
||||
}
|
||||
} else if(measureType == PointToEdge ||
|
||||
measureType == PointToSurface) {
|
||||
// BrepExtema can calculate minimum distance between any set of topology sets.
|
||||
if(numRefs == 2) {
|
||||
TopoDS_Shape shape1 = getShape(objects.at(0), subElements.at(0).c_str());
|
||||
TopoDS_Shape shape2 = getShape(objects.at(1), subElements.at(1).c_str());
|
||||
|
||||
BRepExtrema_DistShapeShape extrema(shape1, shape2);
|
||||
|
||||
if(extrema.IsDone()) {
|
||||
// Found the nearest point between point and curve
|
||||
// NOTE we will assume there is only 1 solution (cyclic topology will create multiple solutions.
|
||||
gp_Pnt P1 = extrema.PointOnShape1(1);
|
||||
gp_Pnt P2 = extrema.PointOnShape2(1);
|
||||
gp_XYZ diff = P2.XYZ() - P1.XYZ();
|
||||
return Base::Vector3d(diff.X(), diff.Y(), diff.Z());
|
||||
}
|
||||
}
|
||||
} else if(measureType == Edges) {
|
||||
// Only case that is supported is straight line edge
|
||||
if(numRefs == 1) {
|
||||
TopoDS_Shape shape = getShape(objects.at(0), subElements.at(0).c_str());
|
||||
const TopoDS_Edge& edge = TopoDS::Edge(shape);
|
||||
BRepAdaptor_Curve curve(edge);
|
||||
|
||||
if(curve.GetType() == GeomAbs_Line) {
|
||||
gp_Pnt P1 = curve.Value(curve.FirstParameter());
|
||||
gp_Pnt P2 = curve.Value(curve.LastParameter());
|
||||
gp_XYZ diff = P2.XYZ() - P1.XYZ();
|
||||
return Base::Vector3d(diff.X(), diff.Y(), diff.Z());
|
||||
}
|
||||
} else if(numRefs == 2) {
|
||||
TopoDS_Shape shape1 = getShape(objects.at(0), subElements.at(0).c_str());
|
||||
TopoDS_Shape shape2 = getShape(objects.at(1), subElements.at(1).c_str());
|
||||
|
||||
BRepAdaptor_Curve curve1(TopoDS::Edge(shape1));
|
||||
BRepAdaptor_Curve curve2(TopoDS::Edge(shape2));
|
||||
|
||||
// Only permit line to line distance
|
||||
if(curve1.GetType() == GeomAbs_Line &&
|
||||
curve2.GetType() == GeomAbs_Line) {
|
||||
BRepExtrema_DistShapeShape extrema(shape1, shape2);
|
||||
|
||||
if(extrema.IsDone()) {
|
||||
// Found the nearest point between point and curve
|
||||
// NOTE we will assume there is only 1 solution (cyclic topology will create multiple solutions.
|
||||
gp_Pnt P1 = extrema.PointOnShape1(1);
|
||||
gp_Pnt P2 = extrema.PointOnShape2(1);
|
||||
gp_XYZ diff = P2.XYZ() - P1.XYZ();
|
||||
return Base::Vector3d(diff.X(), diff.Y(), diff.Z());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw Base::Exception("An invalid selection was made");
|
||||
}
|
||||
|
||||
|
||||
Base::Vector3d Measurement::massCenter() const
|
||||
{
|
||||
|
||||
int numRefs = References.getSize();
|
||||
if(!numRefs || measureType == Invalid)
|
||||
throw Base::Exception("Measurement - massCenter - Invalid References Provided");
|
||||
|
||||
const std::vector<App::DocumentObject*> &objects = References.getValues();
|
||||
const std::vector<std::string> &subElements = References.getSubValues();
|
||||
|
||||
|
||||
GProp_GProps gprops = GProp_GProps();
|
||||
|
||||
if(measureType == Volumes) {
|
||||
// Iterate through edges and calculate each length
|
||||
std::vector<App::DocumentObject*>::const_iterator obj = objects.begin();
|
||||
std::vector<std::string>::const_iterator subEl = subElements.begin();
|
||||
|
||||
for (;obj != objects.end(); ++obj, ++subEl) {
|
||||
const Part::Feature *refObj = static_cast<const Part::Feature*>((*obj));
|
||||
const Part::TopoShape& refShape = refObj->Shape.getShape();
|
||||
|
||||
// Compute inertia properties
|
||||
|
||||
GProp_GProps props = GProp_GProps();
|
||||
BRepGProp::VolumeProperties(getShape((*obj), ""), props);
|
||||
gprops.Add(props);
|
||||
// Get inertia properties
|
||||
}
|
||||
|
||||
double mass = gprops.Mass();
|
||||
gp_Pnt cog = gprops.CentreOfMass();
|
||||
|
||||
return Base::Vector3d(cog.X(), cog.Y(), cog.Z());
|
||||
|
||||
} else {
|
||||
throw Base::Exception("Measurement - massCenter - Invalid References Provided");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Measurement::getMemSize(void) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *Measurement::getPyObject(void)
|
||||
{
|
||||
if (PythonObject.is(Py::_None())) {
|
||||
// ref counter is set to 1
|
||||
PythonObject = Py::Object(new MeasurementPy(this),true);
|
||||
}
|
||||
return Py::new_reference_to(PythonObject);
|
||||
}
|
93
src/Mod/Measure/App/Measurement.h
Normal file
93
src/Mod/Measure/App/Measurement.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2013 Luke Parry <l.parry@warwick.ac.uk> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MEASURE_MEASUREMENT_H
|
||||
#define MEASURE_MEASUREMENT_H
|
||||
|
||||
#include <Base/BaseClass.h>
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
#include <App/DocumentObject.h>
|
||||
#include <App/PropertyLinks.h>
|
||||
|
||||
class TopoDS_Shape;
|
||||
namespace Measure
|
||||
{
|
||||
enum MeasureType {
|
||||
Volumes, // Measure the Volume(s)
|
||||
Edges, // Measure the Edge(s)
|
||||
Surfaces, // Measure the surface(s)
|
||||
Points,
|
||||
PointToPoint, // Measure between TWO points
|
||||
PointToEdge, // Measure between ONE point and ONE edge
|
||||
PointToSurface, // Measure between ONE point and ONE surface
|
||||
EdgeToEdge, // Measure between TWO edges
|
||||
Invalid
|
||||
};
|
||||
|
||||
class MeasureExport Measurement : public Base::BaseClass {
|
||||
TYPESYSTEM_HEADER();
|
||||
public:
|
||||
|
||||
App::PropertyLinkSubList References;
|
||||
|
||||
public:
|
||||
Measurement();
|
||||
~Measurement();
|
||||
|
||||
void clear();
|
||||
bool hasReferences();
|
||||
|
||||
/// Add a reference
|
||||
int addReference(App::DocumentObject *obj, const char *subName);
|
||||
|
||||
MeasureType getType();
|
||||
|
||||
// from base class
|
||||
virtual PyObject *getPyObject(void);
|
||||
virtual unsigned int getMemSize(void) const;
|
||||
|
||||
public:
|
||||
// Methods for distances (edge length, two points, edge and a point
|
||||
double length() const;
|
||||
Base::Vector3d delta() const;
|
||||
|
||||
// Calculates the radius for an arc or circular edge
|
||||
double radius() const;
|
||||
|
||||
// Calculates the angle between two edges
|
||||
double angle(const Base::Vector3d ¶m = Base::Vector3d(0,0,0)) const;
|
||||
|
||||
// Calculate volumetric/mass properties
|
||||
Base::Vector3d massCenter() const;
|
||||
|
||||
protected:
|
||||
TopoDS_Shape getShape(App::DocumentObject *obj , const char *subName) const;
|
||||
MeasureType measureType;
|
||||
Py::Object PythonObject;
|
||||
};
|
||||
|
||||
|
||||
} //namespace measure
|
||||
|
||||
|
||||
#endif // MEASURE_MEASUREMENT_H
|
53
src/Mod/Measure/App/MeasurementPy.xml
Normal file
53
src/Mod/Measure/App/MeasurementPy.xml
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="BaseClassPy"
|
||||
Name="MeasurementPy"
|
||||
Twin="Measurement"
|
||||
TwinPointer="Measurement"
|
||||
Include="Mod/Measure/App/Measurement.h"
|
||||
Namespace="Measure"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
Constructor="true"
|
||||
FatherNamespace="Base">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="Luke Parry" EMail="l.parry@warwick.ac.uk" />
|
||||
<UserDocu>Make a measurement</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="addReference">
|
||||
<Documentation>
|
||||
<UserDocu>add a geometric reference</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="clear">
|
||||
<Documentation>
|
||||
<UserDocu>measure the difference between references to obtain resultant vector</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="delta">
|
||||
<Documentation>
|
||||
<UserDocu>measure the difference between references to obtain resultant vector</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="length">
|
||||
<Documentation>
|
||||
<UserDocu>measure the length of the references</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="angle">
|
||||
<Documentation>
|
||||
<UserDocu>measure the angle between two edges</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="radius">
|
||||
<Documentation>
|
||||
<UserDocu>measure the radius of an arc or circle edge</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="com">
|
||||
<Documentation>
|
||||
<UserDocu>measure the center of mass for selected volumes</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
143
src/Mod/Measure/App/MeasurementPyImp.cpp
Normal file
143
src/Mod/Measure/App/MeasurementPyImp.cpp
Normal file
|
@ -0,0 +1,143 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) Luke Parry (l.parry@warwick.ac.uk) 2013 *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <sstream>
|
||||
#endif
|
||||
|
||||
#include "Mod/Measure/App/Measurement.h"
|
||||
#include <Mod/Part/App/Geometry.h>
|
||||
#include <Base/GeometryPyCXX.h>
|
||||
#include <Base/VectorPy.h>
|
||||
#include <Base/AxisPy.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
// inclusion of the generated files (generated out of SketchObjectSFPy.xml)
|
||||
#include "MeasurementPy.h"
|
||||
#include "MeasurementPy.cpp"
|
||||
|
||||
using namespace Measure;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string MeasurementPy::representation(void) const
|
||||
{
|
||||
return "<Measure::Measurement>";
|
||||
}
|
||||
|
||||
PyObject *MeasurementPy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
|
||||
{
|
||||
// create a new instance of BoundBoxPy and the Twin object
|
||||
return new MeasurementPy(new Measurement);
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int MeasurementPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* MeasurementPy::addReference(PyObject *args)
|
||||
{
|
||||
char *ObjectName;
|
||||
char *SubName;
|
||||
if (!PyArg_ParseTuple(args, "ss:Give an object and subelement name", &ObjectName,&SubName))
|
||||
return 0;
|
||||
|
||||
// get the target object for the external link
|
||||
App::DocumentObject * Obj = App::GetApplication().getActiveDocument()->getObject(ObjectName);
|
||||
if (!Obj) {
|
||||
std::stringstream str;
|
||||
str << ObjectName << "does not exist in the document";
|
||||
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
// add the external
|
||||
if (this->getMeasurementPtr()->addReference(Obj,SubName) < 0) {
|
||||
std::stringstream str;
|
||||
str << "Not able to add reference";
|
||||
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* MeasurementPy::clear(PyObject *)
|
||||
{
|
||||
this->getMeasurementPtr()->clear();
|
||||
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject* MeasurementPy::delta(PyObject *)
|
||||
{
|
||||
Py::Vector delta(this->getMeasurementPtr()->delta());
|
||||
|
||||
return Py::new_reference_to(delta);
|
||||
}
|
||||
|
||||
|
||||
PyObject* MeasurementPy::length(PyObject *)
|
||||
{
|
||||
Py::Float length;
|
||||
length = this->getMeasurementPtr()->length();
|
||||
|
||||
return Py::new_reference_to(length);
|
||||
}
|
||||
|
||||
PyObject* MeasurementPy::radius(PyObject *)
|
||||
{
|
||||
Py::Float radius;
|
||||
radius = this->getMeasurementPtr()->radius();
|
||||
|
||||
return Py::new_reference_to(radius);
|
||||
}
|
||||
|
||||
PyObject* MeasurementPy::angle(PyObject *)
|
||||
{
|
||||
Py::Float angle;
|
||||
angle = this->getMeasurementPtr()->angle();
|
||||
|
||||
return Py::new_reference_to(angle);
|
||||
}
|
||||
|
||||
PyObject* MeasurementPy::com(PyObject *)
|
||||
{
|
||||
Py::Vector com(this->getMeasurementPtr()->massCenter());
|
||||
|
||||
return Py::new_reference_to(com);
|
||||
}
|
||||
|
||||
PyObject *MeasurementPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MeasurementPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
23
src/Mod/Measure/App/PreCompiled.cpp
Normal file
23
src/Mod/Measure/App/PreCompiled.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
59
src/Mod/Measure/App/PreCompiled.h
Normal file
59
src/Mod/Measure/App/PreCompiled.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library 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 Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef __PRECOMPILED__
|
||||
#define __PRECOMPILED__
|
||||
|
||||
#include <FCConfig.h>
|
||||
|
||||
// Exporting of App classes
|
||||
#ifdef FC_OS_WIN32
|
||||
# define MeasureExport __declspec(dllexport)
|
||||
# define PartExport __declspec(dllimport)
|
||||
# define MeshExport __declspec(dllimport)
|
||||
#else // for Linux
|
||||
# define MeasureExport
|
||||
# define PartExport
|
||||
# define MeshExport
|
||||
#endif
|
||||
|
||||
#ifdef _PreComp_
|
||||
|
||||
// standard
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <bitset>
|
||||
|
||||
#include <Mod/Part/App/OpenCascadeAll.h>
|
||||
#include <Python.h>
|
||||
|
||||
#elif defined(FC_OS_WIN32)
|
||||
#include <windows.h>
|
||||
#endif // _PreComp_
|
||||
#endif
|
13
src/Mod/Measure/CMakeLists.txt
Normal file
13
src/Mod/Measure/CMakeLists.txt
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
add_subdirectory(App)
|
||||
if(FREECAD_BUILD_GUI)
|
||||
#add_subdirectory(Gui)
|
||||
endif(FREECAD_BUILD_GUI)
|
||||
|
||||
INSTALL(
|
||||
FILES
|
||||
Init.py
|
||||
InitGui.py
|
||||
DESTINATION
|
||||
Mod/Measure
|
||||
)
|
39
src/Mod/Measure/Init.py
Normal file
39
src/Mod/Measure/Init.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
# FreeCAD init script of the Image module
|
||||
# (c) 2001 Juergen Riegel
|
||||
|
||||
#***************************************************************************
|
||||
#* (c) Juergen Riegel (juergen.riegel@web.de) 2002 *
|
||||
#* *
|
||||
#* This file is part of the FreeCAD CAx development system. *
|
||||
#* *
|
||||
#* This program is free software; you can redistribute it and/or modify *
|
||||
#* it under the terms of the GNU Lesser General Public License (LGPL) *
|
||||
#* as published by the Free Software Foundation; either version 2 of *
|
||||
#* the License, or (at your option) any later version. *
|
||||
#* for detail see the LICENCE text file. *
|
||||
#* *
|
||||
#* 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 Library General Public *
|
||||
#* License along with FreeCAD; if not, write to the Free Software *
|
||||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
#* USA *
|
||||
#* *
|
||||
#* Juergen Riegel 2002 *
|
||||
#***************************************************************************/
|
||||
|
||||
|
||||
|
||||
# Get the Parameter Group of this module
|
||||
ParGrp = App.ParamGet("System parameter:Modules").GetGroup("Image")
|
||||
|
||||
# Set the needed information
|
||||
ParGrp.SetString("HelpIndex", "Image/Help/index.html")
|
||||
ParGrp.SetString("WorkBenchName", "Image")
|
||||
ParGrp.SetString("WorkBenchModule", "ImageWorkbench.py")
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user