1 // Copyright (C) 2014-2023 CEA, EDF
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include <Model_Tools.h>
21 #include <Model_Data.h>
23 #include <ModelAPI_Document.h>
24 #include <ModelAPI_Feature.h>
25 #include <ModelAPI_Result.h>
26 #include <ModelAPI_Session.h>
28 #include <ConstructionPlugin_Axis.h>
29 #include <ConstructionPlugin_Plane.h>
30 #include <ConstructionPlugin_Point.h>
32 #include <Standard_GUID.hxx>
34 #include <TDataStd_Comment.hxx>
35 #include <TDataStd_AsciiString.hxx>
37 #include <TDF_AttributeIterator.hxx>
38 #include <TDF_ChildIterator.hxx>
39 #include <TDF_Reference.hxx>
40 #include <TDF_RelocationTable.hxx>
41 #include <TDF_Tool.hxx>
43 void Model_Tools::copyLabels(TDF_Label theSource, TDF_Label theDestination,
44 Handle(TDF_RelocationTable) theRelocTable)
46 theRelocTable->SetRelocation(theSource, theDestination);
47 // copy the sub-labels hierarchy
48 TDF_ChildIterator aSubLabsIter(theSource);
49 for (; aSubLabsIter.More(); aSubLabsIter.Next()) {
50 copyLabels(aSubLabsIter.Value(),
51 theDestination.FindChild(aSubLabsIter.Value().Tag()),
56 void Model_Tools::copyAttrs(TDF_Label theSource, TDF_Label theDestination,
57 Handle(TDF_RelocationTable) theRelocTable)
59 TDF_AttributeIterator anAttrIter(theSource);
60 for(; anAttrIter.More(); anAttrIter.Next()) {
61 Handle(TDF_Attribute) aTargetAttr;
62 if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
63 // create a new attribute if not yet exists in the destination
64 aTargetAttr = anAttrIter.Value()->NewEmpty();
65 if (aTargetAttr->ID() != anAttrIter.Value()->ID())
66 aTargetAttr->SetID(anAttrIter.Value()->ID());
67 theDestination.AddAttribute(aTargetAttr);
69 // no special relocation, empty map, but self-relocation is on: copy references w/o changes
70 Handle(TDF_RelocationTable) aRelocTable =
71 theRelocTable.IsNull() ? new TDF_RelocationTable(Standard_True) : theRelocTable;
72 anAttrIter.Value()->Paste(aTargetAttr, aRelocTable);
73 // an exception: if a source reference refers itself, a copy must also refer itself
74 if (aTargetAttr->ID() == TDF_Reference::GetID()) {
75 Handle(TDF_Reference) aTargetRef = Handle(TDF_Reference)::DownCast(aTargetAttr);
76 if (aTargetRef->Get().IsEqual(anAttrIter.Value()->Label()))
77 aTargetRef->Set(aTargetRef->Label());
80 // copy the sub-labels content
81 TDF_ChildIterator aSubLabsIter(theSource);
82 for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
83 copyAttrs(aSubLabsIter.Value(),
84 theDestination.FindChild(aSubLabsIter.Value().Tag()),
89 static TCollection_AsciiString labelToString(TDF_Label theLabel)
91 TCollection_AsciiString aLabString;
92 TDF_Tool::Entry(theLabel, aLabString);
96 static void makeExternalReference(TDF_Label theDestination, TDF_Label theReferred)
98 Handle(TDF_Attribute) aReference, aComment, aString;
99 theDestination.FindAttribute(TDF_Reference::GetID(), aReference);
100 // create new attributes if not yet exists in the destination
101 if (!theDestination.FindAttribute(TDataStd_Comment::GetID(), aComment)) {
102 aComment = new TDataStd_Comment;
103 theDestination.AddAttribute(aComment);
105 if (!theDestination.FindAttribute(TDataStd_AsciiString::GetID(), aString)) {
106 aString = new TDataStd_AsciiString;
107 theDestination.AddAttribute(aString);
109 // reference to itself
110 Handle(TDF_Reference)::DownCast(aReference)->Set(theDestination, theDestination);
111 // ID of the document
112 std::ostringstream aDocIdStr;
113 aDocIdStr << ModelAPI_Session::get()->moduleDocument()->id();
114 Handle(TDataStd_Comment)::DownCast(aComment)->Set(aDocIdStr.str().c_str());
115 // value of referred label
116 Handle(TDataStd_AsciiString)::DownCast(aString)->Set(labelToString(theReferred));
119 void Model_Tools::copyAttrsAndKeepRefsToCoordinates(
121 TDF_Label theDestination,
122 const std::set<TCollection_AsciiString>& theCoordinateLabels,
123 Handle(TDF_RelocationTable) theRelocTable)
125 TDF_AttributeIterator anAttrIter(theSource);
126 for(; anAttrIter.More(); anAttrIter.Next()) {
127 Handle(TDF_Attribute) aTargetAttr;
128 if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
129 // create a new attribute if not yet exists in the destination
130 aTargetAttr = anAttrIter.Value()->NewEmpty();
131 if (aTargetAttr->ID() != anAttrIter.Value()->ID())
132 aTargetAttr->SetID(anAttrIter.Value()->ID());
133 theDestination.AddAttribute(aTargetAttr);
135 anAttrIter.Value()->Paste(aTargetAttr, theRelocTable);
136 if (aTargetAttr->ID() == TDF_Reference::GetID()) {
137 Handle(TDF_Reference) aTargetRef = Handle(TDF_Reference)::DownCast(aTargetAttr);
138 if (aTargetRef->Get().IsNull()) {
139 // may be refer to a cartesian coordinate entity
140 Handle(TDF_Reference) aSourceRef = Handle(TDF_Reference)::DownCast(anAttrIter.Value());
141 if (!aSourceRef.IsNull() && !aSourceRef->Get().IsNull()) {
142 std::set<TCollection_AsciiString>::const_iterator aFound =
143 theCoordinateLabels.find(labelToString(aSourceRef->Get()));
144 if (aFound != theCoordinateLabels.end())
145 makeExternalReference(theDestination, aSourceRef->Get());
148 else if (aTargetRef->Get().IsEqual(anAttrIter.Value()->Label())) {
149 // a source reference refers itself, a copy must also refer itself
150 aTargetRef->Set(aTargetRef->Label());
154 // copy the sub-labels content
155 TDF_ChildIterator aSubLabsIter(theSource);
156 for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
157 copyAttrsAndKeepRefsToCoordinates(
158 aSubLabsIter.Value(), theDestination.FindChild(aSubLabsIter.Value().Tag()),
159 theCoordinateLabels, theRelocTable);
163 void Model_Tools::labelsOfCoordinates(std::set<TCollection_AsciiString>& theCoordinateLabels,
164 Handle(TDF_RelocationTable) theRelocTable)
166 DocumentPtr aPartSet = ModelAPI_Session::get()->moduleDocument();
167 std::list<FeaturePtr> aFeatures = aPartSet->allFeatures();
168 for (std::list<FeaturePtr>::iterator aFIt = aFeatures.begin(); aFIt != aFeatures.end(); ++aFIt) {
169 FeaturePtr aCurFeat = *aFIt;
170 if (!aCurFeat->isInHistory() &&
171 (aCurFeat->getKind() == ConstructionPlugin_Point::ID() ||
172 aCurFeat->getKind() == ConstructionPlugin_Axis::ID() ||
173 aCurFeat->getKind() == ConstructionPlugin_Plane::ID())) {
174 ResultPtr aResult = aCurFeat->lastResult();
176 std::shared_ptr<Model_Data> aResData =
177 std::dynamic_pointer_cast<Model_Data>(aResult->data());
178 TDF_Label aLab = aResData->label().Father();
179 theCoordinateLabels.insert(labelToString(aLab));
180 // set relocation to empty, references will be set correctly while copying attributes
181 theRelocTable->SetRelocation(aLab, TDF_Label());