def initAttributes(self):
pass
+ ## Computes unique entry for result: partId:featureId[number of result in feature]
+ def computeEntry(self, theRes):
+ aDoc = theRes.document()
+ aFeat = aDoc.feature(theRes)
+ aFeatId = str(aFeat.data().featureId())
+ aRootDoc = ModelAPI.ModelAPI_Session.get().moduleDocument()
+ aPartFeat = ModelAPI.findPartFeature(aRootDoc, aDoc)
+ aPartFeatureId = str(aPartFeat.data().featureId())
+ aResIndex = 0
+ for aRes in aFeat.results():
+ if aRes.data().isEqual(theRes.data()):
+ break
+ aResIndex += 1
+ if aResIndex != 0:
+ aFeatId += ":" + str(aResIndex)
+ anEntry = aPartFeatureId + ":" + aFeatId
+ return anEntry
+
## Exports all shapes and groups into the GEOM module.
def execute(self):
aSession = ModelAPI.ModelAPI_Session.get()
# collect all processed internal entries to break the link of unprocessed later
allProcessed = []
- # iterate all parts and all results to publish them in SHAPER_STUDY
+ # iterate all parts and all results to find all alive items
for aPartId in range(aPartSet.size(model.ModelAPI_ResultPart_group())):
aPartObject = aPartSet.object(model.ModelAPI_ResultPart_group(), aPartId)
aPartRes = ModelAPI.modelAPI_ResultPart(ModelAPI.modelAPI_Result(aPartObject))
break
aPartFeatureId = aPartSet.feature(aPartRes).data().featureId()
# Collects all features of exported results to find results of the same features and extend id.
- # Map from feature index to index of result. If index is zero (initial), no surrfix to entry is added.
- aFeaturesIndices = {}
for aResId in range(aPartDoc.size(model.ModelAPI_ResultBody_group())):
aResObject = aPartDoc.object(model.ModelAPI_ResultBody_group(), aResId)
aRes = model.objectToResult(aResObject)
- aResFeatureId = str(aPartDoc.feature(aRes).data().featureId())
- if aResFeatureId in aFeaturesIndices:
- aFeaturesIndices[aResFeatureId] += 1
- aResFeatureId += ":" + str(aFeaturesIndices[aResFeatureId])
- else:
- aFeaturesIndices[aResFeatureId] = 0
- aSSEntry = str(aPartFeatureId) + ":" + aResFeatureId
+ aSSEntry = self.computeEntry(aRes)
+ allProcessed.append(aSSEntry)
+
+ # process all SHAPER-STUDY shapes to find dead of evolved
+ allNewReferences = [] # entries of new objects that are now referenced by evolved
+ aSOIter = SHAPERSTUDY_utils.getStudy().NewChildIterator(aComponent)
+ while aSOIter.More():
+ aSO = aSOIter.Value()
+ aSOIter.Next() # here because there is continue inside the loop
+ anIOR = aSO.GetIOR()
+ if len(anIOR):
+ anObj = salome.orb.string_to_object(anIOR)
+ if isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
+ anEntry = anObj.GetEntry()
+ if len(anEntry) == 0:
+ continue;
+ elif anEntry not in allProcessed: # found a removed shape: make it dead for the moment
+ # but before check this result was updated to the new result
+ anEvolutionRes = ModelAPI.singleEvolution(anEntry)
+ if anEvolutionRes:
+ # try to find the last evolution
+ aNewEntry = self.computeEntry(anEvolutionRes)
+ aNewRes = ModelAPI.singleEvolution(aNewEntry)
+ while aNewRes:
+ aNewEntry = self.computeEntry(aNewRes)
+ aNewRes = ModelAPI.singleEvolution(aNewEntry)
+ allNewReferences.append(aNewEntry)
+ anObj.SetEntry(aNewEntry) # set a new entry and a shape
+ anObj.SetShapeByStream(anEvolutionRes.shape().getShapeStream(False))
+ aSO.SetAttrString("AttributeName", anEvolutionRes.data().name()) # also rename
+ else: # remove the reference - red node
+ aRes, aSO2 = aSO.FindSubObject(1)
+ if aRes:
+ aRes, aRef = aSO2.ReferencedObject()
+ if aRes:
+ aBuilder = SHAPERSTUDY_utils.getStudy().NewBuilder()
+ aBuilder.RemoveReference(aSO2)
+
+ # iterate all parts and all results to publish them in SHAPER_STUDY
+ for aPartId in range(aPartSet.size(model.ModelAPI_ResultPart_group())):
+ aPartObject = aPartSet.object(model.ModelAPI_ResultPart_group(), aPartId)
+ aPartRes = ModelAPI.modelAPI_ResultPart(ModelAPI.modelAPI_Result(aPartObject))
+ aPartDoc = aPartRes.partDoc()
+ if aPartDoc is None and aPartObject is not None:
+ break
+ aPartFeatureId = aPartSet.feature(aPartRes).data().featureId()
+ # Collects all features of exported results to find results of the same features and extend id.
+ for aResId in range(aPartDoc.size(model.ModelAPI_ResultBody_group())):
+ aResObject = aPartDoc.object(model.ModelAPI_ResultBody_group(), aResId)
+ aRes = model.objectToResult(aResObject)
+ aSSEntry = self.computeEntry(aRes)
+ if aSSEntry in allNewReferences:
+ continue
aSShape = anEngine.FindOrCreateShape(aSSEntry)
aSShape.SetShapeByStream(aRes.shape().getShapeStream(False))
if not aSShape.GetSO(): # publish in case it is a new shape
# Fields
self.processGroups(aRes, anEngine, aPartFeatureId, aSShape, True)
- # process all SHAPER-STUDY shapes to find dead
- aSOIter = SHAPERSTUDY_utils.getStudy().NewChildIterator(aComponent)
- while aSOIter.More():
- aSO = aSOIter.Value()
- aSOIter.Next() ### here because there is continue inside the loop!
- anIOR = aSO.GetIOR()
- if len(anIOR):
- anObj = salome.orb.string_to_object(anIOR)
- if isinstance(anObj, SHAPERSTUDY_ORB._objref_SHAPER_Object):
- anEntry = anObj.GetEntry()
- if len(anEntry) == 0:
- continue;
- elif anEntry not in allProcessed: # found a removed shape: make it dead for the moment
- # remove the reference - red node
- aRes, aSO2 = aSO.FindSubObject(1)
- if aRes:
- aRes, aRef = aSO2.ReferencedObject()
- if aRes:
- aBuilder = SHAPERSTUDY_utils.getStudy().NewBuilder()
- aBuilder.RemoveReference(aSO2)
-
# Part of the "execute" method: processes the Groups of theRes result publication.
# If theFields is true, the same is performed for Fields.
def processGroups(self, theRes, theEngine, thePartFeatureId, theStudyShape, theFields):
#include <GeomAPI_ShapeIterator.h>
#include <GeomAPI_ShapeExplorer.h>
+#include <TNaming_NamedShape.hxx>
+#include <TNaming_Iterator.hxx>
+#include <TNaming_SameShapeIterator.hxx>
+#include <TNaming_Tool.hxx>
#include <TopoDS_Shape.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TDataStd_UAttribute.hxx>
+#include <TDF_Reference.hxx>
// if this attribute exists, the shape is connected topology
Standard_GUID kIsConnectedTopology("e51392e0-3a4d-405d-8e36-bbfe19858ef5");
}
}
}
+
+void Model_ResultBody::modifiedSources(std::list<ResultPtr>& theSources)
+{
+ TDF_Label aLab = std::dynamic_pointer_cast<Model_Data>(data())->shapeLab();
+ TDF_LabelMap aResMap;
+ if (aLab.IsAttribute(TNaming_NamedShape::GetID())) {
+ for(TNaming_Iterator anIter(aLab); anIter.More(); anIter.Next()) {
+ TopoDS_Shape anOld = anIter.OldShape();
+ if (!anOld.IsNull() && TNaming_Tool::HasLabel(aLab, anOld)) {
+ // searching where this old shape is a new shape
+ for(TNaming_SameShapeIterator aNewIter(anOld, aLab); aNewIter.More(); aNewIter.Next()) {
+ for(TNaming_Iterator aNSIter(aNewIter.Label()); aNSIter.More(); aNSIter.Next()) {
+ if (!aNSIter.NewShape().IsNull() && aNSIter.NewShape().IsSame(anOld)) {
+ aResMap.Add(aNewIter.Label());
+ break;
+ }
+ }
+ }
+ }
+ }
+ } else if (aLab.IsAttribute(TDF_Reference::GetID())) { // check also simple reference to the origin
+ Handle(TDF_Reference) aRef;
+ aLab.FindAttribute(TDF_Reference::GetID(), aRef);
+ aResMap.Add(aRef->Get());
+ }
+
+ std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
+ for(TDF_MapIteratorOfLabelMap aLabIter(aResMap); aLabIter.More(); aLabIter.Next()) {
+ ResultPtr aRes = aDoc->resultByLab(aLabIter.Value());
+ if (aRes.get())
+ theSources.push_back(aRes);
+ }
+}
/// Cleans cash related to the already stored elements
MODEL_EXPORT virtual void cleanCash() override;
+ /// Returns in the set results that are stored as modified or generated in this result
+ MODEL_EXPORT virtual void modifiedSources(std::list<ResultPtr>& theSources) override;
+
protected:
/// Makes a body on the given feature
Model_ResultBody();
/// Cleans cash related to the already stored elements
MODELAPI_EXPORT virtual void cleanCash() = 0;
+ /// Returns in the set results that are stored as modified or generated in this result
+ MODELAPI_EXPORT virtual void modifiedSources(std::list<ResultPtr>& theSources) = 0;
+
protected:
/// Default constructor accessible only from Model_Objects
MODELAPI_EXPORT ModelAPI_ResultBody();
return aResList;
}
+std::shared_ptr<ModelAPI_Result> singleEvolution(const std::string theEntry)
+{
+ ResultPtr aRes;
+ std::size_t aFirstColon = theEntry.find(":");
+ if (aFirstColon == std::string::npos)
+ return aRes;
+ // searching a part
+ std::string aPartIdStr = theEntry.substr(0, aFirstColon);
+ int aPartId = std::stoi(aPartIdStr);
+ SessionPtr aSession = ModelAPI_Session::get();
+ DocumentPtr aRoot = aSession->moduleDocument();
+ int aRootFeatures = aRoot->size(ModelAPI_Feature::group());
+ FeaturePtr aPartFeat;
+ for(int aRootId = 0; aRootId < aRootFeatures; aRootId++) {
+ ObjectPtr aRootObj = aRoot->object(ModelAPI_Feature::group(), aRootId);
+ FeaturePtr aRootFeat = std::dynamic_pointer_cast<ModelAPI_Feature>(aRootObj);
+ if (aRootFeat.get()) {
+ DataPtr aData = aRootFeat->data();
+ if (aData.get() && aData->isValid() && aData->featureId() == aPartId) {
+ aPartFeat = aRootFeat;
+ break;
+ }
+ }
+ }
+ if (!aPartFeat.get() || aPartFeat->results().empty())
+ return aRes;
+ DocumentPtr aPartDoc = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeat->firstResult())->partDoc();
+ if (!aPartDoc.get())
+ return aRes;
+ // searching a feature
+ std::string aFeatIdStr = theEntry.substr(aFirstColon + 1);
+ std::string aResIdStr;
+ std::size_t aSecondColon = aFeatIdStr.find(":");
+ if (aSecondColon != std::string::npos) {
+ aResIdStr = aFeatIdStr.substr(aSecondColon + 1);
+ aFeatIdStr = aFeatIdStr.substr(0, aSecondColon);
+ }
+ int aFeatId = std::stoi(aFeatIdStr);
+ int aFeaturesNum = aPartDoc->size(ModelAPI_Feature::group());
+ FeaturePtr aFeat;
+ for(int anId = 0; anId < aFeaturesNum; anId++) {
+ ObjectPtr anObj = aPartDoc->object(ModelAPI_Feature::group(), anId);
+ aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>(anObj);
+ if (aFeat.get()) {
+ DataPtr aData = aFeat->data();
+ if (aData.get() && aData->isValid() && aData->featureId() == aFeatId)
+ break;
+ aFeat.reset();
+ }
+ }
+ if (!aFeat.get() || aFeat->results().empty())
+ return aRes;
+ // searching for a result
+ int aResId = 0;
+ if (!aResIdStr.empty()) {
+ aResId = std::stoi(aResIdStr);
+ }
+ ResultPtr anOldRes;
+ std::list<ResultPtr>::const_iterator aResIt = aFeat->results().cbegin();
+ for(; aResIt != aFeat->results().cend(); aResIt++) {
+ if (aResId == 0) {
+ anOldRes = *aResIt;
+ break;
+ }
+ aResId--;
+ }
+ if (!anOldRes.get() || !anOldRes->shape().get())
+ return aRes;
+ // searching for a new result
+ std::list<ResultPtr> allRes;
+ allResults(aFeat, allRes);
+ std::list<ObjectPtr> allObjs;
+ allObjs.push_back(aFeat);
+ for(std::list<ResultPtr>::iterator anIter = allRes.begin(); anIter != allRes.end(); anIter++)
+ allObjs.push_back(*anIter);
+ ModelAPI_ValidatorsFactory* aValidators = aSession->validators();
+ FeaturePtr aConcealer;
+ for(std::list<ObjectPtr>::iterator anOld = allObjs.begin(); anOld != allObjs.end(); anOld++) {
+ const std::set<AttributePtr>& aRefs = (*anOld)->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aRefIt = aRefs.cbegin();
+ for(; aRefIt != aRefs.end(); aRefIt++) {
+ FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIt)->owner());
+ if (!aRefFeat.get())
+ continue;
+ if (!aValidators->isConcealed(aRefFeat->getKind(), (*aRefIt)->id()))
+ continue; // use only concealed attributes
+ if (aConcealer.get() && aConcealer != aRefFeat)
+ return aRes; // multiple concealers
+ aConcealer = aRefFeat;
+ }
+ }
+ if (!aConcealer.get() || aConcealer->results().size() != 1)
+ return aRes; // no new features at all or concealer contains may result
+ if (!aConcealer->firstResult()->shape().get() || aConcealer->firstResult()->shape()->shapeType() != anOldRes->shape()->shapeType())
+ return aRes; // shapes in old and new results are not of the same type
+ aRes = aConcealer->firstResult();
+
+ ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aRes);
+ if (aBody.get()) {
+ std::list<ResultPtr> aSources;
+ aBody->modifiedSources(aSources);
+ if (aSources.empty())
+ return ResultPtr(); // no sources of modification stored in the data tree
+ std::list<ResultPtr>::iterator aSourceIter = aSources.begin();
+ for(; aSourceIter != aSources.end(); aSourceIter++) {
+ FeaturePtr aSourceFeat = aPartDoc->feature(*aSourceIter);
+ if (!aSourceFeat.get())
+ return ResultPtr(); // invalid feature or feature from other document
+ if (aSourceFeat != aFeat)
+ return ResultPtr(); // modied by other feature
+ }
+ }
+ return aRes;
+}
+
// LCOV_EXCL_STOP
} // namespace ModelAPI_Tools
std::shared_ptr<ModelAPI_Result> theTarget, const std::string& theFeatureKind,
const bool theSortResults);
+/*! Returns the result that was created from theEntry result: only this result is created, same shape type,
+ * only from this result the result is created.
+* \param theEntry string that identifies a result (part feature id):(feature is)[:(result number in the feature)]
+*/
+MODELAPI_EXPORT std::shared_ptr<ModelAPI_Result> singleEvolution(const std::string theEntry);
}
#endif