/*************************************************************************** * Copyright (c) 2013 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #if defined(__MINGW32__) # define WNT // avoid conflict with GUID #endif #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include # include # include # include // for Precision::Confusion() # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #if OCC_VERSION_HEX >= 0x060500 # include # else # include # endif #endif #include #include #include #include #include #include #include #include "ExportOCAF.h" #include #include #include #include #include using namespace Import; ExportOCAF::ExportOCAF(Handle(TDocStd_Document) h, bool explicitPlacement) : pDoc(h) , keepExplicitPlacement(explicitPlacement) , filterBaseFeature(true) { aShapeTool = XCAFDoc_DocumentTool::ShapeTool(pDoc->Main()); aColorTool = XCAFDoc_DocumentTool::ColorTool(pDoc->Main()); if (keepExplicitPlacement) { // rootLabel = aShapeTool->NewShape(); // TDataStd_Name::Set(rootLabel, "ASSEMBLY"); Interface_Static::SetIVal("write.step.assembly",2); } else { rootLabel = TDF_TagSource::NewChild(pDoc->Main()); } } ExportOCAF::~ExportOCAF() { } std::vector ExportOCAF::filterPart(App::Part* part) const { // Ignore shape of a Part that is referenced by a FeatureBase (#0003807) // std::vector entries = part->Group.getValues(); // get FeatureBases of the out-lists of the features of the Part Base::Type featureBase = Base::Type::fromName("PartDesign::FeatureBase"); std::vector filterType; for (auto it : entries) { std::vector outList = it->getOutList(); for (auto jt : outList) { if (jt->getTypeId() == featureBase) { filterType.push_back(jt); } } } // now check if for a feature of the Part it must be filtered if (!filterType.empty()) { std::vector keepObjects; for (auto it : entries) { std::vector inList = it->getInList(); bool accept = true; for (auto jt : inList) { auto kt = std::find(filterType.begin(), filterType.end(), jt); if (kt != filterType.end()) { accept = false; break; } } if (accept) keepObjects.push_back(it); } entries.swap(keepObjects); } return entries; } int ExportOCAF::exportObject(App::DocumentObject* obj, std::vector & hierarchical_label, std::vector & hierarchical_loc, std::vector & hierarchical_part) { std::vector local_label; int root_id; int return_label = -1; if (obj->getTypeId().isDerivedFrom(App::Part::getClassTypeId())) { App::Part* part = static_cast(obj); // I shall recursively select the elements and call back std::vector entries = part->Group.getValues(); std::vector::iterator it; if (filterBaseFeature) { entries = filterPart(part); } 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::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(obj); std::vector 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 & hierarchical_label, std::vector & hierarchical_loc, std::vector & hierarchical_part) { TDF_Label shapeLabel = aShapeTool->NewShape(); Handle(TDataStd_Name) N; TDataStd_Name::Set(shapeLabel, TCollection_ExtendedString(part->Label.getValue(), 1)); Base::Placement pl = part->Placement.getValue(); Base::Rotation rot(pl.getRotation()); Base::Vector3d axis; double angle; rot.getValue(axis, angle); gp_Trsf trf; trf.SetRotation(gp_Ax1(gp_Pnt(), gp_Dir(axis.x, axis.y, axis.z)), angle); trf.SetTranslationPart(gp_Vec(pl.getPosition().x,pl.getPosition().y,pl.getPosition().z)); TopLoc_Location MyLoc = TopLoc_Location(trf); XCAFDoc_Location::Set(shapeLabel,TopLoc_Location(trf)); hierarchical_label.push_back(shapeLabel); hierarchical_loc.push_back(MyLoc); hierarchical_part.push_back(part); root_id=hierarchical_label.size(); } int ExportOCAF::saveShape(Part::Feature* part, const std::vector& colors, std::vector & hierarchical_label, std::vector & hierarchical_loc, std::vector & hierarchical_part) { const TopoDS_Shape& shape = part->Shape.getValue(); if (shape.IsNull()) return -1; TopoDS_Shape baseShape; TopLoc_Location aLoc; Handle(TDataStd_Name) N; Base::Placement pl = part->Placement.getValue(); Base::Rotation rot(pl.getRotation()); Base::Vector3d axis; double angle; rot.getValue(axis, angle); gp_Trsf trf; trf.SetRotation(gp_Ax1(gp_Pnt(0.,0.,0.), gp_Dir(axis.x, axis.y, axis.z)), angle); trf.SetTranslationPart(gp_Vec(pl.getPosition().x,pl.getPosition().y,pl.getPosition().z)); TopLoc_Location MyLoc = TopLoc_Location(trf); if (keepExplicitPlacement) { // http://www.opencascade.org/org/forum/thread_18813/?forum=3 aLoc = shape.Location(); baseShape = shape.Located(TopLoc_Location()); } else { baseShape = shape; } // Add shape and name TDF_Label shapeLabel = aShapeTool->NewShape(); aShapeTool->SetShape(shapeLabel, baseShape); TDataStd_Name::Set(shapeLabel, TCollection_ExtendedString(part->Label.getValue(), 1)); /* if (keepExplicitPlacement) { aShapeTool->AddComponent(aShapeTool->BaseLabel(), shapeLabel, aLoc); XCAFDoc_Location::Set(shapeLabel,MyLoc); } */ // Add color information Quantity_Color col; std::set face_index; TopTools_IndexedMapOfShape faces; TopExp_Explorer xp(baseShape,TopAbs_FACE); while (xp.More()) { face_index.insert(faces.Add(xp.Current())); xp.Next(); } // define color per face? if (colors.size() == face_index.size()) { xp.Init(baseShape,TopAbs_FACE); while (xp.More()) { int index = faces.FindIndex(xp.Current()); if (face_index.find(index) != face_index.end()) { face_index.erase(index); // If the baseShape is a face then since OCCT 7.3 AddSubShape() returns // a null label. // If faceLabel is null we check if for the current face a label already // exists. If yes then faceLabel is equal to shapeLabel. TDF_Label faceLabel = aShapeTool->AddSubShape(shapeLabel, xp.Current()); // TDF_Label faceLabel= TDF_TagSource::NewChild(shapeLabel); if (!faceLabel.IsNull()) { aShapeTool->SetShape(faceLabel, xp.Current()); } else { aShapeTool->FindShape(xp.Current(), faceLabel); } if (!faceLabel.IsNull()) { const App::Color& color = colors[index-1]; Standard_Real mat[3]; mat[0] = color.r; mat[1] = color.g; mat[2] = color.b; col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf); } } xp.Next(); } } else if (!colors.empty()) { App::Color color = colors.front(); Standard_Real mat[3]; mat[0] = color.r; mat[1] = color.g; mat[2] = color.b; col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); aColorTool->SetColor(shapeLabel, col, XCAFDoc_ColorGen); } hierarchical_label.push_back(shapeLabel); hierarchical_loc.push_back(MyLoc); hierarchical_part.push_back(part); return(hierarchical_label.size()); } // This function is scanning the OCAF doc for Free Shapes and returns the label attached to it // If this Free Shapes are regular Part::Feature, we must use absolute coordinate instead of // allocating a placement into the hierarchy as it is not attached to a hierarchical node void ExportOCAF::getFreeLabels(std::vector & hierarchical_label, std::vector & labels, std::vector & label_part_id) { TDF_LabelSequence FreeLabels; aShapeTool->GetFreeShapes(FreeLabels); int n = FreeLabels.Length(); for (int i = 1; i <= n; i++) { TDF_Label label = FreeLabels.Value(i); for (std::size_t j = 0; j < hierarchical_label.size(); j++) { if (label == hierarchical_label.at(j)) { labels.push_back(label); label_part_id.push_back(j); } } } } void ExportOCAF::getPartColors(std::vector hierarchical_part, std::vector FreeLabels, std::vector part_id, std::vector < std::vector >& 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 colors; Part::Feature * part = static_cast(hierarchical_part.at(part_id.at(i))); findColors(part, colors); Colors.push_back(colors); } } void ExportOCAF::reallocateFreeShape(std::vector hierarchical_part, std::vector FreeLabels, std::vector part_id, std::vector< std::vector >& Colors) { std::size_t n = FreeLabels.size(); for (std::size_t i = 0; i < n; i++) { TDF_Label label = FreeLabels.at(i); // hierarchical part does contain only part currently and not node I should add node if (hierarchical_part.at(part_id.at(i))->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { Part::Feature * part = static_cast(hierarchical_part.at(part_id.at(i))); aShapeTool->SetShape(label, part->Shape.getValue()); // Add color information std::vector colors; colors=Colors.at(i); TopoDS_Shape baseShape = part->Shape.getValue(); // Add color information Quantity_Color col; std::set face_index; TopTools_IndexedMapOfShape faces; TopExp_Explorer xp(baseShape,TopAbs_FACE); while (xp.More()) { face_index.insert(faces.Add(xp.Current())); xp.Next(); } // define color per face? if (colors.size() == face_index.size()) { xp.Init(baseShape,TopAbs_FACE); while (xp.More()) { int index = faces.FindIndex(xp.Current()); if (face_index.find(index) != face_index.end()) { face_index.erase(index); // If the baseShape is a face then since OCCT 7.3 AddSubShape() returns // a null label. // If faceLabel is null we check if for the current face a label already // exists. If yes then faceLabel is equal to label. TDF_Label faceLabel = aShapeTool->AddSubShape(label, xp.Current()); // TDF_Label faceLabel= TDF_TagSource::NewChild(label); if (!faceLabel.IsNull()) { aShapeTool->SetShape(faceLabel, xp.Current()); } else { aShapeTool->FindShape(xp.Current(), faceLabel); } if (!faceLabel.IsNull()) { const App::Color& color = colors[index-1]; Standard_Real mat[3]; mat[0] = color.r; mat[1] = color.g; mat[2] = color.b; col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); aColorTool->SetColor(faceLabel, col, XCAFDoc_ColorSurf); } } xp.Next(); } } else if (!colors.empty()) { App::Color color = colors.front(); Standard_Real mat[3]; mat[0] = color.r; mat[1] = color.g; mat[2] = color.b; col.SetValues(mat[0],mat[1],mat[2],Quantity_TOC_RGB); aColorTool->SetColor(label, col, XCAFDoc_ColorGen); } } } } // 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 & hierarchical_label,std::vector & hierarchical_loc) { TDF_Label root; TDF_Label node; root = hierarchical_label.at(root_id-1); node = hierarchical_label.at(node_id-1); XCAFDoc_DocumentTool::ShapeTool(root)->AddComponent(root, node, hierarchical_loc.at(node_id-1)); } // ---------------------------------------------------------------------------- ExportOCAFCmd::ExportOCAFCmd(Handle(TDocStd_Document) h, bool explicitPlacement) : ExportOCAF(h, explicitPlacement) { } void ExportOCAFCmd::findColors(Part::Feature* part, std::vector& colors) const { std::map >::const_iterator it = partColors.find(part); if (it != partColors.end()) colors = it->second; }