X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_AttributeSelection.cpp;h=a46a49662fd19f0cd6188362d16c69d83dcb42ef;hb=853e0eec6016120b641efa6adf427a239cf203cf;hp=4457c08afba2465019076ba435ea31022ba005d4;hpb=98e21a8e5e9de9c658c11c19fac5c4c7060396c5;p=modules%2Fshaper.git diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 4457c08af..a46a49662 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -54,6 +55,7 @@ #include #include #include +#include using namespace std; //#define DEB_NAMING 1 #ifdef DEB_NAMING @@ -68,6 +70,8 @@ Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29"); Standard_GUID kCONSTUCTION_SIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb28"); // reference to Part sub-object Standard_GUID kPART_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb27"); +// selection is invalid after recomputation +Standard_GUID kINVALID_SELECTION("bce47fd7-80fa-4462-9d63-2f58acddd49d"); // on this label is stored: // TNaming_NamedShape - selected shape @@ -76,8 +80,18 @@ Standard_GUID kPART_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb27"); // TDataStd_Integer - type of the selected shape (for construction) // TDF_Reference - from ReferenceAttribute, the context void Model_AttributeSelection::setValue(const ResultPtr& theContext, - const std::shared_ptr& theSubShape) + const std::shared_ptr& theSubShape, const bool theTemporarily) { + if (theTemporarily) { // just keep the stored without DF update + myTmpContext = theContext; + myTmpSubShape = theSubShape; + owner()->data()->sendAttributeUpdated(this); + return; + } else { + myTmpContext.reset(); + myTmpSubShape.reset(); + } + const std::shared_ptr& anOldShape = value(); bool isOldContext = theContext == myRef.value(); bool isOldShape = isOldContext && @@ -91,6 +105,7 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, TDF_Label aSelLab = selectionLabel(); aSelLab.ForgetAttribute(kSIMPLE_REF_ID); aSelLab.ForgetAttribute(kCONSTUCTION_SIMPLE_REF_ID); + aSelLab.ForgetAttribute(kINVALID_SELECTION); bool isDegeneratedEdge = false; // do not use the degenerated edge as a shape, a null context and shape is used in the case @@ -109,7 +124,6 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, if (theContext->groupName() == ModelAPI_ResultBody::group()) { // do not select the whole shape for body:it is already must be in the data framework // equal and null selected objects mean the same: object is equal to context, - // TODO: synchronize with GUI later that it must be null always if (theContext->shape().get() && (theContext->shape()->isEqual(theSubShape) || !theSubShape.get())) { aSelLab.ForgetAllAttributes(true); @@ -122,6 +136,30 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, // to sub, so the whole result is selected aSelLab.ForgetAllAttributes(true); TDataStd_UAttribute::Set(aSelLab, kCONSTUCTION_SIMPLE_REF_ID); + ResultConstructionPtr aConstruction = + std::dynamic_pointer_cast(theContext); + if (aConstruction->isInfinite()) { + // For correct naming selection, put the shape into the naming structure. + // It seems sub-shapes are not needed: only this shape is (and can be ) selected. + TNaming_Builder aBuilder(aSelLab); + aBuilder.Generated(theContext->shape()->impl()); + std::shared_ptr aMyDoc = + std::dynamic_pointer_cast(owner()->document()); + std::string aName = theContext->data()->name(); + aMyDoc->addNamingName(aSelLab, aName); + TDataStd_Name::Set(aSelLab, aName.c_str()); + } else { // for sketch the naming is needed in DS + BRep_Builder aCompoundBuilder; + TopoDS_Compound aComp; + aCompoundBuilder.MakeCompound(aComp); + for(int a = 0; a < aConstruction->facesNum(); a++) { + TopoDS_Shape aFace = aConstruction->face(a)->impl(); + aCompoundBuilder.Add(aComp, aFace); + } + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(aComp)); + selectConstruction(theContext, aShape); + } } else { selectConstruction(theContext, theSubShape); } @@ -142,9 +180,16 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, std::shared_ptr Model_AttributeSelection::value() { + if (myTmpContext.get() || myTmpSubShape.get()) { + return myTmpSubShape; + } + std::shared_ptr aResult; + TDF_Label aSelLab = selectionLabel(); + if (aSelLab.IsAttribute(kINVALID_SELECTION)) + return aResult; + if (myRef.isInitialized()) { - TDF_Label aSelLab = selectionLabel(); if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape ResultPtr aContext = context(); if (!aContext.get()) @@ -187,6 +232,11 @@ std::shared_ptr Model_AttributeSelection::value() return aResult; } +bool Model_AttributeSelection::isInvalid() +{ + return selectionLabel().IsAttribute(kINVALID_SELECTION) == Standard_True; +} + bool Model_AttributeSelection::isInitialized() { if (ModelAPI_AttributeSelection::isInitialized()) { // additional checkings if it is initialized @@ -229,6 +279,10 @@ void Model_AttributeSelection::setID(const std::string theID) } ResultPtr Model_AttributeSelection::context() { + if (myTmpContext.get() || myTmpSubShape.get()) { + return myTmpContext; + } + ResultPtr aResult = std::dynamic_pointer_cast(myRef.value()); // for parts there could be same-data result, so take the last enabled if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group()) { @@ -262,9 +316,32 @@ TDF_LabelMap& Model_AttributeSelection::scope() DocumentPtr aMyDoc = owner()->document(); std::list > allFeatures = aMyDoc->allFeatures(); std::list >::iterator aFIter = allFeatures.begin(); + bool aMePassed = false; + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(owner()); + FeaturePtr aFeature = std::dynamic_pointer_cast(owner()); + CompositeFeaturePtr aCompositeOwner, aCompositeOwnerOwner; + if (aFeature.get()) { + aCompositeOwner = ModelAPI_Tools::compositeOwner(aFeature); + if (aCompositeOwner.get()) { + aCompositeOwnerOwner = ModelAPI_Tools::compositeOwner(aCompositeOwner); + } + } for(; aFIter != allFeatures.end(); aFIter++) { - if (*aFIter == owner()) break; // the left features are created later - if (aFIter->get() && (*aFIter)->data()->isValid()) { + if (*aFIter == owner()) { // the left features are created later (except subs of composite) + aMePassed = true; + continue; + } + bool isInScope = !aMePassed; + if (!isInScope && aComposite.get()) { // try to add sub-elements of composite if this is composite + if (aComposite->isSub(*aFIter)) + isInScope = true; + } + // remove the composite-owner of this feature (sketch in extrusion-cut) + if (isInScope && (aCompositeOwner == *aFIter || aCompositeOwnerOwner == *aFIter)) + isInScope = false; + + if (isInScope && aFIter->get() && (*aFIter)->data()->isValid()) { TDF_Label aFeatureLab = std::dynamic_pointer_cast( (*aFIter)->data())->label().Father(); TDF_ChildIDIterator aNSIter(aFeatureLab, TNaming_NamedShape::GetID(), 1); @@ -293,21 +370,48 @@ int edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge) return 0; // unknown } +/// Sets the invalid flag if flag is false, or removes it if "true" +/// Returns theFlag +static bool setInvalidIfFalse(TDF_Label& theLab, const bool theFlag) { + if (theFlag) { + theLab.ForgetAttribute(kINVALID_SELECTION); + } else { + TDataStd_UAttribute::Set(theLab, kINVALID_SELECTION); + } + return theFlag; +} + bool Model_AttributeSelection::update() { - ResultPtr aContext = context(); - if (!aContext.get()) return false; TDF_Label aSelLab = selectionLabel(); + ResultPtr aContext = context(); + if (!aContext.get()) + return setInvalidIfFalse(aSelLab, false); if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape - return aContext->shape() && !aContext->shape()->isNull(); + return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); } if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, not sub-shape - return aContext->shape() && !aContext->shape()->isNull(); + // if there is a sketch, the sketch-naming must be updated + ResultConstructionPtr aConstruction = + std::dynamic_pointer_cast(aContext); + if (!aConstruction->isInfinite()) { + BRep_Builder aCompoundBuilder; + TopoDS_Compound aComp; + aCompoundBuilder.MakeCompound(aComp); + for(int a = 0; a < aConstruction->facesNum(); a++) { + TopoDS_Shape aFace = aConstruction->face(a)->impl(); + aCompoundBuilder.Add(aComp, aFace); + } + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(aComp)); + selectConstruction(aContext, aShape); + } + return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); } if (aSelLab.IsAttribute(kPART_REF_ID)) { // it is reference to the part object std::shared_ptr aNoSelection; - return selectPart(aContext, aNoSelection, true); + return setInvalidIfFalse(aSelLab, selectPart(aContext, aNoSelection, true)); } if (aContext->groupName() == ModelAPI_ResultBody::group()) { @@ -315,7 +419,7 @@ bool Model_AttributeSelection::update() TNaming_Selector aSelector(aSelLab); bool aResult = aSelector.Solve(scope()) == Standard_True; owner()->data()->sendAttributeUpdated(this); - return aResult; + return setInvalidIfFalse(aSelLab, aResult); } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { // construction: identification by the results indexes, recompute faces and // take the face that more close by the indexes @@ -330,7 +434,7 @@ bool Model_AttributeSelection::update() // getting a type of selected shape Handle(TDataStd_Integer) aTypeAttr; if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) { - return false; + return setInvalidIfFalse(aSelLab, false); } TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get()); // selected indexes will be needed in each "if" @@ -342,13 +446,13 @@ bool Model_AttributeSelection::update() CompositeFeaturePtr aComposite = std::dynamic_pointer_cast(aContextFeature); if (!aComposite.get() || aComposite->numberOfSubs() == 0) { - return false; + return setInvalidIfFalse(aSelLab, false); } if (aShapeType == TopAbs_FACE) { // compound is for the whole sketch selection // If this is a wire with plane defined thin it is a sketch-like object if (!aConstructionContext->facesNum()) // no faces, update can not work correctly - return false; + return setInvalidIfFalse(aSelLab, false); // if there is no edges indexes, any face can be used: take the first std::shared_ptr aNewSelected; if (aNoIndexes) { @@ -391,11 +495,15 @@ bool Model_AttributeSelection::update() TopoDS_Face aFace = TopoDS::Face(aConstructionContext->face(aFaceIndex)->impl()); TopExp_Explorer anEdgesExp(aFace, TopAbs_EDGE); + TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curved (841) for(; anEdgesExp.More(); anEdgesExp.Next()) { TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current()); if (!anEdge.IsNull()) { Standard_Real aFirst, aLast; Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (alreadyProcessed.Contains(aCurve)) + continue; + alreadyProcessed.Add(aCurve); if (allCurves.IsBound(aCurve)) { aFound++; int anOrient = allCurves.Find(aCurve); @@ -424,7 +532,10 @@ bool Model_AttributeSelection::update() if (aNewSelected) { // store this new selection selectConstruction(aContext, aNewSelected); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); + } else { // if the selection is not found, put the empty shape: it's better to have disappeared shape, than the old, the lost one + TNaming_Builder anEmptyBuilder(selectionLabel()); + return setInvalidIfFalse(aSelLab, false); } } else if (aShapeType == TopAbs_EDGE) { // just reselect the edge by the id @@ -442,7 +553,7 @@ bool Model_AttributeSelection::update() if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found! selectConstruction(aContext, aRes->shape()); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } } } @@ -471,7 +582,7 @@ bool Model_AttributeSelection::update() if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! selectConstruction(aContext, aRes->shape()); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } else if (aRes->shape()->isEdge() && aVertexNum > 0) { const TopoDS_Shape& anEdge = aRes->shape()->impl(); int aVIndex = 1; @@ -481,7 +592,7 @@ bool Model_AttributeSelection::update() aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); selectConstruction(aContext, aVertex); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } aVIndex++; } @@ -494,10 +605,10 @@ bool Model_AttributeSelection::update() } else { // simple construction element: the selected is that needed selectConstruction(aContext, aContext->shape()); owner()->data()->sendAttributeUpdated(this); - return true; + return setInvalidIfFalse(aSelLab, true); } } - return false; // unknown case + return setInvalidIfFalse(aSelLab, false); // unknown case } @@ -661,7 +772,7 @@ void Model_AttributeSelection::selectConstruction( if (allCurves.Contains(aCurve)) { int anID = aComposite->subFeatureId(a); aRefs->Add(anID); - if (aShapeType != TopAbs_EDGE) { // face nneds the sub-edges on sub-labels + if (aShapeType != TopAbs_EDGE) { // face needs the sub-edges on sub-labels // add edges to sub-label to support naming for edges selection TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); for(; anEdgeExp.More(); anEdgeExp.Next()) { @@ -723,7 +834,7 @@ bool Model_AttributeSelection::selectPart( // store the shape (in case part is not loaded it should be usefull TopoDS_Shape aShape; std::string aName = theContext->data()->name(); - if (theSubShape->isNull()) {// the whole part shape is selected + if (!theSubShape.get() || theSubShape->isNull()) {// the whole part shape is selected aShape = theContext->shape()->impl(); } else { aShape = theSubShape->impl();