TestGroupMove.py
TestGroupMove2.py
TestGroupMove3.py
+ TestGroupMove4.py
TestGroupShareTopology.py
)
--- /dev/null
+## 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<mailto:webmaster.salome@opencascade.com>
+##
+
+# Test of deep nested results history. Cylinders divided to two by cut, then each divided to
+# two by partition by plane, then resulting compsolids are collected in compound.
+# Checking that group on initial extrusion moved to the end contains the corresponding
+# results, but divided.
+
+from salome.shaper import model
+from ModelAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(-4.602216748768477, 10.94581280788177, 9.660420057801511)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")], model.selection(), 10, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")])
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), 1, True)
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+SketchCircle_2 = Sketch_2.addCircle(-5.643073116097736, 11.91382008305256, 15.03576198961618)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_2_2r")], model.selection(), 2, -4)
+Cut_1 = model.addCut(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], [model.selection("SOLID", "Extrusion_2_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("COMPOUND", "Cut_1_1"), model.selection("FACE", "Plane_1")])
+Compound_1 = model.addCompound(Part_1_doc, [model.selection("COMPSOLID", "Partition_1_1"), model.selection("COMPSOLID", "Partition_1_2")])
+model.do()
+# move groups to the end
+Part_1_doc.moveFeature(Group_1.feature(), Compound_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+aFactory = ModelAPI_Session.get().validators()
+# check group 1: cylindical face is divided to 6 (because of seam edge)
+selectionList = Group_1.feature().selectionList("group_list")
+assert(selectionList.size() == 6)
+assert(aFactory.validate(Group_1.feature()))
+
+# check group 2: solid is divided to 4 solids
+selectionList = Group_2.feature().selectionList("group_list")
+assert(selectionList.size() == 4)
+assert(aFactory.validate(Group_2.feature()))
+
+assert(model.checkPythonDump())
std::shared_ptr<ModelAPI_ResultBody> aResultBody =
document()->createBody(data(), aResultIndex);
- GeomShapePtr aBaseShape = anObjects.front();
- anObjects.pop_front();
+ ListOfShape anEmptyTools;
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- aBaseShape,
anObjects,
+ anEmptyTools,
aMakeShapeList,
aShape);
+ GeomShapePtr aBaseShape = anObjects.front();
+ anObjects.pop_front();
setResult(aResultBody, aResultIndex);
aResultIndex++;
if (aShapeIt.more() || aResShape->shapeType() == GeomAPI_Shape::VERTEX) {
std::shared_ptr<ModelAPI_ResultBody> aResultBody =
document()->createBody(data(), aResultIndex);
-
+ ListOfShape anObjectList;
+ anObjectList.push_back(anObject);
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- anObject,
+ anObjectList,
aTools,
aMakeShapeList,
aResShape);
std::shared_ptr<ModelAPI_ResultBody> aResultBody =
document()->createBody(data(), aResultIndex);
+ ListOfShape aCompSolidList;
+ aCompSolidList.push_back(aCompSolid);
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- aCompSolid,
+ aCompSolidList,
aTools,
aMakeShapeList,
aResultShape);
std::shared_ptr<ModelAPI_ResultBody> aResultBody =
document()->createBody(data(), aResultIndex);
+ ListOfShape aCompoundList;
+ aCompoundList.push_back(aCompound);
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- aCompound,
+ aCompoundList,
aTools,
aMakeShapeList,
aResultShape);
std::shared_ptr<ModelAPI_ResultBody> aResultBody =
document()->createBody(data(), aResultIndex);
+ ListOfShape anObjectList;
+ anObjectList.push_back(anObject);
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- anObject,
+ anObjectList,
aTools,
aMakeShapeList,
aResShape);
std::shared_ptr<ModelAPI_ResultBody> aResultBody =
document()->createBody(data(), aResultIndex);
+ ListOfShape anObjectList;
+ anObjectList.push_back(aCompSolid);
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- aCompSolid,
+ anObjectList,
aTools,
aMakeShapeList,
aResultShape);
std::shared_ptr<ModelAPI_ResultBody> aResultBody =
document()->createBody(data(), aResultIndex);
+ ListOfShape anObjectList;
+ anObjectList.push_back(aCompound);
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- aCompound,
+ anObjectList,
aTools,
aMakeShapeList,
aResultShape);
int aResultIndex = 0;
- GeomShapePtr aBackShape = anOriginalShapes.back();
- anOriginalShapes.pop_back();
ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+ ListOfShape anEmptyTools;
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- aBackShape,
anOriginalShapes,
+ anEmptyTools,
aMakeShapeList,
aShape);
setResult(aResultBody, aResultIndex);
aResultIndex++;
FeaturesPlugin_Tools::loadDeletedShapes(aResultBody,
- aBackShape,
+ GeomShapePtr(),
anOriginalShapes,
aMakeShapeList,
aShape);
aMakeShapeList->appendAlgo(aFillerAlgo);
}
- std::shared_ptr<GeomAPI_Shape> aFrontShape = anOriginalShapes.front();
- anOriginalShapes.pop_front();
std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
FeaturesPlugin_Tools::loadModifiedShapes(aResultBody,
- aFrontShape,
+ anOriginalShapes,
anOriginalShapes,
aMakeShapeList,
aShape);
aResultIndex++;
FeaturesPlugin_Tools::loadDeletedShapes(aResultBody,
- aFrontShape,
+ GeomShapePtr(),
anOriginalShapes,
aMakeShapeList,
aShape);
//==================================================================================================
void FeaturesPlugin_Tools::loadModifiedShapes(ResultBodyPtr theResultBody,
- const GeomShapePtr theBaseShape,
+ const ListOfShape& theBaseShapes,
const ListOfShape& theTools,
const GeomMakeShapePtr& theMakeShape,
const GeomShapePtr theResultShape)
{
- if (theBaseShape->isEqual(theResultShape)) {
- theResultBody->store(theResultShape, false);
- return;
- }
-
- theResultBody->storeModified(theBaseShape, theResultShape);
+ theResultBody->storeModified(theBaseShapes, theResultShape, theMakeShape);
- ListOfShape aShapes = theTools;
- aShapes.push_front(theBaseShape);
+ ListOfShape aShapes = theBaseShapes;
+ ListOfShape::const_iterator aToolIter = theTools.cbegin();
+ for(; aToolIter != theTools.cend(); aToolIter++)
+ aShapes.push_back(*aToolIter);
for (ListOfShape::const_iterator anIter = aShapes.begin(); anIter != aShapes.end(); ++anIter)
{
//==================================================================================================
void FeaturesPlugin_Tools::loadModifiedShapes(ResultBodyPtr theResultBody,
- const GeomShapePtr theBaseShape,
+ const GeomShapePtr& theBaseShape,
const GeomMakeShapePtr& theMakeShape,
const std::string theName)
{
const GeomShapePtr theResultShapesCompound)
{
ListOfShape aShapes = theTools;
- aShapes.push_front(theBaseShape);
+ if (theBaseShape.get())
+ aShapes.push_front(theBaseShape);
for (ListOfShape::const_iterator anIter = aShapes.begin(); anIter != aShapes.end(); anIter++)
{
public:
static void loadModifiedShapes(ResultBodyPtr theResultBody,
- const GeomShapePtr theBaseShape,
+ const ListOfShape& theBaseShapes,
const ListOfShape& theTools,
const GeomMakeShapePtr& theMakeShape,
const GeomShapePtr theResultShape);
static void loadModifiedShapes(ResultBodyPtr theResultBody,
- const GeomShapePtr theBaseShape,
+ const GeomShapePtr& theBaseShape,
const GeomMakeShapePtr& theMakeShape,
const std::string theName);
-
/// Stores deleted shapes.
static void loadDeletedShapes(ResultBodyPtr theResultBody,
const GeomShapePtr theBaseShape,
std::list<ResultPtr>& theResults, TopTools_ListOfShape& theValShapes)
{
std::set<ResultPtr> aResults; // to avoid duplicates, new context, null if deleted
- TopTools_ListOfShape aResContShapes;
// iterate context and shape, but also if it is sub-shape of main shape, check also it
TopTools_ListOfShape aContextList;
aContextList.Append(theContShape);
aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS);
if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) {
aResults.insert(aModifierObj);
- aResContShapes.Append(aModifierObj->shape()->impl<TopoDS_Shape>());
} else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is empty
aResults.insert(ResultPtr());
} else { // not-processed modification => don't support it
}
}
}
+ // if there exist context composite and sub-result(s), leave only sub(s)
+ for(std::set<ResultPtr>::iterator aResIter = aResults.begin(); aResIter != aResults.end();) {
+ ResultPtr aParent = ModelAPI_Tools::bodyOwner(*aResIter);
+ for(; aParent.get(); aParent = ModelAPI_Tools::bodyOwner(aParent))
+ if (aResults.count(aParent))
+ break;
+ if (aParent.get()) { // erase from set, so, restart iteration
+ aResults.erase(aParent);
+ aResIter = aResults.begin();
+ } else aResIter++;
+ }
+
if (aResults.empty())
return false; // no modifications found, must stay the same
// iterate all results to find further modifications
setValue(*aNewCont, aValueShape);
aFirst = false;
} else if (myParent) {
- myParent->append(*aNewCont, aValueShape);
+ if (!myParent->isInList(*aNewCont, aValueShape)) // avoid addition of duplicates
+ myParent->append(*aNewCont, aValueShape);
}
}
if (aFirst) { // nothing was added, all results were deleted
#include <TopoDS_Shape.hxx>
#include <TopExp_Explorer.hxx>
+#include <TopTools_MapOfShape.hxx>
#include <TDataStd_UAttribute.hxx>
// if this attribute exists, the shape is connected topology
}
}
+// adds to the theSubSubs map all sub-shapes of theSub if it is compound of compsolid
+static void collectSubs(
+ const GeomShapePtr theSub, TopTools_MapOfShape& theSubSubs, const bool theOneLevelMore)
+{
+ if (theSub->isNull())
+ return;
+ if (theSubSubs.Add(theSub->impl<TopoDS_Shape>())) {
+ bool aIsComp = theSub->isCompound() || theSub->isCompSolid();
+ if (aIsComp || theOneLevelMore) {
+ for(GeomAPI_ShapeIterator anIter(theSub); anIter.more(); anIter.next()) {
+ collectSubs(anIter.current(), theSubSubs, aIsComp && theOneLevelMore);
+ }
+ }
+ }
+}
+
void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub,
const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub)
{
+ // the old can be also used for sub-shape of theSub; collect all subs of compound or compsolid
+ TopTools_MapOfShape aSubSubs;
+ collectSubs(theSub, aSubSubs, false);
+
std::list<GeomShapePtr>::const_iterator aRootOlds = theAllOlds.cbegin();
- for(; aRootOlds != theAllOlds.cend(); aRootOlds++) {
- ListOfShape aNews;
- myIsGenerated ? myAlgo->generated(*aRootOlds, aNews) : myAlgo->modified(*aRootOlds, aNews);
- // MakeShape may return alone old shape if there is no history information for this input
- if (aNews.size() == 1 && aNews.front()->isEqual(*aRootOlds))
- aNews.clear();
- if (aNews.empty()) { // try to iterate to sub-elements (for intersection of solids this is face)
- std::list<GeomShapePtr> theAllSubOlds;
- for(GeomAPI_ShapeIterator aSubOld(*aRootOlds); aSubOld.more(); aSubOld.next()) {
- GeomShapePtr aSub = aSubOld.current();
- if (aSub.get() && !aSub->isNull())
- theAllSubOlds.push_back(aSub);
- }
- computeOldForSub(theSub, theAllSubOlds, theOldForSub);
- }
- for(ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
- if (theSub->isSame(*aNewIter)) { // found old that was used for new theSubShape creation
- theOldForSub.push_back(*aRootOlds);
- break;
+ for (; aRootOlds != theAllOlds.cend(); aRootOlds++) {
+ // use sub-shapes of olds too if they are compounds or compsolids
+ TopTools_MapOfShape anOldSubs;
+ // iterate one level more (for intersection of solids this is face)
+ collectSubs(*aRootOlds, anOldSubs, true);
+ for (TopTools_MapOfShape::Iterator anOldIter(anOldSubs); anOldIter.More(); anOldIter.Next()) {
+ GeomShapePtr anOldSub(new GeomAPI_Shape);
+ anOldSub->setImpl<TopoDS_Shape>(new TopoDS_Shape(anOldIter.Value()));
+ ListOfShape aNews;
+ myIsGenerated ? myAlgo->generated(anOldSub, aNews) : myAlgo->modified(anOldSub, aNews);
+ // MakeShape may return alone old shape if there is no history information for this input
+ if (aNews.size() == 1 && aNews.front()->isEqual(anOldSub))
+ aNews.clear();
+
+ for (ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
+ if (aSubSubs.Contains((*aNewIter)->impl<TopoDS_Shape>())) {
+ // check list already contains this sub
+ std::list<GeomShapePtr>::iterator aResIter = theOldForSub.begin();
+ for(; aResIter != theOldForSub.end(); aResIter++)
+ if ((*aResIter)->isSame(anOldSub))
+ break;
+ if (aResIter == theOldForSub.end())
+ theOldForSub.push_back(anOldSub); // found old used for new theSubShape creation
+ break;
+ }
}
}
}