X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_ResultBody.cpp;h=8f8c218bb0bbc22529f54ddf102bd352c96c2066;hb=4db1dc1a2823881c588388fb1d5fa3d302bc7108;hp=9b639f9a7153c894e51421fed92dc6f8321e8e68;hpb=96912644cf6607688466ac69f1f098fd2fff37b7;p=modules%2Fshaper.git diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index 9b639f9a7..8f8c218bb 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -1,711 +1,329 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: Model_ResultBody.cpp -// Created: 08 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 -#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 -// DEB -//#include -//#include -//#define DEB_IMPORT 1 +#include -Model_ResultBody::Model_ResultBody() -{ - setIsConcealed(false); -} +// if this attribute exists, the shape is connected topology +Standard_GUID kIsConnectedTopology("e51392e0-3a4d-405d-8e36-bbfe19858ef5"); +// if this attribute exists, the connected topology flag must be recomputed +Standard_GUID kUpdateConnectedTopology("01ef7a45-0bec-4266-b0b4-4aa570921818"); -void Model_ResultBody::initAttributes() +Model_ResultBody::Model_ResultBody() : ModelAPI_ResultBody() { - // append the color attribute. It is empty, the attribute will be filled by a request - DataPtr aData = data(); - aData->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId()); + myBuilder = new Model_BodyBuilder(this); + myLastConcealed = false; + updateSubs(shape()); // in case of open, etc. } -void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& theName, - std::string& theDefault) +Model_ResultBody::~Model_ResultBody() { - theSection = "Visualization"; - theName = "result_body_color"; - theDefault = DEFAULT_COLOR(); + updateSubs(std::shared_ptr()); // erase sub-results + delete myBuilder; } -bool Model_ResultBody::setDisabled(std::shared_ptr theThis, const bool theFlag) +bool Model_ResultBody::generated(const GeomShapePtr& theNewShape, + const std::string& theName, const bool theCheckIsInResult) { - bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag); - if (aChanged) { // state is changed, so modifications are needed - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (!aData) // unknown case - return aChanged; - TDF_Label& aShapeLab = aData->shapeLab(); - - std::list > aShapePairs; // to store old and new shapes - Handle(TNaming_NamedShape) aName; - int anEvolution = -1; - if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) { - anEvolution = (int)(aName->Evolution()); - for(TNaming_Iterator anIter(aName); anIter.More(); anIter.Next()) { - aShapePairs.push_back(std::pair - (anIter.OldShape(), anIter.NewShape())); - } - } - // remove old - aShapeLab.ForgetAttribute(TNaming_NamedShape::GetID()); - // create new - TNaming_Builder aBuilder(aShapeLab); - TNaming_Evolution anEvol = (TNaming_Evolution)(anEvolution); - std::list >::iterator aPairsIter = aShapePairs.begin(); - for(; aPairsIter != aShapePairs.end(); aPairsIter++) { - if (theFlag) { // disabled => make selection - aBuilder.Select(aPairsIter->first, aPairsIter->second); - } else if (anEvol == TNaming_GENERATED) { - aBuilder.Generated(aPairsIter->first, aPairsIter->second); - } else if (anEvol == TNaming_MODIFY) { - aBuilder.Modify(aPairsIter->first, aPairsIter->second); - } + bool aResult = false; + if (mySubs.size()) { // consists of subs + for (std::vector::const_iterator aSubIter = mySubs.cbegin(); + aSubIter != mySubs.cend(); + ++aSubIter) + { + const ResultBodyPtr& aSub = *aSubIter; + if (aSub->generated(theNewShape, theName, theCheckIsInResult)) + aResult = true; } + } else { // do for this directly + if (myBuilder->generated(theNewShape, theName, theCheckIsInResult)) + aResult = true; } - return aChanged; + return aResult; } -void Model_ResultBody::store(const std::shared_ptr& theShape) +void Model_ResultBody::loadGeneratedShapes(const std::shared_ptr& theAlgo, + const GeomShapePtr& theOldShape, + const GeomAPI_Shape::ShapeType theShapeTypeToExplore, + const std::string& theName) { - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (aData) { - TDF_Label& aShapeLab = aData->shapeLab(); - // clean builders - clean(); - // store the new shape as primitive - TNaming_Builder aBuilder(aShapeLab); - if (!theShape) - return; // bad shape - TopoDS_Shape aShape = theShape->impl(); - if (aShape.IsNull()) - return; // null shape inside - - aBuilder.Generated(aShape); - // register name - if(!aBuilder.NamedShape()->IsEmpty()) { - Handle(TDataStd_Name) anAttr; - if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) { - std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString()); - if(!aName.empty()) { - std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); - aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); - } - } + if (mySubs.size()) { // consists of subs + for (std::vector::const_iterator aSubIter = mySubs.cbegin(); + aSubIter != mySubs.cend(); + ++aSubIter) + { + const ResultBodyPtr& aSub = *aSubIter; + aSub->loadGeneratedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName); } + } else { // do for this directly + myBuilder->loadGeneratedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName); } } -void Model_ResultBody::storeGenerated(const std::shared_ptr& theFromShape, - const std::shared_ptr& theToShape) +void Model_ResultBody::loadModifiedShapes(const std::shared_ptr& theAlgo, + const GeomShapePtr& theOldShape, + const GeomAPI_Shape::ShapeType theShapeTypeToExplore, + const std::string& theName) { - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (aData) { - TDF_Label& aShapeLab = aData->shapeLab(); - // clean builders - clean(); - // store the new shape as primitive - TNaming_Builder aBuilder(aShapeLab); - if (!theFromShape || !theToShape) - return; // bad shape - TopoDS_Shape aShapeBasis = theFromShape->impl(); - if (aShapeBasis.IsNull()) - return; // null shape inside - TopoDS_Shape aShapeNew = theToShape->impl(); - if (aShapeNew.IsNull()) - return; // null shape inside - aBuilder.Generated(aShapeBasis, aShapeNew); - // register name - if(!aBuilder.NamedShape()->IsEmpty()) { - Handle(TDataStd_Name) anAttr; - if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) { - std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString()); - if(!aName.empty()) { - std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); - aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName); + if (/*theSplitInSubs &&*/ mySubs.size()) { // consists of subs + // optimization of getting of new shapes for specific sub-result + if (!theAlgo->isNewShapesCollected(theOldShape, theShapeTypeToExplore)) + theAlgo->collectNewShapes(theOldShape, theShapeTypeToExplore); + std::vector::const_iterator aSubIter = mySubs.cbegin(); + for(; aSubIter != mySubs.cend(); aSubIter++) { + // check that sub-shape was also created as modification of ShapeIn + /* to find when it is needed later to enable: to store modification of sub-bodies not only as primitives + GeomShapePtr aSubGeomShape = (*aSubIter)->shape(); + if (!theIsStoreAsGenerated && aSubGeomShape.get() && !aSubGeomShape->isNull()) { + TopoDS_Shape aSubShape = aSubGeomShape->impl(); + TopoDS_Shape aWholeIn = theShapeIn->impl(); + for(TopExp_Explorer anExp(aWholeIn, aSubShape.ShapeType()); anExp.More(); anExp.Next()) { + ListOfShape aHistory; + std::shared_ptr aSubIn(new GeomAPI_Shape()); + aSubIn->setImpl((new TopoDS_Shape(anExp.Current()))); + theMS->modified(aSubIn, aHistory); + std::list >::const_iterator anIt = aHistory.begin(); + for (; anIt != aHistory.end(); anIt++) { + if ((*anIt)->isSame(aSubGeomShape)) { + (*aSubIter)->storeModified(aSubIn, aSubGeomShape, -2); // -2 is to avoid clearing + } + } } - } - } - } -} - -void Model_ResultBody::storeModified(const std::shared_ptr& theOldShape, - const std::shared_ptr& theNewShape) -{ - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (aData) { - TDF_Label& aShapeLab = aData->shapeLab(); - // clean builders - clean(); - // store the new shape as primitive - TNaming_Builder aBuilder(aShapeLab); - if (!theOldShape || !theNewShape) - return; // bad shape - TopoDS_Shape aShapeOld = theOldShape->impl(); - if (aShapeOld.IsNull()) - return; // null shape inside - TopoDS_Shape aShapeNew = theNewShape->impl(); - if (aShapeNew.IsNull()) - return; // null shape inside - aBuilder.Modify(aShapeOld, aShapeNew); - } -} - -std::shared_ptr Model_ResultBody::shape() -{ - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - if (aData) { - TDF_Label& aShapeLab = aData->shapeLab(); - Handle(TNaming_NamedShape) aName; - if (aShapeLab.FindAttribute(TNaming_NamedShape::GetID(), aName)) { - TopoDS_Shape aShape = aName->Get(); - if (!aShape.IsNull()) { - std::shared_ptr aRes(new GeomAPI_Shape); - aRes->setImpl(new TopoDS_Shape(aShape)); - return aRes; - } + }*/ + (*aSubIter)->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName); } + } else { // do for this directly + myBuilder->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName); } - return std::shared_ptr(); } -void Model_ResultBody::clean() +int Model_ResultBody::numberOfSubs(bool forTree) const { - std::vector::iterator aBuilder = myBuilders.begin(); - for(; aBuilder != myBuilders.end(); aBuilder++) - delete *aBuilder; - myBuilders.clear(); + return int(mySubs.size()); } -Model_ResultBody::~Model_ResultBody() +ResultBodyPtr Model_ResultBody::subResult(const int theIndex, bool forTree) const { - clean(); + if (theIndex >= int(mySubs.size())) + return ResultBodyPtr(); + return mySubs.at(theIndex); } -TNaming_Builder* Model_ResultBody::builder(const int theTag) +bool Model_ResultBody::isSub(ObjectPtr theObject, int& theIndex) const { - if (myBuilders.size() <= (unsigned int)theTag) { - myBuilders.insert(myBuilders.end(), theTag - myBuilders.size() + 1, NULL); - } - if (!myBuilders[theTag]) { - std::shared_ptr aData = std::dynamic_pointer_cast(data()); - myBuilders[theTag] = new TNaming_Builder(aData->shapeLab().FindChild(theTag)); - //TCollection_AsciiString entry;// - //TDF_Tool::Entry(aData->shapeLab().FindChild(theTag), entry); - //cout << "Label = " <::const_iterator aFound = mySubsMap.find(theObject); + if (aFound != mySubsMap.end()) { + theIndex = aFound->second; + return true; } - return myBuilders[theTag]; + return false; } -void Model_ResultBody::buildName(const int theTag, const std::string& theName) -{ - std::string aName = data()->name() + "/" + theName; - std::shared_ptr aDoc = std::dynamic_pointer_cast(document()); - aDoc->addNamingName(builder(theTag)->NamedShape()->Label(), aName); - TDataStd_Name::Set(builder(theTag)->NamedShape()->Label(),aName.c_str()); -} -void Model_ResultBody::generated( - const std::shared_ptr& theNewShape, const std::string& theName, const int theTag) -{ - TopoDS_Shape aShape = theNewShape->impl(); - builder(theTag)->Generated(aShape); - if(!theName.empty()) - buildName(theTag, theName); -} - -void Model_ResultBody::generated(const std::shared_ptr& theOldShape, - const std::shared_ptr& theNewShape, const std::string& theName, const int theTag) +void Model_ResultBody::colorConfigInfo(std::string& theSection, std::string& theName, + std::string& theDefault) { - TopoDS_Shape anOldShape = theOldShape->impl(); - TopoDS_Shape aNewShape = theNewShape->impl(); - builder(theTag)->Generated(anOldShape, aNewShape); - if(!theName.empty()) - buildName(theTag, theName); + theSection = "Visualization"; + theName = "result_body_color"; + theDefault = DEFAULT_COLOR(); } - -void Model_ResultBody::modified(const std::shared_ptr& theOldShape, - const std::shared_ptr& theNewShape, const std::string& theName, const int theTag) +bool Model_ResultBody::setDisabled(std::shared_ptr theThis, const bool theFlag) { - TopoDS_Shape anOldShape = theOldShape->impl(); - TopoDS_Shape aNewShape = theNewShape->impl(); - builder(theTag)->Modify(anOldShape, aNewShape); - if(!theName.empty()) - buildName(theTag, theName); + bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag); + if (aChanged) { // state is changed, so modifications are needed + updateSubs(shape(), false); // to set disabled/enabled + } + return aChanged; } -void Model_ResultBody::deleted(const std::shared_ptr& theOldShape, - const int theTag) +bool Model_ResultBody::isConcealed() { - TopoDS_Shape aShape = theOldShape->impl(); - builder(theTag)->Delete(aShape); + return myLastConcealed; } -void Model_ResultBody::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS, - std::shared_ptr theShapeIn, - const int theKindOfShape, - const int theTag) +void Model_ResultBody::setIsConcealed(const bool theValue) { - TopoDS_Shape aShapeIn = theShapeIn->impl(); - TopTools_MapOfShape aView; - TopExp_Explorer ShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); - for (; ShapeExplorer.More(); ShapeExplorer.Next ()) { - const TopoDS_Shape& aRoot = ShapeExplorer.Current (); - if (!aView.Add(aRoot)) continue; - std::shared_ptr aRShape(new GeomAPI_Shape()); - aRShape->setImpl((new TopoDS_Shape(aRoot))); - if (theMS->isDeleted (aRShape)) { - builder(theTag)->Delete(aRoot); - } + if (ModelAPI_ResultBody::isConcealed() != theValue) { + ModelAPI_ResultBody::setIsConcealed(theValue); + updateConcealment(); } } -void Model_ResultBody::loadAndOrientModifiedShapes ( - GeomAlgoAPI_MakeShape* theMS, - std::shared_ptr theShapeIn, - const int theKindOfShape, - const int theTag, - const std::string& theName, - GeomAPI_DataMapOfShapeShape& theSubShapes) +// recursively check all subs for concealment flag, returns true if everybody have "flag" state, +// in theAll returns results with "flag" state +static bool checkAllSubs(ResultBodyPtr theParent, bool theFlag, std::list& theAll) { - TopoDS_Shape aShapeIn = theShapeIn->impl(); - TopTools_MapOfShape aView; - bool isBuilt = theName.empty(); - TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); - for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { - const TopoDS_Shape& aRoot = aShapeExplorer.Current (); - if (!aView.Add(aRoot)) continue; - ListOfShape aList; - std::shared_ptr aRShape(new GeomAPI_Shape()); - aRShape->setImpl((new TopoDS_Shape(aRoot))); - theMS->modified(aRShape, aList); - std::list >::const_iterator anIt = aList.begin(), aLast = aList.end(); - for (; anIt != aLast; anIt++) { - TopoDS_Shape aNewShape = (*anIt)->impl(); - if (theSubShapes.isBound(*anIt)) { - std::shared_ptr aMapShape(theSubShapes.find(*anIt)); - aNewShape.Orientation(aMapShape->impl().Orientation()); - } - if (!aRoot.IsSame (aNewShape)) { - builder(theTag)->Modify(aRoot,aNewShape); - if(!isBuilt) - buildName(theTag, theName); - } - } + if (theParent->isConcealed() != theFlag) + theAll.push_back(theParent); + bool aResult = theParent->ModelAPI_ResultBody::isConcealed() == theFlag; + for(int a = 0; a < theParent->numberOfSubs(); a++) { + bool aSubRes = checkAllSubs(theParent->subResult(a), theFlag, theAll); + if (theFlag) + aResult = aResult || aSubRes; // concealed: one makes concealed everyone + else + aResult = aResult && aSubRes; // not concealed: all must be not concealed } + return aResult; } -void Model_ResultBody::loadAndOrientGeneratedShapes ( - GeomAlgoAPI_MakeShape* theMS, - std::shared_ptr theShapeIn, - const int theKindOfShape, - const int theTag, - const std::string& theName, - GeomAPI_DataMapOfShapeShape& theSubShapes) +void Model_ResultBody::updateConcealment() { - TopoDS_Shape aShapeIn = theShapeIn->impl(); - TopTools_MapOfShape aView; - bool isBuilt = theName.empty(); - TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape); - for (; aShapeExplorer.More(); aShapeExplorer.Next ()) { - const TopoDS_Shape& aRoot = aShapeExplorer.Current (); - if (!aView.Add(aRoot)) continue; - ListOfShape aList; - std::shared_ptr aRShape(new GeomAPI_Shape()); - aRShape->setImpl((new TopoDS_Shape(aRoot))); - theMS->generated(aRShape, aList); - std::list >::const_iterator anIt = aList.begin(), aLast = aList.end(); - for (; anIt != aLast; anIt++) { - TopoDS_Shape aNewShape = (*anIt)->impl(); - if (theSubShapes.isBound(*anIt)) { - std::shared_ptr aMapShape(theSubShapes.find(*anIt)); - aNewShape.Orientation(aMapShape->impl().Orientation()); - } - if (!aRoot.IsSame (aNewShape)) { - builder(theTag)->Generated(aRoot,aNewShape); - if(!isBuilt) - buildName(theTag, theName); + if (myLastConcealed != ModelAPI_ResultBody::isConcealed()) { + // check the whole tree of results: if one is concealed, everybody are concealed + ResultBodyPtr anOwner = std::dynamic_pointer_cast(data()->owner()); + if (!anOwner.get()) + return; // "this" is invalid + ResultBodyPtr aParent = ModelAPI_Tools::bodyOwner(anOwner); + while(aParent.get()) { + anOwner = aParent; + aParent = ModelAPI_Tools::bodyOwner(anOwner); + } + // iterate all results and collect all results whose state may be updated + std::list anUpdated; + bool aNewFlag = !myLastConcealed; + if (checkAllSubs(anOwner, aNewFlag, anUpdated)) { // state of everyone must be updated + std::list::iterator aRes = anUpdated.begin(); + for(; aRes != anUpdated.end(); aRes++) { + bool aLastConcealed = (*aRes)->isConcealed(); + if (aNewFlag != aLastConcealed) { + std::dynamic_pointer_cast(*aRes)->myLastConcealed = aNewFlag; + if (aNewFlag) { // become concealed, behaves like removed + ModelAPI_EventCreator::get()->sendDeleted(document(), groupName()); + } else { // become not-concealed, behaves like created + static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); + ModelAPI_EventCreator::get()->sendUpdated(*aRes, anEvent); + } + static Events_ID EVENT_DISP = // must be redisplayed in any case + Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + ModelAPI_EventCreator::get()->sendUpdated(*aRes, EVENT_DISP); + } } } } } -//======================================================================= -int getDangleShapes(const TopoDS_Shape& theShapeIn, - const TopAbs_ShapeEnum theGeneratedFrom, - TopTools_DataMapOfShapeShape& theDangles) +void Model_ResultBody::updateSubs(const std::shared_ptr& theThisShape, + const bool theShapeChanged) { - theDangles.Clear(); - TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors; - TopAbs_ShapeEnum GeneratedTo; - if (theGeneratedFrom == TopAbs_FACE) GeneratedTo = TopAbs_EDGE; - else if (theGeneratedFrom == TopAbs_EDGE) GeneratedTo = TopAbs_VERTEX; - else return Standard_False; - TopExp::MapShapesAndAncestors(theShapeIn, GeneratedTo, theGeneratedFrom, subShapeAndAncestors); - for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) { - const TopoDS_Shape& mayBeDangle = subShapeAndAncestors.FindKey(i); - const TopTools_ListOfShape& ancestors = subShapeAndAncestors.FindFromIndex(i); - if (ancestors.Extent() == 1) theDangles.Bind(ancestors.First(), mayBeDangle); - } - return theDangles.Extent(); -} - -//======================================================================= -void loadGeneratedDangleShapes( - const TopoDS_Shape& theShapeIn, - const TopAbs_ShapeEnum theGeneratedFrom, - TNaming_Builder * theBuilder) -{ - TopTools_DataMapOfShapeShape dangles; - if (!getDangleShapes(theShapeIn, theGeneratedFrom, dangles)) return; - TopTools_DataMapIteratorOfDataMapOfShapeShape itr(dangles); - for (; itr.More(); itr.Next()) - theBuilder->Generated(itr.Key(), itr.Value()); -} - -//======================================================================= -void Model_ResultBody::loadNextLevels(std::shared_ptr theShape, - const std::string& theName, int& theTag) -{ - if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); - std::string aName; - if (aShape.ShapeType() == TopAbs_SOLID) { - TopExp_Explorer expl(aShape, TopAbs_FACE); - for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + static Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + static Events_ID EVENT_UPD = aLoop->eventByName(EVENT_OBJECT_UPDATED); + static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); + // erase flag that topology is connected: the shape is new + if (theShapeChanged && data().get()) { + TDF_Label aDataLab = std::dynamic_pointer_cast(data())->label(); + if (!aDataLab.IsNull()) { + TDataStd_UAttribute::Set(aDataLab, kUpdateConnectedTopology); + isConnectedTopology(); // to store this flag in transaction, #2630 } } - else if (aShape.ShapeType() == TopAbs_SHELL || aShape.ShapeType() == TopAbs_FACE) { - // load faces and all the free edges - TopTools_IndexedMapOfShape Faces; - TopExp::MapShapes(aShape, TopAbs_FACE, Faces); - if (Faces.Extent() > 1 || (aShape.ShapeType() == TopAbs_SHELL && Faces.Extent() == 1)) { - TopExp_Explorer expl(aShape, TopAbs_FACE); - for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } - TopTools_IndexedDataMapOfShapeListOfShape anEdgeAndNeighbourFaces; - TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, anEdgeAndNeighbourFaces); - for (Standard_Integer i = 1; i <= anEdgeAndNeighbourFaces.Extent(); i++) - { - const TopTools_ListOfShape& aLL = anEdgeAndNeighbourFaces.FindFromIndex(i); - if (aLL.Extent() < 2) { - if (BRep_Tool::Degenerated(TopoDS::Edge(anEdgeAndNeighbourFaces.FindKey(i)))) - continue; - builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } else { - TopTools_ListIteratorOfListOfShape anIter(aLL); - const TopoDS_Face& aFace = TopoDS::Face(anIter.Value()); - anIter.Next(); - if(aFace.IsEqual(anIter.Value())) { - builder(theTag)->Generated(anEdgeAndNeighbourFaces.FindKey(i)); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; + // iterate all sub-solids of compsolid to make sub-results synchronized with them + TopoDS_Shape aThisShape; + if (theThisShape.get()) aThisShape = theThisShape->impl(); + if (!aThisShape.IsNull() && (aThisShape.ShapeType() == TopAbs_COMPSOLID || + aThisShape.ShapeType() == TopAbs_COMPOUND)) { + bool aWasEmpty = mySubs.empty(); + Model_Objects* anObjects = std::dynamic_pointer_cast(document())->objects(); + unsigned int aSubIndex = 0; + TopoDS_Iterator aShapesIter(aThisShape); + for(; aShapesIter.More(); aShapesIter.Next(), aSubIndex++) { + std::shared_ptr aShape(new GeomAPI_Shape); + aShape->setImpl(new TopoDS_Shape(aShapesIter.Value())); + ResultBodyPtr aSub; + if (mySubs.size() <= aSubIndex) { // it is needed to create a new sub-result + aSub = anObjects->createBody(this->data(), aSubIndex); + mySubs.push_back(aSub); + mySubsMap[aSub] = int(mySubs.size() - 1); + if (isConcealed()) { // for issue #2579 note7 + aSub->ModelAPI_ResultBody::setIsConcealed(true); + std::dynamic_pointer_cast(aSub)->updateConcealment(); } + } else { // just update shape of this result + aSub = mySubs[aSubIndex]; } - } - } else if (aShape.ShapeType() == TopAbs_WIRE) { - TopTools_IndexedMapOfShape Edges; - BRepTools::Map3DEdges(aShape, Edges); - if (Edges.Extent() == 1) { - builder(++theTag)->Generated(Edges.FindKey(1)); - TopExp_Explorer expl(aShape, TopAbs_VERTEX); - for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } else { - TopExp_Explorer expl(aShape, TopAbs_EDGE); - for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - // and load generated vertices. - TopTools_DataMapOfShapeShape generated; - if (getDangleShapes(aShape, TopAbs_EDGE, generated)) - { - TNaming_Builder* pBuilder = builder(theTag++); - loadGeneratedDangleShapes(aShape, TopAbs_EDGE, pBuilder); + GeomShapePtr anOldSubShape = aSub->shape(); + aSub->store(aShape, false); // store even equal to call "clear": #2814 + if (!aShape->isEqual(anOldSubShape)) { + aECreator->sendUpdated(aSub, EVENT_DISP); + aECreator->sendUpdated(aSub, EVENT_UPD); } + aSub->setDisabled(aSub, isDisabled()); } - } else if (aShape.ShapeType() == TopAbs_EDGE) { - TopExp_Explorer expl(aShape, TopAbs_VERTEX); - for (; expl.More(); expl.Next()) { - builder(theTag)->Generated(expl.Current()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } -} - -//======================================================================= -int findAmbiguities(const TopoDS_Shape& theShapeIn, - TopTools_ListOfShape& theList) -{ - int aNumEdges(0); - theList.Clear(); - TopTools_IndexedDataMapOfShapeListOfShape subShapeAndAncestors; - TopAbs_ShapeEnum aTS(TopAbs_EDGE); - TopAbs_ShapeEnum aTA(TopAbs_FACE); - TopTools_MapOfShape aMap1, aMap2; // map1 - for edge ancestors; map2 - for keys => edges - TopTools_ListOfShape aKeyList; - TopExp::MapShapesAndAncestors(theShapeIn, aTS, aTA, subShapeAndAncestors); - for (Standard_Integer i = 1; i <= subShapeAndAncestors.Extent(); i++) { - const TopoDS_Shape& aKeyEdge1 = subShapeAndAncestors.FindKey(i); - const TopTools_ListOfShape& ancestors1 = subShapeAndAncestors.FindFromIndex(i); - aMap1.Clear(); - TopTools_ListIteratorOfListOfShape it(ancestors1); - for(;it.More();it.Next()) aMap1.Add(it.Value()); // fill map with key ancestors => aKey1 - for (Standard_Integer j = 1; j <= subShapeAndAncestors.Extent(); j++) { - if (i == j) continue; - const TopoDS_Shape& aKeyEdge2 = subShapeAndAncestors.FindKey(j); - const TopTools_ListOfShape& ancestors2 = subShapeAndAncestors.FindFromIndex(j); - if(ancestors1.Extent() == ancestors2.Extent() && ancestors1.Extent() > 1) { - int aNum (ancestors2.Extent()); - TopTools_ListIteratorOfListOfShape it(ancestors2); - for(;it.More();it.Next()) - if(aMap1.Contains(it.Value())) aNum--; - if(aNum == 0) { - if(aMap2.Add(aKeyEdge1)) - aKeyList.Append(aKeyEdge1); - if(aMap2.Add(aKeyEdge2)) - aKeyList.Append(aKeyEdge2); - } - } - } // at the end ==> List of edges to be named in addition - } - aNumEdges = aKeyList.Extent(); - if(aNumEdges) - theList.Assign(aKeyList); - return aNumEdges; -} - -//======================================================================= -void Model_ResultBody::loadFirstLevel( - std::shared_ptr theShape, const std::string& theName, int& theTag) -{ - if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); - std::string aName; - if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) { - TopoDS_Iterator itr(aShape); - for (; itr.More(); itr.Next(),theTag++) { - builder(theTag)->Generated(itr.Value()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - if(!theName.empty()) buildName(theTag, aName); - if (itr.Value().ShapeType() == TopAbs_COMPOUND || - itr.Value().ShapeType() == TopAbs_COMPSOLID) - { - std::shared_ptr itrShape(new GeomAPI_Shape()); - itrShape->setImpl(new TopoDS_Shape(itr.Value())); - loadFirstLevel(itrShape, theName, theTag); - } else { - std::shared_ptr itrShape(new GeomAPI_Shape()); - itrShape->setImpl(new TopoDS_Shape(itr.Value())); - loadNextLevels(itrShape, theName, theTag); + // erase left, unused results + while(mySubs.size() > aSubIndex) { + ResultBodyPtr anErased = *(mySubs.rbegin()); + if (anErased->ModelAPI_ResultBody::isConcealed()) { + anErased->ModelAPI_ResultBody::setIsConcealed(false); + std::dynamic_pointer_cast(anErased)->updateConcealment(); } + anErased->setDisabled(anErased, true); + mySubsMap.erase(anErased); + mySubs.pop_back(); } - } else { - std::shared_ptr itrShape(new GeomAPI_Shape()); - itrShape->setImpl(new TopoDS_Shape(aShape)); - loadNextLevels(itrShape, theName, theTag); - } - TopTools_ListOfShape aList; - if(findAmbiguities(aShape, aList)) { - TopTools_ListIteratorOfListOfShape it(aList); - for (; it.More(); it.Next(),theTag++) { - builder(theTag)->Generated(it.Value()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); + if (aWasEmpty) { // erase all subs + // redisplay this because result with and without subs are displayed differently + aECreator->sendUpdated(data()->owner(), EVENT_DISP); } - } -} - -//======================================================================= -void Model_ResultBody::loadDisconnectedEdges( - std::shared_ptr theShape, const std::string& theName, int& theTag) -{ - if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); - TopTools_DataMapOfShapeListOfShape edgeNaborFaces; - TopTools_ListOfShape empty; - TopExp_Explorer explF(aShape, TopAbs_FACE); - for (; explF.More(); explF.Next()) { - const TopoDS_Shape& aFace = explF.Current(); - TopExp_Explorer explV(aFace, TopAbs_EDGE); - for (; explV.More(); explV.Next()) { - const TopoDS_Shape& anEdge = explV.Current(); - if (!edgeNaborFaces.IsBound(anEdge)) edgeNaborFaces.Bind(anEdge, empty); - Standard_Boolean faceIsNew = Standard_True; - TopTools_ListIteratorOfListOfShape itrF(edgeNaborFaces.Find(anEdge)); - for (; itrF.More(); itrF.Next()) { - if (itrF.Value().IsSame(aFace)) { - faceIsNew = Standard_False; - break; - } + } else if (!mySubs.empty()) { // erase all subs + while(!mySubs.empty()) { + ResultBodyPtr anErased = *(mySubs.rbegin()); + if (anErased->ModelAPI_ResultBody::isConcealed()) { + anErased->ModelAPI_ResultBody::setIsConcealed(false); + std::dynamic_pointer_cast(anErased)->updateConcealment(); } - if (faceIsNew) - edgeNaborFaces.ChangeFind(anEdge).Append(aFace); + anErased->setDisabled(anErased, true); // even if it is invalid (to erase subs on abort/undo) + mySubs.pop_back(); } + mySubsMap.clear(); + // redisplay this because result with and without subs are displayed differently + aECreator->sendUpdated(data()->owner(), EVENT_DISP); } - - /* TopTools_IndexedDataMapOfShapeListOfShape aDM; - TopExp::MapShapesAndAncestors(aShape, TopAbs_EDGE, TopAbs_FACE, aDM); - for(int i=1; i <= aDM.Extent(); i++) { - if(aDM.FindFromIndex(i).Extent() > 1) continue; - if (BRep_Tool::Degenerated(TopoDS::Edge(aDM.FindKey(i)))) - continue; - builder(theTag)->Generated(aDM.FindKey(i)); - TCollection_AsciiString aStr(theTag); - std::string aName = theName + aStr.ToCString(); - buildName(theTag, aName); - #ifdef DEB_IMPORT - aName += + ".brep"; - BRepTools::Write(aDM.FindKey(i), aName.c_str()); - #endif - theTag++; - } - */ - TopTools_MapOfShape anEdgesToDelete; - TopExp_Explorer anEx(aShape,TopAbs_EDGE); - std::string aName; - for(;anEx.More();anEx.Next()) { - Standard_Boolean aC0 = Standard_False; - TopoDS_Shape anEdge1 = anEx.Current(); - if (edgeNaborFaces.IsBound(anEdge1)) { - const TopTools_ListOfShape& aList1 = edgeNaborFaces.Find(anEdge1); - if (aList1.Extent()<2) continue; - TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(edgeNaborFaces); - for (; itr.More(); itr.Next()) { - TopoDS_Shape anEdge2 = itr.Key(); - if(anEdgesToDelete.Contains(anEdge2)) continue; - if (anEdge1.IsSame(anEdge2)) continue; - const TopTools_ListOfShape& aList2 = itr.Value(); - // compare lists of the neighbour faces of edge1 and edge2 - if (aList1.Extent() == aList2.Extent()) { - Standard_Integer aMatches = 0; - for(TopTools_ListIteratorOfListOfShape aLIter1(aList1);aLIter1.More();aLIter1.Next()) - for(TopTools_ListIteratorOfListOfShape aLIter2(aList2);aLIter2.More();aLIter2.Next()) - if (aLIter1.Value().IsSame(aLIter2.Value())) aMatches++; - if (aMatches == aList1.Extent()) { - aC0=Standard_True; - builder(theTag)->Generated(anEdge2); - anEdgesToDelete.Add(anEdge2); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } - } - TopTools_MapIteratorOfMapOfShape itDelete(anEdgesToDelete); - for(;itDelete.More();itDelete.Next()) - edgeNaborFaces.UnBind(itDelete.Key()); - edgeNaborFaces.UnBind(anEdge1); - } - if (aC0) { - builder(theTag)->Generated(anEdge1); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } } -void Model_ResultBody::loadDisconnectedVertexes(std::shared_ptr theShape, const std::string& theName, int& theTag) +bool Model_ResultBody::isConnectedTopology() { - if(theShape->isNull()) return; - TopoDS_Shape aShape = theShape->impl(); - TopTools_DataMapOfShapeListOfShape vertexNaborEdges; - TopTools_ListOfShape empty; - TopExp_Explorer explF(aShape, TopAbs_EDGE); - for (; explF.More(); explF.Next()) { - const TopoDS_Shape& anEdge = explF.Current(); - TopExp_Explorer explV(anEdge, TopAbs_VERTEX); - for (; explV.More(); explV.Next()) { - const TopoDS_Shape& aVertex = explV.Current(); - if (!vertexNaborEdges.IsBound(aVertex)) vertexNaborEdges.Bind(aVertex, empty); - Standard_Boolean faceIsNew = Standard_True; - TopTools_ListIteratorOfListOfShape itrF(vertexNaborEdges.Find(aVertex)); - for (; itrF.More(); itrF.Next()) { - if (itrF.Value().IsSame(anEdge)) { - faceIsNew = Standard_False; - break; - } - } - if (faceIsNew) { - vertexNaborEdges.ChangeFind(aVertex).Append(anEdge); + TDF_Label aDataLab = std::dynamic_pointer_cast(data())->label(); + if (!aDataLab.IsNull()) { + if (aDataLab.IsAttribute(kUpdateConnectedTopology)) { // recompute state + aDataLab.ForgetAttribute(kUpdateConnectedTopology); + GeomShapePtr aShape = shape(); + if (aShape.get() && aShape->isConnectedTopology()) { + TDataStd_UAttribute::Set(aDataLab, kIsConnectedTopology); + } else { + aDataLab.ForgetAttribute(kIsConnectedTopology); } } + return aDataLab.IsAttribute(kIsConnectedTopology); } - std::string aName; - TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itr(vertexNaborEdges); - for (; itr.More(); itr.Next()) { - const TopTools_ListOfShape& naborEdges = itr.Value(); - if (naborEdges.Extent() < 2) { - builder(theTag)->Generated(itr.Key()); - TCollection_AsciiString aStr(theTag); - aName = theName + aStr.ToCString(); - buildName(theTag, aName); - theTag++; - } - } + return false; // invalid case }