Merge pull request #159 from DeepSOIC/Attacher16
Attacher16 - fixes, and Py interface
This commit is contained in:
commit
6eb173a54b
|
@ -51,7 +51,6 @@
|
|||
#include "PartFeatures.h"
|
||||
#include "BodyBase.h"
|
||||
#include "PrimitiveFeature.h"
|
||||
#include "Attacher.h"
|
||||
#include "Part2DObject.h"
|
||||
#include "CustomFeature.h"
|
||||
#include "TopoShapePy.h"
|
||||
|
@ -91,6 +90,7 @@
|
|||
#include "ToroidPy.h"
|
||||
#include "BRepOffsetAPI_MakePipeShellPy.h"
|
||||
#include "PartFeaturePy.h"
|
||||
#include "AttachEnginePy.h"
|
||||
#include "PropertyGeometryList.h"
|
||||
#include "DatumFeature.h"
|
||||
#include "Attacher.h"
|
||||
|
@ -210,6 +210,8 @@ PyMODINIT_FUNC initPart()
|
|||
|
||||
Base::Interpreter().addType(&Part::PartFeaturePy ::Type,partModule,"Feature");
|
||||
|
||||
Base::Interpreter().addType(&Attacher::AttachEnginePy ::Type,partModule,"AttachEngine");
|
||||
|
||||
PyObject* brepModule = Py_InitModule3("BRepOffsetAPI", 0, "BrepOffsetAPI");
|
||||
Py_INCREF(brepModule);
|
||||
PyModule_AddObject(partModule, "BRepOffsetAPI", brepModule);
|
||||
|
@ -230,6 +232,7 @@ PyMODINIT_FUNC initPart()
|
|||
Part::Feature ::init();
|
||||
Part::FeatureExt ::init();
|
||||
Part::AttachableObject ::init();
|
||||
Part::AttachableObjectPython::init();
|
||||
Part::BodyBase ::init();
|
||||
Part::FeaturePython ::init();
|
||||
Part::FeatureGeometrySet ::init();
|
||||
|
|
168
src/Mod/Part/App/AttachEnginePy.xml
Normal file
168
src/Mod/Part/App/AttachEnginePy.xml
Normal file
|
@ -0,0 +1,168 @@
|
|||
<?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="AttachEnginePy"
|
||||
Twin="AttachEngine"
|
||||
TwinPointer="AttachEngine"
|
||||
Include="Mod/Part/App/Attacher.h"
|
||||
FatherInclude="Base/BaseClassPy.h"
|
||||
Namespace="Attacher"
|
||||
Constructor="true"
|
||||
Delete="true"
|
||||
FatherNamespace="Base">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DeepSOIC" EMail="vv.titov@gmail.com" />
|
||||
<DeveloperDocu>AttachEngine abstract class</DeveloperDocu>
|
||||
<UserDocu>AttachEngine abstract class - the functinality of AttachableObject, but outside of DocumentObject</UserDocu>
|
||||
</Documentation>
|
||||
<Attribute Name="AttacherType" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>Type of engine: 3d, plane, line, or point.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="AttacherType" Type="String" />
|
||||
</Attribute>
|
||||
<Attribute Name="Mode" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Current attachment mode.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Mode" Type="String" />
|
||||
</Attribute>
|
||||
<Attribute Name="References" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Current attachment mode.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="References" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="SuperPlacement" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Current attachment mode.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="SuperPlacement" Type="Object" />
|
||||
</Attribute>
|
||||
<Attribute Name="Reverse" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>If True, Z axis of attached placement is flipped. X axis is flipped in addition (CS has to remain right-handed).</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Reverse" Type="Boolean" />
|
||||
</Attribute>
|
||||
<Attribute Name="Parameter" ReadOnly="false">
|
||||
<Documentation>
|
||||
<UserDocu>Value of parameter for some curve attachment modes. Range of 0..1 spans the length of the edge (parameter value can be outside of the range for curves that allow extrapolation.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Parameter" Type="Float" />
|
||||
</Attribute>
|
||||
|
||||
<Attribute Name="CompleteModeList" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of all attachment modes of all AttachEngines. This is the list of modes in MapMode enum properties of AttachableObjects.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="CompleteModeList" Type="List" />
|
||||
</Attribute>
|
||||
<Attribute Name="ImplementedModes" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of all attachment modes of all AttachEngines. This is the list of modes in MapMode enum properties of AttachableObjects.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="ImplementedModes" Type="List" />
|
||||
</Attribute>
|
||||
<Attribute Name="CompleteRefTypeList" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>List of all reference shape types recognized by AttachEngine.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="CompleteRefTypeList" Type="List" />
|
||||
</Attribute>
|
||||
|
||||
<Methode Name="getModeInfo">
|
||||
<Documentation>
|
||||
<UserDocu>getModeInfo(mode): returns supported reference combinations, user-friendly name, and so on.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getRefTypeOfShape">
|
||||
<Documentation>
|
||||
<UserDocu>getRefTypeOfShape(shape): returns shape type as interpreted by AttachEngine. Returns a string.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="isFittingRefType">
|
||||
<Documentation>
|
||||
<UserDocu>isFittingRefType(type_shape, type_needed): tests if shape type, specified by type_shape (string), fits a type required by attachment mode type_needed (string). e.g. 'Circle' fits a requirement of 'Edge', and 'Curve' doesn't fit if a 'Circle' is required.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="downgradeRefType">
|
||||
<Documentation>
|
||||
<UserDocu>downgradeRefType(type): returns next more general type. E.g. downgradeType('Circle') yeilds 'Curve'.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getRefTypeInfo">
|
||||
<Documentation>
|
||||
<UserDocu>getRefTypeInfo(type): returns information (dict) on shape type. Keys:'UserFriendlyName', 'TypeIndex', 'Rank'. Rank is the number of times reftype can be downgraded, before it becomes 'Any'.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="copy" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>copy(): returns a new instance of AttachEngine.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="calculateAttachedPlacement" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>calculateAttachedPlacement(orig_placement): returns result of attachment, based
|
||||
on current Mode, References, etc. SuperPlacment is included.
|
||||
|
||||
original_placement is the previous placement of the object being attached. It
|
||||
is used to preserve orientation for Translate attachment mode. For other modes,
|
||||
it is ignored.
|
||||
|
||||
Returns the new placement. If not attached, returns None. If attachment fails,
|
||||
an exception is raised.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="suggestModes">
|
||||
<Documentation>
|
||||
|
||||
<UserDocu>suggestModes(): runs mode suggestion routine and returns a dictionary with
|
||||
results and supplementary information.
|
||||
|
||||
Keys:
|
||||
'allApplicableModes': list of modes that can accept current references. Note
|
||||
that it is only a check by types, and does not guarantee the modes will
|
||||
actually work.
|
||||
|
||||
'bestFitMode': mode that fits current references best. Note that the mode may
|
||||
not be valid for the set of references; check for if 'message' is 'OK'.
|
||||
|
||||
'error': error message for when 'message' is 'UnexpectedError' or
|
||||
'LinkBroken'.
|
||||
|
||||
'message': general result of suggestion. 'IncompatibleGeometry', 'NoModesFit':
|
||||
no modes accept current set of references; 'OK': some modes do accept current
|
||||
set of references (though it's not guarantted the modes will work - surrestor
|
||||
only checks for correct types); 'UnexpectedError': should never happen.
|
||||
|
||||
'nextRefTypeHint': what more can be added to references to reach other modes
|
||||
('reachableModes' provide more extended information on this)
|
||||
|
||||
'reachableModes': a dict, where key is mode, and value is a list of sequences
|
||||
of references that can be added to fit that mode.
|
||||
|
||||
'references_Types': a list of types of geometry linked by references (that's
|
||||
the input information for suggestor, actually).</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="readParametersFromFeature">
|
||||
<Documentation>
|
||||
<UserDocu>readParametersFromFeature(document_object): sets AttachEngine parameters (References, Mode, etc.) by reading out properties of AttachableObject-derived feature.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="writeParametersToFeature">
|
||||
<Documentation>
|
||||
|
||||
<UserDocu>writeParametersToFeature(document_object): updates properties of
|
||||
AttachableObject-derived feature with current AttachEngine parameters
|
||||
(References, Mode, etc.).
|
||||
|
||||
Warning: if a feature linked by AttachEngine.References was deleted, this method
|
||||
will crash FreeCAD.</UserDocu>
|
||||
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
546
src/Mod/Part/App/AttachEnginePyImp.cpp
Normal file
546
src/Mod/Part/App/AttachEnginePyImp.cpp
Normal file
|
@ -0,0 +1,546 @@
|
|||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <Standard_Failure.hxx>
|
||||
#endif
|
||||
|
||||
#include "Mod/Part/App/Attacher.h"
|
||||
#include <Base/PlacementPy.h>
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include "AttachableObjectPy.h"
|
||||
#include "TopoShapePy.h"
|
||||
|
||||
#include "OCCError.h"
|
||||
|
||||
// inclusion of the generated files (generated out of AttachableObjectPy.xml)
|
||||
#include "AttachEnginePy.h"
|
||||
#include "AttachEnginePy.cpp"
|
||||
|
||||
using namespace Attacher;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string AttachEnginePy::representation(void) const
|
||||
{
|
||||
return std::string("<Attacher::AttachEngine>");
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::PyMake(struct _typeobject *, PyObject *, PyObject *)
|
||||
{
|
||||
// create a new instance of AttachEngine3D
|
||||
return new AttachEnginePy(new AttachEngine3D);
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int AttachEnginePy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
{
|
||||
PyObject* o;
|
||||
if (PyArg_ParseTuple(args, "")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
if (PyArg_ParseTuple(args, "O!", &(AttachEnginePy::Type), &o)) {
|
||||
AttachEngine* attacher = static_cast<AttachEnginePy*>(o)->getAttachEnginePtr();
|
||||
AttachEngine* oldAttacher = this->getAttachEnginePtr();
|
||||
this->_pcTwinPointer = attacher->copy();
|
||||
delete oldAttacher;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
char* typeName;
|
||||
if (PyArg_ParseTuple(args, "s", &typeName)) {
|
||||
Base::Type t = Base::Type::fromName(typeName);
|
||||
AttachEngine* pNewAttacher = nullptr;
|
||||
if (t.isDerivedFrom(AttachEngine::getClassTypeId())){
|
||||
pNewAttacher = static_cast<Attacher::AttachEngine*>(Base::Type::createInstanceByName(typeName));
|
||||
}
|
||||
if (!pNewAttacher) {
|
||||
std::stringstream errMsg;
|
||||
errMsg << "Object if this type is not derived from AttachEngine: " << typeName;
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, errMsg.str().c_str());
|
||||
return -1;
|
||||
}
|
||||
AttachEngine* oldAttacher = this->getAttachEnginePtr();
|
||||
this->_pcTwinPointer = pNewAttacher;
|
||||
delete oldAttacher;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, "Wrong set of constructor arguments. Can be: (), ('Attacher::AttachEngine3D'), ('Attacher::AttachEnginePlane'), ('Attacher::AttachEngineLine'), ('Attacher::AttachEnginePoint'), (other_attacher_instance).");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Py::String AttachEnginePy::getAttacherType(void) const
|
||||
{
|
||||
return Py::String(std::string(this->getAttachEnginePtr()->getTypeId().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief macro ATTACHERPY_STDCATCH_ATTR: catch for exceptions in attribute
|
||||
* code (re-throws the exception converted to Py::Exception). It is a helper
|
||||
* to avoid repeating the same error handling code over and over again.
|
||||
*/
|
||||
#define ATTACHERPY_STDCATCH_ATTR \
|
||||
catch (Standard_Failure) {\
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();\
|
||||
throw Py::Exception(Part::PartExceptionOCCError, e->GetMessageString());\
|
||||
} catch (Base::Exception &e) {\
|
||||
throw Py::Exception(Base::BaseExceptionFreeCADError, e.what());\
|
||||
}
|
||||
|
||||
Py::String AttachEnginePy::getMode(void) const
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
return Py::String(attacher.getModeName(attacher.mapMode));
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
void AttachEnginePy::setMode(Py::String arg)
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
std::string modeName = (std::string)arg;
|
||||
attacher.mapMode = attacher.getModeByName(modeName);
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
Py::Object AttachEnginePy::getReferences(void) const
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
AttachEngine::verifyReferencesAreSafe(attacher.references);
|
||||
return Py::Object(attacher.references.getPyObject(),true);
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
void AttachEnginePy::setReferences(Py::Object arg)
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
attacher.references.setPyObject(arg.ptr());
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
Py::Object AttachEnginePy::getSuperPlacement(void) const
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
return Py::Object(new Base::PlacementPy(new Base::Placement(attacher.superPlacement)),true);
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
void AttachEnginePy::setSuperPlacement(Py::Object arg)
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
if (PyObject_TypeCheck(arg.ptr(), &(Base::PlacementPy::Type))) {
|
||||
const Base::PlacementPy* plmPy = static_cast<const Base::PlacementPy*>(arg.ptr());
|
||||
attacher.superPlacement = *(plmPy->getPlacementPtr());
|
||||
} else {
|
||||
std::string error = std::string("type must be 'Placement', not ");
|
||||
error += arg.type().as_string();
|
||||
throw Py::TypeError(error);
|
||||
}
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
Py::Boolean AttachEnginePy::getReverse(void) const
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
return Py::Boolean(attacher.mapReverse);
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
void AttachEnginePy::setReverse(Py::Boolean arg)
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
attacher.mapReverse = arg.isTrue();
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
Py::Float AttachEnginePy::getParameter(void) const
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
return Py::Float(attacher.attachParameter);
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
void AttachEnginePy::setParameter(Py::Float arg)
|
||||
{
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
attacher.attachParameter = (double)arg;
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
|
||||
Py::List AttachEnginePy::getCompleteModeList(void) const
|
||||
{
|
||||
try {
|
||||
Py::List ret;
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
for(int imode = 0 ; imode < mmDummy_NumberOfModes ; imode++){
|
||||
ret.append(Py::String(attacher.getModeName(eMapMode(imode))));
|
||||
}
|
||||
return ret;
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
Py::List AttachEnginePy::getCompleteRefTypeList(void) const
|
||||
{
|
||||
try {
|
||||
Py::List ret;
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
for(int irt = 0 ; irt < rtDummy_numberOfShapeTypes ; irt++){
|
||||
ret.append(Py::String(attacher.getRefTypeName(eRefType(irt))));
|
||||
}
|
||||
return ret;
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
Py::List AttachEnginePy::getImplementedModes(void) const
|
||||
{
|
||||
try {
|
||||
Py::List ret;
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
for(int imode = 0 ; imode < mmDummy_NumberOfModes ; imode++){
|
||||
if(attacher.modeRefTypes[imode].size() > 0){
|
||||
ret.append(Py::String(attacher.getModeName(eMapMode(imode))));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} ATTACHERPY_STDCATCH_ATTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief macro ATTACHERPY_STDCATCH_METH: catch for exceptions in method code
|
||||
* (returns NULL if an exception is caught). It is a helper to avoid repeating
|
||||
* the same error handling code over and over again.
|
||||
*/
|
||||
#define ATTACHERPY_STDCATCH_METH \
|
||||
catch (Standard_Failure) {\
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();\
|
||||
PyErr_SetString(Part::PartExceptionOCCError, e->GetMessageString());\
|
||||
return NULL;\
|
||||
} catch (Base::Exception &e) {\
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());\
|
||||
return NULL;\
|
||||
} catch (const Py::Exception &){\
|
||||
return NULL;\
|
||||
}
|
||||
|
||||
|
||||
PyObject* AttachEnginePy::getModeInfo(PyObject* args)
|
||||
{
|
||||
char* modeName;
|
||||
if (!PyArg_ParseTuple(args, "s", &modeName))
|
||||
return 0;
|
||||
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
eMapMode mmode = attacher.getModeByName(modeName);
|
||||
Py::List pyListOfCombinations;
|
||||
Py::List pyCombination;
|
||||
refTypeStringList &listOfCombinations = attacher.modeRefTypes.at(mmode);
|
||||
for(const refTypeString &combination: listOfCombinations){
|
||||
pyCombination = Py::List(combination.size());
|
||||
for(int iref = 0 ; iref < combination.size() ; iref++){
|
||||
pyCombination[iref] = Py::String(AttachEngine::getRefTypeName(combination[iref]));
|
||||
}
|
||||
pyListOfCombinations.append(pyCombination);
|
||||
}
|
||||
Py::Dict ret;
|
||||
ret["ReferenceCombinations"] = pyListOfCombinations;
|
||||
ret["ModeIndex"] = Py::Int(mmode);
|
||||
|
||||
try {
|
||||
Py::Module module(PyImport_ImportModule("PartGui"),true);
|
||||
if (!module.hasAttr("AttachEngineResources")) {
|
||||
// in v0.14+, the GUI module can be loaded in console mode (but doesn't have all its document methods)
|
||||
throw Py::RuntimeError("Gui is not up");//DeepSOIC: wanted to throw ImportError here, but it's not defined, so I don't know...
|
||||
}
|
||||
Py::Object submod(module.getAttr("AttachEngineResources"));
|
||||
Py::Callable method(submod.getAttr("getModeStrings"));
|
||||
Py::Tuple arg(2);
|
||||
arg.setItem(0, Py::String(this->getAttachEnginePtr()->getTypeId().getName()));
|
||||
arg.setItem(1, Py::Int(mmode));
|
||||
Py::List strs = method.apply(arg);
|
||||
assert(strs.size() == 2);
|
||||
ret["UserFriendlyName"] = strs[0];
|
||||
ret["BriefDocu"] = strs[1];
|
||||
} catch (Py::Exception& e) {
|
||||
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
|
||||
// the GUI is not up.
|
||||
Base::Console().Warning("AttachEngine: Gui not up, so no gui-related entries in getModeInfo.\n");
|
||||
e.clear();
|
||||
} else {
|
||||
Base::Console().Warning("AttachEngine.getModeInfo: error obtaining GUI strings\n");
|
||||
e.clear();
|
||||
}
|
||||
} catch (Base::Exception &e){
|
||||
Base::Console().Warning("AttachEngine.getModeInfo: error obtaining GUI strings:");
|
||||
Base::Console().Warning(e.what());
|
||||
Base::Console().Warning("\n");
|
||||
}
|
||||
|
||||
return Py::new_reference_to(ret);
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::getRefTypeOfShape(PyObject* args)
|
||||
{
|
||||
PyObject *pcObj;
|
||||
if (!PyArg_ParseTuple(args, "O!", &(Part::TopoShapePy::Type), &pcObj))
|
||||
return NULL;
|
||||
|
||||
try{
|
||||
TopoDS_Shape shape = static_cast<Part::TopoShapePy*>(pcObj)->getTopoShapePtr()->_Shape;
|
||||
eRefType rt = AttachEngine::getShapeType(shape);
|
||||
return Py::new_reference_to(Py::String(AttachEngine::getRefTypeName(rt)));
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::isFittingRefType(PyObject* args)
|
||||
{
|
||||
char* type_shape_str;
|
||||
char* type_need_str;
|
||||
if (!PyArg_ParseTuple(args, "ss", &type_shape_str, &type_need_str))
|
||||
return 0;
|
||||
try {
|
||||
eRefType type_shape = AttachEngine::getRefTypeByName(std::string(type_shape_str));
|
||||
eRefType type_need = AttachEngine::getRefTypeByName(std::string(type_need_str));
|
||||
bool result = AttachEngine::isShapeOfType(type_shape, type_need) > -1;
|
||||
return Py::new_reference_to(Py::Boolean(result));
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::downgradeRefType(PyObject* args)
|
||||
{
|
||||
char* type_shape_str;
|
||||
if (!PyArg_ParseTuple(args, "s", &type_shape_str))
|
||||
return 0;
|
||||
try {
|
||||
eRefType type_shape = AttachEngine::getRefTypeByName(std::string(type_shape_str));
|
||||
eRefType result = AttachEngine::downgradeType(type_shape);
|
||||
return Py::new_reference_to(Py::String(AttachEngine::getRefTypeName(result)));
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::getRefTypeInfo(PyObject* args)
|
||||
{
|
||||
char* typeName;
|
||||
if (!PyArg_ParseTuple(args, "s", &typeName))
|
||||
return 0;
|
||||
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
eRefType rt = attacher.getRefTypeByName(typeName);
|
||||
Py::Dict ret;
|
||||
ret["TypeIndex"] = Py::Int(rt);
|
||||
ret["Rank"] = Py::Int(AttachEngine::getTypeRank(rt));
|
||||
|
||||
try {
|
||||
Py::Module module(PyImport_ImportModule("PartGui"),true);
|
||||
if (!module.hasAttr("AttachEngineResources")) {
|
||||
// in v0.14+, the GUI module can be loaded in console mode (but doesn't have all its document methods)
|
||||
throw Py::RuntimeError("Gui is not up");//DeepSOIC: wanted to throw ImportError here, but it's not defined, so I don't know...
|
||||
}
|
||||
Py::Object submod(module.getAttr("AttachEngineResources"));
|
||||
Py::Callable method(submod.getAttr("getRefTypeUserFriendlyName"));
|
||||
Py::Tuple arg(1);
|
||||
arg.setItem(0, Py::Int(rt));
|
||||
Py::String st = method.apply(arg);
|
||||
ret["UserFriendlyName"] = st;
|
||||
} catch (Py::Exception& e) {
|
||||
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
|
||||
// the GUI is not up.
|
||||
Base::Console().Warning("AttachEngine: Gui not up, so no gui-related entries in getModeInfo.\n");
|
||||
e.clear();
|
||||
} else {
|
||||
Base::Console().Warning("AttachEngine.getRefTypeInfo: error obtaining GUI strings\n");
|
||||
e.clear();
|
||||
}
|
||||
} catch (Base::Exception &e){
|
||||
Base::Console().Warning("AttachEngine.getRefTypeInfo: error obtaining GUI strings:");
|
||||
Base::Console().Warning(e.what());
|
||||
Base::Console().Warning("\n");
|
||||
}
|
||||
|
||||
return Py::new_reference_to(ret);
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::copy(PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return 0;
|
||||
|
||||
return new AttachEnginePy(this->getAttachEnginePtr()->copy());
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::calculateAttachedPlacement(PyObject* args)
|
||||
{
|
||||
PyObject *pcObj;
|
||||
if (!PyArg_ParseTuple(args, "O!", &(Base::PlacementPy::Type), &pcObj))
|
||||
return NULL;
|
||||
try{
|
||||
const Base::Placement& plm = *(static_cast<const Base::PlacementPy*>(pcObj)->getPlacementPtr());
|
||||
Base::Placement result;
|
||||
try{
|
||||
result = this->getAttachEnginePtr()->calculateAttachedPlacement(plm);
|
||||
} catch (ExceptionCancel) {
|
||||
Py_IncRef(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
return new Base::PlacementPy(new Base::Placement(result));
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::suggestModes(PyObject* args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return 0;
|
||||
|
||||
try {
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
SuggestResult sugr;
|
||||
attacher.suggestMapModes(sugr);
|
||||
Py::Dict result;
|
||||
{ //sugr.allApplicableModes
|
||||
Py::List pyList;
|
||||
for(eMapMode mmode: sugr.allApplicableModes){
|
||||
pyList.append(Py::String(AttachEngine::getModeName(mmode)));
|
||||
}
|
||||
result["allApplicableModes"] = pyList;
|
||||
}
|
||||
{ //sugr.bestFitMode
|
||||
result["bestFitMode"] = Py::String(AttachEngine::getModeName(sugr.bestFitMode));
|
||||
}
|
||||
{//sugr.error
|
||||
bool isError = sugr.message == SuggestResult::srUnexpectedError
|
||||
|| sugr.message == SuggestResult::srLinkBroken;
|
||||
result["error"] = Py::String(isError ? sugr.error.what() : "");
|
||||
}
|
||||
{//sugr.message
|
||||
std::string msg;
|
||||
switch(sugr.message){
|
||||
case SuggestResult::srIncompatibleGeometry:
|
||||
msg = "IncompatibleGeometry";
|
||||
break;
|
||||
case SuggestResult::srLinkBroken:
|
||||
msg = "LinkBroken";
|
||||
break;
|
||||
case SuggestResult::srNoModesFit:
|
||||
msg = "NoModesFit";
|
||||
break;
|
||||
case SuggestResult::srOK:
|
||||
msg = "OK";
|
||||
break;
|
||||
case SuggestResult::srUnexpectedError:
|
||||
msg = "UnexpectedError";
|
||||
break;
|
||||
default:
|
||||
msg = "<message index out of range>";
|
||||
}
|
||||
result["message"] = Py::String(msg);
|
||||
}
|
||||
{//sugr.nextRefTypeHint
|
||||
Py::List pyList;
|
||||
for(eRefType rt : sugr.nextRefTypeHint){
|
||||
pyList.append(Py::String(AttachEngine::getRefTypeName(rt)));
|
||||
}
|
||||
result["nextRefTypeHint"] = pyList;
|
||||
}
|
||||
{//sugr.reachableModes
|
||||
Py::Dict pyRM;
|
||||
for(std::pair<const eMapMode, refTypeStringList> &rm: sugr.reachableModes){
|
||||
Py::List pyListOfCombinations;
|
||||
for(refTypeString &rts : rm.second){
|
||||
Py::List pyCombination;
|
||||
for(eRefType rt : rts){
|
||||
pyCombination.append(Py::String(AttachEngine::getRefTypeName(rt)));
|
||||
}
|
||||
pyListOfCombinations.append(pyCombination);
|
||||
}
|
||||
pyRM[AttachEngine::getModeName(rm.first)] = pyListOfCombinations;
|
||||
}
|
||||
result["reachableModes"] = pyRM;
|
||||
}
|
||||
{//sugr.references_Types
|
||||
Py::List pyList;
|
||||
for(eRefType rt : sugr.references_Types){
|
||||
pyList.append(Py::String(AttachEngine::getRefTypeName(rt)));
|
||||
}
|
||||
result["references_Types"] = pyList;
|
||||
}
|
||||
|
||||
return Py::new_reference_to(result);
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::readParametersFromFeature(PyObject* args)
|
||||
{
|
||||
PyObject* obj;
|
||||
if (!PyArg_ParseTuple(args, "O!",&(App::DocumentObjectPy::Type),&obj))
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
try{
|
||||
const App::DocumentObjectPy* dobjpy = static_cast<const App::DocumentObjectPy*>(obj);
|
||||
const App::DocumentObject* dobj = dobjpy->getDocumentObjectPtr();
|
||||
if (! dobj->isDerivedFrom(Part::AttachableObject::getClassTypeId())){
|
||||
throw Py::TypeError("Supplied object isn't Part::AttachableObject");
|
||||
}
|
||||
const Part::AttachableObject* feat = static_cast<const Part::AttachableObject*>(dobj);
|
||||
AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
attacher.setUp(feat->Support,
|
||||
eMapMode(feat->MapMode.getValue()),
|
||||
feat->MapReversed.getValue(),
|
||||
feat->MapPathParameter.getValue(),
|
||||
0.0,0.0,
|
||||
feat->superPlacement.getValue());
|
||||
return Py::new_reference_to(Py::None());
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::writeParametersToFeature(PyObject* args)
|
||||
{
|
||||
PyObject* obj;
|
||||
if (!PyArg_ParseTuple(args, "O!",&(App::DocumentObjectPy::Type),&obj))
|
||||
return NULL; // NULL triggers exception
|
||||
|
||||
try{
|
||||
App::DocumentObjectPy* dobjpy = static_cast<App::DocumentObjectPy*>(obj);
|
||||
App::DocumentObject* dobj = dobjpy->getDocumentObjectPtr();
|
||||
if (! dobj->isDerivedFrom(Part::AttachableObject::getClassTypeId())){
|
||||
throw Py::TypeError("Supplied object isn't Part::AttachableObject");
|
||||
}
|
||||
Part::AttachableObject* feat = static_cast<Part::AttachableObject*>(dobj);
|
||||
const AttachEngine &attacher = *(this->getAttachEnginePtr());
|
||||
AttachEngine::verifyReferencesAreSafe(attacher.references);
|
||||
feat->Support.Paste(attacher.references);
|
||||
feat->MapMode.setValue(attacher.mapMode);
|
||||
feat->MapReversed.setValue(attacher.mapReverse);
|
||||
feat->MapPathParameter.setValue(attacher.attachParameter);
|
||||
feat->superPlacement.setValue(attacher.superPlacement);
|
||||
return Py::new_reference_to(Py::None());
|
||||
} ATTACHERPY_STDCATCH_METH;
|
||||
}
|
||||
|
||||
PyObject* AttachEnginePy::getCustomAttributes(const char*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AttachEnginePy::setCustomAttributes(const char*,PyObject*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -30,6 +30,8 @@
|
|||
#include <Base/Console.h>
|
||||
#include <App/Application.h>
|
||||
|
||||
#include <App/FeaturePythonPyImp.h>
|
||||
#include "AttachableObjectPy.h"
|
||||
|
||||
|
||||
using namespace Part;
|
||||
|
@ -40,6 +42,9 @@ PROPERTY_SOURCE(Part::AttachableObject, Part::Feature);
|
|||
AttachableObject::AttachableObject()
|
||||
: _attacher(0)
|
||||
{
|
||||
ADD_PROPERTY_TYPE(AttacherType, ("Attacher::AttachEngine3D"), "Attachment",(App::PropertyType)(App::Prop_None),"Class name of attach engine object driving the attachment.");
|
||||
this->AttacherType.setStatus(App::Property::Status::Hidden, true);
|
||||
|
||||
ADD_PROPERTY_TYPE(Support, (0,0), "Attachment",(App::PropertyType)(App::Prop_None),"Support of the 2D geometry");
|
||||
|
||||
ADD_PROPERTY_TYPE(MapMode, (mmDeactivated), "Attachment", App::Prop_None, "Mode of attachment to other object");
|
||||
|
@ -67,7 +72,44 @@ void AttachableObject::setAttacher(AttachEngine* attacher)
|
|||
if (_attacher)
|
||||
delete _attacher;
|
||||
_attacher = attacher;
|
||||
updateAttacherVals();
|
||||
if (_attacher){
|
||||
const char* typeName = attacher->getTypeId().getName();
|
||||
if(strcmp(this->AttacherType.getValue(),typeName)!=0) //make sure we need to change, to break recursive onChange->changeAttacherType->onChange...
|
||||
this->AttacherType.setValue(typeName);
|
||||
updateAttacherVals();
|
||||
} else {
|
||||
if (strlen(AttacherType.getValue()) != 0){ //make sure we need to change, to break recursive onChange->changeAttacherType->onChange...
|
||||
this->AttacherType.setValue("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AttachableObject::changeAttacherType(const char* typeName)
|
||||
{
|
||||
//check if we need to actually change anything
|
||||
if (_attacher){
|
||||
if (strcmp(_attacher->getTypeId().getName(),typeName)==0){
|
||||
return false;
|
||||
}
|
||||
} else if (strlen(typeName) == 0){
|
||||
return false;
|
||||
}
|
||||
if (strlen(typeName) == 0){
|
||||
setAttacher(nullptr);
|
||||
return true;
|
||||
}
|
||||
Base::Type t = Base::Type::fromName(typeName);
|
||||
if (t.isDerivedFrom(AttachEngine::getClassTypeId())){
|
||||
AttachEngine* pNewAttacher = static_cast<Attacher::AttachEngine*>(Base::Type::createInstanceByName(typeName));
|
||||
this->setAttacher(pNewAttacher);
|
||||
return true;
|
||||
} else {
|
||||
std::stringstream errMsg;
|
||||
errMsg << "Object if this type is not derived from AttachEngine: " << typeName;
|
||||
throw Base::Exception(errMsg.str());
|
||||
}
|
||||
assert(false);//exec shouldn't ever get here
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AttachableObject::positionBySupport()
|
||||
|
@ -136,6 +178,10 @@ void AttachableObject::onChanged(const App::Property* prop)
|
|||
|
||||
}
|
||||
|
||||
if(prop == &(this->AttacherType)){
|
||||
this->changeAttacherType(this->AttacherType.getValue());
|
||||
}
|
||||
|
||||
Part::Feature::onChanged(prop);
|
||||
}
|
||||
|
||||
|
@ -151,4 +197,22 @@ void AttachableObject::updateAttacherVals()
|
|||
this->superPlacement.getValue());
|
||||
}
|
||||
|
||||
namespace App {
|
||||
/// @cond DOXERR
|
||||
PROPERTY_SOURCE_TEMPLATE(Part::AttachableObjectPython, Part::AttachableObject)
|
||||
template<> const char* Part::AttachableObjectPython::getViewProviderName(void) const {
|
||||
return "PartGui::ViewProviderPython";
|
||||
}
|
||||
template<> PyObject* Part::AttachableObjectPython::getPyObject(void) {
|
||||
if (PythonObject.is(Py::_None())) {
|
||||
// ref counter is set to 1
|
||||
PythonObject = Py::Object(new FeaturePythonPyT<Part::AttachableObjectPy>(this),true);
|
||||
}
|
||||
return Py::new_reference_to(PythonObject);
|
||||
}
|
||||
/// @endcond
|
||||
|
||||
// explicit template instantiation
|
||||
template class PartExport FeaturePythonT<Part::AttachableObject>;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,7 @@ class PartExport AttachableObject : public Part::Feature
|
|||
PROPERTY_HEADER(Part::AttachableObject);
|
||||
public:
|
||||
AttachableObject();
|
||||
~AttachableObject();
|
||||
virtual ~AttachableObject();
|
||||
|
||||
/**
|
||||
* @brief setAttacher sets the AttachEngine object. The class takes the
|
||||
|
@ -68,9 +68,20 @@ public:
|
|||
* @param attacher. AttachableObject takes ownership and will delete it eventually.
|
||||
*/
|
||||
virtual void setAttacher(Attacher::AttachEngine* attacher);
|
||||
Attacher::AttachEngine &attacher(void) const {return *_attacher;}
|
||||
|
||||
/// if the 2DObject lies on the Face of an other object this links to it
|
||||
/**
|
||||
* @brief changeAttacherType
|
||||
* @param typeName is the typename of new attacher class. Must be derived
|
||||
* from Attacher::AttachEngine.
|
||||
* @return true if attacher was changed. false if attacher is already of the
|
||||
* type requested. Throws if invalid type is supplied.
|
||||
*/
|
||||
bool changeAttacherType(const char* typeName);
|
||||
|
||||
Attacher::AttachEngine &attacher(void) const {if(!_attacher) throw Base::Exception("AttachableObject: no attacher is set."); return *_attacher;}
|
||||
|
||||
|
||||
App::PropertyString AttacherType;
|
||||
App::PropertyLinkSubList Support;
|
||||
App::PropertyEnumeration MapMode; //see AttachEngine::eMapMode
|
||||
App::PropertyBool MapReversed; //inverts Z and X internal axes
|
||||
|
@ -104,6 +115,8 @@ private:
|
|||
};
|
||||
|
||||
|
||||
typedef App::FeaturePythonT<AttachableObject> AttachableObjectPython;
|
||||
|
||||
} // namespace Part
|
||||
|
||||
#endif // PARTATTACHABLEOBJECT_H
|
||||
|
|
41
src/Mod/Part/App/AttachableObjectPy.xml
Normal file
41
src/Mod/Part/App/AttachableObjectPy.xml
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="PartFeaturePy"
|
||||
Name="AttachableObjectPy"
|
||||
Twin="AttachableObject"
|
||||
TwinPointer="AttachableObject"
|
||||
Include="Mod/Part/App/AttachableObject.h"
|
||||
Namespace="Part"
|
||||
FatherInclude="Mod/Part/App/PartFeaturePy.h"
|
||||
FatherNamespace="Part">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="DeepSOIC" EMail="vv.titov@gmail.com" />
|
||||
<UserDocu>This object represents an attachable object with OCC shape.</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="positionBySupport">
|
||||
<Documentation>
|
||||
<UserDocu>positionBySupport(): Reposition object based on Support, MapMode and MapPathParameter properties.
|
||||
Returns True if attachment calculation was successful, false if object is not attached and Placement wasn't updated,
|
||||
and raises an exception if attachment calculation fails.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name = "changeAttacherType">
|
||||
<Documentation>
|
||||
<UserDocu>changeAttacherType(typename): Changes Attacher class of this object.
|
||||
typename: string. The following are accepted so far:
|
||||
'Attacher::AttachEngine3D'
|
||||
'Attacher::AttachEnginePlane'
|
||||
'Attacher::AttachEngineLine'
|
||||
'Attacher::AttachEnginePoint'</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
|
||||
<Attribute Name="Attacher" ReadOnly="true">
|
||||
<Documentation>
|
||||
<UserDocu>AttachEngine object driving this AttachableObject. Returns a copy.</UserDocu>
|
||||
</Documentation>
|
||||
<Parameter Name="Attacher" Type="Object" />
|
||||
</Attribute>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
87
src/Mod/Part/App/AttachableObjectPyImp.cpp
Normal file
87
src/Mod/Part/App/AttachableObjectPyImp.cpp
Normal file
|
@ -0,0 +1,87 @@
|
|||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "Mod/Part/App/AttachableObject.h"
|
||||
#include "OCCError.h"
|
||||
|
||||
#include "AttachEnginePy.h"
|
||||
|
||||
// inclusion of the generated files (generated out of AttachableObjectPy.xml)
|
||||
#include "AttachableObjectPy.h"
|
||||
#include "AttachableObjectPy.cpp"
|
||||
|
||||
using namespace Part;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string AttachableObjectPy::representation(void) const
|
||||
{
|
||||
return std::string("<Part::AttachableObject>");
|
||||
}
|
||||
|
||||
PyObject* AttachableObjectPy::positionBySupport(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return 0;
|
||||
bool bAttached = false;
|
||||
try{
|
||||
bAttached = this->getAttachableObjectPtr()->positionBySupport();
|
||||
} catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
|
||||
return NULL;
|
||||
} catch (Base::Exception &e) {
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
|
||||
return NULL;
|
||||
}
|
||||
return Py::new_reference_to(Py::Boolean(bAttached));
|
||||
}
|
||||
|
||||
PyObject* AttachableObjectPy::changeAttacherType(PyObject *args)
|
||||
{
|
||||
const char* typeName;
|
||||
if (!PyArg_ParseTuple(args, "s", &typeName))
|
||||
return 0;
|
||||
bool ret;
|
||||
try{
|
||||
ret = this->getAttachableObjectPtr()->changeAttacherType(typeName);
|
||||
} catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
|
||||
return NULL;
|
||||
} catch (Base::Exception &e) {
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
|
||||
return NULL;
|
||||
}
|
||||
return Py::new_reference_to(Py::Boolean(ret));
|
||||
}
|
||||
|
||||
Py::Object AttachableObjectPy::getAttacher(void) const
|
||||
{
|
||||
try {
|
||||
this->getAttachableObjectPtr()->attacher(); //throws if attacher is not set
|
||||
} catch (Base::Exception) {
|
||||
return Py::None();
|
||||
}
|
||||
|
||||
try {
|
||||
return Py::Object( new Attacher::AttachEnginePy(this->getAttachableObjectPtr()->attacher().copy()), true);
|
||||
} catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
throw Py::Exception(Part::PartExceptionOCCError, e->GetMessageString());
|
||||
} catch (Base::Exception &e) {
|
||||
throw Py::Exception(Base::BaseExceptionFreeCADError, e.what());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PyObject *AttachableObjectPy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int AttachableObjectPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -61,6 +61,8 @@
|
|||
#include "Attacher.h"
|
||||
#include <Base/Console.h>
|
||||
#include <App/OriginFeature.h>
|
||||
#include <App/Application.h>
|
||||
#include <App/Document.h>
|
||||
|
||||
using namespace Part;
|
||||
using namespace Attacher;
|
||||
|
@ -120,10 +122,44 @@ const char* AttachEngine::eMapModeStrings[]= {
|
|||
|
||||
NULL};
|
||||
|
||||
//this list must be in sync with eRefType enum.
|
||||
//These strings are used only by Py interface of Attacher. Strings for use in Gui are in Mod/Part/Gui/AttacherTexts.cpp
|
||||
const char* AttachEngine::eRefTypeStrings[]= {
|
||||
"Any",
|
||||
"Vertex",
|
||||
"Edge",
|
||||
"Face",
|
||||
|
||||
"Line",
|
||||
"Curve",
|
||||
"Circle",
|
||||
"Conic",
|
||||
"Ellipse",
|
||||
"Parabola",
|
||||
"Hyperbola",
|
||||
|
||||
"Plane",
|
||||
"Sphere",
|
||||
"Revolve",
|
||||
"Cylinder",
|
||||
"Torus",
|
||||
"Cone",
|
||||
|
||||
"Object",
|
||||
"Solid",
|
||||
"Wire",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TYPESYSTEM_SOURCE_ABSTRACT(Attacher::AttachEngine, Base::BaseClass);
|
||||
|
||||
AttachEngine::AttachEngine()
|
||||
: mapReverse(false), attachParameter(0.0), mapMode(mmDeactivated),
|
||||
surfU(0.0), surfV(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -576,6 +612,57 @@ std::string AttachEngine::getModeName(eMapMode mmode)
|
|||
return std::string(AttachEngine::eMapModeStrings[mmode]);
|
||||
}
|
||||
|
||||
eMapMode AttachEngine::getModeByName(const std::string &modeName)
|
||||
{
|
||||
for (int mmode = 0 ; mmode < mmDummy_NumberOfModes ; mmode++){
|
||||
if (strcmp(eMapModeStrings[mmode],modeName.c_str())==0) {
|
||||
return eMapMode(mmode);
|
||||
}
|
||||
}
|
||||
std::stringstream errMsg;
|
||||
errMsg << "AttachEngine::getModeByName: mode with this name doesn't exist: " << modeName;
|
||||
throw Base::Exception(errMsg.str());
|
||||
}
|
||||
|
||||
std::string AttachEngine::getRefTypeName(eRefType shapeType)
|
||||
{
|
||||
eRefType flagless = eRefType(shapeType & 0xFF);
|
||||
if(flagless < 0 || flagless >= rtDummy_numberOfShapeTypes)
|
||||
throw Base::Exception("eRefType value is out of range");
|
||||
std::string result = std::string(eRefTypeStrings[flagless]);
|
||||
if (shapeType & rtFlagHasPlacement){
|
||||
result.append("|Placement");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
eRefType AttachEngine::getRefTypeByName(const std::string& typeName)
|
||||
{
|
||||
std::string flagless;
|
||||
std::string flags;
|
||||
size_t seppos = typeName.find('|');
|
||||
flagless = typeName.substr(0, seppos);
|
||||
if(seppos != std::string::npos ){
|
||||
flags = typeName.substr(seppos+1);
|
||||
}
|
||||
for(int irt = 0 ; irt < rtDummy_numberOfShapeTypes ; irt++){
|
||||
if(strcmp(flagless.c_str(),eRefTypeStrings[irt]) == 0){
|
||||
if(strcmp("Placement",flags.c_str()) == 0){
|
||||
return eRefType(irt | rtFlagHasPlacement);
|
||||
} else if (flags.length() == 0){
|
||||
return eRefType(irt);
|
||||
} else {
|
||||
std::stringstream errmsg;
|
||||
errmsg << "RefType flag not recognized: " << flags;
|
||||
throw Base::Exception(errmsg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
std::stringstream errmsg;
|
||||
errmsg << "RefType not recognized: " << typeName;
|
||||
throw Base::Exception(errmsg.str());
|
||||
}
|
||||
|
||||
GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector<const TopoDS_Shape*> &shapes)
|
||||
{
|
||||
//explode compounds
|
||||
|
@ -638,7 +725,7 @@ GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector<const TopoD
|
|||
throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only solids/compsolids)");
|
||||
if (sh.Infinite())
|
||||
throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided");
|
||||
BRepGProp::SurfaceProperties(sh,gpr);
|
||||
BRepGProp::VolumeProperties(sh,gpr);
|
||||
gpr_acc.Add(gpr);
|
||||
}
|
||||
return gpr_acc;
|
||||
|
@ -664,6 +751,7 @@ void AttachEngine::readLinks(const App::PropertyLinkSubList &references,
|
|||
std::vector<TopoDS_Shape> &storage,
|
||||
std::vector<eRefType> &types)
|
||||
{
|
||||
verifyReferencesAreSafe(references);
|
||||
const std::vector<App::DocumentObject*> &objs = references.getValues();
|
||||
const std::vector<std::string> &sub = references.getSubValues();
|
||||
geofs.resize(objs.size());
|
||||
|
@ -745,6 +833,23 @@ void AttachEngine::throwWrongMode(eMapMode mmode)
|
|||
throw Base::Exception(errmsg.str().c_str());
|
||||
}
|
||||
|
||||
void AttachEngine::verifyReferencesAreSafe(const App::PropertyLinkSubList &references)
|
||||
{
|
||||
const std::vector<App::DocumentObject*> links = references.getValues();
|
||||
const std::vector<App::Document*> docs = App::GetApplication().getDocuments();
|
||||
for(App::DocumentObject* lnk : links){
|
||||
bool found = false;
|
||||
for(App::Document* doc : docs){
|
||||
if(doc->isIn(lnk)){
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found){
|
||||
throw Base::Exception("AttachEngine: verifyReferencesAreSafe: references point to deleted object.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=================================================================================
|
||||
|
||||
|
|
|
@ -105,7 +105,8 @@ enum eMapMode {
|
|||
|
||||
/**
|
||||
* @brief The eRefType enum lists the types of references. If adding one, see
|
||||
* also AttachEngine::getShapeType(), AttachEngine::downgradeType(), AttacherTexts.cpp/getShTypeText()
|
||||
* also AttachEngine::eRefTypeStrings, AttachEngine::getShapeType(),
|
||||
* AttachEngine::downgradeType(), AttacherTexts.cpp/getShTypeText()
|
||||
*/
|
||||
enum eRefType {
|
||||
//topo //ranks: (number of times the type is downgradable)
|
||||
|
@ -333,11 +334,24 @@ public://helper functions that may be useful outside of the class
|
|||
*/
|
||||
static std::string getModeName(eMapMode mmode);
|
||||
|
||||
static eMapMode getModeByName(const std::string &modeName);
|
||||
|
||||
static std::string getRefTypeName(eRefType shapeType);
|
||||
|
||||
static eRefType getRefTypeByName(const std::string &typeName);
|
||||
|
||||
static GProp_GProps getInertialPropsOfShape(const std::vector<const TopoDS_Shape*> &shapes);
|
||||
|
||||
/**
|
||||
* @brief verifyReferencesAreSafe: checks if pointers in references still
|
||||
* point to objects contained in open documents. This guarantees the links
|
||||
* are valid. Throws Base::Exception if invalid links are found.
|
||||
*/
|
||||
static void verifyReferencesAreSafe(const App::PropertyLinkSubList& references);
|
||||
|
||||
public: //enums
|
||||
static const char* eMapModeStrings[];
|
||||
static const char* eRefTypeStrings[];
|
||||
|
||||
|
||||
public: //members
|
||||
|
|
|
@ -69,7 +69,9 @@ generate_from_xml(RectangularTrimmedSurfacePy)
|
|||
generate_from_xml(SurfaceOfExtrusionPy)
|
||||
generate_from_xml(SurfaceOfRevolutionPy)
|
||||
generate_from_xml(PartFeaturePy)
|
||||
generate_from_xml(AttachableObjectPy)
|
||||
generate_from_xml(Part2DObjectPy)
|
||||
generate_from_xml(AttachEnginePy)
|
||||
generate_from_xml(TopoShapePy)
|
||||
generate_from_xml(TopoShapeCompoundPy)
|
||||
generate_from_xml(TopoShapeCompSolidPy)
|
||||
|
@ -216,8 +218,12 @@ SET(Python_SRCS
|
|||
SurfaceOfRevolutionPyImp.cpp
|
||||
PartFeaturePy.xml
|
||||
PartFeaturePyImp.cpp
|
||||
AttachableObjectPy.xml
|
||||
AttachableObjectPyImp.cpp
|
||||
Part2DObjectPy.xml
|
||||
Part2DObjectPyImp.cpp
|
||||
AttachEnginePy.xml
|
||||
AttachEnginePyImp.cpp
|
||||
TopoShapePy.xml
|
||||
TopoShapePyImp.cpp
|
||||
TopoShapeCompSolidPy.xml
|
||||
|
|
|
@ -66,7 +66,7 @@ PROPERTY_SOURCE(Part::Part2DObject, Part::AttachableObject)
|
|||
|
||||
Part2DObject::Part2DObject()
|
||||
{
|
||||
this->setAttacher(new Attacher::AttachEngine3D);
|
||||
this->setAttacher(new Attacher::AttachEnginePlane);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,24 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="PartFeaturePy"
|
||||
Father="AttachableObjectPy"
|
||||
Name="Part2DObjectPy"
|
||||
Twin="Part2DObject"
|
||||
TwinPointer="Part2DObject"
|
||||
Include="Mod/Part/App/Part2DObject.h"
|
||||
Namespace="Part"
|
||||
FatherInclude="Mod/Part/App/PartFeaturePy.h"
|
||||
FatherInclude="Mod/Part/App/AttachableObjectPy.h"
|
||||
FatherNamespace="Part">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
|
||||
<UserDocu>This object represents a 2D Shape in a 3D World</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="positionBySupport">
|
||||
<Documentation>
|
||||
<UserDocu>positionBySupport(): Reposition object based on Support, MapMode and MapPathParameter properties.
|
||||
Returns True if attachment calculation was successful, false if object is not attached and Placement wasn't updated,
|
||||
and raises an exception if attachment calculation fails.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
||||
|
|
|
@ -16,23 +16,6 @@ std::string Part2DObjectPy::representation(void) const
|
|||
return std::string("<Part::Part2DObject>");
|
||||
}
|
||||
|
||||
PyObject* Part2DObjectPy::positionBySupport(PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return 0;
|
||||
bool bAttached = false;
|
||||
try{
|
||||
bAttached = this->getPart2DObjectPtr()->positionBySupport();
|
||||
} catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
PyErr_SetString(PartExceptionOCCError, e->GetMessageString());
|
||||
return NULL;
|
||||
} catch (Base::Exception &e) {
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
|
||||
return NULL;
|
||||
}
|
||||
return Py::new_reference_to(Py::Boolean(bAttached));
|
||||
}
|
||||
|
||||
|
||||
PyObject *Part2DObjectPy::getCustomAttributes(const char* /*attr*/) const
|
||||
|
|
|
@ -34,6 +34,9 @@
|
|||
# define PartExport
|
||||
#endif
|
||||
|
||||
//needed to make autogenerated Py interface source code to compile
|
||||
#define AttacherExport PartExport
|
||||
|
||||
// here get the warnings of too long specifiers disabled (needed for VC6)
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( disable : 4251 )
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <Mod/Part/App/PropertyTopoShape.h>
|
||||
|
||||
#include "AttacherTexts.h"
|
||||
#include "SoBrepFaceSet.h"
|
||||
#include "SoBrepEdgeSet.h"
|
||||
#include "SoBrepPointSet.h"
|
||||
|
@ -117,9 +118,15 @@ PyMODINIT_FUNC initPartGui()
|
|||
return;
|
||||
}
|
||||
|
||||
(void)PartGui::initModule();
|
||||
PyObject* partGuiModule = PartGui::initModule();
|
||||
Base::Console().Log("Loading GUI of Part module... done\n");
|
||||
|
||||
PyObject* pAttachEngineTextsModule = Py_InitModule3("AttachEngineResources", AttacherGui::AttacherGuiPy::Methods,
|
||||
"AttachEngine Gui resources");
|
||||
Py_INCREF(pAttachEngineTextsModule);
|
||||
PyModule_AddObject(partGuiModule, "AttachEngineResources", pAttachEngineTextsModule);
|
||||
|
||||
|
||||
PartGui::SoBrepFaceSet ::initClass();
|
||||
PartGui::SoBrepEdgeSet ::initClass();
|
||||
PartGui::SoBrepPointSet ::initClass();
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
# include <QApplication>
|
||||
#endif
|
||||
#include "AttacherTexts.h"
|
||||
#include <Base/PyObjectBase.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
using namespace Attacher;
|
||||
|
||||
|
@ -262,7 +264,7 @@ TextSet getUIStrings(Base::Type attacherType, eMapMode mmode)
|
|||
}
|
||||
}
|
||||
|
||||
assert(false && "No user-friendly string defined for this attachment mode.");
|
||||
Base::Console().Warning("No user-friendly string defined for this attachment mode and attacher type: %s %s \n",AttachEngine::getModeName(mmode).c_str(), attacherType.getName());
|
||||
return TwoStrings(QString::fromStdString(AttachEngine::getModeName(mmode)), QString());
|
||||
}
|
||||
|
||||
|
@ -325,4 +327,64 @@ QStringList getRefListForMode(AttachEngine &attacher, eMapMode mmode)
|
|||
return strlist;
|
||||
}
|
||||
|
||||
|
||||
// --------------------Py interface---------------------
|
||||
|
||||
PyObject* AttacherGuiPy::sGetModeStrings(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
|
||||
{
|
||||
int modeIndex = 0;
|
||||
char* attacherType;
|
||||
if (!PyArg_ParseTuple(args, "si", &attacherType, &modeIndex))
|
||||
return NULL;
|
||||
|
||||
try {
|
||||
Base::Type t = Base::Type::fromName(attacherType);
|
||||
if (! t.isDerivedFrom(AttachEngine::getClassTypeId())){
|
||||
std::stringstream ss;
|
||||
ss << "Object of this type is not derived from AttachEngine: ";
|
||||
ss << attacherType;
|
||||
throw Py::TypeError(ss.str());
|
||||
}
|
||||
TextSet strs = getUIStrings(t,eMapMode(modeIndex));
|
||||
Py::List result;
|
||||
for(QString &s : strs){
|
||||
QByteArray ba_utf8 = s.toUtf8();
|
||||
result.append(Py::String(ba_utf8.data(), "utf-8"));
|
||||
}
|
||||
|
||||
return Py::new_reference_to(result);
|
||||
} catch (const Py::Exception&) {
|
||||
return 0;
|
||||
} catch (const Base::Exception& e) {
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* AttacherGuiPy::sGetRefTypeUserFriendlyName(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/)
|
||||
{
|
||||
int refTypeIndex = 0;
|
||||
if (!PyArg_ParseTuple(args, "i", &refTypeIndex))
|
||||
return NULL;
|
||||
|
||||
try {
|
||||
QByteArray ba_utf8 = getShapeTypeText(eRefType(refTypeIndex)).toUtf8();
|
||||
return Py::new_reference_to(Py::String(ba_utf8.data(), "utf-8"));
|
||||
} catch (const Py::Exception&) {
|
||||
return 0;
|
||||
} catch (const Base::Exception& e) {
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PyMethodDef AttacherGuiPy::Methods[] = {
|
||||
{"getModeStrings", (PyCFunction) AttacherGuiPy::sGetModeStrings, 1,
|
||||
"getModeStrings(attacher_type, mode_index) - gets mode user-friendly name and brief description."},
|
||||
{"getRefTypeUserFriendlyName", (PyCFunction) AttacherGuiPy::sGetRefTypeUserFriendlyName, 1,
|
||||
"getRefTypeUserFriendlyName(type_index) - gets user-friendly name of AttachEngine's shape type."},
|
||||
};
|
||||
|
||||
|
||||
} //namespace AttacherGui
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
#include <vector>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <CXX/Objects.hxx>
|
||||
#include <Mod/Part/App/Attacher.h>
|
||||
|
||||
|
||||
namespace AttacherGui {
|
||||
|
||||
typedef std::vector<QString> TextSet;
|
||||
|
@ -54,6 +56,14 @@ QString PartGuiExport getShapeTypeText(Attacher::eRefType type);
|
|||
|
||||
QStringList PartGuiExport getRefListForMode(Attacher::AttachEngine &attacher, Attacher::eMapMode mmode);
|
||||
|
||||
}
|
||||
|
||||
// Python interface
|
||||
class PartGuiExport AttacherGuiPy{
|
||||
public:
|
||||
static PyMethodDef Methods[];
|
||||
static PyObject* sGetModeStrings(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/);
|
||||
static PyObject* sGetRefTypeUserFriendlyName(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/);
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue
Block a user