}
}
+void Model_BodyBuilder::cleanCash()
+{
+ myPrimitivesNamesIndexMap.clear();
+}
+
Model_BodyBuilder::~Model_BodyBuilder()
{
clean();
/// Removes the stored builders
MODEL_EXPORT virtual ~Model_BodyBuilder();
+ /// Cleans cash related to the already stored elements
+ MODEL_EXPORT virtual void cleanCash() override;
protected:
/// Default constructor accessible only by Model_Objects
Model_BodyBuilder(ModelAPI_Object* theOwner);
Handle(Model_Application) anApp = Model_Application::getApplication();
if (isRoot()) {
#ifdef WIN32
- CreateDirectory((LPTSTR) theDirName, NULL);
+ size_t aDirLen = strlen(theDirName);
+ std::wstring aWStr(aDirLen, L'#');
+ mbstowcs(&aWStr[0], theDirName, aDirLen);
+ CreateDirectory(aWStr.c_str(), NULL);
#else
mkdir(theDirName, 0x1ff);
#endif
aSub = mySubs[aSubIndex];
}
GeomShapePtr anOldSubShape = aSub->shape();
- aSub->store(aShape, false); // store even equal to call "clear": #2814
if (!aShape->isEqual(anOldSubShape)) {
+ aSub->store(aShape, false);
aECreator->sendUpdated(aSub, EVENT_DISP);
aECreator->sendUpdated(aSub, EVENT_UPD);
}
// redisplay this because result with and without subs are displayed differently
aECreator->sendUpdated(data()->owner(), EVENT_DISP);
}
+ cleanCash();
} else if (!mySubs.empty()) { // erase all subs
while(!mySubs.empty()) {
ResultBodyPtr anErased = *(mySubs.rbegin());
}
return false; // invalid case
}
+
+void Model_ResultBody::cleanCash()
+{
+ myBuilder->cleanCash();
+ for (std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+ aSubIter != mySubs.cend(); ++aSubIter)
+ {
+ const ResultBodyPtr& aSub = *aSubIter;
+ aSub->cleanCash();
+ }
+}
/// Returns true is the topology is connected.
MODEL_EXPORT virtual bool isConnectedTopology();
+ /// Cleans cash related to the already stored elements
+ MODEL_EXPORT virtual void cleanCash() override;
+
protected:
/// Makes a body on the given feature
Model_ResultBody();
virtual void loadFirstLevel(GeomShapePtr theShape,
const std::string& theName) = 0;
+ /// Cleans cash related to the already stored elements
+ MODELAPI_EXPORT virtual void cleanCash() = 0;
+
protected:
/// Returns the data manager of this object: attributes
MODELAPI_EXPORT virtual std::shared_ptr<ModelAPI_Data> data() const;
MODELAPI_EXPORT virtual void updateSubs(const GeomShapePtr& theThisShape,
const bool theShapeChanged = true) = 0;
+ /// Cleans cash related to the already stored elements
+ MODELAPI_EXPORT virtual void cleanCash() = 0;
+
protected:
/// Default constructor accessible only from Model_Objects
MODELAPI_EXPORT ModelAPI_ResultBody();
myAlwaysGeometricalNaming = false;
}
+static TDF_Label findGoodLabelWithShape(const TDF_Label theAccess, const TopoDS_Shape& theShape) {
+ TDF_Label aResult;
+ if (TNaming_Tool::HasLabel(theAccess, theShape)) { // selection and delete evolution are not used
+ for(TNaming_SameShapeIterator aShapes(theShape, theAccess); aShapes.More(); aShapes.Next())
+ {
+ Handle(TNaming_NamedShape) aNS;
+ if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
+ aNS->Evolution() == TNaming_PRIMITIVE) {
+ aResult = aNS->Label();
+ break;
+ }
+ }
+ }
+ }
+ return aResult;
+}
+
#define SET_ALGO_FLAGS(algo) \
algo->myLab = theAccess; \
algo->myBaseDocumentLab = theBaseDocument; \
// check the value shape can be named as it is, or it is needed to construct it from the
// higher level shapes (like a box vertex by faces that form this vertex)
- bool aIsFound = TNaming_Tool::HasLabel(theAccess, theValue);
- if (aIsFound) { // additional check for selection and delete evolution only: also could not use
- aIsFound = false;
- for(TNaming_SameShapeIterator aShapes(theValue, theAccess); aShapes.More(); aShapes.Next())
- {
- Handle(TNaming_NamedShape) aNS;
- if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
- aNS->Evolution() == TNaming_PRIMITIVE) {
- aIsFound = true;
- break;
- }
- }
- }
- }
- // searching in the base document
- if (!aIsFound && !theBaseDocument.IsNull() && TNaming_Tool::HasLabel(theBaseDocument, theValue))
- {
- TNaming_SameShapeIterator aShapes(theValue, theBaseDocument);
- for(; aShapes.More(); aShapes.Next())
- {
- Handle(TNaming_NamedShape) aNS;
- if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
- aNS->Evolution() == TNaming_PRIMITIVE) {
- aIsFound = true;
- break;
- }
- }
- }
- }
+ bool aIsFound = !findGoodLabelWithShape(theAccess, theValue).IsNull();
+ if (!aIsFound && !theBaseDocument.IsNull()) // searching in the base document
+ aIsFound = !findGoodLabelWithShape(theBaseDocument, theValue).IsNull();
if (!aIsFound) {
TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
// searching by neighbors
Selector_FilterByNeighbors* aNBs = new Selector_FilterByNeighbors;
SET_ALGO_FLAGS(aNBs);
- if (aNBs->select(theContext, theValue)) {
+ // searching a context lab to store in NB algorithm
+ TDF_Label aContextLab = findGoodLabelWithShape(theAccess, theContext);
+ if (aContextLab.IsNull() && !theBaseDocument.IsNull()) // search also in the base document
+ aContextLab = findGoodLabelWithShape(theBaseDocument, theContext);
+ if (aNBs->select(aContextLab, theContext, theValue)) {
delete anIntersect;
return aNBs;
}
// searching by neighbors
Selector_FilterByNeighbors* aNBs = new Selector_FilterByNeighbors;
SET_ALGO_FLAGS(aNBs);
- if (aNBs->select(theContext, theValue)) {
+ // searching a context lab to store in NB algorithm
+ TDF_Label aContextLab = findGoodLabelWithShape(theAccess, theContext);
+ if (aContextLab.IsNull() && !theBaseDocument.IsNull()) // search also in the base document
+ aContextLab = findGoodLabelWithShape(theBaseDocument, theContext);
+ if (aNBs->select(aContextLab, theContext, theValue)) {
delete aModify;
return aNBs;
}
if (aNextModification.IsNull())
continue;
if (isInContext(theContext, aNextModification))
- aResultShapes.Add(aNextModification);
+ // don't add vertices generated from edges
+ if (aNextModification.ShapeType() <= theResult.ShapeType())
+ aResultShapes.Add(aNextModification);
else if (findNewVersion(theContext, aNextModification))
- aResultShapes.Add(aNextModification);
+ if (aNextModification.ShapeType() <= theResult.ShapeType())
+ aResultShapes.Add(aNextModification);
}
}
if (aResultShapes.IsEmpty())
return aGoodCandidate;
}
-bool Selector_FilterByNeighbors::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+bool Selector_FilterByNeighbors::select(
+ const TDF_Label theContextLab, const TopoDS_Shape theContext, const TopoDS_Shape theValue)
{
myShapeType = theValue.ShapeType();
+ myContext = theContextLab;
// searching by neighbors
std::list<std::pair<TopoDS_Shape, int> > aNBs; /// neighbor sub-shape -> level of neighborhood
for(int aLevel = 1; true; aLevel++) {
for(; aSubSel != list().cend(); aSubSel++) {
(*aSubSel)->store();
}
+ // store context reference if exists
+ if (!myContext.IsNull()) {
+ static const TDF_LabelList anEmptyRefList;
+ storeBaseArray(anEmptyRefList, myContext);
+ }
}
bool Selector_FilterByNeighbors::restore()
}
}
}
+ // restore context reference if exists
+ static TDF_LabelList anEmptyRefList;
+ restoreBaseArray(anEmptyRefList, myContext);
+
return myNBLevel.size() == list().size() && !myNBLevel.empty();
}
{
myShapeType = theShapeType;
TDF_Label aContext;
+ std::string aLastLevel; // last level string (after '(' ) to check the context name in the end
for (size_t aStart = 0; aStart != std::string::npos;
aStart = theName.find('(', aStart + 1)) {
size_t anEndPos = theName.find(')', aStart + 1);
anEndPos++) {
aLevel += theName[anEndPos];
}
- if (aLevel.empty())
+ aLastLevel = aLevel;
+ if (aLevel.empty() || aLevel[0] == '_')
myNBLevel.push_back(1); // by default it is 1
else {
int aNum = atoi(aLevel.c_str());
} else
return TDF_Label(); // invalid parentheses
}
+ if (!aLastLevel.empty()) { // get the context
+ size_t aLinePos = aLastLevel.find("_");
+ if (aLinePos != std::string::npos) {
+ std::string aContextName = aLastLevel.substr(aLinePos + 1);
+ if (!aContextName.empty()) {
+ TDF_Label aThisContext, aValue;
+ if (theNameGenerator->restoreContext(aContextName, aThisContext, aValue)) {
+ if (!aThisContext.IsNull())
+ aContext = aThisContext;
+ }
+ }
+ }
+ }
+ myContext = aContext;
return aContext;
}
std::string Selector_FilterByNeighbors::name(Selector_NameGenerator* theNameGenerator)
{
// (nb1)level_if_more_than_1(nb2)level_if_more_than_1(nb3)level_if_more_than_1
+ bool aThisContextNameNeeded = !myContext.IsNull();
+ std::string aContextName;
+ if (aThisContextNameNeeded)
+ aContextName = theNameGenerator->contextName(myContext);
std::string aResult;
std::list<int>::iterator aLevel = myNBLevel.begin();
std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
for(; aSubSel != list().cend(); aSubSel++, aLevel++) {
if (!*aSubSel)
continue;
- aResult += "(" + (*aSubSel)->name(theNameGenerator) + ")";
+ std::string aSubName = (*aSubSel)->name(theNameGenerator);
+ aResult += "(" + aSubName + ")";
if (*aLevel > 1) {
std::ostringstream aLevelStr;
aLevelStr<<*aLevel;
aResult += aLevelStr.str();
}
+ // sub-name already contains the needed context name, so, here it is not needed
+ if (aThisContextNameNeeded && (
+ aSubName.find(aContextName) == 0 || aSubName.substr(1).find(aContextName)) == 0)
+ aThisContextNameNeeded = false;
+ }
+ if (aThisContextNameNeeded) {
+ aResult = aResult + "_" + aContextName;
}
return aResult;
}
{
TopAbs_ShapeEnum myShapeType; ///< type of this shape
std::list<int> myNBLevel; ///< list of integers corresponding to subs neighborhood level
+ TDF_Label myContext; ///< label where the context of filter is stored (needed for python name string)
public:
/// Initializes the selection of this kind
- SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
+ SELECTOR_EXPORT bool select(
+ const TDF_Label theContextLab, const TopoDS_Shape theContext, const TopoDS_Shape theValue);
/// Stores the name to the label and sub-labels tree
SELECTOR_EXPORT virtual void store() override;