fixes 0003491: Import.export not preserving placement of Part Features in STP file export
This commit is contained in:
@@ -252,7 +252,10 @@ private:
|
||||
|
||||
bool keepExplicitPlacement = list.size() > 1;
|
||||
keepExplicitPlacement = Standard_True;
|
||||
Import::ExportOCAF ocaf(hDoc, keepExplicitPlacement);
|
||||
Import::ExportOCAFCmd ocaf(hDoc, keepExplicitPlacement);
|
||||
|
||||
std::map<Part::Feature*, std::vector<App::Color> > partColors;
|
||||
std::vector<Part::Feature*> partObjects;
|
||||
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
PyObject* item = (*it).ptr();
|
||||
@@ -260,11 +263,7 @@ private:
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
|
||||
if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
Part::Feature* part = static_cast<Part::Feature*>(obj);
|
||||
std::vector<App::Color> colors;
|
||||
std::vector <TDF_Label> hierarchical_label;
|
||||
std::vector <TopLoc_Location> hierarchical_loc;
|
||||
std::vector <App::DocumentObject*> hierarchical_part;
|
||||
ocaf.saveShape(part, colors, hierarchical_label, hierarchical_loc, hierarchical_part);
|
||||
partObjects.push_back(part);
|
||||
}
|
||||
else {
|
||||
Base::Console().Message("'%s' is not a shape, export will be ignored.\n", obj->Label.getValue());
|
||||
@@ -280,10 +279,9 @@ private:
|
||||
Part::Feature* part = static_cast<Part::Feature*>(obj);
|
||||
App::PropertyColorList colors;
|
||||
colors.setPyObject(item1.ptr());
|
||||
std::vector <TDF_Label> hierarchical_label;
|
||||
std::vector <TopLoc_Location> hierarchical_loc;
|
||||
std::vector <App::DocumentObject*> hierarchical_part;
|
||||
ocaf.saveShape(part, colors.getValues(), hierarchical_label, hierarchical_loc, hierarchical_part);
|
||||
|
||||
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());
|
||||
@@ -292,10 +290,38 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
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 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();
|
||||
#endif
|
||||
|
||||
Base::FileInfo file(Utf8Name.c_str());
|
||||
if (file.hasExtension("stp") || file.hasExtension("step")) {
|
||||
//Interface_Static::SetCVal("write.step.schema", "AP214IS");
|
||||
STEPCAFControl_Writer writer;
|
||||
Interface_Static::SetIVal("write.step.assembly",1);
|
||||
// writer.SetColorMode(Standard_False);
|
||||
writer.Transfer(hDoc, STEPControl_AsIs);
|
||||
|
||||
// edit STEP header
|
||||
|
||||
@@ -507,9 +507,52 @@ ExportOCAF::ExportOCAF(Handle(TDocStd_Document) h, bool explicitPlacement)
|
||||
}
|
||||
}
|
||||
|
||||
ExportOCAF::~ExportOCAF()
|
||||
{
|
||||
}
|
||||
|
||||
int ExportOCAF::exportObject(App::DocumentObject* obj,
|
||||
std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TopLoc_Location>& hierarchical_loc,
|
||||
std::vector <App::DocumentObject*>& hierarchical_part)
|
||||
{
|
||||
std::vector <int> local_label;
|
||||
int root_id;
|
||||
int return_label = -1;
|
||||
|
||||
if (obj->getTypeId().isDerivedFrom(App::Part::getClassTypeId())) {
|
||||
App::Part* part = static_cast<App::Part*>(obj);
|
||||
// I shall recusrively select the elements and call back
|
||||
std::vector<App::DocumentObject*> entries = part->Group.getValues();
|
||||
std::vector<App::DocumentObject*>::iterator it;
|
||||
|
||||
for ( it = entries.begin(); it != entries.end(); it++ ) {
|
||||
int new_label=0;
|
||||
new_label = exportObject((*it), hierarchical_label, hierarchical_loc, hierarchical_part);
|
||||
local_label.push_back(new_label);
|
||||
}
|
||||
|
||||
createNode(part,root_id, hierarchical_label, hierarchical_loc, hierarchical_part);
|
||||
std::vector<int>::iterator label_it;
|
||||
for (label_it = local_label.begin(); label_it != local_label.end(); ++label_it) {
|
||||
pushNode(root_id,(*label_it), hierarchical_label,hierarchical_loc);
|
||||
}
|
||||
|
||||
return_label = root_id;
|
||||
}
|
||||
|
||||
if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
Part::Feature* part = static_cast<Part::Feature*>(obj);
|
||||
std::vector<App::Color> colors;
|
||||
findColors(part, colors);
|
||||
|
||||
return_label = saveShape(part, colors, hierarchical_label, hierarchical_loc, hierarchical_part);
|
||||
}
|
||||
|
||||
return return_label;
|
||||
}
|
||||
|
||||
// This function creates an Assembly node in an XCAF document with its relative placement information
|
||||
|
||||
void ExportOCAF::createNode(App::Part* part, int& root_id,
|
||||
std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TopLoc_Location>& hierarchical_loc,
|
||||
@@ -657,6 +700,21 @@ void ExportOCAF::getFreeLabels(std::vector <TDF_Label>& hierarchical_label,
|
||||
}
|
||||
}
|
||||
|
||||
void ExportOCAF::getPartColors(std::vector <App::DocumentObject*> hierarchical_part,
|
||||
std::vector <TDF_Label> FreeLabels,
|
||||
std::vector <int> part_id,
|
||||
std::vector < std::vector<App::Color> >& Colors) const
|
||||
{
|
||||
// I am seeking for the colors of each parts
|
||||
std::size_t n = FreeLabels.size();
|
||||
for (std::size_t i = 0; i < n; i++) {
|
||||
std::vector<App::Color> colors;
|
||||
Part::Feature * part = static_cast<Part::Feature *>(hierarchical_part.at(part_id.at(i)));
|
||||
findColors(part, colors);
|
||||
Colors.push_back(colors);
|
||||
}
|
||||
}
|
||||
|
||||
void ExportOCAF::reallocateFreeShape(std::vector <App::DocumentObject*> hierarchical_part,
|
||||
std::vector <TDF_Label> FreeLabels,
|
||||
std::vector <int> part_id,
|
||||
@@ -720,11 +778,7 @@ void ExportOCAF::reallocateFreeShape(std::vector <App::DocumentObject*> hierarch
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// This function is moving a "standard" node into an Assembly node within an XCAF doc
|
||||
|
||||
void ExportOCAF::pushNode(int root_id, int node_id, std::vector <TDF_Label>& hierarchical_label,std::vector <TopLoc_Location>& hierarchical_loc)
|
||||
{
|
||||
TDF_Label root;
|
||||
@@ -737,6 +791,20 @@ void ExportOCAF::pushNode(int root_id, int node_id, std::vector <TDF_Label>& hie
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ExportOCAFCmd::ExportOCAFCmd(Handle(TDocStd_Document) h, bool explicitPlacement)
|
||||
: ExportOCAF(h, explicitPlacement)
|
||||
{
|
||||
}
|
||||
|
||||
void ExportOCAFCmd::findColors(Part::Feature* part, std::vector<App::Color>& colors) const
|
||||
{
|
||||
std::map<Part::Feature*, std::vector<App::Color> >::const_iterator it = partColors.find(part);
|
||||
if (it != partColors.end())
|
||||
colors = it->second;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ImportXCAF::ImportXCAF(Handle(TDocStd_Document) h, App::Document* d, const std::string& name)
|
||||
: hdoc(h), doc(d), default_name(name)
|
||||
{
|
||||
|
||||
@@ -95,15 +95,20 @@ private:
|
||||
class ImportExport ExportOCAF
|
||||
{
|
||||
public:
|
||||
void createNode(App::Part* part, int& root_it,
|
||||
std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TopLoc_Location>& hierarchical_loc,
|
||||
std::vector <App::DocumentObject*>& hierarchical_part);
|
||||
ExportOCAF(Handle(TDocStd_Document) h, bool explicitPlacement);
|
||||
virtual ~ExportOCAF();
|
||||
int exportObject(App::DocumentObject* obj,
|
||||
std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TopLoc_Location>& hierarchical_loc,
|
||||
std::vector <App::DocumentObject*>& hierarchical_part);
|
||||
int saveShape(Part::Feature* part, const std::vector<App::Color>&,
|
||||
std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TopLoc_Location>& hierarchical_loc,
|
||||
std::vector <App::DocumentObject*>& hierarchical_part);
|
||||
void getPartColors(std::vector <App::DocumentObject*> hierarchical_part,
|
||||
std::vector <TDF_Label> FreeLabels,
|
||||
std::vector <int> part_id,
|
||||
std::vector < std::vector<App::Color> >& Colors) const;
|
||||
void reallocateFreeShape(std::vector <App::DocumentObject*> hierarchical_part,
|
||||
std::vector <TDF_Label> FreeLabels,
|
||||
std::vector <int> part_id,
|
||||
@@ -111,9 +116,16 @@ public:
|
||||
void getFreeLabels(std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TDF_Label>& labels,
|
||||
std::vector <int>& label_part_id);
|
||||
void createNode(App::Part* part, int& root_it,
|
||||
std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TopLoc_Location>& hierarchical_loc,
|
||||
std::vector <App::DocumentObject*>& hierarchical_part);
|
||||
void pushNode(int root, int node, std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TopLoc_Location>& hierarchical_loc);
|
||||
|
||||
private:
|
||||
virtual void findColors(Part::Feature*, std::vector<App::Color>&) const {}
|
||||
|
||||
private:
|
||||
Handle(TDocStd_Document) pDoc;
|
||||
Handle(XCAFDoc_ShapeTool) aShapeTool;
|
||||
@@ -122,6 +134,21 @@ private:
|
||||
bool keepExplicitPlacement;
|
||||
};
|
||||
|
||||
class ImportExport ExportOCAFCmd : public ExportOCAF
|
||||
{
|
||||
public:
|
||||
ExportOCAFCmd(Handle(TDocStd_Document) h, bool explicitPlacement);
|
||||
void setPartColorsMap(const std::map<Part::Feature*, std::vector<App::Color> >& colors) {
|
||||
partColors = colors;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void findColors(Part::Feature*, std::vector<App::Color>&) const;
|
||||
|
||||
private:
|
||||
std::map<Part::Feature*, std::vector<App::Color> > partColors;
|
||||
};
|
||||
|
||||
|
||||
class ImportXCAF
|
||||
{
|
||||
|
||||
@@ -271,10 +271,10 @@ void OCAFBrowser::load(const TDF_Label& label, QTreeWidgetItem* item, const QStr
|
||||
}
|
||||
}
|
||||
|
||||
class ImportOCAFExt : public Import::ImportOCAF
|
||||
class ImportOCAFGui : public Import::ImportOCAF
|
||||
{
|
||||
public:
|
||||
ImportOCAFExt(Handle(TDocStd_Document) h, App::Document* d, const std::string& name)
|
||||
ImportOCAFGui(Handle(TDocStd_Document) h, App::Document* d, const std::string& name)
|
||||
: ImportOCAF(h, d, name)
|
||||
{
|
||||
}
|
||||
@@ -290,6 +290,24 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
class ExportOCAFGui : public Import::ExportOCAF
|
||||
{
|
||||
public:
|
||||
ExportOCAFGui(Handle(TDocStd_Document) h, bool explicitPlacement)
|
||||
: ExportOCAF(h, explicitPlacement)
|
||||
{
|
||||
}
|
||||
virtual void findColors(Part::Feature* part, std::vector<App::Color>& colors) const
|
||||
{
|
||||
Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part);
|
||||
if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) {
|
||||
colors = static_cast<PartGui::ViewProviderPartExt*>(vp)->DiffuseColor.getValues();
|
||||
if (colors.empty())
|
||||
colors.push_back(static_cast<PartGui::ViewProviderPart*>(vp)->ShapeColor.getValue());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace ImportGui {
|
||||
class Module : public Py::ExtensionModule<Module>
|
||||
{
|
||||
@@ -412,7 +430,7 @@ private:
|
||||
throw Py::Exception(Base::BaseExceptionFreeCADError, "no supported file format");
|
||||
}
|
||||
|
||||
ImportOCAFExt ocaf(hDoc, pcDoc, file.fileNamePure());
|
||||
ImportOCAFGui ocaf(hDoc, pcDoc, file.fileNamePure());
|
||||
// We must recompute the doc before loading shapes as they are going to be
|
||||
// inserted into the document and computed at the same time so we are going to
|
||||
// purge the document before recomputing it to clear it and settle it in the proper
|
||||
@@ -434,70 +452,6 @@ private:
|
||||
|
||||
return Py::None();
|
||||
}
|
||||
int export_app_object(App::DocumentObject* obj, Import::ExportOCAF ocaf,
|
||||
std::vector <TDF_Label>& hierarchical_label,
|
||||
std::vector <TopLoc_Location>& hierarchical_loc,
|
||||
std::vector <App::DocumentObject*>& hierarchical_part)
|
||||
{
|
||||
std::vector <int> local_label;
|
||||
int root_id;
|
||||
int return_label = -1;
|
||||
|
||||
|
||||
if (obj->getTypeId().isDerivedFrom(App::Part::getClassTypeId())) {
|
||||
App::Part* part = static_cast<App::Part*>(obj);
|
||||
// I shall recusrively select the elements and call back
|
||||
std::vector<App::DocumentObject*> entries = part->Group.getValues();
|
||||
std::vector<App::DocumentObject*>::iterator it;
|
||||
|
||||
for ( it = entries.begin(); it != entries.end(); it++ ) {
|
||||
int new_label=0;
|
||||
new_label=export_app_object((*it),ocaf,hierarchical_label,hierarchical_loc, hierarchical_part);
|
||||
local_label.push_back(new_label);
|
||||
}
|
||||
|
||||
ocaf.createNode(part,root_id,hierarchical_label,hierarchical_loc, hierarchical_part);
|
||||
std::vector<int>::iterator label_it;
|
||||
for (label_it = local_label.begin(); label_it != local_label.end(); ++label_it) {
|
||||
ocaf.pushNode(root_id,(*label_it), hierarchical_label,hierarchical_loc);
|
||||
}
|
||||
|
||||
return_label=root_id;
|
||||
}
|
||||
|
||||
if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) {
|
||||
Part::Feature* part = static_cast<Part::Feature*>(obj);
|
||||
std::vector<App::Color> colors;
|
||||
Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part);
|
||||
if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) {
|
||||
colors = static_cast<PartGui::ViewProviderPartExt*>(vp)->DiffuseColor.getValues();
|
||||
if (colors.empty())
|
||||
colors.push_back(static_cast<PartGui::ViewProviderPart*>(vp)->ShapeColor.getValue());
|
||||
}
|
||||
|
||||
return_label=ocaf.saveShape(part, colors, hierarchical_label, hierarchical_loc, hierarchical_part);
|
||||
}
|
||||
|
||||
return(return_label);
|
||||
}
|
||||
|
||||
void get_parts_colors(std::vector <App::DocumentObject*> hierarchical_part, std::vector <TDF_Label> FreeLabels,
|
||||
std::vector <int> part_id, std::vector< std::vector<App::Color> >& Colors)
|
||||
{
|
||||
// I am seeking for the colors of each parts
|
||||
int n = FreeLabels.size();
|
||||
for (int i = 0; i < n; i++) {
|
||||
std::vector<App::Color> colors;
|
||||
Part::Feature * part = static_cast<Part::Feature *>(hierarchical_part.at(part_id.at(i)));
|
||||
Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(part);
|
||||
if (vp && vp->isDerivedFrom(PartGui::ViewProviderPartExt::getClassTypeId())) {
|
||||
colors = static_cast<PartGui::ViewProviderPartExt*>(vp)->DiffuseColor.getValues();
|
||||
if (colors.empty())
|
||||
colors.push_back(static_cast<PartGui::ViewProviderPart*>(vp)->ShapeColor.getValue());
|
||||
Colors.push_back(colors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Py::Object exporter(const Py::Tuple& args)
|
||||
{
|
||||
@@ -518,7 +472,7 @@ private:
|
||||
|
||||
bool keepExplicitPlacement = list.size() > 1;
|
||||
keepExplicitPlacement = Standard_True;
|
||||
Import::ExportOCAF ocaf(hDoc, keepExplicitPlacement);
|
||||
ExportOCAFGui ocaf(hDoc, keepExplicitPlacement);
|
||||
|
||||
// That stuff is exporting a list of selected objects into FreeCAD Tree
|
||||
std::vector <TDF_Label> hierarchical_label;
|
||||
@@ -529,19 +483,19 @@ private:
|
||||
PyObject* item = (*it).ptr();
|
||||
if (PyObject_TypeCheck(item, &(App::DocumentObjectPy::Type))) {
|
||||
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(item)->getDocumentObjectPtr();
|
||||
export_app_object(obj,ocaf, hierarchical_label, hierarchical_loc,hierarchical_part);
|
||||
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);
|
||||
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;
|
||||
get_parts_colors(hierarchical_part,FreeLabels,part_id,Colors);
|
||||
ocaf.reallocateFreeShape(hierarchical_part,FreeLabels,part_id,Colors);
|
||||
ocaf.getPartColors(hierarchical_part, FreeLabels, part_id, Colors);
|
||||
ocaf.reallocateFreeShape(hierarchical_part, FreeLabels, part_id, Colors);
|
||||
|
||||
#if OCC_VERSION_HEX >= 0x070200
|
||||
// Update is not performed automatically anymore: https://tracker.dev.opencascade.org/view.php?id=28055
|
||||
@@ -571,12 +525,12 @@ private:
|
||||
Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter()
|
||||
.GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part")->GetGroup("STEP");
|
||||
|
||||
makeHeader.SetName(new TCollection_HAsciiString((Standard_CString)(Utf8Name.c_str())));
|
||||
makeHeader.SetName(new TCollection_HAsciiString((Standard_CString)Utf8Name.c_str()));
|
||||
makeHeader.SetAuthorValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Author", "Author").c_str()));
|
||||
makeHeader.SetOrganizationValue (1, new TCollection_HAsciiString(hGrp->GetASCII("Company").c_str()));
|
||||
makeHeader.SetOriginatingSystem(new TCollection_HAsciiString(App::GetApplication().getExecutableName()));
|
||||
makeHeader.SetDescriptionValue(1, new TCollection_HAsciiString("FreeCAD Model"));
|
||||
IFSelect_ReturnStatus ret = writer.Write((const char*)name8bit.c_str());
|
||||
IFSelect_ReturnStatus ret = writer.Write(name8bit.c_str());
|
||||
if (ret == IFSelect_RetError || ret == IFSelect_RetFail || ret == IFSelect_RetStop) {
|
||||
PyErr_Format(PyExc_IOError, "Cannot open file '%s'", Utf8Name.c_str());
|
||||
throw Py::Exception();
|
||||
@@ -606,6 +560,7 @@ private:
|
||||
catch (const Base::Exception& e) {
|
||||
throw Py::RuntimeError(e.what());
|
||||
}
|
||||
|
||||
return Py::None();
|
||||
}
|
||||
Py::Object ocaf(const Py::Tuple& args)
|
||||
|
||||
Reference in New Issue
Block a user