Loading files
3d097a032This file is pinned to the selected release. Download the original to open it in your design tool.
// Created by: DAUTRY Philippe
// Copyright (c) 1997-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Standard_DomainError.hxx>
#include <Standard_ImmutableObject.hxx>
#include <Standard_NullObject.hxx>
#include <TDF_AttributeIterator.hxx>
#include <TDF_ChildIterator.hxx>
#include <TDF_Data.hxx>
#include <TDF_IDFilter.hxx>
#include <TDF_Label.hxx>
#include <TDF_LabelNode.hxx>
#include <TDF_Tool.hxx>
// Attribute methods ++++++++++++++++++++++++++++++++++++++++++++++++++++
//=================================================================================================
void TDF_Label::Imported(const bool aStatus) const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no status.");
}
if (myLabelNode->IsImported() != aStatus)
{
myLabelNode->Imported(aStatus);
for (TDF_ChildIterator itr(*this, true); itr.More(); itr.Next())
{
itr.Value().myLabelNode->Imported(aStatus);
}
}
}
//=================================================================================================
bool TDF_Label::FindAttribute(const Standard_GUID& anID,
occ::handle<TDF_Attribute>& anAttribute) const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no attribute.");
}
TDF_AttributeIterator itr(myLabelNode); // Without removed attributes.
for (; itr.More(); itr.Next())
{
if (itr.PtrValue()->ID() == anID)
{
anAttribute = itr.PtrValue();
return true;
}
}
return false;
}
//=================================================================================================
bool TDF_Label::FindAttribute(const Standard_GUID& anID,
const int aTransaction,
occ::handle<TDF_Attribute>& anAttribute) const
{
occ::handle<TDF_Attribute> locAtt;
if (FindAttribute(anID, locAtt))
{
while ((!locAtt.IsNull()) && (locAtt->myTransaction > aTransaction))
{
locAtt = locAtt->myBackup;
}
if (!locAtt.IsNull())
{
anAttribute = locAtt;
return true;
}
}
return false;
}
// Label comfort methods ++++++++++++++++++++++++++++++++++++++++++++++++
//=================================================================================================
int TDF_Label::Depth() const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no depth.");
}
return myLabelNode->Depth();
}
//=================================================================================================
bool TDF_Label::IsDescendant(const TDF_Label& aLabel) const
{
// This algorithm goes up to the root. We can stop
// if the reached depth is less than that of <aLabel>.
const TDF_LabelNode* lp1 = aLabel.myLabelNode;
TDF_LabelNode* lp2 = myLabelNode;
#ifdef OCCT_DEBUG
if ((lp1 == NULL) || (lp2 == NULL))
throw Standard_NullObject("A null label has no ancestor nor descendant.");
#endif
if ((lp1 != nullptr) && (lp2 != nullptr))
{
const int d1 = lp1->Depth();
int d2 = lp2->Depth();
// Tester (d1 > d2) optimise la recherche ET dispense du test (lp2 != NULL)
while ((d2 > d1) && (lp2 != lp1))
{
lp2 = lp2->Father();
d2 = lp2->Depth();
}
return (lp1 == lp2);
}
return false;
}
//=================================================================================================
const TDF_Label TDF_Label::Root() const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no root.");
}
return myLabelNode->RootNode();
}
//=================================================================================================
int TDF_Label::NbChildren() const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no children.");
}
int n = 0;
if (myLabelNode->FirstChild() != nullptr)
{
for (TDF_ChildIterator itr(*this); itr.More(); itr.Next())
{
++n;
}
}
return n;
}
//=================================================================================================
TDF_Label TDF_Label::FindChild(const int aTag, const bool create) const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no child.");
}
if (create && ((Depth() + 1) & TDF_LabelNodeFlagsMsk))
{
throw Standard_OutOfRange("Depth value out of range");
}
return FindOrAddChild(aTag, create);
}
// Attribute comfort methods ++++++++++++++++++++++++++++++++++++++++++++
//=================================================================================================
// bool TDF_Label::IsA(const Standard_GUID& anID) const
// {
// occ::handle<TDF_Attribute> att;
// return FindAttribute(anID,att);
// }
//=================================================================================================
bool TDF_Label::IsAttribute(const Standard_GUID& anID) const
{
occ::handle<TDF_Attribute> att;
return FindAttribute(anID, att);
}
//=================================================================================================
bool TDF_Label::HasAttribute() const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no attribute.");
}
if (!myLabelNode->FirstAttribute().IsNull())
{
TDF_AttributeIterator itr(myLabelNode); // Without removed attributes.
return itr.More();
}
return false;
}
//=================================================================================================
int TDF_Label::NbAttributes() const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no attribute.");
}
int n = 0;
if (!myLabelNode->FirstAttribute().IsNull())
{
for (TDF_AttributeIterator itr(myLabelNode); itr.More(); itr.Next())
{
++n;
}
}
return n;
}
// Miscelleaneous +++++++++++++++++++++++++++++++++++++++++++++++++++++++
//=================================================================================================
int TDF_Label::Transaction() const
{
if (IsNull())
{
throw Standard_NullObject("A null Label has no transaction.");
}
return myLabelNode->Data()->Transaction();
}
//=================================================================================================
Standard_OStream& TDF_Label::Dump(Standard_OStream& anOS) const
{
TDF_IDFilter f;
NCollection_IndexedMap<occ::handle<TDF_Attribute>> m;
TDF_Label::InternalDump(anOS, f, m, false);
return anOS;
}
//=================================================================================================
void TDF_Label::ExtendedDump(Standard_OStream& anOS,
const TDF_IDFilter& aFilter,
NCollection_IndexedMap<occ::handle<TDF_Attribute>>& aMap) const
{
TDF_Label::InternalDump(anOS, aFilter, aMap, true);
}
//=================================================================================================
void TDF_Label::EntryDump(Standard_OStream& anOS) const
{
if (IsNull())
{
anOS << "This label is null.";
}
else
{
TCollection_AsciiString entry;
TDF_Tool::Entry(*this, entry);
anOS << entry;
}
}
//=================================================================================================
TDF_LabelNode* TDF_Label::FindOrAddChild(const int aTag, const bool create) const
{
TDF_LabelNode* currentLnp = myLabelNode->FirstChild();
TDF_LabelNode* lastLnp = nullptr;
TDF_LabelNode* lastFoundLnp = myLabelNode->myLastFoundChild; // jfa 10.01.2003
TDF_LabelNode* childLabelNode = nullptr;
// Finds the right place.
// jfa 10.01.2003
// 1. Check, if we access to a child, which is after last touched upon
if (lastFoundLnp != nullptr)
{
if (lastFoundLnp->Tag() == aTag)
{
return lastFoundLnp;
}
else if (lastFoundLnp->Tag() < aTag)
{
lastLnp = lastFoundLnp;
currentLnp = lastFoundLnp->Brother();
}
}
// jfa 10.01.2003 end
// To facilitate many tools, label brethren are stored in increasing order.
while ((currentLnp != nullptr) && (currentLnp->Tag() < aTag))
{
lastLnp = currentLnp;
currentLnp = currentLnp->Brother();
}
if ((currentLnp != nullptr) && (currentLnp->Tag() == aTag))
{
// The label exists.
childLabelNode = currentLnp;
}
else if (create)
{
// Creates the label to be inserted always before currentLnp.
const TDF_HAllocator& anAllocator = myLabelNode->Data()->LabelNodeAllocator();
childLabelNode = new (anAllocator) TDF_LabelNode(aTag, myLabelNode);
childLabelNode->myBrother = currentLnp; // May be NULL.
childLabelNode->Imported(IsImported());
// Inserts the label:
if (lastLnp == nullptr)
{ // ... at beginning.
myLabelNode->myFirstChild = childLabelNode;
}
else
{ // ... somewhere.
lastLnp->myBrother = childLabelNode;
}
// Update table for fast access to the labels.
if (myLabelNode->Data()->IsAccessByEntries())
{
myLabelNode->Data()->RegisterLabel(childLabelNode);
}
}
if (lastLnp)
{ // agv 14.07.2010
myLabelNode->myLastFoundChild = lastLnp; // jfa 10.01.2003
}
return childLabelNode;
}
//=================================================================================================
void TDF_Label::InternalDump(Standard_OStream& anOS,
const TDF_IDFilter& aFilter,
NCollection_IndexedMap<occ::handle<TDF_Attribute>>& aMap,
const bool extended) const
{
if (IsNull())
{
anOS << "This label is null.";
}
else
{
TCollection_AsciiString entry;
TDF_Tool::Entry(*this, entry);
anOS << entry << "\t";
if (IsImported())
{
anOS << "IS ";
}
else
{
anOS << "NOT";
}
anOS << " imported; ";
if (MayBeModified())
{
anOS << "MAYBE";
}
else
{
anOS << "NOT";
}
anOS << " modified; ";
if (AttributesModified())
{
anOS << "HAS attributes";
}
else
{
anOS << "NO attribute";
}
anOS << " modified; ";
if (HasAttribute())
{
int nba = NbAttributes();
anOS << "has " << nba << " attribute";
if (nba > 1)
{
anOS << "s";
}
anOS << "." << '\n';
for (TDF_AttributeIterator itr(myLabelNode); itr.More(); itr.Next())
{
// CLE
// const occ::handle<TDF_Attribute>& att = itr.Value();
occ::handle<TDF_Attribute> att = itr.Value();
// ENDCLE
if (extended && aFilter.IsKept(att))
{
anOS << "\t# " << aMap.Add(att);
}
att->TDF_Attribute::Dump(anOS);
}
}
else
{
anOS << " has no attribute" << '\n';
}
}
}
bool TDF_Label::HasLowerNode(const TDF_Label& aLabel) const
{
return (myLabelNode < aLabel.myLabelNode);
}
bool TDF_Label::HasGreaterNode(const TDF_Label& aLabel) const
{
return (myLabelNode > aLabel.myLabelNode);
}
// from insertor ////////////////////////////////////////////////////////
//=================================================================================================
// void TDF_Label::Add(const occ::handle<TDF_Attribute>& anAttribute) const
// { AddToNode(myLabelNode,anAttribute); }
//=================================================================================================
void TDF_Label::AddAttribute(const occ::handle<TDF_Attribute>& anAttribute,
const bool append /* = false*/) const
{
AddToNode(myLabelNode, anAttribute, append);
}
//=================================================================================================
// void TDF_Label::Forget(const occ::handle<TDF_Attribute>& anAttribute) const
// { ForgetFromNode(myLabelNode,anAttribute); }
//=================================================================================================
void TDF_Label::ForgetAttribute(const occ::handle<TDF_Attribute>& anAttribute) const
{
ForgetFromNode(myLabelNode, anAttribute);
}
//=================================================================================================
// bool TDF_Label::Forget (const Standard_GUID& anID) const
// {
// occ::handle<TDF_Attribute> anAttribute;
// //if (Label().FindAttribute(anID,anAttribute)) {
// if (FindAttribute(anID,anAttribute)) {
// Forget(anAttribute);
// return true;
// }
// return false;
// }
//=================================================================================================
bool TDF_Label::ForgetAttribute(const Standard_GUID& anID) const
{
occ::handle<TDF_Attribute> anAttribute;
// if (Label().FindAttribute(anID,anAttribute)) {
if (FindAttribute(anID, anAttribute))
{
ForgetAttribute(anAttribute);
return true;
}
return false;
}
//=================================================================================================
// void TDF_Label::ForgetAll (const bool clearChildren) const
// {
// for (TDF_AttributeIterator itr1(myLabelNode); itr1.More(); itr1.Next())
// ForgetFromNode(myLabelNode,itr1.Value());
// if (clearChildren)
// for (TDF_ChildIterator itr2(myLabelNode); itr2.More(); itr2.Next()) {
// itr2.Value().ForgetAll(clearChildren);
// }
// }
//=================================================================================================
void TDF_Label::ForgetAllAttributes(const bool clearChildren) const
{
TDF_AttributeIterator itr1(myLabelNode);
// AGV-OCC5031: iterator must be incremented before removal of the attribute
while (itr1.More())
{
const occ::handle<TDF_Attribute> anAttr = itr1.Value();
itr1.Next();
ForgetFromNode(myLabelNode, anAttr);
}
// while (itr1.More()) {
// ForgetFromNode(myLabelNode,itr1.Value());
// itr1.Next();
// }
if (clearChildren)
{
for (TDF_ChildIterator itr2(myLabelNode); itr2.More(); itr2.Next())
{
itr2.Value().ForgetAllAttributes(clearChildren);
}
}
}
//=================================================================================================
// void TDF_Label::Resume (const occ::handle<TDF_Attribute>& anAttribute) const
// { ResumeToNode(myLabelNode,anAttribute); }
//=================================================================================================
void TDF_Label::ResumeAttribute(const occ::handle<TDF_Attribute>& anAttribute) const
{
ResumeToNode(myLabelNode, anAttribute);
}
//=================================================================================================
void TDF_Label::AddToNode(TDF_LabelNode* const& toNode,
const occ::handle<TDF_Attribute>& anAttribute,
const bool append) const
{
// check that modification is allowed
if (!toNode->Data()->IsModificationAllowed())
{
TCollection_AsciiString aMess;
aMess = "Attribute \"";
aMess += anAttribute->DynamicType()->Name();
aMess += "\" is added to label outside transaction";
throw Standard_ImmutableObject(aMess.ToCString());
}
if (!anAttribute->Label().IsNull())
{
throw Standard_DomainError("Attribute to add is already attached to a label.");
}
occ::handle<TDF_Attribute> dummyAtt;
// if (Find(anAttribute->ID(),dummyAtt))
if (FindAttribute(anAttribute->ID(), dummyAtt))
{
throw Standard_DomainError("This label has already such an attribute.");
}
anAttribute->myTransaction = toNode->Data()->Transaction(); /// myData->Transaction();
anAttribute->mySavedTransaction = 0;
// append to the end of the attribute list
dummyAtt.Nullify();
if (append)
{
for (TDF_AttributeIterator itr(toNode); itr.More(); itr.Next())
{
dummyAtt = itr.Value();
}
}
toNode->AddAttribute(dummyAtt, anAttribute);
toNode->AttributesModified(anAttribute->myTransaction != 0);
// if (myData->NotUndoMode()) anAttribute->AfterAddition();
if (toNode->Data()->NotUndoMode())
{
anAttribute->AfterAddition();
}
}
//=================================================================================================
void TDF_Label::ForgetFromNode(TDF_LabelNode* const& fromNode,
const occ::handle<TDF_Attribute>& anAttribute) const
{
// check that modification is allowed
if (!fromNode->Data()->IsModificationAllowed())
{
TCollection_AsciiString aMess;
aMess = "Attribute \"";
aMess += anAttribute->DynamicType()->Name();
aMess += "\" is removed from label outside transaction";
throw Standard_ImmutableObject(aMess.ToCString());
}
if (fromNode != anAttribute->Label().myLabelNode)
{
throw Standard_DomainError("Attribute to forget not attached to my label.");
}
int curTrans = fromNode->Data()->Transaction();
if (!anAttribute->IsForgotten())
{
if ((curTrans == 0)
|| ((anAttribute->myTransaction == curTrans) && anAttribute->myBackup.IsNull()))
{
// 1- No transaction is open;
// OR
// 2- The attribute has been created in the current transaction;
// ==> Complete disparition of the attribute.
occ::handle<TDF_Attribute> lastAtt;
for (TDF_AttributeIterator itr(fromNode, false); itr.More(); itr.Next())
{
if (itr.Value() == anAttribute)
{
// if (myData->NotUndoMode()) {
if (fromNode->Data()->NotUndoMode())
{
anAttribute->BeforeForget();
anAttribute->BeforeRemoval();
}
fromNode->RemoveAttribute(lastAtt, anAttribute);
anAttribute->Forget(fromNode->Data()->Transaction());
break;
}
lastAtt = itr.Value();
}
}
else
{
// One case is here ignored:
// The attribute has been modified in the current transaction.
// (It has at least one backup.) We don't restore the previous
// version before forgetting. It may generated a strange behaviour
// in case of forgetting, committing, aborting...
if (fromNode->Data()->NotUndoMode())
{
anAttribute->BeforeForget();
}
anAttribute->Forget(fromNode->Data()->Transaction());
}
}
}
//=================================================================================================
void TDF_Label::ResumeToNode(TDF_LabelNode* const& toNode,
const occ::handle<TDF_Attribute>& anAttribute) const
{
if (anAttribute.IsNull())
{
throw Standard_NullObject("The attribute is a null handle.");
}
if (!anAttribute->Label().IsNull())
{
throw Standard_NullObject("Cannot resume an attribute already attached to a label.");
}
if (!anAttribute->IsForgotten())
{
throw Standard_DomainError("Cannot resume an unforgotten attribute.");
}
AddToNode(toNode, anAttribute, false);
anAttribute->Resume();
if (toNode->Data()->NotUndoMode())
{
anAttribute->AfterResume();
}
}
//////////////////end from insertor ///////////////////////////////////////////////////