Merge pull request #159 from DeepSOIC/Attacher16

Attacher16 - fixes, and Py interface
This commit is contained in:
wwmayer 2016-05-14 18:23:27 +02:00
commit 6eb173a54b
17 changed files with 1142 additions and 37 deletions

View File

@ -51,7 +51,6 @@
#include "PartFeatures.h" #include "PartFeatures.h"
#include "BodyBase.h" #include "BodyBase.h"
#include "PrimitiveFeature.h" #include "PrimitiveFeature.h"
#include "Attacher.h"
#include "Part2DObject.h" #include "Part2DObject.h"
#include "CustomFeature.h" #include "CustomFeature.h"
#include "TopoShapePy.h" #include "TopoShapePy.h"
@ -91,6 +90,7 @@
#include "ToroidPy.h" #include "ToroidPy.h"
#include "BRepOffsetAPI_MakePipeShellPy.h" #include "BRepOffsetAPI_MakePipeShellPy.h"
#include "PartFeaturePy.h" #include "PartFeaturePy.h"
#include "AttachEnginePy.h"
#include "PropertyGeometryList.h" #include "PropertyGeometryList.h"
#include "DatumFeature.h" #include "DatumFeature.h"
#include "Attacher.h" #include "Attacher.h"
@ -210,6 +210,8 @@ PyMODINIT_FUNC initPart()
Base::Interpreter().addType(&Part::PartFeaturePy ::Type,partModule,"Feature"); Base::Interpreter().addType(&Part::PartFeaturePy ::Type,partModule,"Feature");
Base::Interpreter().addType(&Attacher::AttachEnginePy ::Type,partModule,"AttachEngine");
PyObject* brepModule = Py_InitModule3("BRepOffsetAPI", 0, "BrepOffsetAPI"); PyObject* brepModule = Py_InitModule3("BRepOffsetAPI", 0, "BrepOffsetAPI");
Py_INCREF(brepModule); Py_INCREF(brepModule);
PyModule_AddObject(partModule, "BRepOffsetAPI", brepModule); PyModule_AddObject(partModule, "BRepOffsetAPI", brepModule);
@ -230,6 +232,7 @@ PyMODINIT_FUNC initPart()
Part::Feature ::init(); Part::Feature ::init();
Part::FeatureExt ::init(); Part::FeatureExt ::init();
Part::AttachableObject ::init(); Part::AttachableObject ::init();
Part::AttachableObjectPython::init();
Part::BodyBase ::init(); Part::BodyBase ::init();
Part::FeaturePython ::init(); Part::FeaturePython ::init();
Part::FeatureGeometrySet ::init(); Part::FeatureGeometrySet ::init();

View 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>

View 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;
}

View File

@ -30,6 +30,8 @@
#include <Base/Console.h> #include <Base/Console.h>
#include <App/Application.h> #include <App/Application.h>
#include <App/FeaturePythonPyImp.h>
#include "AttachableObjectPy.h"
using namespace Part; using namespace Part;
@ -40,6 +42,9 @@ PROPERTY_SOURCE(Part::AttachableObject, Part::Feature);
AttachableObject::AttachableObject() AttachableObject::AttachableObject()
: _attacher(0) : _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(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"); 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) if (_attacher)
delete _attacher; delete _attacher;
_attacher = 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() 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); Part::Feature::onChanged(prop);
} }
@ -151,4 +197,22 @@ void AttachableObject::updateAttacherVals()
this->superPlacement.getValue()); 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>;
}

View File

@ -59,7 +59,7 @@ class PartExport AttachableObject : public Part::Feature
PROPERTY_HEADER(Part::AttachableObject); PROPERTY_HEADER(Part::AttachableObject);
public: public:
AttachableObject(); AttachableObject();
~AttachableObject(); virtual ~AttachableObject();
/** /**
* @brief setAttacher sets the AttachEngine object. The class takes the * @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. * @param attacher. AttachableObject takes ownership and will delete it eventually.
*/ */
virtual void setAttacher(Attacher::AttachEngine* attacher); 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::PropertyLinkSubList Support;
App::PropertyEnumeration MapMode; //see AttachEngine::eMapMode App::PropertyEnumeration MapMode; //see AttachEngine::eMapMode
App::PropertyBool MapReversed; //inverts Z and X internal axes App::PropertyBool MapReversed; //inverts Z and X internal axes
@ -104,6 +115,8 @@ private:
}; };
typedef App::FeaturePythonT<AttachableObject> AttachableObjectPython;
} // namespace Part } // namespace Part
#endif // PARTATTACHABLEOBJECT_H #endif // PARTATTACHABLEOBJECT_H

View 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>

View 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;
}

View File

@ -61,6 +61,8 @@
#include "Attacher.h" #include "Attacher.h"
#include <Base/Console.h> #include <Base/Console.h>
#include <App/OriginFeature.h> #include <App/OriginFeature.h>
#include <App/Application.h>
#include <App/Document.h>
using namespace Part; using namespace Part;
using namespace Attacher; using namespace Attacher;
@ -120,10 +122,44 @@ const char* AttachEngine::eMapModeStrings[]= {
NULL}; 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); TYPESYSTEM_SOURCE_ABSTRACT(Attacher::AttachEngine, Base::BaseClass);
AttachEngine::AttachEngine() 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]); 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) GProp_GProps AttachEngine::getInertialPropsOfShape(const std::vector<const TopoDS_Shape*> &shapes)
{ {
//explode compounds //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)"); throw Base::Exception("AttachEngine::getInertialPropsOfShape: provided shapes are incompatible (not only solids/compsolids)");
if (sh.Infinite()) if (sh.Infinite())
throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided"); throw Base::Exception("AttachEngine::getInertialPropsOfShape: infinite shape provided");
BRepGProp::SurfaceProperties(sh,gpr); BRepGProp::VolumeProperties(sh,gpr);
gpr_acc.Add(gpr); gpr_acc.Add(gpr);
} }
return gpr_acc; return gpr_acc;
@ -664,6 +751,7 @@ void AttachEngine::readLinks(const App::PropertyLinkSubList &references,
std::vector<TopoDS_Shape> &storage, std::vector<TopoDS_Shape> &storage,
std::vector<eRefType> &types) std::vector<eRefType> &types)
{ {
verifyReferencesAreSafe(references);
const std::vector<App::DocumentObject*> &objs = references.getValues(); const std::vector<App::DocumentObject*> &objs = references.getValues();
const std::vector<std::string> &sub = references.getSubValues(); const std::vector<std::string> &sub = references.getSubValues();
geofs.resize(objs.size()); geofs.resize(objs.size());
@ -745,6 +833,23 @@ void AttachEngine::throwWrongMode(eMapMode mmode)
throw Base::Exception(errmsg.str().c_str()); 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.");
}
}
}
//================================================================================= //=================================================================================

View File

@ -105,7 +105,8 @@ enum eMapMode {
/** /**
* @brief The eRefType enum lists the types of references. If adding one, see * @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 { enum eRefType {
//topo //ranks: (number of times the type is downgradable) //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 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); 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 public: //enums
static const char* eMapModeStrings[]; static const char* eMapModeStrings[];
static const char* eRefTypeStrings[];
public: //members public: //members

View File

@ -69,7 +69,9 @@ generate_from_xml(RectangularTrimmedSurfacePy)
generate_from_xml(SurfaceOfExtrusionPy) generate_from_xml(SurfaceOfExtrusionPy)
generate_from_xml(SurfaceOfRevolutionPy) generate_from_xml(SurfaceOfRevolutionPy)
generate_from_xml(PartFeaturePy) generate_from_xml(PartFeaturePy)
generate_from_xml(AttachableObjectPy)
generate_from_xml(Part2DObjectPy) generate_from_xml(Part2DObjectPy)
generate_from_xml(AttachEnginePy)
generate_from_xml(TopoShapePy) generate_from_xml(TopoShapePy)
generate_from_xml(TopoShapeCompoundPy) generate_from_xml(TopoShapeCompoundPy)
generate_from_xml(TopoShapeCompSolidPy) generate_from_xml(TopoShapeCompSolidPy)
@ -216,8 +218,12 @@ SET(Python_SRCS
SurfaceOfRevolutionPyImp.cpp SurfaceOfRevolutionPyImp.cpp
PartFeaturePy.xml PartFeaturePy.xml
PartFeaturePyImp.cpp PartFeaturePyImp.cpp
AttachableObjectPy.xml
AttachableObjectPyImp.cpp
Part2DObjectPy.xml Part2DObjectPy.xml
Part2DObjectPyImp.cpp Part2DObjectPyImp.cpp
AttachEnginePy.xml
AttachEnginePyImp.cpp
TopoShapePy.xml TopoShapePy.xml
TopoShapePyImp.cpp TopoShapePyImp.cpp
TopoShapeCompSolidPy.xml TopoShapeCompSolidPy.xml

View File

@ -66,7 +66,7 @@ PROPERTY_SOURCE(Part::Part2DObject, Part::AttachableObject)
Part2DObject::Part2DObject() Part2DObject::Part2DObject()
{ {
this->setAttacher(new Attacher::AttachEngine3D); this->setAttacher(new Attacher::AttachEnginePlane);
} }

View File

@ -1,24 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd"> <GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport <PythonExport
Father="PartFeaturePy" Father="AttachableObjectPy"
Name="Part2DObjectPy" Name="Part2DObjectPy"
Twin="Part2DObject" Twin="Part2DObject"
TwinPointer="Part2DObject" TwinPointer="Part2DObject"
Include="Mod/Part/App/Part2DObject.h" Include="Mod/Part/App/Part2DObject.h"
Namespace="Part" Namespace="Part"
FatherInclude="Mod/Part/App/PartFeaturePy.h" FatherInclude="Mod/Part/App/AttachableObjectPy.h"
FatherNamespace="Part"> FatherNamespace="Part">
<Documentation> <Documentation>
<Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" /> <Author Licence="LGPL" Name="Juergen Riegel" EMail="FreeCAD@juergen-riegel.net" />
<UserDocu>This object represents a 2D Shape in a 3D World</UserDocu> <UserDocu>This object represents a 2D Shape in a 3D World</UserDocu>
</Documentation> </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> </PythonExport>
</GenerateModel> </GenerateModel>

View File

@ -16,23 +16,6 @@ std::string Part2DObjectPy::representation(void) const
return std::string("<Part::Part2DObject>"); 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 PyObject *Part2DObjectPy::getCustomAttributes(const char* /*attr*/) const

View File

@ -34,6 +34,9 @@
# define PartExport # define PartExport
#endif #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) // here get the warnings of too long specifiers disabled (needed for VC6)
#ifdef _MSC_VER #ifdef _MSC_VER
# pragma warning( disable : 4251 ) # pragma warning( disable : 4251 )

View File

@ -28,6 +28,7 @@
#include <Mod/Part/App/PropertyTopoShape.h> #include <Mod/Part/App/PropertyTopoShape.h>
#include "AttacherTexts.h"
#include "SoBrepFaceSet.h" #include "SoBrepFaceSet.h"
#include "SoBrepEdgeSet.h" #include "SoBrepEdgeSet.h"
#include "SoBrepPointSet.h" #include "SoBrepPointSet.h"
@ -117,9 +118,15 @@ PyMODINIT_FUNC initPartGui()
return; return;
} }
(void)PartGui::initModule(); PyObject* partGuiModule = PartGui::initModule();
Base::Console().Log("Loading GUI of Part module... done\n"); 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::SoBrepFaceSet ::initClass();
PartGui::SoBrepEdgeSet ::initClass(); PartGui::SoBrepEdgeSet ::initClass();
PartGui::SoBrepPointSet ::initClass(); PartGui::SoBrepPointSet ::initClass();

View File

@ -25,6 +25,8 @@
# include <QApplication> # include <QApplication>
#endif #endif
#include "AttacherTexts.h" #include "AttacherTexts.h"
#include <Base/PyObjectBase.h>
#include <Base/Console.h>
using namespace Attacher; 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()); return TwoStrings(QString::fromStdString(AttachEngine::getModeName(mmode)), QString());
} }
@ -325,4 +327,64 @@ QStringList getRefListForMode(AttachEngine &attacher, eMapMode mmode)
return strlist; 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 } //namespace AttacherGui

View File

@ -33,8 +33,10 @@
#include <vector> #include <vector>
#include <QString> #include <QString>
#include <QStringList> #include <QStringList>
#include <CXX/Objects.hxx>
#include <Mod/Part/App/Attacher.h> #include <Mod/Part/App/Attacher.h>
namespace AttacherGui { namespace AttacherGui {
typedef std::vector<QString> TextSet; typedef std::vector<QString> TextSet;
@ -54,6 +56,14 @@ QString PartGuiExport getShapeTypeText(Attacher::eRefType type);
QStringList PartGuiExport getRefListForMode(Attacher::AttachEngine &attacher, Attacher::eMapMode mmode); 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 #endif