Exporting/importing references to external objects.
fillAttribute(theSelected,
aFeature->selectionList(ExchangePlugin_ExportPart::SELECTION_LIST_ID()));
}
- // restart transaction to execute and delete the marcro-feature
+ // restart transaction to execute and delete the macro-feature
apply();
}
//--------------------------------------------------------------------------------------
FeaturePtr aFeature = thePart->addFeature(ExchangePlugin_ImportPart::ID());
aFeature->string(ExchangePlugin_ImportPart::FILE_PATH_ID())->setValue(theFilePath);
- // restart transaction to execute and delete the marcro-feature
+ // restart transaction to execute and delete the macro-feature
apply();
// restore current feature
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
${PROJECT_SOURCE_DIR}/src/XAO
+ ${PROJECT_SOURCE_DIR}/src/ConstructionPlugin
+ ${PROJECT_SOURCE_DIR}/src/PartSetPlugin
)
SET(PROJECT_HEADERS
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
+#include <ConstructionPlugin_Axis.h>
+#include <ConstructionPlugin_Plane.h>
+#include <ConstructionPlugin_Point.h>
+
// Obtain all features to be exported to get the list of selected results.
static void collectFeatures(AttributeSelectionListPtr theSelected,
std::list<FeaturePtr>& theExport);
// keep constructions only
std::list<FeaturePtr>::iterator anIt = theExport.begin();
while (anIt != theExport.end()) {
- if ((*anIt)->lastResult()->groupName() == ModelAPI_ResultConstruction::group())
+ FeaturePtr aCurFeature = *anIt;
+ ResultPtr aCurResult = aCurFeature->lastResult();
+
+ bool isApplicable =
+ (!aCurResult || aCurResult->groupName() == ModelAPI_ResultConstruction::group());
+
+ if (isApplicable && !aCurFeature->isInHistory()) {
+ isApplicable = aCurFeature->getKind() != ConstructionPlugin_Point::ID() &&
+ aCurFeature->getKind() != ConstructionPlugin_Axis::ID() &&
+ aCurFeature->getKind() != ConstructionPlugin_Plane::ID();
+ }
+
+ if (isApplicable)
++anIt;
else {
std::list<FeaturePtr>::iterator aRemoveIt = anIt++;
#include <ExchangePlugin_ImportPart.h>
#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultPart.h>
#include <ModelAPI_Session.h>
+#include <PartSetPlugin_Part.h>
+
ExchangePlugin_ImportPart::ExchangePlugin_ImportPart()
{
}
// load the file into the active document
SessionPtr aSession = ModelAPI_Session::get();
- if (!aSession->activeDocument()->import(aFilename.c_str()))
+ DocumentPtr aDoc = aSession->activeDocument();
+ bool isPartSet = aDoc == aSession->moduleDocument();
+ bool isOk = aDoc->import(aFilename.c_str(), isPartSet);
+ if (!isOk && isPartSet) {
+ // there are features not appropriate for PartSet,
+ // create new part and load there
+ FeaturePtr aPartFeature = aDoc->addFeature(PartSetPlugin_Part::ID());
+ ResultPartPtr aPartResult;
+ if (aPartFeature) {
+ aPartFeature->execute();
+ aPartResult = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->lastResult());
+ }
+ isOk = aPartResult && aPartResult->partDoc()->import(aFilename.c_str());
+ }
+ if (!isOk)
setError("Cannot import the document.");
}
../GeomAlgoAPI
../GeomAPI
../ModelGeomAlgo
+ ../ConstructionPlugin
${OpenCASCADE_INCLUDE_DIR}
)
myIsInitialized = myLab.FindAttribute(TDF_Reference::GetID(), myRef) == Standard_True;
if (!myIsInitialized) {
myRef = TDF_Reference::Set(myLab, myLab); // not initialized references to itself
+ myIsInitialized = true;
} else {
if (owner()) {
std::shared_ptr<Model_Document> aDoc =
bool Model_AttributeSelection::isInitialized()
{
- if (ModelAPI_AttributeSelection::isInitialized()) { // additional checks if it is initialized
- std::shared_ptr<GeomAPI_Shape> aResult;
- if (myRef.isInitialized()) {
- TDF_Label aSelLab = selectionLabel();
- // it is just reference to shape, not sub-shape
- if (aSelLab.IsAttribute(kSIMPLE_REF_ID) || aSelLab.IsAttribute(kPART_REF_ID)) {
- ResultPtr aContext = context();
- return aContext.get() != NULL;
- }
- Handle(TNaming_NamedShape) aSelection;
- if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
- return !aSelection->Get().IsNull();
- } else { // for simple construction element: just shape of this construction element
- if (myRef.value().get())
- return true;
- // check that this is on open of document, so, results are not initialized yet
- TDF_Label aRefLab = myRef.myRef->Get();
- if (aRefLab.IsNull() || !owner().get())
- return false;
- std::shared_ptr<Model_Document> aMyDoc =
- std::dynamic_pointer_cast<Model_Document>(owner()->document());
- if (!aMyDoc.get())
- return false;
- // check at least the feature exists
- return aMyDoc->featureByLab(aRefLab).get() != NULL;
- }
+ if (myRef.isInitialized()) {
+ TDF_Label aSelLab = selectionLabel();
+ // it is just reference to shape, not sub-shape
+ if (aSelLab.IsAttribute(kSIMPLE_REF_ID) || aSelLab.IsAttribute(kPART_REF_ID)) {
+ ResultPtr aContext = context();
+ return aContext.get() != NULL;
+ }
+ Handle(TNaming_NamedShape) aSelection;
+ if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
+ return !aSelection->Get().IsNull();
+ } else { // for simple construction element: just shape of this construction element
+ if (myRef.value().get())
+ return true;
+ // check that this is on open of document, so, results are not initialized yet
+ TDF_Label aRefLab = myRef.myRef->Get();
+ if (aRefLab.IsNull() || !owner().get())
+ return false;
+ std::shared_ptr<Model_Document> aMyDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ if (!aMyDoc.get())
+ return false;
+ // check at least the feature exists
+ return aMyDoc->featureByLab(aRefLab).get() != NULL;
}
}
return false;
ResultPtr Model_AttributeSelection::context()
{
- if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
+ if (!myRef.isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
return ResultPtr();
if (myTmpContext.get() || myTmpSubShape.get()) {
friend class Model_SelectionNaming;
friend class Model_ResultConstruction;
friend class Model_ResultBody;
+ friend class Model_Tools;
public:
/// The simplest constructor. "setLabel" must be called just after to initialize correctly.
return isOk;
}
-bool Model_Document::import(const char* theFileName)
+bool Model_Document::import(const char* theFileName, bool theCheckBefore)
{
Handle(Model_Application) anApp = Model_Application::getApplication();
TCollection_ExtendedString aFormat;
Handle(TDocStd_Document) aTempDoc;
bool isOk = loadDocument(anApp, aTempDoc, theFileName);
- // copy features from the temporary document to the current
- Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable(Standard_True);
- TDF_LabelList anAllNewFeatures;
- // Perform the copying twice for correct references:
- // 1. copy labels hierarchy and fill the relocation table
- TDF_Label aMain = myDoc->Main();
- for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More(); anIt.Next()) {
- TDF_Label aCurrentLab = anIt.Value();
- Handle(TDataStd_Comment) aFeatureID;
- TDF_Label aNewFeatuerLab;
- if (aCurrentLab.FindAttribute(TDataStd_Comment::GetID(), aFeatureID)) {
- TCollection_AsciiString anID(aFeatureID->Get());
- FeaturePtr aNewFeature = addFeature(anID.ToCString());
- std::shared_ptr<Model_Data> aData =
- std::dynamic_pointer_cast<Model_Data>(aNewFeature->data());
- aNewFeatuerLab = aData->label().Father();
- Model_Tools::copyLabels(aCurrentLab, aNewFeatuerLab, aRelocTable);
- }
- anAllNewFeatures.Append(aNewFeatuerLab);
- }
- // 2. copy attributes
- TDF_ListIteratorOfLabelList aNewIt(anAllNewFeatures);
- for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More(); anIt.Next()) {
- TDF_Label aCurrentLab = anIt.Value();
- TDF_Label aFeatureLab = aNewIt.Value();
- if (aFeatureLab.IsNull())
- anAllNewFeatures.Remove(aNewIt);
- else {
- Model_Tools::copyAttrs(aCurrentLab, aFeatureLab, aRelocTable);
- aNewIt.Next();
+ if (isOk && theCheckBefore) {
+ // verify all features are applicable for the current document type (e.g. PartSet)
+ std::shared_ptr<Model_Session> aSession =
+ std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get());
+ for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More() && isOk; anIt.Next()) {
+ TDF_Label aCurrentLab = anIt.Value();
+ Handle(TDataStd_Comment) aFeatureID;
+ TDF_Label aNewFeatuerLab;
+ if (aCurrentLab.FindAttribute(TDataStd_Comment::GetID(), aFeatureID)) {
+ TCollection_AsciiString anID(aFeatureID->Get());
+ std::string aFeatureKind(anID.ToCString());
+ if (aSession->myPlugins.find(aFeatureKind) != aSession->myPlugins.end()) {
+ std::string& aDocKind = aSession->myPlugins[aFeatureKind].second;
+ isOk = aDocKind.empty() || aDocKind == kind();
+ }
+ }
}
}
- myObjs->synchronizeFeatures(anAllNewFeatures, true, false, false, true);
+ if (isOk) {
+ // copy features from the temporary document to the current
+ Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable();
+ TDF_LabelList anAllNewFeatures;
+ // Perform the copying twice for correct references:
+ // 1. copy labels hierarchy and fill the relocation table
+ TDF_Label aMain = myDoc->Main();
+ for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More(); anIt.Next()) {
+ TDF_Label aCurrentLab = anIt.Value();
+ Handle(TDataStd_Comment) aFeatureID;
+ TDF_Label aNewFeatuerLab;
+ if (aCurrentLab.FindAttribute(TDataStd_Comment::GetID(), aFeatureID)) {
+ TCollection_AsciiString anID(aFeatureID->Get());
+ FeaturePtr aNewFeature = addFeature(anID.ToCString());
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>(aNewFeature->data());
+ aNewFeatuerLab = aData->label().Father();
+ Model_Tools::copyLabels(aCurrentLab, aNewFeatuerLab, aRelocTable);
+ }
+ anAllNewFeatures.Append(aNewFeatuerLab);
+ }
+ // 2. copy attributes
+ std::set<TCollection_AsciiString> aCoordinateLabels;
+ Model_Tools::labelsOfCoordinates(aCoordinateLabels, aRelocTable);
+ TDF_ListIteratorOfLabelList aNewIt(anAllNewFeatures);
+ for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More(); anIt.Next()) {
+ TDF_Label aCurrentLab = anIt.Value();
+ TDF_Label aFeatureLab = aNewIt.Value();
+ if (aFeatureLab.IsNull())
+ anAllNewFeatures.Remove(aNewIt);
+ else {
+ Model_Tools::copyAttrsAndKeepRefsToCoordinates(
+ aCurrentLab, aFeatureLab, aCoordinateLabels, aRelocTable);
+ aNewIt.Next();
+ }
+ }
- if (aTempDoc->CanClose() == CDM_CCS_OK)
- aTempDoc->Close();
+ myObjs->synchronizeFeatures(anAllNewFeatures, true, false, false, true);
+ }
+
+ if (anApp->CanClose(aTempDoc) == CDM_CCS_OK)
+ anApp->Close(aTempDoc);
return isOk;
}
Handle(TDocStd_Document) aTempDoc = new TDocStd_Document(aFormat);
TDF_Label aMain = aTempDoc->Main();
- Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable(Standard_True);
+ Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable();
std::list<FeaturePtr>::const_iterator anIt = theExportFeatures.begin();
// Perform the copying twice for correct references:
// 1. copy labels hierarchy and fill the relocation table
Model_Tools::copyLabels(aData->label().Father(), aFeatureLab, aRelocTable);
}
// 2. copy attributes
+ std::set<TCollection_AsciiString> aCoordinateLabels;
+ Model_Tools::labelsOfCoordinates(aCoordinateLabels, aRelocTable);
TDF_ChildIterator aChildIt(aMain);
for (anIt = theExportFeatures.begin(); anIt != theExportFeatures.end(); ++anIt) {
TDF_Label aFeatureLab = aChildIt.Value();
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>((*anIt)->data());
- Model_Tools::copyAttrs(aData->label().Father(), aFeatureLab, aRelocTable);
+ Model_Tools::copyAttrsAndKeepRefsToCoordinates(
+ aData->label().Father(), aFeatureLab, aCoordinateLabels, aRelocTable);
aChildIt.Next();
}
//! Loads the OCAF document from the file into the current document.
//! All the features are added after the active feature.
//! \param theFileName name of the file to import
+ //! \param theCheckBefore verify the document does not contain unappropriate features
+ //! (useful for import to PartSet)
//! \returns true if file was loaded successfully
- MODEL_EXPORT virtual bool import(const char* theFileName);
+ MODEL_EXPORT virtual bool import(const char* theFileName, bool theCheckBefore = false);
//! Saves the OCAF document to the file.
//! \param theDirName directory where the document will be saved
//
#include <Model_Tools.h>
+#include <Model_Data.h>
+
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_Session.h>
+
+#include <ConstructionPlugin_Axis.h>
+#include <ConstructionPlugin_Plane.h>
+#include <ConstructionPlugin_Point.h>
#include <Standard_GUID.hxx>
+#include <TDataStd_Comment.hxx>
+#include <TDataStd_AsciiString.hxx>
+
#include <TDF_AttributeIterator.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_Reference.hxx>
#include <TDF_RelocationTable.hxx>
+#include <TDF_Tool.hxx>
void Model_Tools::copyLabels(TDF_Label theSource, TDF_Label theDestination,
Handle(TDF_RelocationTable) theRelocTable)
theRelocTable);
}
}
+
+static TCollection_AsciiString labelToString(TDF_Label theLabel)
+{
+ TCollection_AsciiString aLabString;
+ TDF_Tool::Entry(theLabel, aLabString);
+ return aLabString;
+}
+
+static void makeExternalReference(TDF_Label theDestination, TDF_Label theReferred)
+{
+ Handle(TDF_Attribute) aReference, aComment, aString;
+ theDestination.FindAttribute(TDF_Reference::GetID(), aReference);
+ // create new attributes if not yet exists in the destination
+ if (!theDestination.FindAttribute(TDataStd_Comment::GetID(), aComment)) {
+ aComment = new TDataStd_Comment;
+ theDestination.AddAttribute(aComment);
+ }
+ if (!theDestination.FindAttribute(TDataStd_AsciiString::GetID(), aString)) {
+ aString = new TDataStd_AsciiString;
+ theDestination.AddAttribute(aString);
+ }
+ // reference to itself
+ Handle(TDF_Reference)::DownCast(aReference)->Set(theDestination, theDestination);
+ // ID of the document
+ std::ostringstream aDocIdStr;
+ aDocIdStr << ModelAPI_Session::get()->moduleDocument()->id();
+ Handle(TDataStd_Comment)::DownCast(aComment)->Set(aDocIdStr.str().c_str());
+ // value of referred label
+ Handle(TDataStd_AsciiString)::DownCast(aString)->Set(labelToString(theReferred));
+}
+
+void Model_Tools::copyAttrsAndKeepRefsToCoordinates(
+ TDF_Label theSource,
+ TDF_Label theDestination,
+ const std::set<TCollection_AsciiString>& theCoordinateLabels,
+ Handle(TDF_RelocationTable) theRelocTable)
+{
+ TDF_AttributeIterator anAttrIter(theSource);
+ for(; anAttrIter.More(); anAttrIter.Next()) {
+ Handle(TDF_Attribute) aTargetAttr;
+ if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
+ // create a new attribute if not yet exists in the destination
+ aTargetAttr = anAttrIter.Value()->NewEmpty();
+ theDestination.AddAttribute(aTargetAttr);
+ }
+ anAttrIter.Value()->Paste(aTargetAttr, theRelocTable);
+ if (aTargetAttr->ID() == TDF_Reference::GetID()) {
+ Handle(TDF_Reference) aTargetRef = Handle(TDF_Reference)::DownCast(aTargetAttr);
+ if (aTargetRef->Get().IsNull()) {
+ // may be refer to a cartesian coordinate entity
+ Handle(TDF_Reference) aSourceRef = Handle(TDF_Reference)::DownCast(anAttrIter.Value());
+ if (!aSourceRef.IsNull() && !aSourceRef->Get().IsNull()) {
+ std::set<TCollection_AsciiString>::const_iterator aFound =
+ theCoordinateLabels.find(labelToString(aSourceRef->Get()));
+ if (aFound != theCoordinateLabels.end())
+ makeExternalReference(theDestination, aSourceRef->Get());
+ }
+ }
+ else if (aTargetRef->Get().IsEqual(anAttrIter.Value()->Label())) {
+ // a source reference refers itself, a copy must also refer itself
+ aTargetRef->Set(aTargetRef->Label());
+ }
+ }
+ }
+ // copy the sub-labels content
+ TDF_ChildIterator aSubLabsIter(theSource);
+ for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
+ copyAttrsAndKeepRefsToCoordinates(
+ aSubLabsIter.Value(), theDestination.FindChild(aSubLabsIter.Value().Tag()),
+ theCoordinateLabels, theRelocTable);
+ }
+}
+
+void Model_Tools::labelsOfCoordinates(std::set<TCollection_AsciiString>& theCoordinateLabels,
+ Handle(TDF_RelocationTable) theRelocTable)
+{
+ DocumentPtr aPartSet = ModelAPI_Session::get()->moduleDocument();
+ std::list<FeaturePtr> aFeatures = aPartSet->allFeatures();
+ for (std::list<FeaturePtr>::iterator aFIt = aFeatures.begin(); aFIt != aFeatures.end(); ++aFIt) {
+ FeaturePtr aCurFeat = *aFIt;
+ if (!aCurFeat->isInHistory() &&
+ (aCurFeat->getKind() == ConstructionPlugin_Point::ID() ||
+ aCurFeat->getKind() == ConstructionPlugin_Axis::ID() ||
+ aCurFeat->getKind() == ConstructionPlugin_Plane::ID())) {
+ ResultPtr aResult = aCurFeat->lastResult();
+ if (aResult) {
+ std::shared_ptr<Model_Data> aResData =
+ std::dynamic_pointer_cast<Model_Data>(aResult->data());
+ TDF_Label aLab = aResData->label().Father();
+ theCoordinateLabels.insert(labelToString(aLab));
+ // set relocation to empty, references will be set correctly while copying attributes
+ theRelocTable->SetRelocation(aLab, TDF_Label());
+ }
+ }
+ }
+}
#include <TDF_Label.hxx>
#include <TDF_RelocationTable.hxx>
+#include <memory>
+#include <set>
+
/// A collection of methods useful for different parts of data model.
-namespace Model_Tools
+class Model_Tools
{
+public:
/// makes copy of label and all its sub-labels without copying the attributes;
/// and feel the relocation table
- void copyLabels(TDF_Label theSource, TDF_Label theDestination,
- Handle(TDF_RelocationTable) theRelocTable);
+ static void copyLabels(TDF_Label theSource, TDF_Label theDestination,
+ Handle(TDF_RelocationTable) theRelocTable);
/// makes copy of all attributes on the given label and all sub-labels
- void copyAttrs(TDF_Label theSource, TDF_Label theDestination,
- Handle(TDF_RelocationTable) theRelocTable = Handle(TDF_RelocationTable)());
+ static void copyAttrs(TDF_Label theSource, TDF_Label theDestination,
+ Handle(TDF_RelocationTable) theRelocTable = Handle(TDF_RelocationTable)());
+
+ /// makes copy of all attributes on the given label and all sub-labels,
+ /// but keep references to the Origin, coordinate axes and coordinate planes
+ static void copyAttrsAndKeepRefsToCoordinates(TDF_Label theSource, TDF_Label theDestination,
+ const std::set<TCollection_AsciiString>& theCoordinateLabels,
+ Handle(TDF_RelocationTable) theRelocTable);
+
+ /// collect labels of coordinate planes, axes, and origin
+ static void labelsOfCoordinates(
+ std::set<TCollection_AsciiString>& theCoordinateLabels,
+ Handle(TDF_RelocationTable) theRelocTable);
};
#endif
/// Loads the OCAF document from the file into the current document.
/// All the features are added after the active feature.
/// \param theFileName name of the file to import
+ /// \param theCheckBefore verify the document does not contain unappropriate features
+ /// (useful for import to PartSet)
/// \returns true if file was loaded successfully
- MODELAPI_EXPORT virtual bool import(const char* theFileName) = 0;
+ MODELAPI_EXPORT virtual bool import(const char* theFileName, bool theCheckBefore = false) = 0;
/// Export the list of features to the file
/// \param theFilename path to save the file