Import: code-refactoring and clean-up

* Add new method ExportOCAF::exportObjects() to avoid code duplication
* Simplify handling of arguments passed to Python handler
* Fix several lint warnings
* Move ImportOCAFExt to the corresponding source files
This commit is contained in:
wmayer
2023-10-01 17:11:28 +02:00
committed by wwmayer
parent 58cc0f2a0d
commit abda1438ad
6 changed files with 105 additions and 101 deletions

View File

@@ -74,22 +74,6 @@
namespace Import
{
class ImportOCAFExt: public Import::ImportOCAF2
{
public:
ImportOCAFExt(Handle(TDocStd_Document) hStdDoc, App::Document* doc, const std::string& name)
: ImportOCAF2(hStdDoc, doc, name)
{}
std::map<Part::Feature*, std::vector<App::Color>> partColors;
private:
void applyFaceColors(Part::Feature* part, const std::vector<App::Color>& colors) override
{
partColors[part] = colors;
}
};
class Module: public Py::ExtensionModule<Module>
{
public:
@@ -126,7 +110,7 @@ public:
private:
Py::Object importer(const Py::Tuple& args, const Py::Dict& kwds)
{
char* Name;
char* Name = nullptr;
char* DocName = nullptr;
PyObject* importHidden = Py_None;
PyObject* merge = Py_None;
@@ -153,7 +137,6 @@ private:
std::string Utf8Name = std::string(Name);
PyMem_Free(Name);
std::string name8bit = Part::encodeFilename(Utf8Name);
try {
Base::FileInfo file(Utf8Name.c_str());
@@ -235,7 +218,7 @@ private:
list.append(tuple);
}
return list;
return list; // NOLINT
}
}
catch (Standard_Failure& e) {
@@ -250,11 +233,11 @@ private:
}
Py::Object exporter(const Py::Tuple& args, const Py::Dict& kwds)
{
PyObject* object;
char* Name;
PyObject* exportHidden = Py_None;
PyObject* legacy = Py_None;
PyObject* keepPlacement = Py_None;
PyObject* object = nullptr;
char* Name = nullptr;
PyObject* pyexportHidden = Py_None;
PyObject* pylegacy = Py_None;
PyObject* pykeepPlacement = Py_None;
static const std::array<const char*, 6> kwd_list {"obj",
"name",
"exportHidden",
@@ -269,68 +252,56 @@ private:
"utf-8",
&Name,
&PyBool_Type,
&exportHidden,
&pyexportHidden,
&PyBool_Type,
&legacy,
&pylegacy,
&PyBool_Type,
&keepPlacement)) {
&pykeepPlacement)) {
throw Py::Exception();
}
std::string Utf8Name = std::string(Name);
PyMem_Free(Name);
// clang-format off
// determine export options
Part::OCAF::ImportExportSettings settings;
bool legacyExport = (pylegacy == Py_None ? settings.getExportLegacy()
: Base::asBoolean(pylegacy));
bool exportHidden = (pyexportHidden == Py_None ? settings.getExportHiddenObject()
: Base::asBoolean(pyexportHidden));
bool keepPlacement = (pykeepPlacement == Py_None ? settings.getExportKeepPlacement()
: Base::asBoolean(pykeepPlacement));
// clang-format on
try {
Py::Sequence list(object);
Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication();
Handle(TDocStd_Document) hDoc;
hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);
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))) {
objs.push_back(
static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr());
auto pydoc = static_cast<App::DocumentObjectPy*>(item);
objs.push_back(pydoc->getDocumentObjectPtr());
}
}
if (legacy == Py_None) {
Part::OCAF::ImportExportSettings settings;
legacy = settings.getExportLegacy() ? Py_True : Py_False;
}
Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication();
Handle(TDocStd_Document) hDoc;
hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);
Import::ExportOCAF2 ocaf(hDoc);
if (!Base::asBoolean(legacy) || !ocaf.canFallback(objs)) {
if (!legacyExport || !ocaf.canFallback(objs)) {
ocaf.setExportOptions(ExportOCAF2::customExportOptions());
if (exportHidden != Py_None) {
ocaf.setExportHiddenObject(Base::asBoolean(exportHidden));
}
if (keepPlacement != Py_None) {
ocaf.setKeepPlacement(Base::asBoolean(keepPlacement));
}
ocaf.setExportHiddenObject(exportHidden);
ocaf.setKeepPlacement(keepPlacement);
ocaf.exportObjects(objs);
}
else {
bool 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);
// Update is not performed automatically anymore:
// https://tracker.dev.opencascade.org/view.php?id=28055
XCAFDoc_DocumentTool::ShapeTool(hDoc->Main())->UpdateAssemblies();
bool keepExplicitPlacement = true;
ExportOCAFCmd ocaf(hDoc, keepExplicitPlacement);
ocaf.exportObjects(objs);
}
Base::FileInfo file(Utf8Name.c_str());
@@ -362,7 +333,7 @@ private:
Py::Object readDXF(const Py::Tuple& args)
{
char* Name;
char* Name = nullptr;
const char* DocName = nullptr;
const char* optionSource = nullptr;
std::string defaultOptions = "User parameter:BaseApp/Preferences/Mod/Draft";
@@ -389,7 +360,7 @@ private:
defaultOptions = optionSource;
}
App::Document* pcDoc;
App::Document* pcDoc = nullptr;
if (DocName) {
pcDoc = App::GetApplication().getDocument(DocName);
}
@@ -419,8 +390,8 @@ private:
Py::Object writeDXFShape(const Py::Tuple& args)
{
PyObject* shapeObj;
char* fname;
PyObject* shapeObj = nullptr;
char* fname = nullptr;
std::string filePath;
std::string layerName;
const char* optionSource = nullptr;
@@ -531,8 +502,8 @@ private:
Py::Object writeDXFObject(const Py::Tuple& args)
{
PyObject* docObj;
char* fname;
PyObject* docObj = nullptr;
char* fname = nullptr;
std::string filePath;
std::string layerName;
const char* optionSource = nullptr;

View File

@@ -67,8 +67,8 @@ static inline Quantity_ColorRGBA convertColor(const App::Color& c)
using namespace Import;
ExportOCAF::ExportOCAF(Handle(TDocStd_Document) h, bool explicitPlacement)
: pDoc(h)
ExportOCAF::ExportOCAF(Handle(TDocStd_Document) hDoc, bool explicitPlacement)
: pDoc(hDoc)
, keepExplicitPlacement(explicitPlacement)
{
aShapeTool = XCAFDoc_DocumentTool::ShapeTool(pDoc->Main());
@@ -129,6 +129,30 @@ std::vector<App::DocumentObject*> ExportOCAF::filterPart(App::Part* part) const
return entries;
}
void ExportOCAF::exportObjects(std::vector<App::DocumentObject*>& objs)
{
// 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) {
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;
getFreeLabels(hierarchical_label, FreeLabels, part_id);
std::vector<std::vector<App::Color>> Colors;
getPartColors(hierarchical_part, FreeLabels, part_id, Colors);
reallocateFreeShape(hierarchical_part, FreeLabels, part_id, Colors);
// Update is not performed automatically anymore:
// https://tracker.dev.opencascade.org/view.php?id=28055
XCAFDoc_DocumentTool::ShapeTool(pDoc->Main())->UpdateAssemblies();
}
int ExportOCAF::exportObject(App::DocumentObject* obj,
std::vector<TDF_Label>& hierarchical_label,
std::vector<TopLoc_Location>& hierarchical_loc,

View File

@@ -57,8 +57,9 @@ namespace Import
class ImportExport ExportOCAF
{
public:
ExportOCAF(Handle(TDocStd_Document) h, bool explicitPlacement);
ExportOCAF(Handle(TDocStd_Document) hDoc, bool explicitPlacement);
virtual ~ExportOCAF();
void exportObjects(std::vector<App::DocumentObject*>& objs);
int exportObject(App::DocumentObject* obj,
std::vector<TDF_Label>& hierarchical_label,
std::vector<TopLoc_Location>& hierarchical_loc,

View File

@@ -1004,6 +1004,19 @@ bool ImportOCAF2::createAssembly(App::Document* _doc,
// ----------------------------------------------------------------------------
ImportOCAFExt::ImportOCAFExt(Handle(TDocStd_Document) hStdDoc,
App::Document* doc,
const std::string& name)
: ImportOCAF2(hStdDoc, doc, name)
{}
void ImportOCAFExt::applyFaceColors(Part::Feature* part, const std::vector<App::Color>& colors)
{
partColors[part] = colors;
}
// ----------------------------------------------------------------------------
ExportOCAFOptions::ExportOCAFOptions()
{
defaultColor.setPackedValue(0xCCCCCC00);

View File

@@ -228,6 +228,17 @@ private:
Base::SequencerLauncher* sequencer {nullptr};
};
class ImportExport ImportOCAFExt: public ImportOCAF2
{
public:
ImportOCAFExt(Handle(TDocStd_Document) hStdDoc, App::Document* doc, const std::string& name);
std::map<Part::Feature*, std::vector<App::Color>> partColors;
private:
void applyFaceColors(Part::Feature* part, const std::vector<App::Color>& colors) override;
};
struct ImportExport ExportOCAFOptions
{
ExportOCAFOptions();

View File

@@ -589,16 +589,18 @@ private:
std::string Utf8Name = std::string(Name);
PyMem_Free(Name);
// clang-format off
// determine export options
Part::OCAF::ImportExportSettings settings;
// still support old way
bool legacyExport =
(pylegacy == Py_None ? settings.getExportLegacy() : Base::asBoolean(pylegacy));
bool exportHidden = (pyexportHidden == Py_None ? settings.getExportHiddenObject()
: Base::asBoolean(pyexportHidden));
bool legacyExport = (pylegacy == Py_None ? settings.getExportLegacy()
: Base::asBoolean(pylegacy));
bool exportHidden = (pyexportHidden == Py_None ? settings.getExportHiddenObject()
: Base::asBoolean(pyexportHidden));
bool keepPlacement = (pykeepPlacement == Py_None ? settings.getExportKeepPlacement()
: Base::asBoolean(pykeepPlacement));
// clang-format on
// new way
if (pyoptions) {
@@ -616,19 +618,19 @@ private:
try {
Py::Sequence list(object);
Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication();
Handle(TDocStd_Document) hDoc;
hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);
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))) {
objs.push_back(
static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr());
auto pydoc = static_cast<App::DocumentObjectPy*>(item);
objs.push_back(pydoc->getDocumentObjectPtr());
}
}
Handle(XCAFApp_Application) hApp = XCAFApp_Application::GetApplication();
Handle(TDocStd_Document) hDoc;
hApp->NewDocument(TCollection_ExtendedString("MDTV-CAF"), hDoc);
Import::ExportOCAF2 ocaf(hDoc, &getShapeColors);
if (!legacyExport || !ocaf.canFallback(objs)) {
ocaf.setExportOptions(Import::ExportOCAF2::customExportOptions());
@@ -638,27 +640,9 @@ private:
ocaf.exportObjects(objs);
}
else {
bool keepExplicitPlacement = Standard_True;
bool keepExplicitPlacement = true;
ExportOCAFGui 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);
// 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);
XCAFDoc_DocumentTool::ShapeTool(hDoc->Main())->UpdateAssemblies();
ocaf.exportObjects(objs);
}
Base::FileInfo file(Utf8Name.c_str());