#include <TDF_LabelMap.hxx>
#include <TDF_ListIteratorOfLabelList.hxx>
+int kUNDEFINED_FEATURE_INDEX = -1;
+
static const std::string& groupNameFoldering(const std::string& theGroupID,
const bool theAllowFolder)
{
} else { // extend array by one more element
Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(),
aRefs->Upper() + 1);
- int aPassedPrev = 0; // prev feature is found and passed
+ int aPassedPrev = 0; // previous feature is found and passed
if (thePrevLab.IsNull()) { // null means that inserted feature must be the first
aNewArray->SetValue(aRefs->Lower(), theReferenced);
aPassedPrev = 1;
for(; aRefIter != aRefs.end(); aRefIter++) {
std::shared_ptr<ModelAPI_CompositeFeature> aComposite =
std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
- if (aComposite.get() && aComposite->isSub(theFeature)) {
+ if (aComposite.get() && aComposite->data()->isValid() && aComposite->isSub(theFeature)) {
aComposite->removeFeature(theFeature);
}
}
Handle(TDataStd_HLabelArray1) aNewArray =
new TDataStd_HLabelArray1(aRefs->Lower(), aRefs->Upper());
- int aPassedMovedFrom = 0; // the prev feature location is found and passed
+ int aPassedMovedFrom = 0; // the previous feature location is found and passed
int aPassedMovedTo = 0; // the feature is added and this location is passed
if (!theAfterThis.get()) { // null means that inserted feature must be the first
aNewArray->SetValue(aRefs->Lower(), aMovedLab);
createHistory(theGroupID);
if (theGroupID == ModelAPI_Feature::group()) { // searching among features (in history or not)
std::list<std::shared_ptr<ModelAPI_Feature> > allObjs = allFeatures();
- std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anObjIter = allObjs.begin();
- for(; anObjIter != allObjs.end(); anObjIter++) {
+ // from the end to find the latest result with such name
+ std::list<std::shared_ptr<ModelAPI_Feature> >::reverse_iterator anObjIter = allObjs.rbegin();
+ for(; anObjIter != allObjs.rend(); anObjIter++) {
if ((*anObjIter)->data()->name() == theName)
return *anObjIter;
}
} else { // searching among results (concealed or not)
std::list<std::shared_ptr<ModelAPI_Feature> > allObjs = allFeatures();
- std::list<std::shared_ptr<ModelAPI_Feature> >::iterator anObjIter = allObjs.begin();
- for(; anObjIter != allObjs.end(); anObjIter++) {
+ // from the end to find the latest result with such name
+ std::list<std::shared_ptr<ModelAPI_Feature> >::reverse_iterator anObjIter = allObjs.rbegin();
+ for(; anObjIter != allObjs.rend(); anObjIter++) {
std::list<ResultPtr> allRes;
ModelAPI_Tools::allResults(*anObjIter, allRes);
for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
// first count all features of such kind to start with index = count + 1
int aNumObjects = -1; // this feature is already in this map
NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myFeatures);
+ std::set<std::string> allNames;
for (; aFIter.More(); aFIter.Next()) {
if (aFIter.Value()->getKind() == theFeature->getKind())
aNumObjects++;
+ allNames.insert(aFIter.Value()->data()->name());
}
// generate candidate name
aName = composeName(theFeature->getKind(), aNumObjects + 1);
// check this is unique, if not, increase index by 1
- for (aFIter.Initialize(myFeatures); aFIter.More();) {
- FeaturePtr aFeature = aFIter.Value();
- bool isSameName = aFeature->data()->name() == aName;
- if (!isSameName) { // check also results to avoid same results names (actual for Parts)
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
- for (; aRIter != aResults.cend(); aRIter++) {
- isSameName = (*aRIter)->data()->name() == aName;
- }
- }
-
- if (isSameName) {
- aNumObjects++;
- aName = composeName(theFeature->getKind(), aNumObjects + 1);
- // reinitialize iterator to make sure a new name is unique
- aFIter.Initialize(myFeatures);
- } else
- aFIter.Next();
+ for(aNumObjects++; allNames.find(aName) != allNames.end(); aNumObjects++) {
+ aName = composeName(theFeature->getKind(), aNumObjects + 1);
}
theFeature->data()->setName(aName);
}
ObjectPtr aFeature = isFolder ? ObjectPtr(new ModelAPI_Folder)
: ObjectPtr(aSession->createFeature(aFeatureID, anOwner));
if (!aFeature.get()) {
- // somethig is wrong, most probably, the opened document has invalid structure
+ // something is wrong, most probably, the opened document has invalid structure
Events_InfoMessage("Model_Objects", "Invalid type of object in the document").send();
aLabIter.Value()->Label().ForgetAllAttributes();
continue;
}
// update results of the features (after features created because
// they may be connected, like sketch and sub elements)
- // After synchronisation of back references because sketch
+ // After synchronization of back references because sketch
// must be set in sub-elements before "execute" by updateResults
std::set<FeaturePtr> aProcessed; // composites must be updated after their subs (issue 360)
TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
anOwner->setExecuteFeatures(true);
}
-/// synchronises back references for the given object basing on the collected data
+/// synchronizes back references for the given object basing on the collected data
void Model_Objects::synchronizeBackRefsForObject(const std::set<AttributePtr>& theNewRefs,
ObjectPtr theObject)
{
if (!theObject.get() || !theObject->data()->isValid())
return; // invalid
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theObject->data());
- // iterate new list to compare with curent
+ // iterate new list to compare with current
std::set<AttributePtr>::iterator aNewIter = theNewRefs.begin();
for(; aNewIter != theNewRefs.end(); aNewIter++) {
if (aData->refsToMe().find(*aNewIter) == aData->refsToMe().end()) {
void Model_Objects::synchronizeBackRefs()
{
// collect all back references in the separated container: to update everything at once,
- // without additional Concealment switchin on and off: only the final modification
+ // without additional Concealment switching on and off: only the final modification
- // referenced (slave) objects to referencing attirbutes
+ // referenced (slave) objects to referencing attributes
std::map<ObjectPtr, std::set<AttributePtr> > allRefs;
NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFeatures(myFeatures);
for(; aFeatures.More(); aFeatures.Next()) {
FeaturePtr aFeature = aFeatures.Value();
std::list<ResultPtr> aResults;
ModelAPI_Tools::allResults(aFeature, aResults);
- // update the concealment status for disply in isConcealed of ResultBody
+ // update the concealment status for display in isConcealed of ResultBody
std::list<ResultPtr>::iterator aRIter = aResults.begin();
for(; aRIter != aResults.cend(); aRIter++) {
(*aRIter)->isConcealed();
std::shared_ptr<Model_Data> aPrevData =
std::dynamic_pointer_cast<Model_Data>(theBeforeThis->data());
if (aPrevData.get()) {
- aPrevFeatureLab = nextLabel(aPrevData->label().Father(), true);
+ int anIndex = kUNDEFINED_FEATURE_INDEX;
+ aPrevFeatureLab = nextLabel(aPrevData->label().Father(), anIndex, true);
}
} else { // find the label of the last feature
Handle(TDataStd_ReferenceArray) aRefs;
if (!aLastFeatureInFolder.IsNull()) {
if (IsEqual(aCurLabel, aLastFeatureInFolder))
- aLastFeatureInFolder.Nullify(); // the last feature in the folder is achived
+ aLastFeatureInFolder.Nullify(); // the last feature in the folder is achieved
continue;
}
const std::shared_ptr<ModelAPI_Result>& theResult)
{
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(theResult->data());
- if (aData.get()) {
+ if (aData.get() && aData->isValid()) {
TDF_Label aFeatureLab = aData->label().Father().Father().Father();
FeaturePtr aFeature = feature(aFeatureLab);
while(!aFeature.get() && aFeatureLab.Depth() > 1) { // this may be sub-result of result
if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
aNewBody = createBody(theFeature->data(), aResIndex);
} else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
- std::shared_ptr<ModelAPI_ResultPart> aNewP = createPart(theFeature->data(), aResIndex);
- theFeature->setResult(aNewP, aResIndex);
- if (!aNewP->partDoc().get())
- // create the part result: it is better to restore the previous result if it is possible
- theFeature->execute();
+ if (aResIndex <= theFeature->results().size()) { // to avoid crash if previous execute
+ // for index = 0 erases result
+ std::shared_ptr<ModelAPI_ResultPart> aNewP = createPart(theFeature->data(), aResIndex);
+ theFeature->setResult(aNewP, aResIndex);
+ if (!aNewP->partDoc().get())
+ // create the part result: it is better to restore the previous result if possible
+ theFeature->execute();
+ }
} else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
ResultConstructionPtr aConstr = createConstruction(theFeature->data(), aResIndex);
if (!aConstr->updateShape())
return aResult;
}
-TDF_Label Model_Objects::nextLabel(TDF_Label theCurrent, const bool theReverse)
+TDF_Label Model_Objects::nextLabel(TDF_Label theCurrent, int& theIndex, const bool theReverse)
{
Handle(TDataStd_ReferenceArray) aRefs;
if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
- for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { // iterate all existing features
+ int aStart = theIndex == kUNDEFINED_FEATURE_INDEX ? aRefs->Lower() : theIndex;
+ for(int a = aStart; a <= aRefs->Upper(); a++) { // iterate all existing features
TDF_Label aCurLab = aRefs->Value(a);
if (aCurLab.IsEqual(theCurrent)) {
a += theReverse ? -1 : 1;
- if (a >= aRefs->Lower() && a <= aRefs->Upper())
+ if (a >= aRefs->Lower() && a <= aRefs->Upper()) {
+ theIndex = a;
return aRefs->Value(a);
- break; // finish iiteration: it's last feature
+ }
+ break; // finish iteration: it's last feature
}
}
}
return TDF_Label();
}
-FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse)
+FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, int& theIndex, const bool theReverse)
{
std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
if (aData.get() && aData->isValid()) {
TDF_Label aFeatureLabel = aData->label().Father();
do {
- TDF_Label aNextLabel = nextLabel(aFeatureLabel, theReverse);
+ TDF_Label aNextLabel = nextLabel(aFeatureLabel, theIndex, theReverse);
if (aNextLabel.IsNull())
- break; // last or something is wrong
+ break; // the last or something is wrong
FeaturePtr aFound = feature(aNextLabel);
if (aFound)
return aFound; // the feature is found