From: Clarisse Genrault Date: Fri, 17 Mar 2017 09:57:38 +0000 (+0100) Subject: Merge branch 'master' into cgt/devCEA X-Git-Tag: V_2.9.0~51 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=37d3df3f82d632f471935a042292d5ead9e4a2f9;hp=7b8c858edd665530aa62b4ea42a3f4b86db0fc3a;p=modules%2Fshaper.git Merge branch 'master' into cgt/devCEA --- diff --git a/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp b/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp index 4112b4ace..26023890b 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp @@ -108,6 +108,12 @@ void FeaturesPlugin_MultiTranslation::performOneDirection() int nbCopies = integer(FeaturesPlugin_MultiTranslation::NB_COPIES_FIRST_DIR_ID())->value(); + if (nbCopies <=0) { + std::string aFeatureError = "Multitranslation builder "; + aFeatureError+=":: the number of copies for the first direction is null or negative."; + setError(aFeatureError); + } + // Moving each object. int aResultIndex = 0; std::list::iterator aContext = aContextes.begin(); @@ -237,6 +243,18 @@ void FeaturesPlugin_MultiTranslation::performTwoDirection() int aSecondNbCopies = integer(FeaturesPlugin_MultiTranslation::NB_COPIES_SECOND_DIR_ID())->value(); + if (aFirstNbCopies <=0) { + std::string aFeatureError = "Multitranslation builder "; + aFeatureError+=":: the number of copies for the first direction is null or negative."; + setError(aFeatureError); + } + + if (aSecondNbCopies <=0) { + std::string aFeatureError = "Multitranslation builder "; + aFeatureError+=":: the number of copies for the second direction is null or negative."; + setError(aFeatureError); + } + // Coord aFirstAxis double x1 = aFirstAxis->dir()->x(); double y1 = aFirstAxis->dir()->y(); diff --git a/src/FeaturesPlugin/rotation_widget.xml b/src/FeaturesPlugin/rotation_widget.xml index 9508b57ce..2ec8b40fd 100755 --- a/src/FeaturesPlugin/rotation_widget.xml +++ b/src/FeaturesPlugin/rotation_widget.xml @@ -56,6 +56,7 @@ shape_types="vertex"> + #include -#include #include #define MY_TRSF implPtr() diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp index 55050b96a..160b22beb 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ShapeAPI.cpp @@ -459,6 +459,12 @@ namespace GeomAlgoAPI_ShapeAPI const double theStep, const int theNumber) throw (GeomAlgoAPI_Exception) { + if (theNumber <=0) { + std::string aError = "Multitranslation builder "; + aError+=":: the number of copies for the first direction is null or negative."; + throw GeomAlgoAPI_Exception(aError); + } + ListOfShape aListOfShape; for (int i=0; idir()->x(); double y1 = theFirstAxis->dir()->y(); diff --git a/src/GeomValidators/GeomValidators_ShapeType.cpp b/src/GeomValidators/GeomValidators_ShapeType.cpp index 6c0077c6a..6371c1a46 100755 --- a/src/GeomValidators/GeomValidators_ShapeType.cpp +++ b/src/GeomValidators/GeomValidators_ShapeType.cpp @@ -90,6 +90,7 @@ bool GeomValidators_ShapeType::isValid(const AttributePtr& theAttribute, for (; anIt != aLast; anIt++) { if (!aTypes.empty()) aTypes += ", "; + aTypes += *anIt; } theError = "It does not contain element with acceptable shape type. " "The type should be one of the next: %1"; diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 83c61b4e3..7af146794 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -12,55 +12,33 @@ #include "Model_SelectionNaming.h" #include #include +#include #include #include #include #include #include #include -#include #include -#include #include #include #include #include #include -#include #include #include -#include -#include -#include -#include #include #include #include -#include -#include -#include #include -#include #include -#include #include -#include -#include #include #include -#include -#include -#include -#include -#include -#include #include #include -#include -#include #include -#include //#define DEB_NAMING 1 #ifdef DEB_NAMING @@ -71,8 +49,6 @@ static const int kSTART_VERTEX_DELTA = 1000000; // identifier that there is simple reference: selection equals to context Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29"); -// simple reference in the construction -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 @@ -110,7 +86,6 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, // do noth use naming if selected shape is result shape itself, but not sub-shape TDF_Label aSelLab = selectionLabel(); aSelLab.ForgetAttribute(kSIMPLE_REF_ID); - aSelLab.ForgetAttribute(kCONSTUCTION_SIMPLE_REF_ID); aSelLab.ForgetAttribute(kINVALID_SELECTION); bool isDegeneratedEdge = false; @@ -138,45 +113,19 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, selectBody(theContext, theSubShape); } } else if (theContext->groupName() == ModelAPI_ResultConstruction::group()) { - if (!theSubShape.get()) { - // 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 = contextName(theContext); - // for selection in different document, add the document 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); - } + aSelLab.ForgetAllAttributes(true); // to remove old selection data + std::shared_ptr aConstruction = + std::dynamic_pointer_cast(theContext); + std::shared_ptr aSubShape; + if (theSubShape.get() && !theContext->shape()->isEqual(theSubShape)) + aSubShape = theSubShape; // the whole context + int anIndex = aConstruction->select(theSubShape, owner()->document()); + TDataStd_Integer::Set(aSelLab, anIndex); } else if (theContext->groupName() == ModelAPI_ResultPart::group()) { aSelLab.ForgetAllAttributes(true); TDataStd_UAttribute::Set(aSelLab, kPART_REF_ID); selectPart(theContext, theSubShape); } - //the attribute initialized state should be changed by sendAttributeUpdated only - //myIsInitialized = true; owner()->data()->sendAttributeUpdated(this); } @@ -213,21 +162,17 @@ std::shared_ptr Model_AttributeSelection::value() return aResult; // empty result return aContext->shape(); } - if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { - // it is just reference to construction, nothing is in value - return aResult; // empty result - } if (aSelLab.IsAttribute(kPART_REF_ID)) { ResultPartPtr aPart = std::dynamic_pointer_cast(context()); if (!aPart.get() || !aPart->isActivated()) return std::shared_ptr(); // postponed naming needed Handle(TDataStd_Integer) anIndex; - if (selectionLabel().FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { if (anIndex->Get()) { // special selection attribute was created, use it return aPart->selectionValue(anIndex->Get()); } else { // face with name is already in the data model, so try to take it by name Handle(TDataStd_Name) aName; - if (selectionLabel().FindAttribute(TDataStd_Name::GetID(), aName)) { + if (aSelLab.FindAttribute(TDataStd_Name::GetID(), aName)) { std::string aSubShapeName(TCollection_AsciiString(aName->Get()).ToCString()); std::size_t aPartEnd = aSubShapeName.find('/'); if (aPartEnd != std::string::npos && aPartEnd != aSubShapeName.rfind('/')) { @@ -242,15 +187,20 @@ std::shared_ptr Model_AttributeSelection::value() } Handle(TNaming_NamedShape) aSelection; - if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { + if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { TopoDS_Shape aSelShape = aSelection->Get(); aResult = std::shared_ptr(new GeomAPI_Shape); aResult->setImpl(new TopoDS_Shape(aSelShape)); } else { // for simple construction element: just shape of this construction element - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(context()); + std::shared_ptr aConstr = + std::dynamic_pointer_cast(context()); if (aConstr) { - return aConstr->shape(); + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + if (anIndex->Get() == 0) // it is just reference to construction, nothing is in value + return aResult; + return aConstr->shape(anIndex->Get(), owner()->document()); + } } } } @@ -272,19 +222,19 @@ bool Model_AttributeSelection::isInitialized() ResultPtr aContext = context(); return aContext.get() != NULL; } - if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { - // it is just reference to construction, nothing is in value - return true; - } - 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 - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(context()); + std::shared_ptr aConstr = + std::dynamic_pointer_cast(context()); if (aConstr.get()) { - return aConstr->shape().get() != NULL; + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + if (anIndex->Get() == 0) // it is just reference to construction, nothing is in value + return true; + return aConstr->shape(anIndex->Get(), owner()->document()).get() != NULL; + } } } } @@ -375,7 +325,7 @@ TDF_LabelMap& Model_AttributeSelection::scope() 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); + TDF_ChildIDIterator aNSIter(aFeatureLab, TNaming_NamedShape::GetID(), true); for(; aNSIter.More(); aNSIter.Next()) { Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); if (!aNS.IsNull() && aNS->Evolution() != TNaming_SELECTED) { @@ -384,6 +334,16 @@ TDF_LabelMap& Model_AttributeSelection::scope() } } } + // also add all naming labels created for external constructions + std::shared_ptr aDoc = std::dynamic_pointer_cast(aMyDoc); + TDF_Label anExtDocLab = aDoc->extConstructionsLabel(); + TDF_ChildIDIterator aNSIter(anExtDocLab, TNaming_NamedShape::GetID(), true); + for(; aNSIter.More(); aNSIter.Next()) { + Handle(TNaming_NamedShape) aNS = Handle(TNaming_NamedShape)::DownCast(aNSIter.Value()); + if (!aNS.IsNull() && aNS->Evolution() != TNaming_SELECTED) { + myScope.Add(aNS->Label()); + } + } } return myScope; } @@ -434,32 +394,6 @@ bool Model_AttributeSelection::update() if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); } - if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { - // it is just reference to construction, not sub-shape - // 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); - } else { - // 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(aContext->shape()->impl()); - std::shared_ptr aMyDoc = - std::dynamic_pointer_cast(owner()->document()); - } - 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; @@ -500,162 +434,16 @@ bool Model_AttributeSelection::update() } if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { - // construction: identification by the results indexes, recompute faces and - // take the face that more close by the indexes - ResultConstructionPtr aConstructionContext = - std::dynamic_pointer_cast(aContext); - FeaturePtr aContextFeature = aContext->document()->feature(aContext); - // sketch sub-element - if (aConstructionContext && - std::dynamic_pointer_cast(aContextFeature).get()) - { - TDF_Label aLab = myRef.myRef->Label(); - // getting a type of selected shape - Handle(TDataStd_Integer) aTypeAttr; - if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) { - return setInvalidIfFalse(aSelLab, false); - } - TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get()); - // selected indexes will be needed in each "if" - Handle(TDataStd_IntPackedMap) aSubIds; - std::shared_ptr aNewSelected; - bool aNoIndexes = - !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0; - // for now working only with composite features - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(aContextFeature); - if (!aComposite.get() || aComposite->numberOfSubs() == 0) { - return setInvalidIfFalse(aSelLab, false); - } - - if (aShapeType == TopAbs_FACE || aShapeType == TopAbs_WIRE) { - // compound is for the whole sketch selection - // If this is a wire with plane defined then it is a sketch-like object - if (!aConstructionContext->facesNum()) // no faces, update can not work correctly - return setInvalidIfFalse(aSelLab, false); - // if there is no edges indexes, any face can be used: take the first - std::shared_ptr aNewSelected; - if (aNoIndexes) { - aNewSelected = aConstructionContext->face(0); - } else { // searching for most looks-like initial face by the indexes - // prepare edges of the current result for the fast searching - // curves and orientations of edges - NCollection_DataMap allCurves; - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - int aSubID = aComposite->subFeatureId(a); - if (aSubIds->Contains(aSubID)) { - FeaturePtr aSub = aComposite->subFeature(a); - const std::list >& aResults = aSub->results(); - std::list >::const_iterator aRes; - for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) { - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(*aRes); - if (aConstr->shape() && aConstr->shape()->isEdge()) { - const TopoDS_Shape& aResShape = aConstr->shape()->impl(); - TopoDS_Edge anEdge = TopoDS::Edge(aResShape); - if (!anEdge.IsNull()) { - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - // searching for orientation information - int anOrient = 0; - Handle(TDataStd_Integer) anInt; - if (aSelLab.FindChild(aSubID).FindAttribute(TDataStd_Integer::GetID(), anInt)){ - anOrient = anInt->Get(); - } - allCurves.Bind(aCurve, anOrient); - } - } - } - } - } - aNewSelected = Model_SelectionNaming::findAppropriateFace( - aContext, allCurves, aShapeType == TopAbs_WIRE); - } - if (aNewSelected) { // store this new selection - selectConstruction(aContext, aNewSelected); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return 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 - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - // if aSubIds take any, the first appropriate - if (aSubIds->IsEmpty() || aSubIds->Contains(aComposite->subFeatureId(a))) { - // found the appropriate feature - FeaturePtr aFeature = aComposite->subFeature(a); - std::list >::const_iterator aResIter = - aFeature->results().cbegin(); - for(;aResIter != aFeature->results().cend(); aResIter++) { - ResultConstructionPtr aRes = - std::dynamic_pointer_cast(*aResIter); - if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found! - selectConstruction(aContext, aRes->shape()); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; - } - } - } - } - } else if (aShapeType == TopAbs_VERTEX) { - // just reselect the vertex by the id of edge - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - // if aSubIds take any, the first appropriate - int aFeatureID = aComposite->subFeatureId(a); - if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID) || - aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA) || - aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) { - // searching for deltas - int aVertexNum = 0; - if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1; - else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2; - // found the feature with appropriate edge - FeaturePtr aFeature = aComposite->subFeature(a); - std::list >::const_iterator aResIter = - aFeature->results().cbegin(); - for(;aResIter != aFeature->results().cend(); aResIter++) { - ResultConstructionPtr aRes = - std::dynamic_pointer_cast(*aResIter); - if (aRes && aRes->shape()) { - if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! - selectConstruction(aContext, aRes->shape()); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; - } else if (aRes->shape()->isEdge() && aVertexNum > 0) { - const TopoDS_Shape& anEdge = aRes->shape()->impl(); - int aVIndex = 1; - for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { - if (aVIndex == aVertexNum) { // found! - std::shared_ptr aVertex(new GeomAPI_Shape); - aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); - selectConstruction(aContext, aVertex); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; - } - aVIndex++; - } - } - } - } - } - } - } - } else { // simple construction element: the selected is that needed - selectConstruction(aContext, aContext->shape()); - setInvalidIfFalse(aSelLab, true); - owner()->data()->sendAttributeUpdated(this); - return true; + Handle(TDataStd_Integer) anIndex; + if (aSelLab.FindAttribute(TDataStd_Integer::GetID(), anIndex)) { + std::shared_ptr aConstructionContext = + std::dynamic_pointer_cast(aContext); + bool aModified = true; + bool aValid = aConstructionContext->update(anIndex->Get(), owner()->document(), aModified); + setInvalidIfFalse(aSelLab, aValid); + if (aModified) + owner()->data()->sendAttributeUpdated(this); + return aValid; } } return setInvalidIfFalse(aSelLab, false); // unknown case @@ -762,200 +550,6 @@ void Model_AttributeSelection::selectBody( } } -/// registers the name of the shape in the label (theID == 0) of sub label (theID is a tag) -/// if theID is zero, -/// theOrientation is additional information about the positioning of edge relatively to face -/// it is stored in the integer attribute of the edge sub-label: -/// -1 is out, 1 is in, 0 is not needed -static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, - const int theID, const FeaturePtr& theContextFeature, std::shared_ptr theDoc, - std::map& theOrientations, - // name of sub-elements by ID to be exported instead of indexes - std::map& theSubNames, - Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(), - const int theOrientation = 0) -{ - TDF_Label aLab = theID == 0 ? theMainLabel : theMainLabel.FindChild(theID); - if (theOrientation != 0) { // store the orientation of edge relatively to face if needed - TDataStd_Integer::Set(aLab, theOrientation); - } - TNaming_Builder aBuilder(aLab); - aBuilder.Generated(theShape); - std::stringstream aName; - // #1839 : do not store name of the feature in the tree, since this name could be changed - //aName<name(); - if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction - //aName<<"/"; - if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face"; - else if (theShape.ShapeType() == TopAbs_WIRE) aName<<"Wire"; - else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge"; - else if (theShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex"; - - if (theRefs.IsNull()) { - aName<GetMap()); - for(; aRef.More(); aRef.Next()) { - aName<<"-"<addNamingName(aLab, aName.str()); - TDataStd_Name::Set(aLab, aName.str().c_str()); -} - -void Model_AttributeSelection::selectConstruction( - const ResultPtr& theContext, const std::shared_ptr& theSubShape) -{ - std::shared_ptr aMyDoc = - std::dynamic_pointer_cast(owner()->document()); - FeaturePtr aContextFeature = theContext->document()->feature(theContext); - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(aContextFeature); - const TopoDS_Shape& aSubShape = theSubShape->impl(); - if (!aComposite || aComposite->numberOfSubs() == 0) { - // saving of context is enough: result construction contains exactly the needed shape - TNaming_Builder aBuilder(selectionLabel()); - aBuilder.Generated(aSubShape); - //std::string aName = contextName(theContext); - //aMyDoc->addNamingName(selectionLabel(), aName); - //TDataStd_Name::Set(selectionLabel(), aName.c_str()); - return; - } - std::shared_ptr aData = std::dynamic_pointer_cast(owner()->data()); - TDF_Label aLab = myRef.myRef->Label(); - // identify the results of sub-object of the composite by edges - // save type of the selected shape in integer attribute - TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType(); - TDataStd_Integer::Set(aLab, (int)aShapeType); - gp_Pnt aVertexPos; - TColStd_MapOfTransient allCurves; - if (aShapeType == TopAbs_VERTEX) { // compare positions - aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape)); - } else { - for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) { - TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - allCurves.Add(aCurve); - } - } - // iterate and store the result ids of sub-elements and sub-elements to sub-labels - Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab); - std::map anOrientations; //map from edges IDs to orientations of these edges in face - std::map aSubNames; //map from edges IDs to names of edges - aRefs->Clear(); - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - FeaturePtr aSub = aComposite->subFeature(a); - const std::list >& aResults = aSub->results(); - std::list >::const_iterator aRes = aResults.cbegin(); - // there may be many shapes (circle and center): register if at least one is in selection - for(; aRes != aResults.cend(); aRes++) { - ResultConstructionPtr aConstr = - std::dynamic_pointer_cast(*aRes); - if (!aConstr->shape()) { - continue; - } - if (aShapeType == TopAbs_VERTEX) { - if (aConstr->shape()->isVertex()) { // compare vertices positions - const TopoDS_Shape& aVertex = aConstr->shape()->impl(); - gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex)); - if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { - aRefs->Add(aComposite->subFeatureId(a)); - aSubNames[aComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr); - } - } else { // get first or last vertex of the edge: last is stored with additional delta - const TopoDS_Shape& anEdge = aConstr->shape()->impl(); - int aDelta = kSTART_VERTEX_DELTA; - for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { - gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current())); - if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { - aRefs->Add(aDelta + aComposite->subFeatureId(a)); - aSubNames[aDelta + aComposite->subFeatureId(a)] = - Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA); - break; - } - aDelta += kSTART_VERTEX_DELTA; - } - } - } else { - if (aConstr->shape()->isEdge()) { - const TopoDS_Shape& aResShape = aConstr->shape()->impl(); - TopoDS_Edge anEdge = TopoDS::Edge(aResShape); - if (!anEdge.IsNull()) { - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (allCurves.Contains(aCurve)) { - int anID = aComposite->subFeatureId(a); - aRefs->Add(anID); - aSubNames[anID] = Model_SelectionNaming::shortName(aConstr); - 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()) { - TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (aFaceCurve == aCurve) { - int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge); - anOrientations[anID] = anOrient; - - TDF_Label aLab = selectionLabel().FindChild(anID); - std::string aName = "Edge-" + Model_SelectionNaming::shortName(aConstr, 0); - TNaming_Builder aBuilder(aLab); - aBuilder.Generated(anEdge); - aMyDoc->addNamingName(aLab, aName.c_str()); - TDataStd_Name::Set(aLab, aName.c_str()); - - if (anOrient != 0) { - // store the orientation of edge relatively to face if needed - TDataStd_Integer::Set(aLab, anOrient); - } - } - } - } else { // put vertices of the selected edge to sub-labels - // add edges to sub-label to support naming for edges selection - int aDelta = kSTART_VERTEX_DELTA; - int aTagIndex = anID + kSTART_VERTEX_DELTA; - for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_VERTEX); - anEdgeExp.More(); - anEdgeExp.Next(), - aTagIndex += kSTART_VERTEX_DELTA, - aDelta += kSTART_VERTEX_DELTA) { - TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current()); - - TDF_Label aLab = selectionLabel().FindChild(aTagIndex); - std::string aName = "Vertex-" - + Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA); - TNaming_Builder aBuilder(aLab); - aBuilder.Generated(aV); - aMyDoc->addNamingName(aLab, aName.c_str()); - TDataStd_Name::Set(aLab, aName.c_str()); - } - } - } - } - } - } - } - } - // store the selected as primitive - registerSubShape( - selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, anOrientations, aSubNames, aRefs); -} - bool Model_AttributeSelection::selectPart( const ResultPtr& theContext, const std::shared_ptr& theSubShape, const bool theUpdate) diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index 93fb9876e..b387297ef 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -93,10 +93,6 @@ protected: virtual void selectBody( const ResultPtr& theContext, const std::shared_ptr& theSubShape); - /// Performs the selection for the construction result (selection by index) - virtual void selectConstruction( - const ResultPtr& theContext, const std::shared_ptr& theSubShape); - /// Performs the selection for the part result (selection by name of body result inside of part) /// \param theContext the result - owner of the selection /// \param theSubShape selected shape diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index f34306dcb..f31891b8b 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -77,6 +77,7 @@ class Model_Data : public ModelAPI_Data friend class Model_AttributeSelectionList; friend class Model_ValidatorsFactory; friend class Model_SelectionNaming; + friend class Model_ResultConstruction; public: /// The simplest constructor. "setLabel" must be called just after to initialize correctly. diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 89c596d6d..805327150 100755 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -73,6 +73,8 @@ static const int TAG_CURRENT_FEATURE = 1; ///< reference to the current feature static const int TAG_CURRENT_TRANSACTION = 2; ///< integer, index of the transaction static const int TAG_SELECTION_FEATURE = 3; ///< integer, tag of the selection feature label static const int TAG_NODES_STATE = 4; ///< array, tag of the Object Browser nodes states +///< naming structures constructions selected from other document +static const int TAG_EXTERNAL_CONSTRUCTIONS = 5; Model_Document::Model_Document(const int theID, const std::string theKind) : myID(theID), myKind(theKind), myIsActive(false), @@ -1329,6 +1331,11 @@ void Model_Document::decrementTransactionID() TDataStd_Integer::Set(generalLabel().FindChild(TAG_CURRENT_TRANSACTION), aNewVal); } +TDF_Label Model_Document::extConstructionsLabel() const +{ + return myDoc->Main().FindChild(TAG_EXTERNAL_CONSTRUCTIONS); +} + bool Model_Document::isOpened() { return myObjs && !myDoc.IsNull(); diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 3a031419e..639d84b0b 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -288,6 +288,9 @@ class Model_Document : public ModelAPI_Document /// Appends the values to theStates list. virtual void restoreNodesState(std::list& theStates) const; + /// Label that constains structures for selection of constructions of another document + TDF_Label extConstructionsLabel() const; + friend class Model_Application; friend class Model_Session; friend class Model_Update; @@ -298,6 +301,7 @@ class Model_Document : public ModelAPI_Document friend class Model_AttributeSelection; friend class Model_ResultPart; friend class Model_ResultCompSolid; + friend class Model_ResultConstruction; friend class Model_SelectionNaming; friend class DFBrowser; diff --git a/src/Model/Model_ResultConstruction.cpp b/src/Model/Model_ResultConstruction.cpp index d48fd305b..fa2767f9a 100644 --- a/src/Model/Model_ResultConstruction.cpp +++ b/src/Model/Model_ResultConstruction.cpp @@ -6,12 +6,34 @@ #include +#include +#include +#include #include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + void Model_ResultConstruction::colorConfigInfo(std::string& theSection, std::string& theName, std::string& theDefault) { @@ -90,3 +112,446 @@ void Model_ResultConstruction::setIsConcealed(const bool theValue) { // do nothing: the construction element is never consealed } + +static const int kSTART_VERTEX_DELTA = 1000000; + +static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, + const int theID, std::shared_ptr theDoc, + std::map& theOrientations, + // name of sub-elements by ID to be exported instead of indexes + std::map& theSubNames, + Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(), + const int theOrientation = 0) +{ + TDF_Label aLab = theID == 0 ? theMainLabel : theMainLabel.FindChild(theID); + if (theOrientation != 0) { // store the orientation of edge relatively to face if needed + TDataStd_Integer::Set(aLab, theOrientation); + } + TNaming_Builder aBuilder(aLab); + aBuilder.Generated(theShape); + std::stringstream aName; + // #1839 : do not store name of the feature in the tree, since this name could be changed + //aName<name(); + if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction + //aName<<"/"; + if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face"; + else if (theShape.ShapeType() == TopAbs_WIRE) aName<<"Wire"; + else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge"; + else if (theShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex"; + + if (theRefs.IsNull()) { + aName<GetMap()); + for(; aRef.More(); aRef.Next()) { + aName<<"-"<addNamingName(aLab, aName.str()); + TDataStd_Name::Set(aLab, aName.str().c_str()); +} + +TDF_Label Model_ResultConstruction::startLabel( + const std::shared_ptr theExtDoc, bool& theExternal) +{ + theExternal = theExtDoc.get() && theExtDoc != document(); + if (theExternal) { // external document is used + std::shared_ptr aDoc = std::dynamic_pointer_cast(theExtDoc); + return aDoc->extConstructionsLabel(); + } + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + return aData->label(); +} + +int Model_ResultConstruction::select(const std::shared_ptr& theSubShape, + const std::shared_ptr theExtDoc, const int theIndex) +{ + int anIndex; // resulting index of the sub-label + TopoDS_Shape aSubShape; + if (theSubShape.get()) { + aSubShape = theSubShape->impl(); + } else if (shape().get()) { + aSubShape = shape()->impl(); + } + // if external document requires this selection, put the naming structures to this doc + // to support the naming mechanism in this document correctly + bool anExternal; + TDF_Label aDataLab = startLabel(theExtDoc, anExternal); + if (theIndex == -1) { + anIndex = anExternal ? 2 : 1; // for the external doc don't mind about the main shape + + if (theSubShape.get() || anExternal) { // searching for already selected sub (or whole for ext) + // iterate all the already presented shapes to see the same + TDF_ChildIterator aSubsIter(aDataLab, Standard_False); + for(; aSubsIter.More(); aSubsIter.Next()) { + const TDF_Label aLab = aSubsIter.Value(); + if (aLab.Tag() == 1) // skip the root shape label + continue; + Handle(TNaming_NamedShape) aNS; + if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + if (aNS->Get().IsSame(aSubShape)) { + return aLab.Tag() - 1; // found exactly the needed shape, nothing else to do + } + } + anIndex = aLab.Tag(); // searching for the latest index + } + anIndex = (anIndex == 1) ? 2 : (anIndex + 1); // next after 1-root, or next after all + } + } else { + anIndex = theIndex + 1; + } + + // set the naming structure at index + TDF_Label aLab = aDataLab.FindChild(anIndex, Standard_True); + TNaming_Builder aBuilder(aLab); + if (aSubShape.IsNull()) + return anIndex - 1; // just keep empty named shape + aBuilder.Generated(aSubShape); + + if (anIndex == 1 && isInfinite()) { // infinitive results has no sub-selection + return anIndex - 1; + } + ResultPtr aThisPtr = std::dynamic_pointer_cast(data()->owner()); + FeaturePtr aThisFeature = document()->feature(aThisPtr); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aThisFeature); + if (!aComposite || aComposite->numberOfSubs() == 0) { + // saving of context is enough: result construction contains exactly the needed shape + return anIndex - 1; + } + // identify the results of sub-object of the composite by edges + // save type of the selected shape in integer attribute + TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType(); + TDataStd_Integer::Set(aLab, (int)aShapeType); + gp_Pnt aVertexPos; + TColStd_MapOfTransient allCurves; + if (aShapeType == TopAbs_VERTEX) { // compare positions + aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape)); + } else { + for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + allCurves.Add(aCurve); + } + } + std::shared_ptr aMyDoc = + std::dynamic_pointer_cast(document()); + // iterate and store the result ids of sub-elements and sub-elements to sub-labels + Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab); + std::map anOrientations; //map from edges IDs to orientations of these edges in face + std::map aSubNames; //map from edges IDs to names of edges + aRefs->Clear(); + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + FeaturePtr aSub = aComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + // there may be many shapes (circle and center): register if at least one is in selection + for(; aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (!aConstr->shape()) { + continue; + } + if (aShapeType == TopAbs_VERTEX) { + if (aConstr->shape()->isVertex()) { // compare vertices positions + const TopoDS_Shape& aVertex = aConstr->shape()->impl(); + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex)); + if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { + aRefs->Add(aComposite->subFeatureId(a)); + aSubNames[aComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr); + } + } else { // get first or last vertex of the edge: last is stored with additional delta + const TopoDS_Shape& anEdge = aConstr->shape()->impl(); + int aDelta = kSTART_VERTEX_DELTA; + for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current())); + if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { + aRefs->Add(aDelta + aComposite->subFeatureId(a)); + aSubNames[aDelta + aComposite->subFeatureId(a)] = + Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA); + break; + } + aDelta += kSTART_VERTEX_DELTA; + } + } + } else { + if (aConstr->shape()->isEdge()) { + const TopoDS_Shape& aResShape = aConstr->shape()->impl(); + TopoDS_Edge anEdge = TopoDS::Edge(aResShape); + if (!anEdge.IsNull()) { + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (allCurves.Contains(aCurve)) { + int anID = aComposite->subFeatureId(a); + aRefs->Add(anID); + aSubNames[anID] = Model_SelectionNaming::shortName(aConstr); + 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()) { + TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (aFaceCurve == aCurve) { + int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge); + anOrientations[anID] = anOrient; + + TDF_Label aSubLab = aLab.FindChild(anID); + std::string aName = "Edge-" + Model_SelectionNaming::shortName(aConstr, 0); + TNaming_Builder aBuilder(aSubLab); + aBuilder.Generated(anEdge); + aMyDoc->addNamingName(aSubLab, aName.c_str()); + TDataStd_Name::Set(aSubLab, aName.c_str()); + + if (anOrient != 0) { + // store the orientation of edge relatively to face if needed + TDataStd_Integer::Set(aSubLab, anOrient); + } + } + } + } else { // put vertices of the selected edge to sub-labels + // add edges to sub-label to support naming for edges selection + int aDelta = kSTART_VERTEX_DELTA; + int aTagIndex = anID + kSTART_VERTEX_DELTA; + for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_VERTEX); + anEdgeExp.More(); + anEdgeExp.Next(), + aTagIndex += kSTART_VERTEX_DELTA, + aDelta += kSTART_VERTEX_DELTA) { + TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current()); + + TDF_Label aSubLab = aLab.FindChild(aTagIndex); + std::string aName = "Vertex-" + + Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA); + TNaming_Builder aBuilder(aLab); + aBuilder.Generated(aV); + aMyDoc->addNamingName(aLab, aName.c_str()); + TDataStd_Name::Set(aLab, aName.c_str()); + } + } + } + } + } + } + } + } + // store the selected as primitive + registerSubShape(aLab, aSubShape, 0, aMyDoc, anOrientations, aSubNames, aRefs); + + return anIndex - 1; +} + +std::shared_ptr Model_ResultConstruction::shape(const int theIndex, + const std::shared_ptr theExtDoc) +{ + std::shared_ptr aResult; + if (theIndex == 0) + return aResult; // the whole shape, so, NULL + + bool isExt; + TDF_Label aLab = startLabel(theExtDoc, isExt).FindChild(theIndex + 1); + if (!aLab.IsNull()) { // index is not bad + Handle(TNaming_NamedShape) aSelection; + if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aSelection)) { + TopoDS_Shape aSelShape = aSelection->Get(); + aResult = std::shared_ptr(new GeomAPI_Shape); + aResult->setImpl(new TopoDS_Shape(aSelShape)); + } + } + + return aResult; +} + +bool Model_ResultConstruction::update(const int theIndex, + const std::shared_ptr theExtDoc, bool& theModified) +{ + theModified = false; + bool anExt; + TDF_Label aLab = startLabel(theExtDoc, anExt).FindChild(theIndex + 1, Standard_True); + if (theIndex == 0) { + // it is just reference to construction, not sub-shape + // if there is a sketch, the sketch-naming must be updated + if (!isInfinite()) { + BRep_Builder aCompoundBuilder; + TopoDS_Compound aComp; + aCompoundBuilder.MakeCompound(aComp); + for(int a = 0; a < facesNum(); a++) { + TopoDS_Shape aFace = face(a)->impl(); + aCompoundBuilder.Add(aComp, aFace); + } + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(aComp)); + select(aShape, theExtDoc, theIndex); + } else { + // 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(aLab); + aBuilder.Generated(shape()->impl()); + } + return shape() && !shape()->isNull(); + } + // construction: identification by the results indexes, recompute faces and + // take the face that more close by the indexes + ResultPtr aThisPtr = std::dynamic_pointer_cast(data()->owner()); + FeaturePtr aContextFeature = document()->feature(aThisPtr); + // sketch sub-element + if (std::dynamic_pointer_cast(aContextFeature).get()) + { + // getting a type of selected shape + Handle(TDataStd_Integer) aTypeAttr; + if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) { + return false; + } + TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get()); + // selected indexes will be needed in each "if" + Handle(TDataStd_IntPackedMap) aSubIds; + std::shared_ptr aNewSelected; + bool aNoIndexes = + !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0; + // for now working only with composite features + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aContextFeature); + if (!aComposite.get() || aComposite->numberOfSubs() == 0) { + return false; + } + + if (aShapeType == TopAbs_FACE || aShapeType == TopAbs_WIRE) { + // compound is for the whole sketch selection + // If this is a wire with plane defined then it is a sketch-like object + if (!facesNum()) // no faces, update can not work correctly + return false; + // if there is no edges indexes, any face can be used: take the first + std::shared_ptr aNewSelected; + if (aNoIndexes) { + aNewSelected = face(0); + } else { // searching for most looks-like initial face by the indexes + // prepare edges of the current result for the fast searching + // curves and orientations of edges + NCollection_DataMap allCurves; + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + int aSubID = aComposite->subFeatureId(a); + if (aSubIds->Contains(aSubID)) { + FeaturePtr aSub = aComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes; + for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (aConstr->shape() && aConstr->shape()->isEdge()) { + const TopoDS_Shape& aResShape = aConstr->shape()->impl(); + TopoDS_Edge anEdge = TopoDS::Edge(aResShape); + if (!anEdge.IsNull()) { + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + // searching for orientation information + int anOrient = 0; + Handle(TDataStd_Integer) anInt; + if (aLab.FindChild(aSubID).FindAttribute(TDataStd_Integer::GetID(), anInt)) { + anOrient = anInt->Get(); + } + allCurves.Bind(aCurve, anOrient); + } + } + } + } + } + aNewSelected = Model_SelectionNaming::findAppropriateFace( + aThisPtr, allCurves, aShapeType == TopAbs_WIRE); + } + if (aNewSelected) { // store this new selection + select(aNewSelected, theExtDoc, theIndex); + theModified = true; + return 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(aLab); + return false; + } + } else if (aShapeType == TopAbs_EDGE) { + // just reselect the edge by the id + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + // if aSubIds take any, the first appropriate + if (aSubIds->IsEmpty() || aSubIds->Contains(aComposite->subFeatureId(a))) { + // found the appropriate feature + FeaturePtr aFeature = aComposite->subFeature(a); + std::list >::const_iterator aResIter = + aFeature->results().cbegin(); + for(;aResIter != aFeature->results().cend(); aResIter++) { + ResultConstructionPtr aRes = + std::dynamic_pointer_cast(*aResIter); + if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found! + select(aRes->shape(), theExtDoc, theIndex); + theModified = true; + return true; + } + } + } + } + } else if (aShapeType == TopAbs_VERTEX) { + // just reselect the vertex by the id of edge + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + // if aSubIds take any, the first appropriate + int aFeatureID = aComposite->subFeatureId(a); + if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID) || + aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA) || + aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) { + // searching for deltas + int aVertexNum = 0; + if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1; + else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA * 2)) aVertexNum = 2; + // found the feature with appropriate edge + FeaturePtr aFeature = aComposite->subFeature(a); + std::list >::const_iterator aResIter = + aFeature->results().cbegin(); + for(;aResIter != aFeature->results().cend(); aResIter++) { + ResultConstructionPtr aRes = + std::dynamic_pointer_cast(*aResIter); + if (aRes && aRes->shape()) { + if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! + select(aRes->shape(), theExtDoc, theIndex); + theModified = true; + return true; + } else if (aRes->shape()->isEdge() && aVertexNum > 0) { + const TopoDS_Shape& anEdge = aRes->shape()->impl(); + int aVIndex = 1; + for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { + if (aVIndex == aVertexNum) { // found! + std::shared_ptr aVertex(new GeomAPI_Shape); + aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); + select(aVertex, theExtDoc, theIndex); + theModified = true; + return true; + } + aVIndex++; + } + } + } + } + } + } + } + } else { // simple construction element: the selected is that needed + select(shape(), theExtDoc, theIndex); + theModified = true; + return true; + } + return false; // unknown case +} diff --git a/src/Model/Model_ResultConstruction.h b/src/Model/Model_ResultConstruction.h index 151d8a46a..4efeb0e3e 100644 --- a/src/Model/Model_ResultConstruction.h +++ b/src/Model/Model_ResultConstruction.h @@ -11,6 +11,9 @@ #include #include +class ModelAPI_Document; +class TDF_Label; + /**\class Model_ResultConstruction * \ingroup DataModel * \brief The construction element result of a feature. @@ -58,10 +61,40 @@ class Model_ResultConstruction : public ModelAPI_ResultConstruction /// The construction element is never concealed MODEL_EXPORT virtual void setIsConcealed(const bool theValue); + // methods related to selection of sub-shapes in construction, used by SelectionAttribute + + /// Selects theSubShape in the construction. Returns an index of the selected sub-shape. + /// Puts the selected shape with a needed BRepNaming sub-structure to the data tree of result. + /// If theSubShape is null, it selects the whole construction and returns zero index. + /// If theIndex is not -1, it re-selects over the existing data (used for update selection). + /// If theExtDoc is document where this selection is needed, if it differs from this, + /// naming structures will be located there. + int select(const std::shared_ptr& theSubShape, + const std::shared_ptr theExtDoc, const int theIndex = -1); + + /// Returns already selected shape by the given index. Zero index means the whole construction, + /// so, the returned shape in this case is null. + /// If theExtDoc is document where this selection is needed, if it differs from this, + /// naming structures will be located there. + std::shared_ptr shape(const int theIndex, + const std::shared_ptr theExtDoc); + + /// Updates the existing selection by the index. + /// Returns false if update is failed. Returns theModified true if the selection was updated. + /// If theExtDoc is document where this selection is needed, if it differs from this, + /// naming structures will be updated there. + bool update(const int theIndex, const std::shared_ptr theExtDoc, + bool& theModified); + protected: /// Makes a body on the given feature Model_ResultConstruction(); + /// Searchies for the working label selection/update will start from + /// Returns true if this is label of the external document. + /// theExtDoc is document where this selection is required + TDF_Label startLabel(const std::shared_ptr theExtDoc, bool& theExternal); + friend class Model_Objects; }; diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index dac80bb5f..42c97b2a9 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -55,7 +55,6 @@ std::string Model_SelectionNaming::getShapeName( // add the result name to the name of the shape // (it was in BodyBuilder, but did not work on Result rename) bool isNeedContextName = theContext->shape().get() != NULL; - // && !theContext->shape()->isEqual(theSubSh); // check if the subShape is already in DF Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(theShape, myLab); Handle(TDataStd_Name) anAttr; diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index 0e90444bc..198696aef 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -142,4 +142,5 @@ ADD_UNIT_TESTS(TestConstants.py TestDoubleArray.py Test1757.py Test1998.py + Test1995.py ) diff --git a/src/ModelAPI/Test/Test1995.py b/src/ModelAPI/Test/Test1995.py new file mode 100644 index 000000000..9a64c6502 --- /dev/null +++ b/src/ModelAPI/Test/Test1995.py @@ -0,0 +1,38 @@ +# Lighter case to reproduce problem of #1995 +# The problem was in axis that contained sub-shapes naming of the sketch and the extrusion becomes +# use this axis. So, on remove of the axis, the naming is failed. Same for modifications of the sketch 1. + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(175.5289977047663, 37.215818549061, -134.623385345167, 37.215818549061) +SketchLine_2 = Sketch_1.addLine(-134.623385345167, 37.215818549061, -134.623385345167, -108.7867760111381) +SketchLine_3 = Sketch_1.addLine(-134.623385345167, -108.7867760111381, 175.5289977047663, -108.7867760111381) +SketchLine_4 = Sketch_1.addLine(175.5289977047663, -108.7867760111381, 175.5289977047663, 37.215818549061) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +model.do() +Axis_4 = model.addAxis(Part_1_doc, model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f-SketchLine_4f"), model.selection("VERTEX", "Sketch_1/Vertex-SketchLine_3s-SketchLine_2e")) +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1f-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 50, 0) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face_2")) +SketchCircle_1 = Sketch_2.addCircle(12.88847795756506, 28.93359954982685, 11.55225986344597) +model.do() + +# now remove axis to destroy naming structure if extrusion refers to it +Part_1_doc.removeFeature(Axis_4.feature()) +# also update sketch_1 to launch recomputation of everything +SketchLine_1.setStartPoint(170, -130) +model.end() + +import ModelAPI +assert(ModelAPI.ModelAPI_Session.get().validators().validate(Sketch_2.feature())) diff --git a/src/PartSet/PartSet_Tools.cpp b/src/PartSet/PartSet_Tools.cpp index e7e2458f5..2099f347c 100755 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@ -273,114 +273,6 @@ void PartSet_Tools::createConstraint(CompositeFeaturePtr theSketch, Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); } -/*std::shared_ptr PartSet_Tools:: - findAttributePoint(CompositeFeaturePtr theSketch, double theX, double theY, - double theTolerance, const QList& theIgnore) -{ - std::shared_ptr aClickedPoint = std::shared_ptr( - new GeomAPI_Pnt2d(theX, theY)); - - std::list > anAttiributes; - for (int i = 0; i < theSketch->numberOfSubs(); i++) { - FeaturePtr aFeature = theSketch->subFeature(i); - if (!theIgnore.contains(aFeature)) { - anAttiributes = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - - std::list >::const_iterator anIt; - for (anIt = anAttiributes.cbegin(); anIt != anAttiributes.cend(); ++anIt) { - std::shared_ptr aCurPoint = - std::dynamic_pointer_cast(*anIt); - double x = aCurPoint->x(); - double y = aCurPoint->y(); - if (aCurPoint && (aCurPoint->pnt()->distance(aClickedPoint) < theTolerance)) { - return aCurPoint; - } - } - } - } - return std::shared_ptr(); -}*/ - - -std::shared_ptr PartSet_Tools::findFirstEqualPointInArgumentFeatures( - const FeaturePtr& theFeature, const std::shared_ptr& thePoint) -{ - std::shared_ptr aFeaturePoint; - - // may be feature is not updated yet, execute is not performed and references features - // are not created. Case: rectangle macro feature - ModuleBase_Tools::flushUpdated(theFeature); - - std::list anAttributes = theFeature->data()->attributes( - ModelAPI_AttributeRefList::typeId()); - std::list::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end(); - for (; anIt != aLast && !aFeaturePoint.get(); anIt++) { - std::shared_ptr aCurSelList = - std::dynamic_pointer_cast(*anIt); - for (int i = 0, aNb = aCurSelList->size(); i < aNb && !aFeaturePoint.get(); i++) { - ObjectPtr anObject = aCurSelList->object(i); - FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); - if (aFeature.get()) - aFeaturePoint = PartSet_Tools::findFirstEqualPoint(aFeature, thePoint); - } - } - return aFeaturePoint; -} - -std::shared_ptr PartSet_Tools::findFirstEqualPoint( - const FeaturePtr& theFeature, - const std::shared_ptr& thePoint) -{ - std::shared_ptr aFPoint; - - // find the given point in the feature attributes - std::list > anAttiributes = - theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list >::const_iterator anIt = anAttiributes.begin(), - aLast = anAttiributes.end(); - ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); - - for (; anIt != aLast && !aFPoint; anIt++) { - std::shared_ptr aCurPoint = - std::dynamic_pointer_cast(*anIt); - if (aCurPoint && aCurPoint->isInitialized() && - aValidators->isCase(theFeature, aCurPoint->id()) && - (aCurPoint->pnt()->distance(thePoint) < Precision::Confusion())) { - aFPoint = aCurPoint; - break; - } - } - return aFPoint; -} - -std::shared_ptr PartSet_Tools::findFirstEqualPointInSketch( - const CompositeFeaturePtr& theSketch, - const std::shared_ptr& theFeaturePoint, - const std::shared_ptr& thePoint) -{ - // get all sketch features. If the point with the given coordinates belong to any sketch feature, - // the constraint is created between the feature point and the found sketch point - std::shared_ptr aData = theSketch->data(); - std::shared_ptr aRefList = std::dynamic_pointer_cast< - ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID())); - - std::list aFeatures = aRefList->list(); - std::list::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end(); - std::list > anAttiributes; - - FeaturePtr aFeatureOfPoint = ModelAPI_Feature::feature(theFeaturePoint->owner()); - std::shared_ptr aFPoint; - for (; anIt != aLast; anIt++) { - FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); - if (!aFeature.get() || aFeatureOfPoint == aFeature) - continue; - aFPoint = PartSet_Tools::findFirstEqualPoint(aFeature, thePoint); - if (aFPoint.get()) - break; - } - return aFPoint; -} - std::shared_ptr PartSet_Tools::sketchPlane(CompositeFeaturePtr theSketch) { std::shared_ptr aPlane; diff --git a/src/PartSet/PartSet_Tools.h b/src/PartSet/PartSet_Tools.h index ef4659704..1b9937dd1 100755 --- a/src/PartSet/PartSet_Tools.h +++ b/src/PartSet/PartSet_Tools.h @@ -121,25 +121,6 @@ public: std::shared_ptr thePoint1, std::shared_ptr thePoint2); - /// Finds in the feature's sub-features first Point2D attribute with the given point coordinates - /// \param theFeature a feature with sub-feature attributes - /// \param thePoint a point to provided searched coordinates - /// \return found point or null - static std::shared_ptr findFirstEqualPointInArgumentFeatures( - const FeaturePtr& theFeature, const std::shared_ptr& thePoint); - - /// Finds in the feature first Point2D attribute with the given point coordinates - /// \param theFeature a feature with point attributes - /// \param thePoint a point to provided searched coordinates - /// \return found point or null - static std::shared_ptr findFirstEqualPoint(const FeaturePtr& theFeature, - const std::shared_ptr& thePoint); - - static std::shared_ptr findFirstEqualPointInSketch( - const CompositeFeaturePtr& theSketch, - const std::shared_ptr& theFeaturePoint, - const std::shared_ptr& thePoint); - /// Create a sketch plane instance /// \param theSketch a sketch feature /// \return API object of geom plane diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index 2fef715df..03995e897 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -29,6 +29,9 @@ #include #include #include +#include +#include +#include #include #include @@ -157,7 +160,7 @@ bool PartSet_WidgetPoint2D::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr /// analysis of AIS std::shared_ptr aData = myFeature->data(); - std::shared_ptr aPointAttr = std::dynamic_pointer_cast( + AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast( aData->attribute(attributeID())); std::shared_ptr aPoint = aPointAttr->pnt(); if (anAISShape.get()) @@ -225,8 +228,7 @@ bool PartSet_WidgetPoint2D::setSelection(QList& theValu const TopoDS_Shape& aTDShape = aShape->impl(); if (getPoint2d(aView, aTDShape, aX, aY)) { isDone = setPoint(aX, aY); - setConstraintTo(aX, aY); - //PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); + setConstraintToPoint(aX, aY); } } return isDone; @@ -259,7 +261,7 @@ bool PartSet_WidgetPoint2D::storeValueCustom() std::shared_ptr aData = myFeature->data(); if (!aData) // can be on abort of sketcher element return false; - std::shared_ptr aPoint = std::dynamic_pointer_cast( + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( aData->attribute(attributeID())); PartSet_WidgetPoint2D* that = (PartSet_WidgetPoint2D*) this; @@ -285,7 +287,7 @@ bool PartSet_WidgetPoint2D::storeValueCustom() bool PartSet_WidgetPoint2D::restoreValueCustom() { std::shared_ptr aData = myFeature->data(); - std::shared_ptr aPoint = std::dynamic_pointer_cast( + AttributePoint2DPtr aPoint = std::dynamic_pointer_cast( aData->attribute(attributeID())); double aValueX = aPoint->isInitialized() ? aPoint->x() : 0.; double aValueY = aPoint->isInitialized() ? aPoint->y() : 0.; @@ -393,7 +395,7 @@ bool PartSet_WidgetPoint2D::getPoint2d(const Handle(V3d_View)& theView, return false; } -bool PartSet_WidgetPoint2D::setConstraintTo(double theClickedX, double theClickedY) +bool PartSet_WidgetPoint2D::setConstraintToPoint(double theClickedX, double theClickedY) { FeaturePtr aFeature = feature(); std::string anAttribute = attributeID(); @@ -403,61 +405,60 @@ bool PartSet_WidgetPoint2D::setConstraintTo(double theClickedX, double theClicke std::shared_ptr aClickedPoint = std::shared_ptr( new GeomAPI_Pnt2d(theClickedX, theClickedY)); - - // find a feature point by the selection mode - std::shared_ptr aFeaturePoint; - if (aFeature->isMacro()) { - // the macro feature will be removed after the operation is stopped, so we need to build - // coicidence to possible sub-features - aFeaturePoint = PartSet_Tools::findFirstEqualPointInArgumentFeatures(aFeature, aClickedPoint); - } - else { - aFeaturePoint = std::dynamic_pointer_cast< - GeomDataAPI_Point2D>(aFeature->data()->attribute(anAttribute)); - } - if (!aFeaturePoint.get()) - return false; - - std::shared_ptr aFPoint = PartSet_Tools::findFirstEqualPointInSketch( - mySketch, aFeaturePoint, aClickedPoint); - if (!aFPoint.get()) + AttributePoint2DPtr aClickedFeaturePoint = findFirstEqualPointInSketch(mySketch, + aFeature, aClickedPoint); + if (!aClickedFeaturePoint.get()) return false; AttributeRefAttrPtr aRefAttr = attributeRefAttr(); if (aRefAttr.get()) - aRefAttr->setAttr(aFPoint); - else - PartSet_Tools::createConstraint(mySketch, aFPoint, aFeaturePoint); - - return true; -} - -bool PartSet_WidgetPoint2D::setConstraintWith(const ObjectPtr& theObject) -{ - std::shared_ptr aFeaturePoint; - - if (feature()->isMacro()) { - AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); - std::shared_ptr anAttrPoint = - std::dynamic_pointer_cast(aThisAttr); - if (anAttrPoint.get()) { + aRefAttr->setAttr(aClickedFeaturePoint); + else { + // find a feature point by the selection mode + AttributePoint2DPtr aFeaturePoint; + if (aFeature->isMacro()) { // the macro feature will be removed after the operation is stopped, so we need to build // coicidence to possible sub-features - aFeaturePoint = PartSet_Tools::findFirstEqualPointInArgumentFeatures(feature(), - anAttrPoint->pnt()); + aFeaturePoint = findFirstEqualPointInArgumentFeatures(aFeature, aClickedPoint); } + else { + aFeaturePoint = std::dynamic_pointer_cast< + GeomDataAPI_Point2D>(aFeature->data()->attribute(anAttribute)); + } + if (!aFeaturePoint.get()) + return false; + + PartSet_Tools::createConstraint(mySketch, aClickedFeaturePoint, aFeaturePoint); } - else { - AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); - aFeaturePoint = std::dynamic_pointer_cast(aThisAttr); - } - if (!aFeaturePoint.get()) - return false; + return true; +} +bool PartSet_WidgetPoint2D::setConstraintToObject(const ObjectPtr& theObject) +{ AttributeRefAttrPtr aRefAttr = attributeRefAttr(); - if (aRefAttr.get()) + if (aRefAttr.get()) { aRefAttr->setObject(theObject); + } else { + AttributePoint2DPtr aFeaturePoint; + + if (feature()->isMacro()) { + AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); + AttributePoint2DPtr anAttrPoint = std::dynamic_pointer_cast(aThisAttr); + if (anAttrPoint.get()) { + // the macro feature will be removed after the operation is stopped, so we need to build + // coicidence to possible sub-features + aFeaturePoint = findFirstEqualPointInArgumentFeatures(feature(), + anAttrPoint->pnt()); + } + } + else { + AttributePtr aThisAttr = feature()->data()->attribute(attributeID()); + aFeaturePoint = std::dynamic_pointer_cast(aThisAttr); + } + if (!aFeaturePoint.get()) + return false; + // Create point-edge coincedence FeaturePtr aFeature = mySketch->addFeature(SketchPlugin_ConstraintCoincidence::ID()); std::shared_ptr aData = aFeature->data(); @@ -544,7 +545,7 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo } } if (aFixedObject.get()) - setConstraintWith(aFixedObject); + setConstraintToObject(aFixedObject); // fignal updated should be flushed in order to visualize possible created // external objects e.g. selection of trihedron axis when input end arc point updateObject(feature()); @@ -573,8 +574,7 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo setPoint(aX, aY); feature()->execute(); - setConstraintTo(aX, aY); - //PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY); + setConstraintToPoint(aX, aY); } else if (aShape.ShapeType() == TopAbs_EDGE) { // point is taken from mouse event and set in attribute. It should be done before setting @@ -583,7 +583,7 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView()); PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, aY); setPoint(aX, aY); - setConstraintWith(aObject); + setConstraintToObject(aObject); setValueState(Stored); // in case of edge selection, Apply state should also be updated isAuxiliaryFeature = PartSet_Tools::isAuxiliarySketchEntity(aObject); } @@ -611,21 +611,6 @@ void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMo if (!setPoint(aX, anY) || isFeatureContainsPoint(myFeature, aX, anY)) return; - /// Start alternative code - //std::shared_ptr aFeaturePoint = std::dynamic_pointer_cast< - // GeomDataAPI_Point2D>(feature()->data()->attribute(attributeID())); - //QList aIgnore; - //aIgnore.append(feature()); - - //double aTolerance = aView->Convert(7); - //std::shared_ptr aAttrPnt = - // PartSet_Tools::findAttributePoint(mySketch, aX, anY, aTolerance, aIgnore); - //if (aAttrPnt.get() != NULL) { - // aFeaturePoint->setValue(aAttrPnt->pnt()); - // PartSet_Tools::createConstraint(mySketch, aAttrPnt, aFeaturePoint); - // emit vertexSelected(); - //} - /// End alternative code emit focusOutWidget(this); } } @@ -733,7 +718,7 @@ bool PartSet_WidgetPoint2D::isOrphanPoint(const FeaturePtr& theFeature, { bool anOrphanPoint = false; if (theFeature.get()) { - std::shared_ptr aPointAttr; + AttributePoint2DPtr aPointAttr; std::string aFeatureKind = theFeature->getKind(); if (aFeatureKind == SketchPlugin_Point::ID()) aPointAttr = std::dynamic_pointer_cast( @@ -810,3 +795,81 @@ AttributeRefAttrPtr PartSet_WidgetPoint2D::attributeRefAttr() const return std::dynamic_pointer_cast(anAttributeRef); } + +std::shared_ptr PartSet_WidgetPoint2D::findFirstEqualPointInArgumentFeatures( + const FeaturePtr& theFeature, const std::shared_ptr& thePoint) +{ + std::shared_ptr aFeaturePoint; + + // may be feature is not updated yet, execute is not performed and references features + // are not created. Case: rectangle macro feature + ModuleBase_Tools::flushUpdated(theFeature); + + std::list anAttributes = theFeature->data()->attributes( + ModelAPI_AttributeRefList::typeId()); + std::list::const_iterator anIt = anAttributes.begin(), aLast = anAttributes.end(); + for (; anIt != aLast && !aFeaturePoint.get(); anIt++) { + std::shared_ptr aCurSelList = + std::dynamic_pointer_cast(*anIt); + for (int i = 0, aNb = aCurSelList->size(); i < aNb && !aFeaturePoint.get(); i++) { + ObjectPtr anObject = aCurSelList->object(i); + FeaturePtr aFeature = std::dynamic_pointer_cast(anObject); + if (aFeature.get()) + aFeaturePoint = findFirstEqualPoint(aFeature, thePoint); + } + } + return aFeaturePoint; +} + +std::shared_ptr PartSet_WidgetPoint2D::findFirstEqualPoint( + const FeaturePtr& theFeature, + const std::shared_ptr& thePoint) +{ + std::shared_ptr aFPoint; + + // find the given point in the feature attributes + std::list > anAttiributes = + theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list >::const_iterator anIt = anAttiributes.begin(), + aLast = anAttiributes.end(); + ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators(); + + for (; anIt != aLast && !aFPoint; anIt++) { + std::shared_ptr aCurPoint = + std::dynamic_pointer_cast(*anIt); + if (aCurPoint && aCurPoint->isInitialized() && + aValidators->isCase(theFeature, aCurPoint->id()) && + (aCurPoint->pnt()->distance(thePoint) < Precision::Confusion())) { + aFPoint = aCurPoint; + break; + } + } + return aFPoint; +} + +std::shared_ptr PartSet_WidgetPoint2D::findFirstEqualPointInSketch( + const CompositeFeaturePtr& theSketch, + const FeaturePtr& theSkipFeature, + const std::shared_ptr& thePoint) +{ + // get all sketch features. If the point with the given coordinates belong to any sketch feature, + // the constraint is created between the feature point and the found sketch point + std::shared_ptr aData = theSketch->data(); + std::shared_ptr aRefList = std::dynamic_pointer_cast< + ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID())); + + std::list aFeatures = aRefList->list(); + std::list::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end(); + std::list > anAttiributes; + + std::shared_ptr aFPoint; + for (; anIt != aLast; anIt++) { + FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); + if (!aFeature.get() || (theSkipFeature.get() && theSkipFeature == aFeature)) + continue; + aFPoint = PartSet_WidgetPoint2D::findFirstEqualPoint(aFeature, thePoint); + if (aFPoint.get()) + break; + } + return aFPoint; +} diff --git a/src/PartSet/PartSet_WidgetPoint2d.h b/src/PartSet/PartSet_WidgetPoint2d.h index 2e17c1dd1..b54b76c0a 100755 --- a/src/PartSet/PartSet_WidgetPoint2d.h +++ b/src/PartSet/PartSet_WidgetPoint2d.h @@ -20,6 +20,7 @@ class ModelAPI_Feature; class ModelAPI_AttributeRefAttr; +class GeomDataAPI_Point2D; class ModuleBase_IWorkshop; class ModuleBase_ParamSpinBox; class ModuleBase_IViewWindow; @@ -177,12 +178,12 @@ protected: /// Creates constrains of the clicked point /// \param theClickedX the horizontal coordnate of the point /// \param theClickedY the vertical coordnate of the point - bool setConstraintTo(double theClickedX, double theClickedY); + bool setConstraintToPoint(double theClickedX, double theClickedY); /// Create a coincidence constraint between the attribute and the parameter object /// \theObject a result object /// \return true if succed - bool setConstraintWith(const ObjectPtr& theObject); + bool setConstraintToObject(const ObjectPtr& theObject); /// Returns if the feature is an orphan point, circle or an arc. Returns true if it /// has no a coincident to other lines. It processes point, circle and arc features @@ -204,7 +205,33 @@ protected: const std::shared_ptr& thePoint, const CompositeFeaturePtr& theSketch); - std::shared_ptr attributeRefAttr() const; + /// Finds in the feature's sub-features first Point2D attribute with the given point coordinates + /// \param theFeature a feature with sub-feature attributes + /// \param thePoint a point to provided searched coordinates + /// \return found point or null + static std::shared_ptr findFirstEqualPointInArgumentFeatures( + const FeaturePtr& theFeature, const std::shared_ptr& thePoint); + + /// Finds in the feature first Point2D attribute with the given point coordinates + /// \param theFeature a feature with point attributes + /// \param thePoint a point to provided searched coordinates + /// \return found point or null + static std::shared_ptr findFirstEqualPoint(const FeaturePtr& theFeature, + const std::shared_ptr& thePoint); + + /// Finds in the sketch attribute point of any feature that is nearest to the given point + /// \param theSketch a sketch, that is a container of features + /// \param theSkipFeature a feature that do not participate in the search + /// \param thePoint a point to provided searched coordinates + /// \return found point or null + static std::shared_ptr findFirstEqualPointInSketch( + const CompositeFeaturePtr& theSketch, + const FeaturePtr& theSkipFeature, + const std::shared_ptr& thePoint); + + /// Returns attribute reference if the key is defined in XML definition of this control + /// \return found attribute or null + std::shared_ptr attributeRefAttr() const; protected: ModuleBase_IWorkshop* myWorkshop; ///< workshop diff --git a/src/SketchPlugin/SketchPlugin_Sketch.cpp b/src/SketchPlugin/SketchPlugin_Sketch.cpp index 9f6b63a77..04cf7331b 100755 --- a/src/SketchPlugin/SketchPlugin_Sketch.cpp +++ b/src/SketchPlugin/SketchPlugin_Sketch.cpp @@ -212,9 +212,10 @@ bool SketchPlugin_Sketch::isSub(ObjectPtr theObject) const void SketchPlugin_Sketch::attributeChanged(const std::string& theID) { if (theID == SketchPlugin_SketchEntity::EXTERNAL_ID()) { - std::shared_ptr aSelection = - data()->selection(SketchPlugin_SketchEntity::EXTERNAL_ID())->value(); - if (aSelection) { // update arguments due to the selection value + AttributeSelectionPtr aSelAttr = selection(SketchPlugin_SketchEntity::EXTERNAL_ID()); + if (aSelAttr->context().get()) { // update arguments due to the selection value + std::shared_ptr aSelection = aSelAttr->value(); + if (!aSelection.get()) aSelection = aSelAttr->context()->shape(); // update the sketch plane std::shared_ptr aFace(new GeomAPI_Face(aSelection)); std::shared_ptr aPlane = aFace->getPlane();