#include <TDF_ChildIDIterator.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
+#include <Geom_TrimmedCurve.hxx>
#include <BRep_Builder.hxx>
//#define DEB_NAMING 1
} else if (theContext->groupName() == ModelAPI_ResultGroup::group()) {
aSelLab.ForgetAllAttributes(true);
TDataStd_UAttribute::Set(aSelLab, kSIMPLE_REF_ID);
- } else { // check the feature context: parent-Part of this feature should not be used
+ } else { // check the feature context: only construction features of PartSet could be selected
FeaturePtr aFeatureContext = std::dynamic_pointer_cast<ModelAPI_Feature>(theContext);
- if (aFeatureContext.get()) {
- if (owner()->document() != aFeatureContext->document()) {
+ if (aFeatureContext.get() && owner()->document() != aFeatureContext->document()) {
+ if (aFeatureContext->results().empty() ||
+ aFeatureContext->firstResult()->groupName() != ModelAPI_ResultConstruction::group()) {
aSelLab.ForgetAllAttributes(true);
myRef.setValue(ObjectPtr());
if (aToUnblock)
}
}
-// returns the center of the edge: circular or elliptical
+// returns the center of the edge: circular or elliptic
GeomShapePtr centerByEdge(GeomShapePtr theEdge, ModelAPI_AttributeSelection::CenterType theType)
{
if (theType != ModelAPI_AttributeSelection::NOT_CENTER && theEdge.get() != NULL) {
TopoDS_Vertex aVertex;
BRep_Builder aBuilder;
if (theType == ModelAPI_AttributeSelection::CIRCLE_CENTER) {
+ while(!aCurve.IsNull() && aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+ aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(aCurve);
if (!aCirc.IsNull()) {
aBuilder.MakeVertex(aVertex, aCirc->Location(), Precision::Confusion());
}
} else { // ellipse
+ while(!aCurve.IsNull() && aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+ aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
Handle(Geom_Ellipse) anEll = Handle(Geom_Ellipse)::DownCast(aCurve);
if (!anEll.IsNull()) {
aBuilder.MakeVertex(aVertex,
std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
{
- if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
+ if (!myRef.isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
return std::shared_ptr<GeomAPI_Shape>();
CenterType aType = NOT_CENTER;
std::shared_ptr<GeomAPI_Shape> aResult = internalValue(aType);
bool Model_AttributeSelection::isInitialized()
{
- if (ModelAPI_AttributeSelection::isInitialized()) { // additional checks if it is initialized
- std::shared_ptr<GeomAPI_Shape> aResult;
- if (myRef.isInitialized()) {
- TDF_Label aSelLab = selectionLabel();
- // it is just reference to shape, not sub-shape
- if (aSelLab.IsAttribute(kSIMPLE_REF_ID) || aSelLab.IsAttribute(kPART_REF_ID)) {
- ResultPtr aContext = context();
- return aContext.get() != NULL;
- }
- Handle(TNaming_NamedShape) aSelection;
- if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
- return !aSelection->Get().IsNull();
- } else { // for simple construction element: just shape of this construction element
- if (myRef.value().get())
- return true;
- // check that this is on open of document, so, results are not initialized yet
- TDF_Label aRefLab = myRef.myRef->Get();
- if (aRefLab.IsNull() || !owner().get())
- return false;
- std::shared_ptr<Model_Document> aMyDoc =
- std::dynamic_pointer_cast<Model_Document>(owner()->document());
- if (!aMyDoc.get())
- return false;
- // check at least the feature exists
- return aMyDoc->featureByLab(aRefLab).get() != NULL;
- }
+ if (myRef.isInitialized()) {
+ TDF_Label aSelLab = selectionLabel();
+ // it is just reference to shape, not sub-shape
+ if (aSelLab.IsAttribute(kSIMPLE_REF_ID) || aSelLab.IsAttribute(kPART_REF_ID)) {
+ ResultPtr aContext = context();
+ return aContext.get() != NULL;
+ }
+ Handle(TNaming_NamedShape) aSelection;
+ if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
+ return !aSelection->Get().IsNull();
+ } else { // for simple construction element: just shape of this construction element
+ if (myRef.value().get())
+ return true;
+ // check that this is on open of document, so, results are not initialized yet
+ TDF_Label aRefLab = myRef.myRef->Get();
+ if (aRefLab.IsNull() || !owner().get())
+ return false;
+ std::shared_ptr<Model_Document> aMyDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ if (!aMyDoc.get())
+ return false;
+ // check at least the feature exists
+ return aMyDoc->featureByLab(aRefLab).get() != NULL;
}
}
return false;
ResultPtr Model_AttributeSelection::context()
{
- if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
+ if (!myRef.isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
return ResultPtr();
if (myTmpContext.get() || myTmpSubShape.get()) {
TopoDS_Shape aContextShape = aContext->shape()->impl<TopoDS_Shape>();
Selector_Selector aSelector(aSelLab, baseDocumentLab());
aResult = aSelector.restore(aContextShape);
+ bool aWasInvalid = aSelLab.IsAttribute(kINVALID_SELECTION);
setInvalidIfFalse(aSelLab, aResult);
TopoDS_Shape aNewShape;
if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
aNewShape = aNS->Get();
- if (anOldShape.IsNull() || aNewShape.IsNull() || !anOldShape.IsEqual(aNewShape)) {
+ if (anOldShape.IsNull() || aNewShape.IsNull() || !anOldShape.IsEqual(aNewShape) || aWasInvalid)
+ {
// shape type should not be changed: if shape becomes compound of such shapes, then split
if (myParent && !anOldShape.IsNull() && !aNewShape.IsNull() &&
anOldShape.ShapeType() != aNewShape.ShapeType() &&
aNewShape.ShapeType() == TopAbs_COMPOUND) {
split(aContext, aNewShape, anOldShape.ShapeType());
}
+ // for issue #3076 check that the new value belongs to the new context
+ if (!aNewShape.IsNull() && !aContextShape.IsNull() &&
+ (aNewShape.ShapeType() == TopAbs_VERTEX || aNewShape.ShapeType() == TopAbs_EDGE ||
+ aNewShape.ShapeType() == TopAbs_FACE)) {
+ TopExp_Explorer anExp(aContextShape, aNewShape.ShapeType());
+ for(; anExp.More(); anExp.Next()) {
+ if (anExp.Current().IsSame(aNewShape))
+ break;
+ }
+ aResult = setInvalidIfFalse(aSelLab, anExp.More());
+ }
owner()->data()->sendAttributeUpdated(this); // send updated if shape is changed
}
return aResult;
CenterType aCenterType = NOT_CENTER;
std::shared_ptr<GeomAPI_Shape> aSubSh = internalValue(aCenterType);
- ResultPtr aCont = context();
- if (!aCont.get() ||
- (aCont->groupName() == ModelAPI_ResultConstruction::group() && contextFeature().get())) {
+ FeaturePtr aContFeature = contextFeature();
+ if (aContFeature.get()) {
+ std::string aResName;
+ // checking part-owner
+ if (aContFeature->document() != owner()->document())
+ aResName += aContFeature->document()->kind() + "/";
// selection of a full feature
- FeaturePtr aFeatureCont = contextFeature();
- if (aFeatureCont.get()) {
- return kWHOLE_FEATURE + aFeatureCont->name();
+ if (aContFeature.get()) {
+ return aResName + kWHOLE_FEATURE + aContFeature->name();
}
// in case of selection of removed result
return "";
}
+ ResultPtr aCont = context();
TDF_Label aSelLab = selectionLabel();
if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // whole context, no value
return contextName(aCont);
if (aCont->groupName() == ModelAPI_ResultPart::group()) {
ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aCont);
int anIndex;
- GeomShapePtr aValue = value();
- if (aValue.get())
- return aPart->data()->name() + "/" + aPart->nameInPart(aValue, anIndex);
- else
- return aPart->data()->name();
+ std::string aResult = aSubSh.get() ?
+ aPart->data()->name() + "/" + aPart->nameInPart(aSubSh, anIndex) : aPart->data()->name();
+ if (aCenterType != NOT_CENTER)
+ aResult += centersMap()[aCenterType];
+ return aResult;
}
-
// whole infinitive construction
if (aCont->groupName() == ModelAPI_ResultConstruction::group()) {
ResultConstructionPtr aConstr = std::dynamic_pointer_cast<Model_ResultConstruction>(aCont);
}
}
+
+void Model_AttributeSelection::concealedFeature(
+ const FeaturePtr theFeature, const FeaturePtr theStop, const bool theCheckCopy,
+ std::list<FeaturePtr>& theConcealers, const ResultPtr theResultOfFeature)
+{
+ std::set<FeaturePtr> alreadyProcessed;
+ alreadyProcessed.insert(theFeature);
+ if (theStop.get())
+ alreadyProcessed.insert(theStop);
+ /// iterate all results to find the concealment-attribute
+ std::list<ResultPtr> aRootRes;
+ if (theResultOfFeature.get()) {
+ ResultPtr aRoot = ModelAPI_Tools::bodyOwner(theResultOfFeature, true);
+ aRootRes.push_back(aRoot ? aRoot : theResultOfFeature);
+ } else { // all results of a feature
+ aRootRes = theFeature->results();
+ }
+ std::list<ResultPtr>::const_iterator aRootIter = aRootRes.cbegin();
+ for(; aRootIter != aRootRes.cend(); aRootIter++) {
+ std::list<ResultPtr> allRes;
+ allRes.push_back(*aRootIter);
+ ResultBodyPtr aRootBody = ModelAPI_Tools::bodyOwner(*aRootIter, true);
+ if (!aRootBody.get())
+ aRootBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRootIter);
+ if (aRootBody.get()) {
+ ModelAPI_Tools::allSubs(aRootBody, allRes);
+ }
+ for(std::list<ResultPtr>::iterator aRIter = allRes.begin(); aRIter != allRes.end(); aRIter++) {
+ const std::set<AttributePtr>& aRefs = (*aRIter)->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aRef = aRefs.cbegin();
+ for (; aRef != aRefs.cend(); aRef++) {
+ if (!aRef->get() || !(*aRef)->owner().get())
+ continue;
+ // concealed attribute only
+ FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+ if (alreadyProcessed.find(aRefFeat) != alreadyProcessed.end()) // optimization
+ continue;
+ alreadyProcessed.insert(aRefFeat);
+ if (ModelAPI_Session::get()->validators()->isConcealed(aRefFeat->getKind(), (*aRef)->id())
+ || (theCheckCopy &&
+ std::dynamic_pointer_cast<ModelAPI_FeatureCopyInterface>(aRefFeat).get()))
+ {
+ // for extrusion cut in python script the nested sketch reference may be concealed before
+ // it is nested, so, check this composite feature is valid
+ static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+ // need to be validated to update the "Apply" state if not previewed
+ if (aFactory->validate(aRefFeat)) {
+ if (theStop.get()) {
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(theStop->document());
+ if (!aDoc->isLaterByDep(theStop, aRefFeat)) // skip feature later than stop
+ continue;
+ }
+ theConcealers.push_back(aRefFeat);
+ }
+ }
+ }
+ }
+ }
+}
+
bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document> theDoc,
const TopoDS_Shape theContShape, ResultPtr theContext, TopoDS_Shape theValShape,
TDF_Label theAccessLabel,
} else aResIter++;
}
+ bool aStaySame = false;
if (aResults.empty()) {
// check the context become concealed by operation which is earlier than this selection
- std::list<ResultPtr> allRes;
- ResultPtr aRoot = ModelAPI_Tools::bodyOwner(theContext, true);
- if (!aRoot.get())
- aRoot = theContext;
- ResultBodyPtr aRootBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aRoot);
- if (aRootBody.get()) {
- ModelAPI_Tools::allSubs(aRootBody, allRes);
- allRes.push_back(aRootBody);
- } else
- allRes.push_back(aRoot);
-
FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
- for (std::list<ResultPtr>::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) {
- ResultPtr aResCont = *aSub;
- const std::set<AttributePtr>& aRefs = aResCont->data()->refsToMe();
- std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
- for (; aRef != aRefs.end(); aRef++) {
- if (!aRef->get() || !(*aRef)->owner().get())
+ FeaturePtr aContextOwner = theDoc->feature(theContext);
+ std::list<FeaturePtr> aConcealers;
+ concealedFeature(aContextOwner, aThisFeature, false, aConcealers, theContext);
+ std::list<FeaturePtr>::iterator aConcealer = aConcealers.begin();
+ for(; aConcealer != aConcealers.end(); aConcealer++) {
+ std::list<ResultPtr> aRefResults;
+ ModelAPI_Tools::allResults(*aConcealer, aRefResults);
+ std::list<ResultPtr>::iterator aRefIter = aRefResults.begin();
+ for(; aRefIter != aRefResults.end(); aRefIter++) {
+ ResultBodyPtr aRefBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRefIter);
+ if (!aRefBody.get() || aRefBody->numberOfSubs() != 0) // iterate only leafs
continue;
- // concealed attribute only
- FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
- if (aRefFeat == aThisFeature)
+ GeomShapePtr aRefShape = aRefBody->shape();
+ if (!aRefShape.get() || aRefShape->isNull())
continue;
- if (!ModelAPI_Session::get()->validators()->isConcealed(
- aRefFeat->getKind(), (*aRef)->id()))
- continue;
- if (theDoc->isLaterByDep(aThisFeature, aRefFeat)) {
- // for extrusion cut in python script the nested sketch reference may be concealed before
- // it is nested, so, check this composite feature is valid
- static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
- // need to be validated to update the "Apply" state if not previewed
- if (aFactory->validate(aRefFeat)) {
- // there could be a reference to unmodified object, check result contain same shape
- std::list<ResultPtr> aRefResults;
- ModelAPI_Tools::allResults(aRefFeat, aRefResults);
- std::list<ResultPtr>::iterator aRefIter = aRefResults.begin();
- for(; aRefIter != aRefResults.end(); aRefIter++) {
- ResultBodyPtr aRefBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRefIter);
- if (!aRefBody.get() || aRefBody->numberOfSubs() != 0) // iterate only leafs
- continue;
- GeomShapePtr aRefShape = aRefBody->shape();
- if (!aRefShape.get() || aRefShape->isNull())
- continue;
- if (aRefShape->impl<TopoDS_Shape>().IsSame(theContShape)) {
- // add the new context result with the same shape
- aResults.insert(aRefBody);
- }
- }
- if (aResults.empty())
- return true; // feature conceals result, return true, so the context will be removed
- }
+ if (aRefShape->impl<TopoDS_Shape>().IsSame(theContShape)) {
+ // add the new context result with the same shape
+ aResults.insert(aRefBody);
}
}
+ if (aResults.empty())
+ return true; // feature conceals result, return true, so the context will be removed
+ }
+ aStaySame = aResults.empty();
+ }
+ if (myParent && myParent->isMakeCopy()) {
+ // check there are copies before the new results, so, make a copy
+ std::set<ResultPtr>::iterator aResIter = aResults.begin();
+ std::list<ObjectPtr> aCopyContext;
+ std::list<GeomShapePtr> aCopyVals;
+ // features between the new and the old: check the "Move" interface to get a copy
+ FeaturePtr aRootOwner = theDoc->feature(theContext);
+ FeaturePtr anOwner = ModelAPI_Tools::compositeOwner(aRootOwner);
+ for(; anOwner.get(); anOwner = ModelAPI_Tools::compositeOwner(anOwner))
+ aRootOwner = anOwner;
+ FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ // iterate all results to find a "Copy" features between the new and one and to add the
+ // copy-results also to results if this attribute refers to the copied shape
+ int anIndex = kUNDEFINED_FEATURE_INDEX;
+ for(FeaturePtr aFeat = theDoc->objects()->nextFeature(aRootOwner, anIndex); aFeat.get() &&
+ aFeat != aThisFeature; aFeat = theDoc->objects()->nextFeature(aFeat, anIndex)) {
+ std::shared_ptr<ModelAPI_FeatureCopyInterface> aCopier =
+ std::dynamic_pointer_cast<ModelAPI_FeatureCopyInterface>(aFeat);
+ if (aCopier.get()) {
+ GeomShapePtr aValShape(new GeomAPI_Shape);
+ aValShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(
+ theValShape.IsNull() ? theContShape : theValShape));
+ aCopier->getCopies(theContext, aValShape, aCopyContext, aCopyVals);
+ }
+ }
+ // check for the further modifications of the copy contexts and values
+ std::list<ObjectPtr>::iterator aCopyContIter = aCopyContext.begin();
+ std::list<GeomShapePtr>::iterator aCopyValIter = aCopyVals.begin();
+ for(; aCopyContIter != aCopyContext.end(); aCopyContIter++, aCopyValIter++) {
+ ResultPtr aNewCont = std::dynamic_pointer_cast<ModelAPI_Result>(*aCopyContIter);
+ TopoDS_Shape aNewContShape = aNewCont->shape()->impl<TopoDS_Shape>();
+ GeomShapePtr aNewVal = *aCopyValIter;
+ TopoDS_Shape aNewValShape;
+ if (aNewVal.get() && !aNewVal->isNull())
+ aNewValShape = aNewVal->impl<TopoDS_Shape>();
+ std::list<ResultPtr> aNewRes;
+ TopTools_ListOfShape aNewUpdatedVal;
+ if (searchNewContext(theDoc, aNewContShape, aNewCont, aNewValShape,
+ theAccessLabel, aNewRes, aNewUpdatedVal)) {
+ // append new results instead of the current ones
+ std::list<ResultPtr>::iterator aNewIter = aNewRes.begin();
+ TopTools_ListIteratorOfListOfShape aNewUpdVal(aNewUpdatedVal);
+ for(; aNewIter != aNewRes.end(); aNewIter++, aNewUpdVal.Next()) {
+ theResults.push_back(*aNewIter);
+ theValShapes.Append(aNewUpdVal.Value());
+ }
+ } else { // the current result is good
+ theResults.push_back(aNewCont);
+ theValShapes.Append(aNewValShape);
+ }
+ }
+ if (aStaySame && !theResults.empty()) { // no changes except copy, so, keep the origin as first
+ theResults.push_front(theContext);
+ theValShapes.Prepend(theValShape);
+ return true;
}
- if (aResults.empty())
- return false; // no modifications found, must stay the same
}
+ if (aStaySame)
+ return false;
+
// iterate all results to find further modifications
std::set<ResultPtr>::iterator aResIter = aResults.begin();
- for(; aResIter != aResults.end(); aResIter++) {
+ for(aResIter = aResults.begin(); aResIter != aResults.end(); aResIter++) {
if (aResIter->get() != NULL) {
+ ResultPtr aNewResObj = *aResIter;
// compute new values by two contexts: the old and the new
TopTools_ListOfShape aValShapes;
- computeValues(theContext, *aResIter, theValShape, aValShapes);
+ computeValues(theContext, aNewResObj, theValShape, aValShapes);
TopTools_ListIteratorOfListOfShape aNewVal(aValShapes);
for(; aNewVal.More(); aNewVal.Next()) {
std::list<ResultPtr> aNewRes;
TopTools_ListOfShape aNewUpdatedVal;
TopoDS_Shape aNewValSh = aNewVal.Value();
- TopoDS_Shape aNewContShape = (*aResIter)->shape()->impl<TopoDS_Shape>();
+ TopoDS_Shape aNewContShape = aNewResObj->shape()->impl<TopoDS_Shape>();
+
if (theValShape.IsNull() && aNewContShape.IsSame(aNewValSh))
aNewValSh.Nullify();
- if (searchNewContext(theDoc, aNewContShape, *aResIter, aNewValSh,
+ if (searchNewContext(theDoc, aNewContShape, aNewResObj, aNewValSh,
theAccessLabel, aNewRes, aNewUpdatedVal))
{
// append new results instead of the current ones
theValShapes.Append(aNewUpdVal.Value());
}
} else { // the current result is good
- theResults.push_back(*aResIter);
+ theResults.push_back(aNewResObj);
theValShapes.Append(aNewValSh);
}
}
void Model_AttributeSelection::updateInHistory(bool& theRemove)
{
+ static std::shared_ptr<GeomAPI_Shape> anEmptyShape;
+
ResultPtr aContext = std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
- // only bodies and parts may be modified later in the history, don't do anything otherwise
if (!aContext.get() || (aContext->groupName() != ModelAPI_ResultBody::group() &&
- aContext->groupName() != ModelAPI_ResultPart::group()))
- return;
+ aContext->groupName() != ModelAPI_ResultPart::group())) {
+ // but check the case the whole results are allowed: whole features may be selected
+ if (myParent && myParent->isWholeResultAllowed()) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(myRef.value());
+ if (aFeature.get()) {
+ FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ std::list<FeaturePtr> aConcealers;
+ bool aCopyPossible = myParent && myParent->isMakeCopy();
+ concealedFeature(aFeature, aThisFeature, aCopyPossible, aConcealers, ResultPtr());
+ if (aConcealers.empty())
+ return;
+ // if there are copies, but no direct modification, keep the original
+ bool aKeepOrigin = false;
+ if (aCopyPossible) {
+ std::list<FeaturePtr>::iterator aConcealer = aConcealers.begin();
+ for(aKeepOrigin = true; aConcealer != aConcealers.end(); aConcealer++)
+ if (!std::dynamic_pointer_cast<ModelAPI_FeatureCopyInterface>(*aConcealer).get()) {
+ aKeepOrigin = false;
+ break;
+ }
+ if (aKeepOrigin) {
+ aConcealers.push_front(aFeature);
+ }
+ }
+ bool aChanged = false;
+ std::list<FeaturePtr>::iterator aConcealer = aConcealers.begin();
+ for(; aConcealer != aConcealers.end(); aConcealer++)
+ if (aChanged) {
+ if (aKeepOrigin || !myParent->isInList(*aConcealer, anEmptyShape))
+ myParent->append(*aConcealer, anEmptyShape);
+ } else {
+ if (!myParent->isInList(*aConcealer, anEmptyShape)) {// avoid addition of duplicates
+ setValue(*aConcealer, anEmptyShape);
+ aChanged = true;
+ } else if (aCopyPossible && *aConcealer == aFeature) {// keep origin in case of copy
+ aChanged = true;
+ }
+ }
+ if (!aChanged) // remove this
+ theRemove = true;
+ else if (!aKeepOrigin) // searching further modifications only if current changed
+ updateInHistory(theRemove);
+ }
+ }
+ return;// only bodies and parts may be modified later in the history, skip otherwise
+ }
+
std::shared_ptr<Model_Document> aDoc =
std::dynamic_pointer_cast<Model_Document>(aContext->document());
std::shared_ptr<Model_Data> aContData = std::dynamic_pointer_cast<Model_Data>(aContext->data());
aListShapeType = GeomAPI_Shape::FACE;
}
+ // issue #3031: skip topology if there is more convenient shape type presents in the
+ // same context as a result of this
+ bool isWholeResult = myParent && myParent->isWholeResultAllowed() && !aSubShape.get();
+ GeomAPI_Shape::ShapeType allowedType = GeomAPI_Shape::SHAPE;
+ if (isWholeResult) {
+ std::list<ResultPtr>::iterator aNewCont = aNewContexts.begin();
+ TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
+ for(; aNewCont != aNewContexts.end(); aNewCont++, aNewValues.Next()) {
+ if (aNewValues.Value().IsNull()) { // only for the whole context
+ GeomAPI_Shape::ShapeType aShapeType = (*aNewCont)->shape()->shapeType();
+ if (allowedType == GeomAPI_Shape::SHAPE) { // just set this one
+ allowedType = aShapeType;
+ } else {
+ GeomAPI_Shape::ShapeType anAllowed = allowedType;
+ if (anAllowed != aShapeType) { // select the best, nearest to the origin
+ GeomAPI_Shape::ShapeType anOldShapeType = aContext->shape()->shapeType();
+ GeomAPI_Shape::ShapeType aDeltaAllowed =
+ (GeomAPI_Shape::ShapeType)(anOldShapeType - anAllowed);
+ if (aDeltaAllowed < 0)
+ aDeltaAllowed = (GeomAPI_Shape::ShapeType)(-aDeltaAllowed);
+ GeomAPI_Shape::ShapeType aDeltaThis =
+ (GeomAPI_Shape::ShapeType)(anOldShapeType - aShapeType);
+ if (aDeltaThis < 0)
+ aDeltaThis = (GeomAPI_Shape::ShapeType)(-aDeltaThis);
+ if (aDeltaThis == aDeltaAllowed) { // equal distance to context, select complicated
+ if (anOldShapeType < anAllowed)
+ allowedType = aShapeType;
+ } else if (aDeltaAllowed > aDeltaThis) { // this wins
+ allowedType = aShapeType;
+ }
+ }
+ }
+ }
+ }
+ }
+
std::list<ResultPtr>::iterator aNewCont = aNewContexts.begin();
TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
bool aFirst = true; // first is set to this, next are appended to parent
if (aSkippedContext.count(*aNewCont))
continue;
+ if (isWholeResult && aNewValues.Value().IsNull())
+ if (allowedType != GeomAPI_Shape::SHAPE &&
+ (*aNewCont)->shape()->shapeType() != allowedType)
+ continue; // there is better result exists with the better shape type (issue #3031)
+
GeomShapePtr aValueShape;
if (!aNewValues.Value().IsNull()) {
aValueShape = std::make_shared<GeomAPI_Shape>();
aShapeShapeType = (*aNewCont)->shape()->shapeType();
}
if (aListShapeType != GeomAPI_Shape::SHAPE && aListShapeType != aShapeShapeType) {
- continue;
+ // exception is for whole results selected
+ if (!isWholeResult) {
+ continue;
+ }
}
ResultPtr aNewContext = *aNewCont;
if (!myParent || !myParent->isInList(aNewContext, aValueShape)) { // avoid duplicates
setValue(aNewContext, aValueShape);
aFirst = false;
+ } else if (aNewContext == aContext && myParent && myParent->isMakeCopy()) {
+ // this may be exactly the old one, not modified in case of copy
+ aFirst = false;
}
} else if (myParent) {
if (!myParent->isInList(aNewContext, aValueShape)) // avoid addition of duplicates
if (myParent) {
theRemove = true;
} else {
- ResultPtr anEmptyContext;
- std::shared_ptr<GeomAPI_Shape> anEmptyShape;
+ static ResultPtr anEmptyContext;
setValue(anEmptyContext, anEmptyShape); // nullify the selection
return;
}
static TDF_Label anEmpty;
return anEmpty;
}
+
+void Model_AttributeSelection::reset()
+{
+ ModelAPI_AttributeSelection::reset();
+ myRef.reset();
+}