Skip to content

Commit

Permalink
Import: add new implementation of STEP importer/exporter
Browse files Browse the repository at this point in the history
For better supporting Link and groups. The original implementation can
still be used by uncheck the STEP import setting 'Use Link Group'.
  • Loading branch information
realthunder committed Jul 14, 2019
1 parent b0c8c54 commit 2f4d10c
Show file tree
Hide file tree
Showing 9 changed files with 2,423 additions and 528 deletions.
158 changes: 83 additions & 75 deletions src/Mod/Import/App/AppImportPy.cpp
Expand Up @@ -56,8 +56,7 @@
#include <CXX/Extensions.hxx>
#include <CXX/Objects.hxx>

#include "ImportOCAF.h"
#include "ExportOCAF.h"
#include "ImportOCAF2.h"
//#include "ImportOCAFAssembly.h"
#include <Base/PyObjectBase.h>
#include <Base/Console.h>
Expand All @@ -76,22 +75,38 @@

#include "ImpExpDxf.h"

class ImportOCAFExt : public Import::ImportOCAF2
{
public:
ImportOCAFExt(Handle(TDocStd_Document) h, App::Document* d, const std::string& name)
: ImportOCAF2(h, d, name)
{
}

std::map<Part::Feature*, std::vector<App::Color> > partColors;

private:
virtual void applyFaceColors(Part::Feature* part, const std::vector<App::Color>& colors) override {
partColors[part] = colors;
}
};

namespace Import {
class Module : public Py::ExtensionModule<Module>
{
public:
Module() : Py::ExtensionModule<Module>("Import")
{
add_varargs_method("open",&Module::importer,
add_keyword_method("open",&Module::importer,
"open(string) -- Open the file and create a new document."
);
add_varargs_method("insert",&Module::importer,
add_keyword_method("insert",&Module::importer,
"insert(string,string) -- Insert the file into the given document."
);
// add_varargs_method("openAssembly",&Module::importAssembly,
// "openAssembly(string) -- Open the assembly file and create a new document."
// );
add_varargs_method("export",&Module::exporter,
add_keyword_method("export",&Module::exporter,
"export(list,string) -- Export a list of objects into a single file."
);
add_varargs_method("readDXF",&Module::readDXF,
Expand All @@ -109,11 +124,17 @@ class Module : public Py::ExtensionModule<Module>
virtual ~Module() {}

private:
Py::Object importer(const Py::Tuple& args)
Py::Object importer(const Py::Tuple& args, const Py::Dict &kwds)
{
char* Name;
char* DocName=0;
if (!PyArg_ParseTuple(args.ptr(), "et|s","utf-8",&Name,&DocName))
PyObject *importHidden = Py_None;
PyObject *merge = Py_None;
PyObject *useLinkGroup = Py_None;
int mode = -1;
static char* kwd_list[] = {"name", "docName","importHidden","merge","useLinkGroup","mode",0};
if(!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "et|sOOOi",
kwd_list,"utf-8",&Name,&DocName,&importHidden,&merge,&useLinkGroup,&mode))
throw Py::Exception();

std::string Utf8Name = std::string(Name);
Expand All @@ -135,6 +156,7 @@ class Module : public Py::ExtensionModule<Module>
Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication();
Handle(TDocStd_Document) hDoc;
hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);
ImportOCAFExt ocaf(hDoc, pcDoc, file.fileNamePure());

if (file.hasExtension("stp") || file.hasExtension("step")) {
try {
Expand Down Expand Up @@ -201,19 +223,25 @@ class Module : public Py::ExtensionModule<Module>
}

#if 1
Import::ImportOCAFCmd ocaf(hDoc, pcDoc, file.fileNamePure());
if(merge!=Py_None)
ocaf.setMerge(PyObject_IsTrue(merge));
if(importHidden!=Py_None)
ocaf.setImportHiddenObject(PyObject_IsTrue(importHidden));
if(useLinkGroup!=Py_None)
ocaf.setUseLinkGroup(PyObject_IsTrue(useLinkGroup));
if(mode>=0)
ocaf.setMode(mode);
ocaf.loadShapes();
#else
Import::ImportXCAF xcaf(hDoc, pcDoc, file.fileNamePure());
xcaf.loadShapes();
#endif
pcDoc->recompute();
#endif
hApp->Close(hDoc);

std::map<Part::Feature*, std::vector<App::Color> > colorMap = ocaf.getPartColorsMap();
if (!colorMap.empty()) {
if (!ocaf.partColors.size()) {
Py::List list;
for (auto it : colorMap) {
for (auto &it : ocaf.partColors) {
Py::Tuple tuple(2);
tuple.setItem(0, Py::asObject(it.first->getPyObject()));

Expand All @@ -236,11 +264,16 @@ class Module : public Py::ExtensionModule<Module>

return Py::None();
}
Py::Object exporter(const Py::Tuple& args)
Py::Object exporter(const Py::Tuple& args, const Py::Dict &kwds)
{
PyObject* object;
char* Name;
if (!PyArg_ParseTuple(args.ptr(), "Oet",&object,"utf-8",&Name))
PyObject *exportHidden = Py_None;
PyObject *legacy = Py_None;
PyObject *keepPlacement = Py_None;
static char* kwd_list[] = {"obj", "name", "exportHidden", "legacy", "keepPlacement",0};
if(!PyArg_ParseTupleAndKeywords(args.ptr(), kwds.ptr(), "Oet|OOO",
kwd_list,&object,"utf-8",&Name,&exportHidden,&legacy,&keepPlacement))
throw Py::Exception();

std::string Utf8Name = std::string(Name);
Expand All @@ -253,71 +286,46 @@ class Module : public Py::ExtensionModule<Module>
Handle(TDocStd_Document) hDoc;
hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);

//bool keepExplicitPlacement = list.size() > 1;
bool keepExplicitPlacement = Standard_True;
Import::ExportOCAFCmd ocaf(hDoc, keepExplicitPlacement);

std::map<Part::Feature*, std::vector<App::Color> > partColors;
std::vector<Part::Feature*> partObjects;

std::vector<App::DocumentObject*> objs;
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
PyObject* item = (*it).ptr();
if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
Part::Feature* part = static_cast<Part::Feature*>(obj);
partObjects.push_back(part);
}
else {
Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue());
}
}
else if (PyTuple_Check(item) && PyTuple_Size(item) == 2) {
Py::Tuple tuple(*it);
Py::Object item0 = tuple.getItem(0);
Py::Object item1 = tuple.getItem(1);
if (PyObject_TypeCheck(item0.ptr(), &(App::DocumentObjectPy::Type))) {
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item0.ptr())->getDocumentObjectPtr();
if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
Part::Feature* part = static_cast<Part::Feature*>(obj);
App::PropertyColorList colors;
colors.setPyObject(item1.ptr());

partObjects.push_back(part);
partColors[part] = colors.getValues();
}
else {
Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue());
}
}
}
}

ocaf.setPartColorsMap(partColors);

// That stuff is exporting a list of selected objects into FreeCAD Tree
std::vector <TDF_Label> hierarchical_label;
std::vector <TopLoc_Location> hierarchical_loc;
std::vector <App::DocumentObject*> hierarchical_part;

for (auto it : partObjects) {
ocaf.exportObject(it, hierarchical_label, hierarchical_loc, hierarchical_part);
}

// Free Shapes must have absolute placement and not explicit
std::vector <TDF_Label> FreeLabels;
std::vector <int> part_id;
ocaf.getFreeLabels(hierarchical_label, FreeLabels, part_id);
// Got issue with the colors as they are coming from the View Provider they can't be determined into
// the App Code.
std::vector< std::vector<App::Color> > Colors;
ocaf.getPartColors(hierarchical_part, FreeLabels, part_id, Colors);
ocaf.reallocateFreeShape(hierarchical_part, FreeLabels, part_id, Colors);

if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type)))
objs.push_back(static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr());
}

if(legacy == Py_None) {
auto hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Import");
legacy = hGrp->GetBool("ExportLegacy",false)?Py_True:Py_False;
}

Import::ExportOCAF2 ocaf(hDoc);
if(!PyObject_IsTrue(legacy) || !ocaf.canFallback(objs)) {
if(exportHidden!=Py_None)
ocaf.setExportHiddenObject(PyObject_IsTrue(exportHidden));
if(keepPlacement!=Py_None)
ocaf.setKeepPlacement(PyObject_IsTrue(keepPlacement));
ocaf.exportObjects(objs);
}else{
bool keepExplicitPlacement = objs.size() > 1;
keepExplicitPlacement = Standard_True;
ExportOCAF ocaf(hDoc, keepExplicitPlacement);
// That stuff is exporting a list of selected objects into FreeCAD Tree
std::vector <TDF_Label> hierarchical_label;
std::vector <TopLoc_Location> hierarchical_loc;
std::vector <App::DocumentObject*> hierarchical_part;
for(auto obj : objs)
ocaf.exportObject(obj,hierarchical_label, hierarchical_loc,hierarchical_part);

// Free Shapes must have absolute placement and not explicit
std::vector <TDF_Label> FreeLabels;
std::vector <int> part_id;
ocaf.getFreeLabels(hierarchical_label,FreeLabels, part_id);
#if OCC_VERSION_HEX >= 0x070200
// Update is not performed automatically anymore: https://tracker.dev.opencascade.org/view.php?id=28055
XCAFDoc_DocumentTool::ShapeTool(hDoc->Main())->UpdateAssemblies();
// Update is not performed automatically anymore: https://tracker.dev.opencascade.org/view.php?id=28055
XCAFDoc_DocumentTool::ShapeTool(hDoc->Main())->UpdateAssemblies();
#endif
}

Base::FileInfo file(Utf8Name.c_str());
if (file.hasExtension("stp") || file.hasExtension("step")) {
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Import/App/CMakeLists.txt
Expand Up @@ -31,6 +31,8 @@ SET(Import_SRCS
ExportOCAF.h
ImportOCAF.cpp
ImportOCAF.h
ImportOCAF2.cpp
ImportOCAF2.h
#ImportOCAFAssembly.cpp
#ImportOCAFAssembly.h
StepShapePy.xml
Expand Down
8 changes: 5 additions & 3 deletions src/Mod/Import/App/ImportOCAF.cpp
Expand Up @@ -54,7 +54,9 @@
# include <XCAFDoc_ShapeTool.hxx>
# include <XCAFDoc_ColorTool.hxx>
# include <XCAFDoc_Location.hxx>
# include <XCAFDoc_GraphNode.hxx>
# include <TDF_Label.hxx>
# include <TDF_Tool.hxx>
# include <TDF_LabelSequence.hxx>
# include <TDF_ChildIterator.hxx>
# include <TDataStd_Name.hxx>
Expand All @@ -81,11 +83,14 @@
# endif
#endif

#include <boost/algorithm/string.hpp>
#include <Base/Parameter.h>
#include <Base/Console.h>
#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObjectPy.h>
#include <App/Part.h>
#include <App/Link.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/FeatureCompound.h>
#include "ImportOCAF.h"
Expand All @@ -102,11 +107,8 @@
#include <tbb/task_group.h>
#endif



using namespace Import;


#define OCAF_KEEP_PLACEMENT

ImportOCAF::ImportOCAF(Handle(TDocStd_Document) h, App::Document* d, const std::string& name)
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Import/App/ImportOCAF.h
Expand Up @@ -29,10 +29,12 @@
#include <XCAFDoc_ShapeTool.hxx>
#include <Quantity_Color.hxx>
#include <TopoDS_Shape.hxx>
#include <TDF_LabelMapHasher.hxx>
#include <climits>
#include <string>
#include <set>
#include <map>
#include <unordered_map>
#include <vector>
#include <App/Material.h>
#include <App/Part.h>
Expand Down

0 comments on commit 2f4d10c

Please sign in to comment.