Download src/Mod/Import/App/ImportOCAF2.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 29.8 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Import/App/ImportOCAF2.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Import/App/ImportOCAF2.cpp
-
curl -L -o ImportOCAF2.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Import/App/ImportOCAF2.cpp
29.8 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /**************************************************************************** | |
| * Copyright (c) 2018 Zheng, Lei (realthunder) <realthunder.dev@gmail.com>* | |
| * * | |
| * 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 * | |
| * * | |
| ****************************************************************************/ | |
| // See https://dev.opencascade.org/content/occt-3d-viewer-becomes-srgb-aware | |
| FC_LOG_LEVEL_INIT("Import", true, true) | |
| using namespace Import; | |
| ImportOCAFOptions::ImportOCAFOptions() | |
| { | |
| defaultFaceColor.setPackedValue(0xCCCCCC00); | |
| defaultFaceColor.a = 1.0F; | |
| defaultEdgeColor.setPackedValue(421075455UL); | |
| defaultEdgeColor.a = 1.0F; | |
| } | |
| ImportOCAF2::ImportOCAF2(Handle(TDocStd_Document) hDoc, App::Document* doc, const std::string& name) | |
| : pDoc(hDoc) | |
| , pDocument(doc) | |
| , default_name(name) | |
| { | |
| aShapeTool = XCAFDoc_DocumentTool::ShapeTool(pDoc->Main()); | |
| aColorTool = XCAFDoc_DocumentTool::ColorTool(pDoc->Main()); | |
| if (pDocument->isSaved()) { | |
| Base::FileInfo fi(pDocument->FileName.getValue()); | |
| filePath = fi.dirPath(); | |
| } | |
| setUseLinkGroup(options.useLinkGroup); | |
| } | |
| ImportOCAF2::~ImportOCAF2() = default; | |
| ImportOCAFOptions ImportOCAF2::customImportOptions() | |
| { | |
| Part::OCAF::ImportExportSettings settings; | |
| ImportOCAFOptions defaultOptions; | |
| defaultOptions.merge = settings.getReadShapeCompoundMode(); | |
| defaultOptions.useLinkGroup = settings.getUseLinkGroup(); | |
| defaultOptions.useBaseName = settings.getUseBaseName(); | |
| defaultOptions.importHidden = settings.getImportHiddenObject(); | |
| defaultOptions.reduceObjects = settings.getReduceObjects(); | |
| defaultOptions.showProgress = settings.getShowProgress(); | |
| defaultOptions.expandCompound = settings.getExpandCompound(); | |
| defaultOptions.mode = static_cast<int>(settings.getImportMode()); | |
| auto hGrp = App::GetApplication().GetParameterGroupByPath( | |
| "User parameter:BaseApp/Preferences/View" | |
| ); | |
| defaultOptions.defaultFaceColor.setPackedValue( | |
| hGrp->GetUnsigned("DefaultShapeColor", defaultOptions.defaultFaceColor.getPackedValue()) | |
| ); | |
| defaultOptions.defaultFaceColor.a = 1.0F; | |
| defaultOptions.defaultEdgeColor.setPackedValue( | |
| hGrp->GetUnsigned("DefaultShapeLineColor", defaultOptions.defaultEdgeColor.getPackedValue()) | |
| ); | |
| defaultOptions.defaultEdgeColor.a = 1.0F; | |
| return defaultOptions; | |
| } | |
| void ImportOCAF2::setImportOptions(ImportOCAFOptions opts) | |
| { | |
| options = opts; | |
| setUseLinkGroup(options.useLinkGroup); | |
| } | |
| void ImportOCAF2::setUseLinkGroup(bool enable) | |
| { | |
| options.useLinkGroup = enable; | |
| aShapeTool->SetAutoNaming(!enable); | |
| } | |
| void ImportOCAF2::setMode(int m) | |
| { | |
| if (m < 0 || m >= ModeMax) { | |
| FC_WARN("Invalid import mode " << m); | |
| } | |
| else { | |
| options.mode = m; | |
| } | |
| if (options.mode != SingleDoc) { | |
| if (pDocument->isSaved()) { | |
| Base::FileInfo fi(pDocument->FileName.getValue()); | |
| filePath = fi.dirPath(); | |
| } | |
| else { | |
| FC_WARN("Disable multi-document mode because the input document is not saved."); | |
| } | |
| } | |
| } | |
| static void setPlacement(App::PropertyPlacement* prop, const TopoDS_Shape& shape) | |
| { | |
| prop->setValue( | |
| Base::Placement(Part::TopoShape::convert(shape.Location().Transformation())) * prop->getValue() | |
| ); | |
| } | |
| std::string ImportOCAF2::getLabelName(TDF_Label label) | |
| { | |
| std::string name; | |
| if (label.IsNull()) { | |
| return name; | |
| } | |
| if (!XCAFDoc_ShapeTool::IsReference(label)) { | |
| return Tools::labelName(label); | |
| } | |
| if (!options.useBaseName) { | |
| name = Tools::labelName(label); | |
| } | |
| TDF_Label ref; | |
| if (name.empty() && XCAFDoc_ShapeTool::GetReferredShape(label, ref)) { | |
| name = Tools::labelName(ref); | |
| } | |
| return name; | |
| } | |
| void ImportOCAF2::setObjectName(Info& info, TDF_Label label) | |
| { | |
| if (!info.obj) { | |
| return; | |
| } | |
| info.baseName = getLabelName(label); | |
| if (!info.baseName.empty()) { | |
| info.obj->Label.setValue(info.baseName.c_str()); | |
| } | |
| else { | |
| auto linked = info.obj->getLinkedObject(false); | |
| if (!linked || linked == info.obj) { | |
| return; | |
| } | |
| info.obj->Label.setValue(linked->Label.getValue()); | |
| } | |
| } | |
| bool ImportOCAF2::getColor(const TopoDS_Shape& shape, Info& info, bool check, bool noDefault) | |
| { | |
| bool ret = false; | |
| Quantity_ColorRGBA aColor; | |
| if (aColorTool->GetColor(shape, XCAFDoc_ColorSurf, aColor)) { | |
| Base::Color c = Tools::convertColor(aColor); | |
| if (!check || info.faceColor != c) { | |
| info.faceColor = c; | |
| info.hasFaceColor = true; | |
| ret = true; | |
| } | |
| } | |
| if (!noDefault && !info.hasFaceColor && aColorTool->GetColor(shape, XCAFDoc_ColorGen, aColor)) { | |
| Base::Color c = Tools::convertColor(aColor); | |
| if (!check || info.faceColor != c) { | |
| info.faceColor = c; | |
| info.hasFaceColor = true; | |
| ret = true; | |
| } | |
| } | |
| if (aColorTool->GetColor(shape, XCAFDoc_ColorCurv, aColor)) { | |
| Base::Color c = Tools::convertColor(aColor); | |
| // Some STEP include a curve color with the same value of the face | |
| // color. And this will look weird in FC. So for shape with face | |
| // we'll ignore the curve color, if it is the same as the face color. | |
| if ((c != info.faceColor || !TopExp_Explorer(shape, TopAbs_FACE).More()) | |
| && (!check || info.edgeColor != c)) { | |
| info.edgeColor = c; | |
| info.hasEdgeColor = true; | |
| ret = true; | |
| } | |
| } | |
| if (!check) { | |
| if (!info.hasFaceColor) { | |
| info.faceColor = options.defaultFaceColor; | |
| } | |
| if (!info.hasEdgeColor) { | |
| info.edgeColor = options.defaultEdgeColor; | |
| } | |
| } | |
| return ret; | |
| } | |
| App::DocumentObject* ImportOCAF2::expandShape(App::Document* doc, TDF_Label label, const TopoDS_Shape& shape) | |
| { | |
| if (shape.IsNull() || !TopExp_Explorer(shape, TopAbs_VERTEX).More()) { | |
| return nullptr; | |
| } | |
| std::vector<App::DocumentObject*> objs; | |
| if (shape.ShapeType() == TopAbs_COMPOUND) { | |
| for (TopoDS_Iterator it(shape, Standard_False, Standard_False); it.More(); it.Next()) { | |
| TDF_Label childLabel; | |
| if (!label.IsNull()) { | |
| aShapeTool->FindSubShape(label, it.Value(), childLabel); | |
| } | |
| auto child = expandShape(doc, childLabel, it.Value()); | |
| if (child) { | |
| objs.push_back(child); | |
| Info info; | |
| info.free = false; | |
| info.obj = child; | |
| myShapes.emplace(it.Value().Located(TopLoc_Location()), info); | |
| } | |
| } | |
| if (objs.empty()) { | |
| return nullptr; | |
| } | |
| auto compound = doc->addObject<Part::Compound2>("Compound"); | |
| compound->Links.setValues(objs); | |
| setPlacement(&compound->Placement, shape); | |
| return compound; | |
| } | |
| Info info; | |
| info.obj = nullptr; | |
| createObject(doc, label, shape, info, false); | |
| return info.obj; | |
| } | |
| bool ImportOCAF2::createObject( | |
| App::Document* doc, | |
| TDF_Label label, | |
| const TopoDS_Shape& shape, | |
| Info& info, | |
| bool newDoc | |
| ) | |
| { | |
| if (shape.IsNull() || !TopExp_Explorer(shape, TopAbs_VERTEX).More()) { | |
| FC_WARN(Tools::labelName(label) << " has empty shape"); | |
| return false; | |
| } | |
| getColor(shape, info); | |
| bool hasFaceColors = false; | |
| bool hasEdgeColors = false; | |
| Part::TopoShape tshape(shape); | |
| std::vector<Base::Color> faceColors; | |
| std::vector<Base::Color> edgeColors; | |
| TDF_LabelSequence seq; | |
| if (!label.IsNull() && aShapeTool->GetSubShapes(label, seq)) { | |
| TopTools_IndexedMapOfShape faceMap, edgeMap; | |
| TopExp::MapShapes(tshape.getShape(), TopAbs_FACE, faceMap); | |
| TopExp::MapShapes(tshape.getShape(), TopAbs_EDGE, edgeMap); | |
| faceColors.assign(faceMap.Extent(), info.faceColor); | |
| edgeColors.assign(edgeMap.Extent(), info.edgeColor); | |
| // Two passes to get sub shape colors. First pass, look for solid, and | |
| // second pass look for face and edges. This allows lower level | |
| // subshape to override color of higher level ones. | |
| for (int j = 0; j < 2; ++j) { | |
| for (int i = 1; i <= seq.Length(); ++i) { | |
| TDF_Label l = seq.Value(i); | |
| TopoDS_Shape subShape = aShapeTool->GetShape(l); | |
| if (subShape.IsNull()) { | |
| continue; | |
| } | |
| if (subShape.ShapeType() == TopAbs_FACE || subShape.ShapeType() == TopAbs_EDGE) { | |
| if (j == 0) { | |
| continue; | |
| } | |
| } | |
| else if (j != 0) { | |
| continue; | |
| } | |
| bool foundFaceColor = false, foundEdgeColor = false; | |
| Base::Color faceColor, edgeColor; | |
| Quantity_ColorRGBA aColor; | |
| if (aColorTool->GetColor(l, XCAFDoc_ColorSurf, aColor) | |
| || aColorTool->GetColor(l, XCAFDoc_ColorGen, aColor)) { | |
| faceColor = Tools::convertColor(aColor); | |
| foundFaceColor = true; | |
| } | |
| if (aColorTool->GetColor(l, XCAFDoc_ColorCurv, aColor)) { | |
| edgeColor = Tools::convertColor(aColor); | |
| foundEdgeColor = true; | |
| if (j == 0 && foundFaceColor && !faceColors.empty() && edgeColor == faceColor) { | |
| // Do not set edge the same color as face | |
| foundEdgeColor = false; | |
| } | |
| } | |
| if (foundFaceColor) { | |
| for (TopExp_Explorer exp(subShape, TopAbs_FACE); exp.More(); exp.Next()) { | |
| int idx = faceMap.FindIndex(exp.Current()) - 1; | |
| if (idx >= 0 && idx < (int)faceColors.size()) { | |
| faceColors[idx] = faceColor; | |
| hasFaceColors = true; | |
| info.hasFaceColor = true; | |
| } | |
| } | |
| } | |
| if (foundEdgeColor) { | |
| for (TopExp_Explorer exp(subShape, TopAbs_EDGE); exp.More(); exp.Next()) { | |
| int idx = edgeMap.FindIndex(exp.Current()) - 1; | |
| if (idx >= 0 && idx < (int)edgeColors.size()) { | |
| edgeColors[idx] = edgeColor; | |
| hasEdgeColors = true; | |
| info.hasEdgeColor = true; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| Part::Feature* feature; | |
| if (newDoc && (options.mode == ObjectPerDoc || options.mode == ObjectPerDir)) { | |
| doc = getDocument(doc, label); | |
| } | |
| if (options.expandCompound | |
| && (tshape.countSubShapes(TopAbs_SOLID) > 1 | |
| || (!tshape.countSubShapes(TopAbs_SOLID) && tshape.countSubShapes(TopAbs_SHELL) > 1))) { | |
| feature = dynamic_cast<Part::Feature*>(expandShape(doc, label, shape)); | |
| assert(feature); | |
| } | |
| else { | |
| feature = doc->addObject<Part::Feature>(tshape.shapeName().c_str()); | |
| feature->Shape.setValue(shape); | |
| } | |
| applyFaceColors(feature, {info.faceColor}); | |
| applyEdgeColors(feature, {info.edgeColor}); | |
| if (hasFaceColors) { | |
| applyFaceColors(feature, faceColors); | |
| } | |
| if (hasEdgeColors) { | |
| applyEdgeColors(feature, edgeColors); | |
| } | |
| info.propPlacement = &feature->Placement; | |
| info.obj = feature; | |
| return true; | |
| } | |
| App::Document* ImportOCAF2::getDocument(App::Document* doc, TDF_Label label) | |
| { | |
| if (filePath.empty() || options.mode == SingleDoc || options.merge) { | |
| return doc; | |
| } | |
| auto name = getLabelName(label); | |
| if (name.empty()) { | |
| return doc; | |
| } | |
| App::DocumentInitFlags initFlags {.createView = false}; | |
| auto newDoc = App::GetApplication().newDocument(name.c_str(), name.c_str(), initFlags); | |
| std::ostringstream ss; | |
| Base::FileInfo fi(doc->FileName.getValue()); | |
| std::string path = fi.dirPath(); | |
| if (options.mode == GroupPerDir || options.mode == ObjectPerDir) { | |
| for (int i = 0; i < 1000; ++i) { | |
| ss.str(""); | |
| ss << path << '/' << fi.fileNamePure() << "_parts"; | |
| if (i > 0) { | |
| ss << '_' << std::setfill('0') << std::setw(3) << i; | |
| } | |
| Base::FileInfo fi2(ss.str()); | |
| if (fi2.exists()) { | |
| if (!fi2.isDir()) { | |
| continue; | |
| } | |
| } | |
| else if (!fi2.createDirectory()) { | |
| FC_WARN("Failed to create directory " << fi2.filePath()); | |
| break; | |
| } | |
| path = fi2.filePath(); | |
| break; | |
| } | |
| } | |
| for (int i = 0; i < 1000; ++i) { | |
| ss.str(""); | |
| ss << path << '/' << newDoc->getName() << ".fcstd"; | |
| if (i > 0) { | |
| ss << '_' << std::setfill('0') << std::setw(3) << i; | |
| } | |
| Base::FileInfo fi(ss.str()); | |
| if (!fi.exists()) { | |
| if (!newDoc->saveAs(fi.filePath().c_str())) { | |
| break; | |
| } | |
| return newDoc; | |
| } | |
| } | |
| FC_WARN("Cannot save document for part '" << name << "'"); | |
| return doc; | |
| } | |
| bool ImportOCAF2::createGroup( | |
| App::Document* doc, | |
| Info& info, | |
| const TopoDS_Shape& shape, | |
| std::vector<App::DocumentObject*>& children, | |
| const boost::dynamic_bitset<>& visibilities, | |
| bool canReduce | |
| ) | |
| { | |
| assert(children.size() == visibilities.size()); | |
| if (children.empty()) { | |
| return false; | |
| } | |
| bool hasColor = getColor(shape, info, false, true); | |
| if (canReduce && !hasColor && options.reduceObjects && children.size() == 1 && visibilities[0]) { | |
| info.obj = children.front(); | |
| info.free = true; | |
| info.propPlacement = dynamic_cast<App::PropertyPlacement*>( | |
| info.obj->getPropertyByName("Placement") | |
| ); | |
| myCollapsedObjects.emplace(info.obj, info.propPlacement); | |
| return true; | |
| } | |
| auto group = doc->addObject<App::LinkGroup>("LinkGroup"); | |
| for (auto& child : children) { | |
| if (child->getDocument() != doc) { | |
| auto link = doc->addObject<App::Link>("Link"); | |
| link->Label.setValue(child->Label.getValue()); | |
| link->setLink(-1, child); | |
| auto pla = freecad_cast<App::PropertyPlacement*>(child->getPropertyByName("Placement")); | |
| if (pla) { | |
| link->Placement.setValue(pla->getValue()); | |
| } | |
| child = link; | |
| } | |
| } | |
| group->ElementList.setValues(children); | |
| group->VisibilityList.setValue(visibilities); | |
| info.obj = group; | |
| info.propPlacement = &group->Placement; | |
| if (getColor(shape, info, false, true)) { | |
| if (info.hasFaceColor) { | |
| applyLinkColor(group, -1, info.faceColor); | |
| } | |
| } | |
| return true; | |
| } | |
| App::DocumentObject* ImportOCAF2::loadShapes() | |
| { | |
| if (!options.useLinkGroup) { | |
| ImportLegacy legacy(*this); | |
| legacy.setMerge(options.merge); | |
| legacy.loadShapes(); | |
| return nullptr; | |
| } | |
| if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { | |
| Tools::dumpLabels(pDoc->Main(), aShapeTool, aColorTool); | |
| } | |
| TDF_LabelSequence labels; | |
| aShapeTool->GetShapes(labels); | |
| Base::SequencerLauncher seq("Importing...", labels.Length()); | |
| FC_LOG("free shape count " << labels.Length()); | |
| sequencer = options.showProgress ? &seq : nullptr; | |
| labels.Clear(); | |
| myShapes.clear(); | |
| myNames.clear(); | |
| myCollapsedObjects.clear(); | |
| std::vector<App::DocumentObject*> objs; | |
| aShapeTool->GetFreeShapes(labels); | |
| boost::dynamic_bitset<> vis; | |
| int count = 0; | |
| for (Standard_Integer i = 1; i <= labels.Length(); i++) { | |
| auto label = labels.Value(i); | |
| if (!options.importHidden && !aColorTool->IsVisible(label)) { | |
| continue; | |
| } | |
| ++count; | |
| } | |
| for (Standard_Integer i = 1; i <= labels.Length(); i++) { | |
| auto label = labels.Value(i); | |
| if (!options.importHidden && !aColorTool->IsVisible(label)) { | |
| continue; | |
| } | |
| auto obj = loadShape(pDocument, label, aShapeTool->GetShape(label), false, count > 1); | |
| if (obj) { | |
| objs.push_back(obj); | |
| vis.push_back(aColorTool->IsVisible(label)); | |
| } | |
| } | |
| App::DocumentObject* ret = nullptr; | |
| if (objs.size() == 1) { | |
| ret = objs.front(); | |
| } | |
| else { | |
| Info info; | |
| if (createGroup(pDocument, info, TopoDS_Shape(), objs, vis)) { | |
| ret = info.obj; | |
| } | |
| } | |
| if (ret) { | |
| ret->recomputeFeature(true); | |
| } | |
| if (options.merge && ret && !ret->isDerivedFrom<Part::Feature>()) { | |
| auto shape = Part::Feature::getTopoShape( | |
| ret, | |
| Part::ShapeOption::ResolveLink | Part::ShapeOption::Transform | |
| ); | |
| auto feature = pDocument->addObject<Part::Feature>("Feature"); | |
| auto name = Tools::labelName(pDoc->Main()); | |
| feature->Label.setValue(name.empty() ? default_name.c_str() : name.c_str()); | |
| feature->Shape.setValue(shape); | |
| applyFaceColors(feature, {}); | |
| std::vector<std::pair<App::Document*, std::string>> objNames; | |
| for (auto obj : App::Document::getDependencyList(objs, App::Document::DepSort)) { | |
| objNames.emplace_back(obj->getDocument(), obj->getNameInDocument()); | |
| } | |
| for (auto& v : objNames) { | |
| v.first->removeObject(v.second.c_str()); | |
| } | |
| ret = feature; | |
| ret->recomputeFeature(true); | |
| } | |
| sequencer = nullptr; | |
| return ret; | |
| } | |
| void ImportOCAF2::getSHUOColors(TDF_Label label, std::map<std::string, Base::Color>& colors, bool appendFirst) | |
| { | |
| TDF_AttributeSequence seq; | |
| if (label.IsNull() || !aShapeTool->GetAllComponentSHUO(label, seq)) { | |
| return; | |
| } | |
| std::ostringstream ss; | |
| for (int i = 1; i <= seq.Length(); ++i) { | |
| Handle(XCAFDoc_GraphNode) shuo = Handle(XCAFDoc_GraphNode)::DownCast(seq.Value(i)); | |
| if (shuo.IsNull()) { | |
| continue; | |
| } | |
| TDF_Label slabel = shuo->Label(); | |
| // We only want to process the main shuo, i.e. those without upper_usage | |
| TDF_LabelSequence uppers; | |
| aShapeTool->GetSHUOUpperUsage(slabel, uppers); | |
| if (uppers.Length()) { | |
| continue; | |
| } | |
| // appendFirst tells us whether we shall append the object name of the first label | |
| bool skipFirst = !appendFirst; | |
| ss.str(""); | |
| while (true) { | |
| if (skipFirst) { | |
| skipFirst = false; | |
| } | |
| else { | |
| TDF_Label l = shuo->Label().Father(); | |
| auto it = myNames.find(l); | |
| if (it == myNames.end()) { | |
| FC_WARN("Failed to find object of label " << Tools::labelName(l)); | |
| ss.str(""); | |
| break; | |
| } | |
| if (!it->second.empty()) { | |
| ss << it->second << '.'; | |
| } | |
| } | |
| if (!shuo->NbChildren()) { | |
| break; | |
| } | |
| shuo = shuo->GetChild(1); | |
| } | |
| std::string subname = ss.str(); | |
| if (subname.empty()) { | |
| continue; | |
| } | |
| if (!aColorTool->IsVisible(slabel)) { | |
| subname += App::DocumentObject::hiddenMarker(); | |
| colors.emplace(subname, Base::Color()); | |
| } | |
| else { | |
| Quantity_ColorRGBA aColor; | |
| if (aColorTool->GetColor(slabel, XCAFDoc_ColorSurf, aColor) | |
| || aColorTool->GetColor(slabel, XCAFDoc_ColorGen, aColor)) { | |
| colors.emplace(subname, Tools::convertColor(aColor)); | |
| } | |
| } | |
| } | |
| } | |
| App::DocumentObject* ImportOCAF2::loadShape( | |
| App::Document* doc, | |
| TDF_Label label, | |
| const TopoDS_Shape& shape, | |
| bool baseOnly, | |
| bool newDoc | |
| ) | |
| { | |
| if (shape.IsNull()) { | |
| return nullptr; | |
| } | |
| auto baseShape = shape.Located(TopLoc_Location()); | |
| auto it = myShapes.find(baseShape); | |
| if (it == myShapes.end()) { | |
| Info info; | |
| auto baseLabel = aShapeTool->FindShape(baseShape); | |
| if (sequencer && !baseLabel.IsNull() && aShapeTool->IsTopLevel(baseLabel)) { | |
| sequencer->next(true); | |
| } | |
| bool res; | |
| if (baseLabel.IsNull() || !aShapeTool->IsAssembly(baseLabel)) { | |
| res = createObject(doc, baseLabel, baseShape, info, newDoc); | |
| } | |
| else { | |
| res = createAssembly(doc, baseLabel, baseShape, info, newDoc); | |
| } | |
| if (!res) { | |
| return nullptr; | |
| } | |
| setObjectName(info, baseLabel); | |
| it = myShapes.emplace(baseShape, info).first; | |
| } | |
| if (baseOnly) { | |
| return it->second.obj; | |
| } | |
| std::map<std::string, Base::Color> shuoColors; | |
| if (!options.useLinkGroup) { | |
| getSHUOColors(label, shuoColors, false); | |
| } | |
| auto info = it->second; | |
| getColor(shape, info, true); | |
| if (shuoColors.empty() && info.free && doc == info.obj->getDocument()) { | |
| it->second.free = false; | |
| auto name = getLabelName(label); | |
| if (info.faceColor != it->second.faceColor || info.edgeColor != it->second.edgeColor | |
| || (!name.empty() && !info.baseName.empty() && name != info.baseName)) { | |
| auto compound = doc->addObject<Part::Compound2>("Compound"); | |
| compound->Links.setValue(info.obj); | |
| info.propPlacement = &compound->Placement; | |
| if (info.faceColor != it->second.faceColor) { | |
| applyFaceColors(compound, {info.faceColor}); | |
| } | |
| if (info.edgeColor != it->second.edgeColor) { | |
| applyEdgeColors(compound, {info.edgeColor}); | |
| } | |
| info.obj = compound; | |
| setObjectName(info, label); | |
| } | |
| setPlacement(info.propPlacement, shape); | |
| myNames.emplace(label, info.obj->getNameInDocument()); | |
| return info.obj; | |
| } | |
| auto link = doc->addObject<App::Link>("Link"); | |
| link->setLink(-1, info.obj); | |
| setPlacement(&link->Placement, shape); | |
| info.obj = link; | |
| setObjectName(info, label); | |
| if (info.faceColor != it->second.faceColor) { | |
| applyLinkColor(link, -1, info.faceColor); | |
| } | |
| myNames.emplace(label, link->getNameInDocument()); | |
| if (!shuoColors.empty()) { | |
| applyElementColors(link, shuoColors); | |
| } | |
| return link; | |
| } | |
| struct ChildInfo | |
| { | |
| std::vector<Base::Placement> plas; | |
| boost::dynamic_bitset<> vis; | |
| std::map<size_t, Base::Color> colors; | |
| std::vector<TDF_Label> labels; | |
| TopoDS_Shape shape; | |
| }; | |
| bool ImportOCAF2::createAssembly( | |
| App::Document* _doc, | |
| TDF_Label label, | |
| const TopoDS_Shape& shape, | |
| Info& info, | |
| bool newDoc | |
| ) | |
| { | |
| (void)label; | |
| std::vector<App::DocumentObject*> children; | |
| std::map<App::DocumentObject*, ChildInfo> childrenMap; | |
| boost::dynamic_bitset<> visibilities; | |
| std::map<std::string, Base::Color> shuoColors; | |
| auto doc = _doc; | |
| if (newDoc) { | |
| doc = getDocument(_doc, label); | |
| } | |
| for (TopoDS_Iterator it(shape, Standard_False, Standard_False); it.More(); it.Next()) { | |
| TopoDS_Shape childShape = it.Value(); | |
| if (childShape.IsNull()) { | |
| continue; | |
| } | |
| TDF_Label childLabel; | |
| aShapeTool->Search(childShape, childLabel, Standard_True, Standard_True, Standard_False); | |
| if (!childLabel.IsNull() && !options.importHidden && !aColorTool->IsVisible(childLabel)) { | |
| continue; | |
| } | |
| auto obj = loadShape(doc, childLabel, childShape, options.reduceObjects); | |
| if (!obj) { | |
| continue; | |
| } | |
| bool vis = true; | |
| if (!childLabel.IsNull() && aShapeTool->IsComponent(childLabel)) { | |
| vis = aColorTool->IsVisible(childLabel); | |
| } | |
| if (!options.reduceObjects) { | |
| visibilities.push_back(vis); | |
| children.push_back(obj); | |
| getSHUOColors(childLabel, shuoColors, true); | |
| continue; | |
| } | |
| auto& childInfo = childrenMap[obj]; | |
| if (childInfo.plas.empty()) { | |
| children.push_back(obj); | |
| visibilities.push_back(vis); | |
| childInfo.shape = childShape; | |
| } | |
| childInfo.vis.push_back(vis); | |
| childInfo.labels.push_back(childLabel); | |
| childInfo.plas.emplace_back(Part::TopoShape::convert(childShape.Location().Transformation())); | |
| Quantity_ColorRGBA aColor; | |
| if (aColorTool->GetColor(childShape, XCAFDoc_ColorSurf, aColor)) { | |
| childInfo.colors[childInfo.plas.size() - 1] = Tools::convertColor(aColor); | |
| } | |
| } | |
| assert(visibilities.size() == children.size()); | |
| if (children.empty()) { | |
| if (doc != _doc) { | |
| App::GetApplication().closeDocument(doc->getName()); | |
| } | |
| return false; | |
| } | |
| if (options.reduceObjects) { | |
| int i = -1; | |
| for (auto& child : children) { | |
| ++i; | |
| auto& childInfo = childrenMap[child]; | |
| if (childInfo.plas.size() == 1) { | |
| child = loadShape(doc, childInfo.labels.front(), childInfo.shape); | |
| getSHUOColors(childInfo.labels.front(), shuoColors, true); | |
| continue; | |
| } | |
| visibilities[i] = true; | |
| // Okay, we are creating a link array | |
| auto link = doc->addObject<App::Link>("Link"); | |
| link->setLink(-1, child); | |
| link->ShowElement.setValue(false); | |
| link->ElementCount.setValue(childInfo.plas.size()); | |
| auto it = myCollapsedObjects.find(child); | |
| if (it != myCollapsedObjects.end()) { | |
| // child is a single component assembly that has been | |
| // collapsed, so we have to honour its placement | |
| for (auto& pla : childInfo.plas) { | |
| pla *= it->second->getValue(); | |
| } | |
| } | |
| link->PlacementList.setValue(childInfo.plas); | |
| link->VisibilityList.setValue(childInfo.vis); | |
| for (auto& v : childInfo.colors) { | |
| applyLinkColor(link, v.first, v.second); | |
| } | |
| int i = 0; | |
| std::string name = link->getNameInDocument(); | |
| name += '.'; | |
| for (auto childLabel : childInfo.labels) { | |
| myNames.emplace(childLabel, name + std::to_string(i++)); | |
| getSHUOColors(childLabel, shuoColors, true); | |
| } | |
| child = link; | |
| Info objInfo; | |
| objInfo.obj = child; | |
| setObjectName(objInfo, childInfo.labels.front()); | |
| } | |
| } | |
| if (children.empty()) { | |
| return false; | |
| } | |
| if (!createGroup(doc, info, shape, children, visibilities, shuoColors.empty())) { | |
| return false; | |
| } | |
| if (!shuoColors.empty()) { | |
| applyElementColors(info.obj, shuoColors); | |
| } | |
| return true; | |
| } | |
| // ---------------------------------------------------------------------------- | |
| 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<Base::Color>& colors) | |
| { | |
| partColors[part] = colors; | |
| } | |