X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_ResultConstruction.cpp;h=6307b4130304394146105430a78de62fd9b587fa;hb=06e7f5859095193fc7f498bd89a7d28009794f53;hp=737a63d25df6cfeab3d39769e870f5ad5be33e4f;hpb=b9540bdcf46cd2ec524383a9101de71715b6ca12;p=modules%2Fshaper.git diff --git a/src/Model/Model_ResultConstruction.cpp b/src/Model/Model_ResultConstruction.cpp index 737a63d25..6307b4130 100644 --- a/src/Model/Model_ResultConstruction.cpp +++ b/src/Model/Model_ResultConstruction.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2023 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,68 +12,107 @@ // // 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 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #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 - -// identifier that it is full result selected, but in external document (for internal index is 0) -Standard_GUID kFULL_RESULT_ID("ee87e529-da6f-46af-be25-5e0fefde52f7"); - +#include +#include + +#include + +typedef NCollection_IndexedDataMap MapFaceToEdgeIndices; + +/// Convert each edge of sketch to corresponding integer value +/// \param[in] theComposite sketch feature +/// \param[out] theCurvesIndices map curve to its index +/// \param[out] theEdgesIndices indexed edge +/// \param[out] theEdgesNames indexed name for edge +static void indexingSketchEdges( + const CompositeFeaturePtr& theComposite, + NCollection_DataMap& theCurvesIndices, + NCollection_DataMap& theEdgesIndices, + std::map& theEdgesNames); + +/// Convert each face to the list of indices of its edges +/// \param[in] theFaces list of faces to proceed +/// \param[in] theCurvesIndices index of each curve +/// \param[out] theFaceEdges map face to indices of its edges +static void faceToEdgeIndices( + const ListOfShape& theFaces, + const NCollection_DataMap& theCurvesIndices, + MapFaceToEdgeIndices& theFaceEdges); + +/// Assign faces to tags for the specified label +/// \param theDocument current document +/// \param theShapeLabel label to store shapes +/// \param theName name of the object +/// \param theShape shape to be stored to the label +/// \param theFacesOrder faces to be assigned to specified tag +/// \param theUnorderedFaces faces which may be stored to any tag +/// \param theFaceEdges indices of edges for each face +/// \param theEdgesIndices indices of edges +/// \param theEdgesNames named of edges +static void storeFacesOnLabel(std::shared_ptr& theDocument, + TDF_Label& theShapeLabel, + const std::wstring& theName, + const TopoDS_Shape& theShape, + NCollection_DataMap& theFacesOrder, + NCollection_List& theUnorderedFaces, + const MapFaceToEdgeIndices& theFaceEdges, + const NCollection_DataMap& theEdgesIndices, + const std::map& theEdgesNames); + + +// identifier of the infinite result +Standard_GUID kIS_INFINITE("dea8cc5a-53f2-49c1-94e8-a947bed20a9f"); +// identifier of the result not in history +Standard_GUID kIS_IN_HISTORY("a9aec01c-805e-44d1-b5d2-a63f06522f8a"); void Model_ResultConstruction::colorConfigInfo(std::string& theSection, std::string& theName, std::string& theDefault) { theSection = "Visualization"; - theName = "result_construction_color"; + theName = RESULT_COLOR_NAME(); theDefault = DEFAULT_COLOR(); } void Model_ResultConstruction::setShape(std::shared_ptr theShape) { if (myShape != theShape) { + storeShape(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); + static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(data()->owner(), anEvent); } myShape = theShape; - if (theShape.get()) { - myFacesUpToDate = false; - myFaces.clear(); - } } } @@ -82,718 +121,469 @@ std::shared_ptr Model_ResultConstruction::shape() return myShape; } -Model_ResultConstruction::Model_ResultConstruction() -{ - myIsInHistory = true; - myIsInfinite = false; - myFacesUpToDate = false; -} - -void Model_ResultConstruction::setIsInHistory(const bool isInHistory) +static std::wstring shortName( + std::shared_ptr& theConstr) { - myIsInHistory = isInHistory; + std::wstring aName = theConstr->data()->name(); + // remove "-", "/" and "&" command-symbols + aName.erase(std::remove(aName.begin(), aName.end(), '-'), aName.end()); + aName.erase(std::remove(aName.begin(), aName.end(), '/'), aName.end()); + aName.erase(std::remove(aName.begin(), aName.end(), '&'), aName.end()); + // remove the last 's', 'e', 'f' and 'r' symbols: + // they are used as markers of start/end/forward/reversed indicators + static const std::wstring aSyms(L"sefr"); + std::wstring::iterator aSuffix = aName.end() - 1; + while(aSyms.find(*aSuffix) != std::wstring::npos) { + --aSuffix; + } + aName.erase(aSuffix + 1, aName.end()); + return aName; } -int Model_ResultConstruction::facesNum() +bool Model_ResultConstruction::updateShape() { - if (!myFacesUpToDate) { - std::shared_ptr aWirePtr = - std::dynamic_pointer_cast(myShape); - if (aWirePtr.get()) { - std::list > aFaces; - GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(), - aWirePtr->norm(), aWirePtr, aFaces); - std::list >::iterator aFIter = aFaces.begin(); - for(; aFIter != aFaces.end(); aFIter++) { - std::shared_ptr aFace(new GeomAPI_Face(*aFIter)); - if (aFace.get() && !aFace->isNull()) - myFaces.push_back(aFace); + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData && aData->isValid()) { + TDF_Label aShapeLab = aData->shapeLab(); + Handle(TNaming_NamedShape) aNS; + if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aNS)) { + TopoDS_Shape aShape = aNS->Get(); + if (!aShape.IsNull()) { + if (aShape.ShapeType() == TopAbs_COMPOUND) { + // restore the sketch planar edges object + std::shared_ptr aBigWire(new GeomAPI_PlanarEdges); + aBigWire->setImpl(new TopoDS_Shape(aShape)); + FeaturePtr aSketch = + document()->feature(std::dynamic_pointer_cast(data()->owner())); + std::shared_ptr anOrigin = + std::dynamic_pointer_cast(aSketch->data()->attribute("Origin")); + std::shared_ptr aDirX = + std::dynamic_pointer_cast(aSketch->data()->attribute("DirX")); + std::shared_ptr aNorm = + std::dynamic_pointer_cast(aSketch->data()->attribute("Norm")); + if (anOrigin.get() && aDirX.get() && aNorm.get()) { + aBigWire->setPlane(anOrigin->pnt(), aDirX->dir(), aNorm->dir()); + myShape = aBigWire; + return true; + } + } + // just restore shape + GeomShapePtr aGShape(new GeomAPI_Shape); + aGShape->setImpl(new TopoDS_Shape(aShape)); + myShape = GeomAPI_Tools::getTypedShape(aGShape); // restore the sketch sub-components + return true; } } - myFacesUpToDate = true; } - return int(myFaces.size()); + return false; } -std::shared_ptr Model_ResultConstruction::face(const int theIndex) +Model_ResultConstruction::Model_ResultConstruction() { - return myFaces[theIndex]; } -bool Model_ResultConstruction::isInfinite() +bool Model_ResultConstruction::isInHistory() { - return myIsInfinite; + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData.get() && aData->isValid()) { + return !aData->label().IsAttribute(kIS_IN_HISTORY); // by default no attribute, but in history + } + return true; // unknown case } -void Model_ResultConstruction::setInfinite(const bool theInfinite) +void Model_ResultConstruction::setIsInHistory(const bool isInHistory) { - myIsInfinite = theInfinite; + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData.get() && aData->isValid()) { + if (!isInHistory) + TDataStd_UAttribute::Set(aData->label(), kIS_IN_HISTORY); + else + aData->label().ForgetAttribute(kIS_IN_HISTORY); + } } -void Model_ResultConstruction::setIsConcealed(const bool theValue) +bool Model_ResultConstruction::isInfinite() { - // do nothing: the construction element is never consealed + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData.get() && aData->isValid()) { + return aData->label().IsAttribute(kIS_INFINITE); + } + return false; // unknown case } -static const int kSTART_VERTEX_DELTA = 1000000; - -static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, std::string theFullName, - const int theID, std::shared_ptr theDoc, - bool theSelectionMode) +void Model_ResultConstruction::setInfinite(const bool theInfinite) { - TDF_Label aLab = theID == 0 ? theMainLabel : theMainLabel.FindChild(theID); - TNaming_Builder aBuilder(aLab); - // wire never happens as sub, it must be generated to be found - // by SelectionNaming TNaming_Tool::NamedShape - if (theSelectionMode && theShape.ShapeType() != TopAbs_WIRE) - aBuilder.Select(theShape, theShape); - else - aBuilder.Generated(theShape); - - theDoc->addNamingName(aLab, theFullName); - TDataStd_Name::Set(aLab, theFullName.c_str()); + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData.get() && aData->isValid()) { + if (theInfinite) + TDataStd_UAttribute::Set(aData->label(), kIS_INFINITE); + else + aData->label().ForgetAttribute(kIS_INFINITE); + } } -// generates a full-name for sub-element of the composite feature (sketch) -std::string fullName(CompositeFeaturePtr theComposite, const TopoDS_Shape& theSubShape, - Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)()) +int Model_ResultConstruction::facesNum(const bool /*theUpdateNaming*/) { - TopAbs_ShapeEnum aShapeType = theSubShape.ShapeType(); - gp_Pnt aVertexPos; - TColStd_MapOfTransient allCurves; - if (aShapeType == TopAbs_VERTEX) { // compare positions - aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(theSubShape)); - } else { - for(TopExp_Explorer anEdgeExp(theSubShape, 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::map anOrientations; //map from edges IDs to orientations of these edges in face - std::map aSubNames; //map from edges IDs to names of edges - TColStd_PackedMapOfInteger aRefs; // indixes of sub-elements in composite - - const int aSubNum = theComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - FeaturePtr aSub = theComposite->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(theComposite->subFeatureId(a)); - aSubNames[theComposite->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 + theComposite->subFeatureId(a)); - aSubNames[aDelta + theComposite->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 = theComposite->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(theSubShape, 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(theSubShape, anEdge); - anOrientations[anID] = anOrient; - } - } - } - } - } - } - } - } - } - std::stringstream aName; - // #1839 : do not store name of the feature in the tree, since this name could be changed - 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"; - else if (theSubShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex"; - - // make a composite name from all sub-elements indexes: "1_2_3_4" - TColStd_MapIteratorOfPackedMapOfInteger aRef(aRefs); - for(; aRef.More(); aRef.Next()) { - aName<<"-"< aData = std::dynamic_pointer_cast(data()); + if (aData.get() && aData->isValid()) { + TDF_Label aShapeLab = aData->shapeLab(); + TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID()); + for (; anOldIter.More(); anOldIter.Next()) { + aResult++; } } - if (!theRefs.IsNull()) { - Handle(TColStd_HPackedMapOfInteger) aMap = new TColStd_HPackedMapOfInteger(aRefs); - theRefs->ChangeMap(aMap); - } - return aName.str(); + return aResult; } -// stores shape and name on sub-label of the main stored shape -static void saveSubName(CompositeFeaturePtr theComposite, - TDF_Label& theLab, const bool isSelectionMode, TopoDS_Shape aSub, - std::shared_ptr theDoc, std::string theFullName) +std::shared_ptr Model_ResultConstruction::face(const int theIndex) { - // 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; - } - } + std::shared_ptr aResult; + int anIndex = 0; + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData.get() && aData->isValid()) { + TDF_Label aShapeLab = aData->shapeLab(); + TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID()); + for (; anOldIter.More(); anOldIter.Next()) { + if (anIndex == theIndex) { + Handle(TNaming_NamedShape) aNS; + anOldIter.Value()->Label().FindAttribute(TNaming_NamedShape::GetID(), aNS); + aResult.reset(new GeomAPI_Face); + aResult->setImpl(new TopoDS_Shape(aNS->Get())); + break; } + anIndex++; } } - - TNaming_Builder aBuilder(theLab); - if (isSelectionMode) - aBuilder.Select(aSub, aSub); - else - aBuilder.Generated(aSub); - theDoc->addNamingName(theLab, theFullName.c_str()); - TDataStd_Name::Set(theLab, theFullName.c_str()); + return aResult; } - -TDF_Label Model_ResultConstruction::startLabel( - const std::shared_ptr theExtDoc, bool& theExternal) +void Model_ResultConstruction::setIsConcealed(const bool theValue, const bool theForced) { - theExternal = theExtDoc.get() && theExtDoc != document(); - if (theExternal) { // external document is used - std::shared_ptr aDoc = std::dynamic_pointer_cast(theExtDoc); - return aDoc->extConstructionsLabel(); + // the construction element may be concealed only by "delete" feature + if (!theValue || theForced) { + ModelAPI_ResultConstruction::setIsConcealed(theValue, theForced); } - 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) +void Model_ResultConstruction::storeShape(std::shared_ptr theShape) { - 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 + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData && aData->isValid()) { + std::wstring aMyName = data()->name(); + TDF_Label aShapeLab = aData->shapeLab(); + if (!theShape.get() || theShape->isNull()) { + aShapeLab.ForgetAllAttributes(); + TDataStd_Name::Set(aShapeLab, aMyName.c_str()); // restore name forgotten + return; } - } else { - anIndex = theIndex + 1; - } - - // set the naming structure at index - TDF_Label aLab = aDataLab.FindChild(anIndex, Standard_True); - - // 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) { - // but before check that sub-vertex correctly detected as intersection of sketch edges (#2389) - int anEdgesNum = 2; - if (aSubShape.ShapeType() == TopAbs_VERTEX) { - anEdgesNum = 0; + std::shared_ptr aMyDoc = + std::dynamic_pointer_cast(document()); + const TopoDS_Shape& aShape = theShape->impl(); + if (isInfinite() || aShape.ShapeType() == TopAbs_VERTEX) { + aShapeLab.ForgetAllAttributes(); // clear all previously stored + TNaming_Builder aBuilder(aShapeLab); + aBuilder.Generated(aShape); + TDataStd_Name::Set(aShapeLab, aMyName.c_str()); + aMyDoc->addNamingName(aShapeLab, aMyName); + } else if (aShape.ShapeType() == TopAbs_EDGE) { // store sub-vertices on sub-labels + aShapeLab.ForgetAllAttributes(); // clear all previously stored + TNaming_Builder aBuilder(aShapeLab); + aBuilder.Generated(aShape); + + TopExp_Explorer anExp(aShape, TopAbs_VERTEX); + for(int anIndex = 1; anExp.More(); anExp.Next(), anIndex++) { + TDF_Label aSubLab = aShapeLab.FindChild(anIndex); + TNaming_Builder aSubBuilder(aSubLab); + aSubBuilder.Generated(anExp.Current()); + std::wstring aVertexName = aMyName + L"_" + + (anIndex == 1 ? L"StartVertex" : L"EndVertex"); + TDataStd_Name::Set(aSubLab, aVertexName.c_str()); + aMyDoc->addNamingName(aSubLab, aVertexName); + } + TDataStd_Name::Set(aShapeLab, aMyName.c_str()); + aMyDoc->addNamingName(aShapeLab, aMyName); + } else { // this is probably sketch, so, work with it as with composite + std::shared_ptr aWirePtr = + std::dynamic_pointer_cast(theShape); + if (!aWirePtr.get()) + return; // unknown case ResultPtr aThisPtr = std::dynamic_pointer_cast(data()->owner()); - FeaturePtr aThisFeature = document()->feature(aThisPtr); + FeaturePtr aThisFeature = aMyDoc->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 (!aComposite || aComposite->numberOfSubs() == 0) + return; // unknown case + // collect indices of curves of current composite + NCollection_DataMap aCurvesIndices; + NCollection_DataMap anEdgeIndices; + std::map aComponentsNames; // names of components that lay on index + indexingSketchEdges(aComposite, aCurvesIndices, anEdgeIndices, aComponentsNames); + + GeomAlgoAPI_SketchBuilder aSketchBuilder(aWirePtr->origin(), aWirePtr->dirX(), + aWirePtr->norm(), aWirePtr); + const ListOfShape& aFaces = aSketchBuilder.faces(); + // order is important to store faces in the same order if sketch is created from scratch + MapFaceToEdgeIndices aNewIndices; // edges indices + faceToEdgeIndices(aFaces, aCurvesIndices, aNewIndices); + + NCollection_DataMap aFacesOrder; // faces -> tag where they must be set + NCollection_List anUnorderedFaces; // faces that may be located at any index + // searching for the best new candidate to old location + MapFaceToEdgeIndices::Iterator aNewIter(aNewIndices); + for (; aNewIter.More(); aNewIter.Next()) { + double aBestFound = 0, aBestNotFound = 1.e+100; + int aBestTag = 0; + const TColStd_ListOfInteger& aNewInd = aNewIter.Value(); + // old faces indices where they where located + TDF_ChildIDIterator anOldIter(aShapeLab, TDataStd_IntPackedMap::GetID()); + for (; anOldIter.More(); anOldIter.Next()) { + int aTag = anOldIter.Value()->Label().Tag(); + if (aFacesOrder.IsBound(aTag)) + continue; // already found a best candidate + Handle(TDataStd_IntPackedMap) anOldIndices = + Handle(TDataStd_IntPackedMap)::DownCast(anOldIter.Value()); + double aFound = 0, aNotFound = 0; + TColStd_ListOfInteger::Iterator aNewIndIter(aNewInd); + for (; aNewIndIter.More(); aNewIndIter.Next()) { + if (anOldIndices->Contains(aNewIndIter.Value())) { + aFound += 1.; + } + else if (anOldIndices->Contains(-aNewIndIter.Value())) { // different orientation + aFound += 0.001; + } + else { + aNotFound += 1.; } } - } - } - } - 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; + if (aNotFound <= aBestNotFound) { // less and equal to find better "found": #2859 + if (aFound > aBestFound) { + aBestNotFound = aNotFound; + aBestFound = aFound; + aBestTag = aTag; + } } } + if (aBestTag != 0) { // found an appropriate face + aFacesOrder.Bind(aBestTag, aNewIter.Key()); + } else { + anUnorderedFaces.Append(aNewIter.Key()); + } } + storeFacesOnLabel(aMyDoc, aShapeLab, aMyName, aShape, aFacesOrder, anUnorderedFaces, + aNewIndices, anEdgeIndices, aComponentsNames); } } +} - // external full result is not identified by index == 0, so, add here the ID - if (!theSubShape.get()) { - TDataStd_UAttribute::Set(aLab, kFULL_RESULT_ID); - // empty NS - TNaming_Builder aBuilder(aLab); - // store all sub-faces naming since faces may be used for extrusion, where all edges are needed - Handle(TDataStd_IntPackedMap) anIndices = TDataStd_IntPackedMap::Set(aLab); - std::list aFacesIndexes; - for(int a = 0; a < facesNum(); a++) { - anIndices->Add(select(face(a), theExtDoc, -1)); +void Model_ResultConstruction::setFacesOrder(const std::list& theFaces) +{ + std::shared_ptr aData = std::dynamic_pointer_cast(data()); + if (aData && aData->isValid()) { + std::wstring aMyName = data()->name(); + TDF_Label aShapeLab = aData->shapeLab(); + GeomShapePtr aResShape = shape(); + if (!aResShape.get() || aResShape->isNull()) { + // do nothing + return; } - return anIndex - 1; - } + std::shared_ptr aMyDoc = + std::dynamic_pointer_cast(document()); + const TopoDS_Shape& aShape = aResShape->impl(); + if (aShape.ShapeType() != TopAbs_VERTEX && + aShape.ShapeType() != TopAbs_EDGE) { + ResultPtr aThisPtr = std::dynamic_pointer_cast(data()->owner()); + FeaturePtr aThisFeature = aMyDoc->feature(aThisPtr); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aThisFeature); + if (!aComposite || aComposite->numberOfSubs() == 0) + return; // unknown case + // collect indices of curves of current composite + NCollection_DataMap aCurvesIndices; + NCollection_DataMap anEdgeIndices; + std::map aComponentsNames; // names of components that lay on index + indexingSketchEdges(aComposite, aCurvesIndices, anEdgeIndices, aComponentsNames); + + ListOfShape aFaces; + NCollection_DataMap aFacesOrder; // faces -> tag where they must be set + NCollection_List anUnorderedFaces; // unordered faces are empty in this case + int aTagId = 0; + for (std::list::const_iterator aFIt = theFaces.begin(); + aFIt != theFaces.end(); ++aFIt) { + aFaces.push_back(*aFIt); + aFacesOrder.Bind(++aTagId, (*aFIt)->impl()); + } - { // this to have erased Builder after the shape was generated (NS on this label may be changed) - TNaming_Builder aBuilder(aLab); - if (aSubShape.IsNull()) { - return anIndex - 1; // just keep empty named shape - } - // wire never happens as sub, it must be generated to be found - // by SelectionNaming TNaming_Tool::NamedShape - if (isSelectionMode && aSubShape.ShapeType() != TopAbs_WIRE) { - aBuilder.Select(aSubShape, aSubShape); - } else { - aBuilder.Generated(aSubShape); - } - } + MapFaceToEdgeIndices aNewIndices; // edges indices + faceToEdgeIndices(aFaces, aCurvesIndices, aNewIndices); - 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; + storeFacesOnLabel(aMyDoc, aShapeLab, aMyName, aShape, aFacesOrder, anUnorderedFaces, + aNewIndices, anEdgeIndices, aComponentsNames); + } } +} - // 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); +// ========================== Auxiliary functions ========================================= + +void storeFacesOnLabel(std::shared_ptr& theDocument, + TDF_Label& theShapeLabel, + const std::wstring& theName, + const TopoDS_Shape& theShape, + NCollection_DataMap& theFacesOrder, + NCollection_List& theUnorderedFaces, + const MapFaceToEdgeIndices& theFaceEdges, + const NCollection_DataMap& theEdgesIndices, + const std::map& theEdgesNames) +{ + theShapeLabel.ForgetAllAttributes(); // clear all previously stored + TDataStd_Name::Set(theShapeLabel, theName.c_str()); // restore name forgotten + TNaming_Builder aBuilder(theShapeLabel); // store the compound to get it ready on open of document + aBuilder.Generated(theShape); + theDocument->addNamingName(theShapeLabel, theName); + // set new faces to the labels + NCollection_List::Iterator anUnordered(theUnorderedFaces); + for (int aCurrentTag = 1; !theFacesOrder.IsEmpty() || anUnordered.More(); aCurrentTag++) { + TopoDS_Face aFaceToPut; + if (theFacesOrder.IsBound(aCurrentTag)) { + aFaceToPut = theFacesOrder.Find(aCurrentTag); + theFacesOrder.UnBind(aCurrentTag); } - } - 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); - 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(); - 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; + else if (anUnordered.More()) { + aFaceToPut = anUnordered.Value(); + anUnordered.Next(); + } + + if (aFaceToPut.IsNull()) + continue; + + TopTools_MapOfShape aFaceEdges; + for (TopExp_Explorer anEdges(aFaceToPut, TopAbs_EDGE); anEdges.More(); anEdges.Next()) + aFaceEdges.Add(anEdges.Current()); + + TDF_Label aLab = theShapeLabel.FindChild(aCurrentTag); + TNaming_Builder aFaceBuilder(aLab); + aFaceBuilder.Generated(aFaceToPut); + // store also indices of the new face edges + Handle(TDataStd_IntPackedMap) aNewMap = TDataStd_IntPackedMap::Set(aLab); + const TColStd_ListOfInteger& aNewInd = theFaceEdges.FindFromKey(aFaceToPut); + std::wstringstream aName; + aName<<"Face"; + TopExp_Explorer aPutEdges(aFaceToPut, TopAbs_EDGE); + TNaming_Builder *anEdgesBuilder = 0, *aVerticesBuilder = 0; + for(TColStd_ListOfInteger::Iterator anIter(aNewInd); anIter.More(); anIter.Next()) { + int anIndex = anIter.Value(); + int aModIndex = anIndex > 0 ? anIndex : -anIndex; + aNewMap->Add(anIndex); + aName<<"-"<second; + if (anIter.Value() > 0) + aName<<"f"; + else + aName<<"r"; + // collect all edges of the face which are modified in sub-label of the face + if (theEdgesIndices.IsBound(aModIndex) && + !aFaceEdges.Contains(theEdgesIndices.Find(aModIndex))) { + if (!anEdgesBuilder) { + TDF_Label anEdgesLabel = aLab.FindChild(1); + anEdgesBuilder = new TNaming_Builder(anEdgesLabel); + std::ostringstream aSubName; + // tag is needed for Test1922 to distinguish sub-edges of different faces + aSubName<<"SubEdge_"<Modify(theEdgesIndices.Find(aModIndex), aPutEdges.Current()); } - if (aShapeType != TopAbs_VERTEX) { - 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); - 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) { - while(aUsedIDMap.Contains(anID)) - anID += 100000; - aUsedIDMap.Add(anID); - TDF_Label aSubLab = aLab.FindChild(anID); - std::string aFullNameSub = fullName(aComposite, anEdge); - saveSubName(aComposite, aSubLab, isSelectionMode, anEdge, aMyDoc, aFullNameSub); - - int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge); - 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 - for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_VERTEX); - anEdgeExp.More(); anEdgeExp.Next()) { - TopoDS_Vertex aV = TopoDS::Vertex(anEdgeExp.Current()); - while(aUsedIDMap.Contains(anID)) - anID += 100000; - aUsedIDMap.Add(anID); - TDF_Label aSubLab = aLab.FindChild(anID); - std::string aFullNameSub = fullName(aComposite, aV); - saveSubName(aComposite, aSubLab, isSelectionMode, aV, aMyDoc, aFullNameSub); - } - } + // put also modified vertices, otherwise vertex of original edge has no history + if (theEdgesIndices.IsBound(aModIndex)) { + TopExp_Explorer aVExpOld(theEdgesIndices.Find(aModIndex), TopAbs_VERTEX); + TopExp_Explorer aVExpNew(aPutEdges.Current(), TopAbs_VERTEX); + for(; aVExpNew.More() && aVExpOld.More(); aVExpNew.Next(), aVExpOld.Next()) { + if (!aVExpOld.Current().IsSame(aVExpNew.Current())) { + if (!aVerticesBuilder) { + TDF_Label aVertLabel = aLab.FindChild(2); + aVerticesBuilder = new TNaming_Builder(aVertLabel); + std::ostringstream aSubName; + // tag is needed for Test1922 to distinguish sub-edges of different faces + aSubName<<"SubVertex_"<Modify(aVExpOld.Current(), aVExpNew.Current()); + } } } + aPutEdges.Next(); } - } - std::string aFullName = fullName(aComposite, aSubShape, aRefs); - // store the selected as primitive - registerSubShape(aLab, aSubShape, aFullName, 0, aMyDoc, isSelectionMode); - 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(); - if (aSelShape.IsNull()) - return aResult; // shape equal to context => null - aResult = std::shared_ptr(new GeomAPI_Shape); - aResult->setImpl(new TopoDS_Shape(aSelShape)); + if (anEdgesBuilder) + delete anEdgesBuilder; + if (aVerticesBuilder) + delete aVerticesBuilder; + TDataStd_Name::Set(aLab, TCollection_ExtendedString(aName.str().c_str())); + theDocument->addNamingName(aLab, aName.str()); + // put also wires to sub-labels to correctly select them instead of collection by edges + int aWireTag = 3; // first tag is for SubEdge-s, second - for vertices + for(TopExp_Explorer aWires(aFaceToPut, TopAbs_WIRE); aWires.More(); aWires.Next()) { + TDF_Label aWireLab = aLab.FindChild(aWireTag); + TNaming_Builder aWireBuilder(aWireLab); + aWireBuilder.Generated(aWires.Current()); + std::wostringstream aWireName; + aWireName< 3) + aWireName<<"_"<addNamingName(aWireLab, aWireName.str()); + aWireTag++; } } - - return aResult; } -bool Model_ResultConstruction::update(const int theIndex, - const std::shared_ptr theExtDoc, bool& theModified) +void indexingSketchEdges(const CompositeFeaturePtr& theComposite, + NCollection_DataMap& theCurvesIndices, + NCollection_DataMap& theEdgesIndices, + std::map& theEdgesNames) { - theModified = false; - bool anExt; - TDF_Label aLab = startLabel(theExtDoc, anExt).FindChild(theIndex + 1, Standard_True); - if (theIndex == 0 || aLab.IsAttribute(kFULL_RESULT_ID)) { // full for external same as index == 0 - // it is just reference to construction, not sub-shape - // if there is a sketch, the sketch-naming must be updated - if (!isInfinite()) { - // update all faces named by the whole result - bool aRes = true; - Handle(TDataStd_IntPackedMap) anIndices; - if (aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), anIndices)) { - NCollection_Map aFaces; // collect faces, updated in the tree - TColStd_MapIteratorOfPackedMapOfInteger anIndexIter(anIndices->GetMap()); - Handle(TColStd_HPackedMapOfInteger) aNewPackedMap = - new TColStd_HPackedMapOfInteger; // with only faces that are ok - // iterate to find existing faces, updated - for(; anIndexIter.More(); anIndexIter.Next()) { - if (update(anIndexIter.Key(), theExtDoc, theModified)) { - GeomShapePtr aFace = shape(anIndexIter.Key(), theExtDoc); - if (!aFaces.Contains(aFace->impl())) { - aNewPackedMap->ChangeMap().Add(anIndexIter.Key()); - aFaces.Add(aFace->impl()); - } - } - } - // then iterate all existing faces to find new faces - int aCurrentFacesNum = facesNum(); - for(int a = 0; a < aCurrentFacesNum; a++) { - GeomShapePtr aFace = face(a); - if (!aFaces.Contains(aFace->impl())) { - // add this one - int aNewFaceIndex = select(aFace, theExtDoc, -1); - if (aNewFaceIndex > 0) { - aNewPackedMap->ChangeMap().Add(aNewFaceIndex); - } - } - } - anIndices->ChangeMap(aNewPackedMap); - } - 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; + const int aSubNum = theComposite->numberOfSubs(); + for (int a = 0; a < aSubNum; a++) { + FeaturePtr aSub = theComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes = aResults.cbegin(); + for (; aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + std::dynamic_pointer_cast(*aRes); + if (aConstr->shape() && aConstr->shape()->isEdge()) { + TopoDS_Edge anEdge = TopoDS::Edge(aConstr->shape()->impl()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + theCurvesIndices.Bind(aCurve, a); + theEdgesIndices.Bind(a, anEdge); + theEdgesNames[a] = shortName(aConstr); } - - // 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(aNewShape->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()) - { - // update the referenced object if it is sub - 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 - Model_ResultConstruction::update(aFaceIndex, theExtDoc, theModified); - } - // 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++; - } - } - } - } +void faceToEdgeIndices(const ListOfShape& theFaces, + const NCollection_DataMap& theCurvesIndices, + MapFaceToEdgeIndices& theFaceEdges) +{ + std::list >::const_iterator aFIter = theFaces.begin(); + for (; aFIter != theFaces.end(); aFIter++) { + std::shared_ptr aFace(new GeomAPI_Face(*aFIter)); + // put them to a label, trying to keep the same faces on the same labels + if (aFace.get() && !aFace->isNull()) { + TopoDS_Face aTopoFace = TopoDS::Face(aFace->impl()); + theFaceEdges.Add(aTopoFace, TColStd_ListOfInteger()); + // keep new indices of sub-elements used in this face + for (TopExp_Explorer anEdges(aTopoFace, TopAbs_EDGE); anEdges.More(); anEdges.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anEdges.Current()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (theCurvesIndices.IsBound(aCurve)) { + int anIndex = theCurvesIndices.Find(aCurve); + if ((aFirst > aLast) != (anEdge.Orientation() == TopAbs_REVERSED)) + anIndex = -anIndex; + theFaceEdges.ChangeFromKey(aTopoFace).Append(anIndex); } } } - } else { // simple construction element: the selected is that needed - select(shape(), theExtDoc, theIndex); - theModified = true; - return true; } - return false; // unknown case }