X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_ResultConstruction.cpp;h=ad9c9a3070e2f9c060b0a9affef787a4e46d243f;hb=b73fb7468bea81901dbeed8e229d742f788ec282;hp=18d3cdcf80e452ed5ed5509ae712babfa8c49c1e;hpb=f9d184932396590fe9eddb5d38a2be34054eba8e;p=modules%2Fshaper.git diff --git a/src/Model/Model_ResultConstruction.cpp b/src/Model/Model_ResultConstruction.cpp index 18d3cdcf8..ad9c9a307 100644 --- a/src/Model/Model_ResultConstruction.cpp +++ b/src/Model/Model_ResultConstruction.cpp @@ -1,8 +1,22 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: ModelAPI_ResultConstruction.cpp -// Created: 07 Jul 2014 -// Author: Mikhail PONIKAROV +// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// #include @@ -54,12 +68,12 @@ void Model_ResultConstruction::setShape(std::shared_ptr theShape) if (!theShape.get() || !theShape->isEqual(myShape)) { static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), anEvent); + if (theShape.get()) { + myFacesUpToDate = false; + myFaces.clear(); + } } myShape = theShape; - if (theShape.get()) { - myFacesUpToDate = false; - myFaces.clear(); - } } } @@ -80,7 +94,7 @@ void Model_ResultConstruction::setIsInHistory(const bool isInHistory) myIsInHistory = isInHistory; } -int Model_ResultConstruction::facesNum() +int Model_ResultConstruction::facesNum(const bool theUpdateNaming) { if (!myFacesUpToDate) { std::shared_ptr aWirePtr = @@ -97,6 +111,23 @@ int Model_ResultConstruction::facesNum() } } myFacesUpToDate = true; + + // update all the faces and sub-elements in the naming structure + if (theUpdateNaming) { + DocumentPtr anEmptyExt; + bool aNotExt = false; + TDF_Label aDataLab = startLabel(anEmptyExt, aNotExt); + 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)) { + update(aLab.Tag() - 1, anEmptyExt, aNotExt); + } + } + } } return int(myFaces.size()); } @@ -118,7 +149,7 @@ void Model_ResultConstruction::setInfinite(const bool theInfinite) void Model_ResultConstruction::setIsConcealed(const bool theValue) { - // do nothing: the construction element is never consealed + // do nothing: the construction element is never concealed } static const int kSTART_VERTEX_DELTA = 1000000; @@ -227,9 +258,7 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu } std::stringstream aName; // #1839 : do not store name of the feature in the tree, since this name could be changed - //aName<name(); - if (theSubShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction - //aName<<"/"; + if (theSubShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole construction result if (theSubShape.ShapeType() == TopAbs_FACE) aName<<"Face"; else if (theSubShape.ShapeType() == TopAbs_WIRE) aName<<"Wire"; else if (theSubShape.ShapeType() == TopAbs_EDGE) aName<<"Edge"; @@ -255,9 +284,36 @@ std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSu } // stores shape and name on sub-label of the main stored shape -static void saveSubName(TDF_Label& theLab, const bool isSelectionMode, const TopoDS_Shape& aSub, +static void saveSubName(CompositeFeaturePtr theComposite, + TDF_Label& theLab, const bool isSelectionMode, TopoDS_Shape aSub, std::shared_ptr theDoc, std::string theFullName) { + // trying to store the edge of composite result, not sketch sub as it is + if (aSub.ShapeType() == TopAbs_EDGE) { + ResultPtr aRes = theComposite->firstResult(); + ResultConstructionPtr aConstr = std::dynamic_pointer_cast(aRes); + if (aConstr.get()) { + Standard_Real aSubFirst, aSubLast; + TopoDS_Edge aSubEdge = TopoDS::Edge(aSub); + Handle(Geom_Curve) aSubCurve = BRep_Tool::Curve(aSubEdge, aSubFirst, aSubLast); + for(int aFaceIndex = 0; aFaceIndex < aConstr->facesNum(); aFaceIndex++) { + GeomShapePtr aGFace = aConstr->face(aFaceIndex); + TopoDS_Shape aFace = aGFace->impl(); + for(TopExp_Explorer anExp(aFace, TopAbs_EDGE); anExp.More(); anExp.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (aCurve == aSubCurve && + ((fabs(aFirst - aSubFirst) < 1.e-9 && fabs(aLast - aSubLast) < 1.e-9)) || + (fabs(aFirst - aSubLast) < 1.e-9 && fabs(aLast - aSubFirst) < 1.e-9)) { + aSub = anEdge; + break; + } + } + } + } + } + TNaming_Builder aBuilder(theLab); if (isSelectionMode) aBuilder.Select(aSub, aSub); @@ -324,17 +380,50 @@ int Model_ResultConstruction::select(const std::shared_ptr& theSu // if the subshape is part of a result face, select the whole face (#1997) bool isSelectionMode = false; // and other don't set shapes - all the naming is in face label if (!aSubShape.IsNull() && aSubShape.ShapeType() > TopAbs_FACE) { - for(int aFaceIndex = 0; aFaceIndex < facesNum(); aFaceIndex++) { - TopExp_Explorer anExp(face(aFaceIndex)->impl(), aSubShape.ShapeType()); - for(; anExp.More(); anExp.Next()) { - if (aSubShape.IsSame(anExp.Current())) { // this is the case: select the whole face - // here just store the face index (to update face if update of edge is needed) - TNaming_Builder aBuilder(aLab); - aBuilder.Select(aSubShape, aSubShape); - int aFaceSelID = select(face(aFaceIndex), theExtDoc, -1); - TDF_Reference::Set(aLab, aLab.Father().FindChild(aFaceSelID)); - isSelectionMode = true; - break; + // but before check that sub-vertex correctly detected as intersection of sketch edges (#2389) + int anEdgesNum = 2; + if (aSubShape.ShapeType() == TopAbs_VERTEX) { + anEdgesNum = 0; + ResultPtr aThisPtr = std::dynamic_pointer_cast(data()->owner()); + FeaturePtr aThisFeature = document()->feature(aThisPtr); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aThisFeature); + if (aComposite.get()) { + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + int aSubID = aComposite->subFeatureId(a); + 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()) { + TopoDS_Shape aResShape = aConstr->shape()->impl(); + for(TopExp_Explorer anExp(aResShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) { + if (aSubShape.IsSame(anExp.Current())) { + anEdgesNum++; + break; + } + } + } + } + } + } + } + if (anEdgesNum > 1) { + for(int aFaceIndex = 0; aFaceIndex < facesNum(); aFaceIndex++) { + TopExp_Explorer anExp(face(aFaceIndex)->impl(), aSubShape.ShapeType()); + for(; anExp.More(); anExp.Next()) { + if (aSubShape.IsSame(anExp.Current())) { // this is the case: select the whole face + // here just store the face index (to update face if update of edge is needed) + TNaming_Builder aBuilder(aLab); + aBuilder.Select(aSubShape, aSubShape); + int aFaceSelID = select(face(aFaceIndex), theExtDoc, -1); + TDF_Reference::Set(aLab, aLab.Father().FindChild(aFaceSelID)); + isSelectionMode = true; + break; + } } } } @@ -401,6 +490,10 @@ int Model_ResultConstruction::select(const std::shared_ptr& theSu // iterate and store the result ids of sub-elements and sub-elements to sub-labels Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab); const int aSubNum = aComposite->numberOfSubs(); + // subs are placed on unique labels because of #2248: sketch curve may produce several edges, + // but #2401 - on stable labels + NCollection_Map aUsedIDMap; // already used lab tags for placement of shapes + for(int a = 0; a < aSubNum; a++) { FeaturePtr aSub = aComposite->subFeature(a); const std::list >& aResults = aSub->results(); @@ -429,9 +522,12 @@ int Model_ResultConstruction::select(const std::shared_ptr& theSu Standard_Real aFirst, aLast; Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); if (aFaceCurve == aCurve) { + while(aUsedIDMap.Contains(anID)) + anID += 100000; + aUsedIDMap.Add(anID); TDF_Label aSubLab = aLab.FindChild(anID); std::string aFullNameSub = fullName(aComposite, anEdge); - saveSubName(aSubLab, isSelectionMode, anEdge, aMyDoc, aFullNameSub); + saveSubName(aComposite, aSubLab, isSelectionMode, anEdge, aMyDoc, aFullNameSub); int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge); if (anOrient != 0) { @@ -442,14 +538,15 @@ int Model_ResultConstruction::select(const std::shared_ptr& theSu } } else { // put vertices of the selected edge to sub-labels // add edges to sub-label to support naming for edges selection - int aTagIndex = anID + kSTART_VERTEX_DELTA; for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_VERTEX); - anEdgeExp.More(); - anEdgeExp.Next(), aTagIndex += kSTART_VERTEX_DELTA) { + anEdgeExp.More(); anEdgeExp.Next()) { TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current()); - TDF_Label aSubLab = aLab.FindChild(aTagIndex); + while(aUsedIDMap.Contains(anID)) + anID += 100000; + aUsedIDMap.Add(anID); + TDF_Label aSubLab = aLab.FindChild(anID); std::string aFullNameSub = fullName(aComposite, aV); - saveSubName(aSubLab, isSelectionMode, aV, aMyDoc, aFullNameSub); + saveSubName(aComposite, aSubLab, isSelectionMode, aV, aMyDoc, aFullNameSub); } } } @@ -531,10 +628,30 @@ bool Model_ResultConstruction::update(const int theIndex, } return aRes; } else { + // check is this modified or not + std::shared_ptr aNewShape = shape(); + TopoDS_Shape anOldSh; + Handle(TNaming_NamedShape) aNS; + if (aLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + anOldSh = aNS->Get(); + } + if (aNewShape.get()) { + if (anOldSh.IsNull()) + theModified = true; + else { + std::shared_ptr anOldShape(new GeomAPI_Shape); + anOldShape->setImpl(new TopoDS_Shape(anOldSh)); + theModified = !anOldShape->isEqual(aNewShape); + } + } + else if (!anOldSh.IsNull()) { + theModified = true; + } + // 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()); + aBuilder.Generated(aNewShape->impl()); } return shape() && !shape()->isNull(); } @@ -550,7 +667,7 @@ bool Model_ResultConstruction::update(const int theIndex, Handle(TDF_Reference) aRef; if (aLab.FindAttribute(TDF_Reference::GetID(), aRef)) { int aFaceIndex = aRef->Get().Tag(); - // don't check selection ,since face may disappear, but the shape stays correct + // don't check selection since face may disappear, but the shape stays correct Model_ResultConstruction::update(aFaceIndex, theExtDoc, theModified); } // getting a type of selected shape