#include <TNaming_SameShapeIterator.hxx>
#include <TDataStd_Name.hxx>
#include <TDataStd_Integer.hxx>
+#include <TDataStd_ExtStringList.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Face.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_ChildIDIterator.hxx>
#include <TDF_Reference.hxx>
+#include <TDF_Tool.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_ListOfShape.hxx>
#include <Config_PropManager.h>
// DEB
//#include <TCollection_AsciiString.hxx>
-//#include <TDF_Tool.hxx>
//#define DEB_IMPORT 1
+/// reference to the shape in external document: sting list attribute identifier
+static const Standard_GUID kEXTERNAL_SHAPE_REF("9aa5dd14-6d34-4a8d-8786-05842fd7bbbd");
+
static const int INVALID_TAG = -1;
static const int GENERATED_VERTICES_TAG = 1;
static const int GENERATED_EDGES_TAG = 2;
delete aBuilder->second;
// clear also shapes on cleaned sub-labels (#2241)
Handle(TNaming_NamedShape) aNS;
- if (aLab.FindChild(aBuilder->first).FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ TDF_Label aSubLab = aLab.FindChild(aBuilder->first);
+ if (aSubLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
aNS->Clear();
}
}
// remove the old reference (if any)
aLab.ForgetAttribute(TDF_Reference::GetID());
myFreePrimitiveTag = PRIMITIVES_START_TAG;
+ TDF_ChildIDIterator anEntriesIter(aLab, kEXTERNAL_SHAPE_REF, true);
+ for(; anEntriesIter.More(); anEntriesIter.Next()) {
+ anEntriesIter.Value()->Label().ForgetAttribute(kEXTERNAL_SHAPE_REF);
+ }
}
Model_BodyBuilder::~Model_BodyBuilder()
}
/// Checks that shape is presented in the tree with not-selection evolution
+/// In theOriginalLabel it returns label where NS of old sub-shape is stored
static bool isShapeInTree(const TDF_Label& theAccess1, const TDF_Label& theAccess2,
- TopoDS_Shape theShape)
+ TopoDS_Shape theShape, TDF_Label& theOriginalLabel)
{
bool aResult = TNaming_Tool::HasLabel(theAccess1, theShape);
if (aResult) { //check evolution and a label of this shape
static Handle(TNaming_NamedShape) aNS;
if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
if (aNS->Evolution() != TNaming_SELECTED) {
+ theOriginalLabel = aNS->Label();
return true;
}
}
}
if (!theAccess2.IsNull()) {
static const TDF_Label anEmpty;
- return isShapeInTree(theAccess2, anEmpty, theShape);
+ return isShapeInTree(theAccess2, anEmpty, theShape, theOriginalLabel);
}
return false;
}
+/// Stores entry to the external label in the entries list at this label
+static void storeExternalReference(const TDF_Label& theExternal, const TDF_Label theThis)
+{
+ // store information about the external document reference to restore old shape on open
+ if (!theExternal.IsNull() && !theExternal.Root().IsEqual(theThis.Root())) {
+ Handle(TDataStd_ExtStringList) anEntries;
+ if (!theThis.FindAttribute(kEXTERNAL_SHAPE_REF, anEntries)) {
+ anEntries = TDataStd_ExtStringList::Set(theThis, kEXTERNAL_SHAPE_REF);
+ }
+ TCollection_AsciiString anEntry;
+ TDF_Tool::Entry(theExternal, anEntry);
+ // check it already contains this entry
+ TDataStd_ListOfExtendedString::Iterator anIter(anEntries->List());
+ for(; anIter.More(); anIter.Next())
+ if (anIter.Value() == anEntry)
+ break;
+ if (!anIter.More()) {
+ anEntries->Append(anEntry);
+ }
+ }
+}
+
void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo,
const GeomShapePtr& theOldShape,
const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
bool anOldSubShapeAlreadyProcessed = !anAlreadyProcessedShapes.Add(anOldSubShape_);
TDF_Label anAccess2 = std::dynamic_pointer_cast<Model_Document>(
ModelAPI_Session::get()->moduleDocument())->generalLabel();
- bool anOldSubShapeNotInTree = !isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_);
+ TDF_Label anOriginalLabel;
+ bool anOldSubShapeNotInTree =
+ !isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_, anOriginalLabel);
if (anOldSubShapeAlreadyProcessed || anOldSubShapeNotInTree) {
continue;
}
isGenerated ? aBuilder->Generated(anOldSubShape_, aNewShape_)
: aBuilder->Modify(anOldSubShape_, aNewShape_);
+ // store information about the external document reference to restore old shape on open
+ storeExternalReference(anOriginalLabel, aBuilder->NamedShape()->Label());
}
}
}
bool anOldSubShapeAlreadyProcessed = !anAlreadyProcessedShapes.Add(anOldSubShape_);
TDF_Label anAccess2 = std::dynamic_pointer_cast<Model_Document>(
ModelAPI_Session::get()->moduleDocument())->generalLabel();
- bool anOldSubShapeNotInTree = !isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_);
+ TDF_Label anOriginalLabel;
+ bool anOldSubShapeNotInTree =
+ !isShapeInTree(aData->shapeLab(), anAccess2, anOldSubShape_, anOriginalLabel);
if (anOldSubShapeAlreadyProcessed || anOldSubShapeNotInTree) {
continue;
}
int aTag = TopAbs_WIRE ? GENERATED_EDGES_TAG : GENERATED_FACES_TAG;
for (TopExp_Explorer anExp(aNewShape_, aShapeTypeToExplore); anExp.More(); anExp.Next()) {
builder(aTag)->Generated(anOldSubShape_, anExp.Current());
+ // store information about the external document reference to restore old shape on open
+ storeExternalReference(anOriginalLabel, builder(aTag)->NamedShape()->Label());
}
buildName(aTag, theName);
}
if (aTag == INVALID_TAG) return;
builder(aTag)->Generated(anOldSubShape_, aNewShape_);
buildName(aTag, theName);
+ // store information about the external document reference to restore old shape on open
+ storeExternalReference(anOriginalLabel, builder(aTag)->NamedShape()->Label());
}
}
}
#include <ModelAPI_ResultBody.h>
#include <Events_Loop.h>
#include <Events_InfoMessage.h>
+#include <GeomAPI_Tools.h>
#include <TDataStd_Integer.hxx>
#include <TDataStd_Comment.hxx>
#include <TDF_ListIteratorOfAttributeDeltaList.hxx>
#include <TDF_ListIteratorOfLabelList.hxx>
#include <TDF_LabelMap.hxx>
+#include <TDF_Tool.hxx>
#include <TDF_DeltaOnAddition.hxx>
+#include <TDataStd_ExtStringList.hxx>
#include <TDataStd_UAttribute.hxx>
#include <TNaming_Builder.hxx>
#include <TNaming_SameShapeIterator.hxx>
#include <TNaming_Iterator.hxx>
#include <TNaming_NamedShape.hxx>
#include <TNaming_Tool.hxx>
+#include<TNaming_OldShapeIterator.hxx>
+#include <TopTools_DataMapOfShapeShape.hxx>
+#include <TopTools_ListOfShape.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Shape.hxx>
///< naming structures constructions selected from other document
static const int TAG_EXTERNAL_CONSTRUCTIONS = 5;
+/// reference to the shape in external document: sting list attribute identifier
+static const Standard_GUID kEXTERNAL_SHAPE_REF("9aa5dd14-6d34-4a8d-8786-05842fd7bbbd");
+
Model_Document::Model_Document(const int theID, const std::string theKind)
: myID(theID), myKind(theKind), myIsActive(false), myIsSetCurrentFeature(false),
myDoc(new TDocStd_Document("BinOcaf")) // binary OCAF format
return this == Model_Session::get()->moduleDocument().get();
}
+/// Makes all modification and generation naming shapes that have old shapes corresponding to
+/// shapes in a root document be equal to this root document
+static void updateShapesFromRoot(const TDF_Label theThisAccess, const TDF_Label theRootAccess)
+{
+ TopTools_DataMapOfShapeShape aCurrentToRoot; // shapes that must be updated: from this to root
+ TDF_ChildIDIterator aThisIter(theThisAccess.Root(), kEXTERNAL_SHAPE_REF, true);
+ for(; aThisIter.More(); aThisIter.Next()) {
+ aCurrentToRoot.Clear();
+ Handle(TNaming_NamedShape) aNS;
+ if (!aThisIter.Value()->Label().FindAttribute(TNaming_NamedShape::GetID(), aNS))
+ continue;
+ if (aNS->Evolution() != TNaming_GENERATED && aNS->Evolution() != TNaming_MODIFY)
+ continue;
+ for (TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) {
+ const TopoDS_Shape& anOld = aNSIter.OldShape();
+ if (anOld.IsNull())
+ continue;
+ TNaming_OldShapeIterator aNewIter(anOld, theThisAccess);
+ for (; aNewIter.More(); aNewIter.Next()) {
+ TNaming_Evolution anEvolution = aNewIter.NamedShape()->Evolution();
+ if (anEvolution != TNaming_SELECTED && anEvolution != TNaming_DELETE)
+ break;
+ }
+ if (aNewIter.More())
+ continue;
+ GeomShapePtr anOldShape(new GeomAPI_Shape), aRootShape(new GeomAPI_Shape);
+ anOldShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(anOld));
+ anOldShape = GeomAPI_Tools::getTypedShape(anOldShape);
+
+ // search the same shape in the root document
+ Handle(TDataStd_ExtStringList) anEntries =
+ Handle(TDataStd_ExtStringList)::DownCast(aThisIter.Value());
+ TDataStd_ListOfExtendedString::Iterator anIter(anEntries->List());
+ for (; anIter.More(); anIter.Next()) {
+ TDF_Label aRootLab;
+ TDF_Tool::Label(theRootAccess.Data(), anIter.Value(), aRootLab);
+ if (aRootLab.IsNull())
+ continue;
+ Handle(TNaming_NamedShape) aRootNS;
+ if (!aRootLab.FindAttribute(TNaming_NamedShape::GetID(), aRootNS))
+ continue;
+ TNaming_Iterator aRootShapes(aRootNS);
+ for (; aRootShapes.More(); aRootShapes.Next()) {
+ if (aRootShapes.NewShape().IsNull())
+ continue;
+ aRootShape->setImpl(new TopoDS_Shape(aRootShapes.NewShape()));
+ aRootShape = GeomAPI_Tools::getTypedShape(aRootShape);
+ if (!anOldShape->isEqual(aRootShape)) // special checking by geometry
+ continue;
+ // found a good corresponded shape
+ if (!anOld.IsEqual(aRootShapes.NewShape()))
+ aCurrentToRoot.Bind(anOld, aRootShapes.NewShape());
+ }
+ }
+ }
+ if (!aCurrentToRoot.IsEmpty()) { // update the whole named shape content
+ TopTools_ListOfShape anOld, aNew;
+ TNaming_Evolution anEvol = aNS->Evolution();
+ for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next()) {
+ anOld.Prepend(aCurrentToRoot.IsBound(aNSIter.OldShape()) ?
+ aCurrentToRoot.Find(aNSIter.OldShape()) : aNSIter.OldShape());
+ aNew.Prepend(aNSIter.NewShape());
+ }
+ TNaming_Builder aBuilder(aNS->Label());
+ TopTools_ListOfShape::Iterator anOldIter(anOld), aNewIter(aNew);
+ for(; anOldIter.More(); anOldIter.Next(), aNewIter.Next()) {
+ if (anEvol == TNaming_GENERATED) {
+ aBuilder.Generated(anOldIter.Value(), aNewIter.Value());
+ } else if (anEvol == TNaming_MODIFY) {
+ aBuilder.Modify(anOldIter.Value(), aNewIter.Value());
+ }
+ }
+ }
+ }
+}
+
bool Model_Document::load(const char* theDirName, const char* theFileName, DocumentPtr theThis)
{
Handle(Model_Application) anApp = Model_Application::getApplication();
// update the current features status
setCurrentFeature(currentFeature(false), false);
aSession->setCheckTransactions(true);
- aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
+ aSession->setActiveDocument(aSession->moduleDocument(), false);
// this is done in Part result "activate", so no needed here. Causes not-blue active part.
// aSession->setActiveDocument(anApp->getDocument(myID), true);
anApp->setLoadByDemand(aPart->data()->name(),
aPart->data()->document(ModelAPI_ResultPart::DOC_REF())->docId());
}
-
+ if (!isRoot()) {
+ updateShapesFromRoot(myDoc->Main(),
+ std::dynamic_pointer_cast<Model_Document>(aSession->moduleDocument())->generalLabel());
+ }
} else { // open failed, but new document was created to work with it: inform the model
aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
}
#include <Selector_NameGenerator.h>
#include <Selector_NExplode.h>
-#include <TDF_ChildIDIterator.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopoDS_Builder.hxx>
#include <TopoDS.hxx>
#include <TopTools_MapOfShape.hxx>
#include <BRep_Tool.hxx>
+#include <TDF_ChildIDIterator.hxx>
+#include <TDF_Tool.hxx>
#include <TDataStd_Integer.hxx>
#include <TDataStd_ReferenceArray.hxx>
#include <TDataStd_IntegerArray.hxx>
#include <TDataStd_Name.hxx>
#include <TDataStd_UAttribute.hxx>
+#include <TDataStd_ExtStringList.hxx>
#include <list>
// reference attribute that contains the reference to labels where the "from" or "base" shapes
// of selection are located
static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f");
+// if the base array contains reference to the root label, this means that it refers to an
+// external document and this list contains a tag in the document
+static const Standard_GUID kBASE_LIST("7c515b1a-9549-493d-9946-a4933a22f45a");
// array of the neighbor levels
static const Standard_GUID kLEVELS_ARRAY("ee4c4b45-e859-4e86-aa4f-6eac68e0ca1f");
// weak index (integer) of the sub-shape
return false;
}
+/// Stores the array of references to the label: references to elements of ref-list, then the last
+static void storeBaseArray(const TDF_Label& theLab,
+ const TDF_LabelList& theRef, const TDF_Label& theLast)
+{
+ Handle(TDataStd_ReferenceArray) anArray =
+ TDataStd_ReferenceArray::Set(theLab, kBASE_ARRAY, 0, theRef.Extent());
+ Handle(TDataStd_ExtStringList) anEntries; // entries of references to external document
+ const TDF_Label aThisDocRoot = theLab.Root();
+ TDF_LabelList::Iterator aBIter(theRef);
+ for(int anIndex = 0; true; aBIter.Next(), anIndex++) {
+ const TDF_Label& aLab = aBIter.More() ? aBIter.Value() : theLast;
+ // check this is a label of this document
+ if (aLab.Root().IsEqual(aThisDocRoot)) {
+ anArray->SetValue(anIndex, aLab);
+ } else { // store reference to external document as an entry-string
+ if (anEntries.IsNull()) {
+ anEntries = TDataStd_ExtStringList::Set(theLab, kBASE_LIST);
+ }
+ TCollection_AsciiString anEntry;
+ TDF_Tool::Entry(aLab, anEntry);
+ anEntries->Append(anEntry);
+ anArray->SetValue(anIndex, aThisDocRoot); // stored root means it is external reference
+ }
+ if (!aBIter.More())
+ break;
+ }
+}
+
void Selector_Selector::store()
{
+ static const TDF_LabelList anEmptyRefList;
myLab.ForgetAllAttributes(true); // remove old naming data
TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
if (myGeometricalNaming)
break;
}
case SELTYPE_PRIMITIVE: {
- Handle(TDataStd_ReferenceArray) anArray =
- TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, 0);
- anArray->SetValue(0, myFinal);
+ storeBaseArray(myLab, anEmptyRefList, myFinal);
break;
}
case SELTYPE_MODIFICATION: {
- Handle(TDataStd_ReferenceArray) anArray =
- TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, myBases.Extent());
- TDF_LabelList::Iterator aBIter(myBases);
- for(int anIndex = 0; aBIter.More(); aBIter.Next(), anIndex++) {
- anArray->SetValue(anIndex, aBIter.Value());
- }
- anArray->SetValue(myBases.Extent(), myFinal); // final is in the end of array
+ storeBaseArray(myLab, myBases, myFinal);
if (myWeakIndex != -1) {
TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
}
case SELTYPE_WEAK_NAMING: {
TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
- // store myFinal in the base array
if (!myFinal.IsNull()) {
- Handle(TDataStd_ReferenceArray) anArray =
- TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, 0);
- anArray->SetValue(0, myFinal);
+ storeBaseArray(myLab, anEmptyRefList, myFinal);
}
break;
}
}
}
+/// Restores references to the labels: references to elements of ref-list, then the last
+static bool restoreBaseArray(const TDF_Label& theLab, const TDF_Label& theBaseDocumetnLab,
+ TDF_LabelList& theRef, TDF_Label& theLast)
+{
+ const TDF_Label aThisDocRoot = theLab.Root();
+ Handle(TDataStd_ExtStringList) anEntries; // entries of references to external document
+ TDataStd_ListOfExtendedString::Iterator anIter;
+ Handle(TDataStd_ReferenceArray) anArray;
+ if (theLab.FindAttribute(kBASE_ARRAY, anArray)) {
+ int anUpper = anArray->Upper();
+ for(int anIndex = anArray->Lower(); anIndex <= anUpper; anIndex++) {
+ TDF_Label aLab = anArray->Value(anIndex);
+ if (aLab.IsEqual(aThisDocRoot)) { // external document reference
+ if (theBaseDocumetnLab.IsNull())
+ return false;
+ if (anEntries.IsNull()) {
+ if (!theLab.FindAttribute(kBASE_LIST, anEntries))
+ return false;
+ anIter.Initialize(anEntries->List());
+ }
+ if (!anIter.More())
+ return false;
+ TDF_Tool::Label(theBaseDocumetnLab.Data(), anIter.Value(), aLab);
+ anIter.Next();
+ }
+ if (anIndex == anUpper) {
+ theLast = aLab;
+ } else {
+ theRef.Append(aLab);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+
bool Selector_Selector::restore()
{
Handle(TDataStd_Integer) aTypeAttr;
return aSubResult;
}
case SELTYPE_PRIMITIVE: {
- Handle(TDataStd_ReferenceArray) anArray;
- if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
- myFinal = anArray->Value(0);
- return true;
- }
- return false;
+ return restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal);
}
case SELTYPE_MODIFICATION: {
- Handle(TDataStd_ReferenceArray) anArray;
- if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
- int anUpper = anArray->Upper();
- for(int anIndex = 0; anIndex < anUpper; anIndex++) {
- myBases.Append(anArray->Value(anIndex));
- }
- myFinal = anArray->Value(anUpper);
+ if (restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal)) {
Handle(TDataStd_Integer) aWeakInt;
if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
myWeakIndex = aWeakInt->Get();
if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
return false;
myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
- Handle(TDataStd_ReferenceArray) anArray;
- if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
- myFinal = anArray->Value(0);
- }
+ if (!restoreBaseArray(myLab, myBaseDocumentLab, myBases, myFinal))
+ return false;
return true;
}
default: { // unknown case