int anIndexToRemove = 0;
if (aCopyCompound) {
ResultBodyPtr aResultBody = document()->createBody(data(), anIndexToRemove++);
- aResultBody->store(aCopyCompound);
+ aResultBody->storeModified(anOriginalShapes, aCopyCompound, aCopyAlgo);
aResultBody->loadModifiedShapes(aCopyAlgo, aCompound, GeomAPI_Shape::VERTEX);
aResultBody->loadModifiedShapes(aCopyAlgo, aCompound, GeomAPI_Shape::EDGE);
aResultBody->loadModifiedShapes(aCopyAlgo, aCompound, GeomAPI_Shape::FACE);
setResult(aResultBody, aResultIndex);
aResultIndex++;
-
// remove the rest results if there were produced in the previous pass
removeResults(aResultIndex);
}
return;
}
- theResultBody->storeModified(theObjects.front(), aResultShape);
+ theResultBody->storeModified(theObjects, aResultShape, theMakeShape);
const int aShapeTypesNb = 3;
const GeomAPI_Shape::ShapeType aShapeTypes[aShapeTypesNb] = {GeomAPI_Shape::VERTEX,
assert(aList2.value(0).value().shapeTypeStr() == "SOLID")
assert(aList2.value(1).value().shapeTypeStr() == "SOLID")
assert(aList1.value(0).value().isSame(aList2.value(0).value()) or aList1.value(1).value().isSame(aList2.value(0).value()) or
-aList1.value(1).value().isSame(aList2.value(0).value()) or aList1.value(1).value().isSame(aList2.value(1).value()))
+aList1.value(0).value().isSame(aList2.value(1).value()) or aList1.value(1).value().isSame(aList2.value(1).value()))
Face_1_objects = [model.selection("EDGE", "Sketch_1/SketchArc_2_2"), model.selection("EDGE", "Sketch_1/SketchLine_4"), model.selection("EDGE", "Sketch_1/SketchLine_5"), model.selection("EDGE", "Sketch_1/SketchLine_6"), model.selection("EDGE", "Sketch_1/SketchLine_7"), model.selection("EDGE", "Sketch_1/SketchLine_8"), model.selection("EDGE", "Sketch_1/SketchLine_1"), model.selection("EDGE", "Sketch_1/SketchLine_2")]
Face_1 = model.addFace(Part_1_doc, Face_1_objects)
Intersection_1 = model.addIntersection(Part_1_doc, [model.selection("SOLID", "Recover_1_1"), model.selection("FACE", "Face_1_1")])
-Group_1_objects = [model.selection("VERTEX", "[Intersection_1_1_3/Intersection_1_1_3&Face_1_1/Edge_3][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_1/Intersection_1_1_1][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_9/Intersection_1_1_9&Face_1_1/Edge_7][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_7/Intersection_1_1_7&Face_1_1/Edge_5][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_4/Intersection_1_1_4][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_1/Intersection_1_1_1][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_2/Intersection_1_1_2&Face_1_1/Edge_2][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_4/Intersection_1_1_4][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_6/Intersection_1_1_6&Face_1_1/Edge_4][weak_name_2]"), model.selection("VERTEX", "[Intersection_1_1_10/Intersection_1_1_10&Face_1_1/Edge_8][weak_name_1]"), model.selection("VERTEX", "[Intersection_1_1_8/Intersection_1_1_8&Face_1_1/Edge_6][weak_name_1]")]
+Group_1_objects = [
+model.selection("VERTEX", "[Intersection_1_1_3/Intersection_1_1_3&Face_1_1/Edge_3][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_1/Intersection_1_1_1][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_9/Intersection_1_1_9&Face_1_1/Edge_7][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_7/Intersection_1_1_7&Face_1_1/Edge_5][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_4/Intersection_1_1_4][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_1/Intersection_1_1_1][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_2/Intersection_1_1_2&Face_1_1/Edge_2][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_4/Intersection_1_1_4][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_6/Intersection_1_1_6&Face_1_1/Edge_4][weak_name_2]"),
+model.selection("VERTEX", "[Intersection_1_1_10/Intersection_1_1_10&Face_1_1/Edge_8][weak_name_1]"),
+model.selection("VERTEX", "[Intersection_1_1_8/Intersection_1_1_8&Face_1_1/Edge_6][weak_name_1]")]
+
Group_1 = model.addGroup(Part_1_doc, Group_1_objects)
Group_2_objects = [model.selection("EDGE", "Intersection_1_1_7"), model.selection("EDGE", "Intersection_1_1_6"), model.selection("EDGE", "Intersection_1_1_3"), model.selection("EDGE", "Intersection_1_1_11"), model.selection("EDGE", "Intersection_1_1_5"), model.selection("EDGE", "Intersection_1_1_1"), model.selection("EDGE", "Intersection_1_1_4"), model.selection("EDGE", "Intersection_1_1_2"), model.selection("EDGE", "Intersection_1_1_10"), model.selection("EDGE", "Intersection_1_1_9"), model.selection("EDGE", "Intersection_1_1_8")]
Group_2 = model.addGroup(Part_1_doc, Group_2_objects)
}
}
if (aToFindPart == 2 && !aNewToOld.IsEmpty()) {
+ // also iterate the whole old shape to find not-modified shapes that contain this old
+ TopoDS_Shape anOldContShape = theOldContext->shape()->impl<TopoDS_Shape>();
+ NCollection_Map<TopAbs_ShapeEnum> aNewTypes; // types of shapes to iterate
+ TopTools_DataMapOfShapeShape::Iterator aNewTypeIter(aNewToOld);
+ for(; aNewTypeIter.More(); aNewTypeIter.Next()) {
+ if (aNewTypeIter.Key().ShapeType() != theValShape.ShapeType())
+ aNewTypes.Add(aNewTypeIter.Key().ShapeType());
+ }
+ NCollection_Map<TopAbs_ShapeEnum>::Iterator aTypeIter(aNewTypes);
+ for(; aTypeIter.More(); aTypeIter.Next()) {
+ for(TopExp_Explorer anExp(anOldContShape, aTypeIter.Value()); anExp.More(); anExp.Next()) {
+ TopoDS_Shape anOld = anExp.Current();
+ if (aNewToOld.IsBound(anOld) || anOlds.Contains(anOld)) // this was modified
+ continue;
+ TopExp_Explorer aValExp(anOld, theValShape.ShapeType());
+ for(; aValExp.More(); aValExp.Next()) {
+ const TopoDS_Shape& anUnchanged = aValExp.Current();
+ if (anUnchanged.IsSame(theValShape)) {
+ aNewToOld.Bind(anOld, anOld);
+ anOlds.Add(anOld);
+ break;
+ }
+ }
+ }
+ }
+
// map of sub-shapes -> number of occurrences of these shapes in containers
NCollection_DataMap<TopoDS_Shape, TopTools_MapOfShape, TopTools_ShapeMapHasher> aSubs;
TopTools_DataMapOfShapeShape::Iterator aContIter(aNewToOld);
aSubsIter(aSubs);
for(; aSubsIter.More(); aSubsIter.Next()) {
if (aSubsIter.Value().Size() == aCountInOld) {
- theShapes.Append(aSubsIter.Key());
+ TopoDS_Shape anOld = aSubsIter.Key();
+ // check this exists in the new shape
+ TopExp_Explorer aNew(aNewContShape, anOld.ShapeType());
+ for (; aNew.More(); aNew.Next()) {
+ if (aNew.Current().IsSame(anOld))
+ break;
+ }
+ if (aNew.More())
+ theShapes.Append(anOld);
}
}
}
if (theShapes.IsEmpty()) { // nothing was changed
- theShapes.Append(aWasWholeContext ? TopoDS_Shape() : theValShape);
+ if (aWasWholeContext)
+ theShapes.Append(TopoDS_Shape());
+ else { // if theValShape exists in new context, add it without changes, otherwise - nothing
+ for (TopExp_Explorer aNew(aNewContShape, theValShape.ShapeType()); aNew.More(); aNew.Next()){
+ if (aNew.Current().IsSame(theValShape)) {
+ theShapes.Append(theValShape);
+ break;
+ }
+ }
+ }
}
}
{
}
+/// Checks that shape is presented in the tree with not-selection evolution
+/// In theOriginalLabel it returns label where NS of old sub-shape is stored
+static bool isShapeInTree(const TDF_Label& theAccess1, const TDF_Label& theAccess2,
+ TopoDS_Shape theShape, TDF_Label& theOriginalLabel)
+{
+ bool aResult = TNaming_Tool::HasLabel(theAccess1, theShape);
+ if (aResult) { //check evolution and a label of this shape
+ for(TNaming_SameShapeIterator aShapes(theShape, theAccess1); aShapes.More(); aShapes.Next())
+ {
+ static Handle(TNaming_NamedShape) aNS;
+ if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+ if (aNS->Evolution() != TNaming_SELECTED) {
+ theOriginalLabel = aNS->Label();
+ return true;
+ }
+ }
+ }
+ }
+ if (!theAccess2.IsNull()) {
+ static const TDF_Label anEmpty;
+ return isShapeInTree(theAccess2, anEmpty, theShape, theOriginalLabel);
+ }
+ return false;
+}
+
+/// Stores entry to the external label in the entries list at this label
+static void storeExternalReference(const TDF_Label& theExternal, const TDF_Label theThis)
+{
+ // store information about the external document reference to restore old shape on open
+ if (!theExternal.IsNull() && !theExternal.Root().IsEqual(theThis.Root())) {
+ Handle(TDataStd_ExtStringList) anEntries;
+ if (!theThis.FindAttribute(kEXTERNAL_SHAPE_REF, anEntries)) {
+ anEntries = TDataStd_ExtStringList::Set(theThis, kEXTERNAL_SHAPE_REF);
+ }
+ TCollection_AsciiString anEntry;
+ TDF_Tool::Entry(theExternal, anEntry);
+ // check it already contains this entry
+ TDataStd_ListOfExtendedString::Iterator anIter(anEntries->List());
+ for(; anIter.More(); anIter.Next())
+ if (anIter.Value() == anEntry)
+ break;
+ if (!anIter.More()) {
+ anEntries->Append(anEntry);
+ }
+ }
+}
+
void Model_BodyBuilder::store(const GeomShapePtr& theShape,
const bool theIsStoreSameShapes)
{
// clean builders
if (theIsCleanStored)
clean();
- // store the new shape as primitive
- TNaming_Builder aBuilder(aShapeLab);
+ TNaming_Builder* aBuilder = builder(0);
if (!theFromShape || !theToShape)
return; // bad shape
TopoDS_Shape aShapeBasis = theFromShape->impl<TopoDS_Shape>();
TopoDS_Shape aShapeNew = theToShape->impl<TopoDS_Shape>();
if (aShapeNew.IsNull())
return; // null shape inside
- aBuilder.Generated(aShapeBasis, aShapeNew);
+
+ // There is no sense to write history if old shape does not exist in the document.
+ TDF_Label anAccess2 = std::dynamic_pointer_cast<Model_Document>(
+ ModelAPI_Session::get()->moduleDocument())->generalLabel();
+ TDF_Label anOriginalLabel;
+ if (!isShapeInTree(aData->shapeLab(), anAccess2, aShapeBasis, anOriginalLabel)) {
+ if (aBuilder->NamedShape()->Get().IsNull()) { // store as primitive if alone anyway
+ aBuilder->Generated(aShapeNew);
+ }
+ } else {
+ if (aBuilder->NamedShape()->Evolution() == TNaming_PRIMITIVE) { // erase primitive before
+ myBuilders.erase(0);
+ aBuilder = builder(0);
+ }
+
+ aBuilder->Generated(aShapeBasis, aShapeNew);
+ // store information about the external document reference to restore old shape on open
+ storeExternalReference(anOriginalLabel, aBuilder->NamedShape()->Label());
+ }
+
// register name
- if(!aBuilder.NamedShape()->IsEmpty()) {
+ if(!aBuilder->NamedShape()->IsEmpty()) {
Handle(TDataStd_Name) anAttr;
- if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+ if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
if(!aName.empty()) {
std::shared_ptr<Model_Document> aDoc =
std::dynamic_pointer_cast<Model_Document>(document());
- aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
+ aDoc->addNamingName(aBuilder->NamedShape()->Label(), aName);
}
}
}
if (aData) {
// clean builders
if (theIsCleanStored) clean();
- // store the new shape as primitive
TNaming_Builder* aBuilder = builder(0);
if (!theOldShape || !theNewShape)
return; // bad shape
TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
if (aShapeNew.IsNull())
return; // null shape inside
- aBuilder->Modify(aShapeOld, aShapeNew);
+
+ // There is no sense to write history if old shape does not exist in the document.
+ TDF_Label anAccess2 = std::dynamic_pointer_cast<Model_Document>(
+ ModelAPI_Session::get()->moduleDocument())->generalLabel();
+ TDF_Label anOriginalLabel;
+ if (!isShapeInTree(aData->shapeLab(), anAccess2, aShapeOld, anOriginalLabel)) {
+ if (aBuilder->NamedShape()->Get().IsNull()) { // store as primitive if alone anyway
+ aBuilder->Generated(aShapeNew);
+ }
+ } else {
+ if (aBuilder->NamedShape()->Evolution() == TNaming_PRIMITIVE) { // erase primitive before
+ myBuilders.erase(0);
+ aBuilder = builder(0);
+ }
+
+ aBuilder->Modify(aShapeOld, aShapeNew);
+ // store information about the external document reference to restore old shape on open
+ storeExternalReference(anOriginalLabel, aBuilder->NamedShape()->Label());
+ }
+
if(!aBuilder->NamedShape()->IsEmpty()) {
Handle(TDataStd_Name) anAttr;
if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) {
}
}
-/// Checks that shape is presented in the tree with not-selection evolution
-/// In theOriginalLabel it returns label where NS of old sub-shape is stored
-static bool isShapeInTree(const TDF_Label& theAccess1, const TDF_Label& theAccess2,
- TopoDS_Shape theShape, TDF_Label& theOriginalLabel)
-{
- bool aResult = TNaming_Tool::HasLabel(theAccess1, theShape);
- if (aResult) { //check evolution and a label of this shape
- for(TNaming_SameShapeIterator aShapes(theShape, theAccess1); aShapes.More(); aShapes.Next())
- {
- static Handle(TNaming_NamedShape) aNS;
- if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
- if (aNS->Evolution() != TNaming_SELECTED) {
- theOriginalLabel = aNS->Label();
- return true;
- }
- }
- }
- }
- if (!theAccess2.IsNull()) {
- static const TDF_Label anEmpty;
- return isShapeInTree(theAccess2, anEmpty, theShape, theOriginalLabel);
- }
- return false;
-}
-
-/// Stores entry to the external label in the entries list at this label
-static void storeExternalReference(const TDF_Label& theExternal, const TDF_Label theThis)
-{
- // store information about the external document reference to restore old shape on open
- if (!theExternal.IsNull() && !theExternal.Root().IsEqual(theThis.Root())) {
- Handle(TDataStd_ExtStringList) anEntries;
- if (!theThis.FindAttribute(kEXTERNAL_SHAPE_REF, anEntries)) {
- anEntries = TDataStd_ExtStringList::Set(theThis, kEXTERNAL_SHAPE_REF);
- }
- TCollection_AsciiString anEntry;
- TDF_Tool::Entry(theExternal, anEntry);
- // check it already contains this entry
- TDataStd_ListOfExtendedString::Iterator anIter(anEntries->List());
- for(; anIter.More(); anIter.Next())
- if (anIter.Value() == anEntry)
- break;
- if (!anIter.More()) {
- anEntries->Append(anEntry);
- }
- }
-}
-
void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo,
const GeomShapePtr& theOldShape,
const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
#include <ModelAPI_Tools.h>
#include <Model_Data.h>
#include <Events_Loop.h>
+#include <GeomAPI_ShapeIterator.h>
#include <TopoDS_Shape.hxx>
#include <TopExp_Explorer.hxx>
if (!aShape->isEqual(anOldSubShape)) {
if (myAlgo.get()) {
std::list<GeomShapePtr> anOldForSub;
- computeOldForSub(aShape, anOldForSub);
+ computeOldForSub(aShape, myOlds, anOldForSub);
myIsGenerated ? aSub->storeGenerated(anOldForSub, aShape, myAlgo) :
aSub->storeModified(anOldForSub, aShape, myAlgo);
} else {
}
}
-void Model_ResultBody::computeOldForSub(
- const GeomShapePtr& theSubShape, std::list<GeomShapePtr>& theOldForSub)
+void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub,
+ const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub)
{
- std::list<GeomShapePtr>::iterator aRootOlds = myOlds.begin();
- for(; aRootOlds != myOlds.end(); aRootOlds++) {
+ 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 (theSubShape->isSame(*aNewIter)) { // found old that was used for new theSubShape creation
+ if (theSub->isSame(*aNewIter)) { // found old that was used for new theSubShape creation
theOldForSub.push_back(*aRootOlds);
break;
}
// Checks the state of children and parents to send events of creation/erase when needed
void updateConcealment();
- /// Adds to theOldForSub only old shapes that where used for theSubShape creation
- void computeOldForSub(const GeomShapePtr& theSubShape, std::list<GeomShapePtr>& theOldForSub);
+ /// Adds to theOldForSub only old shapes that where used for theSub creation
+ void computeOldForSub(const GeomShapePtr& theSub,
+ const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub);
friend class Model_Objects;
};
double aNX = aNorm->x(), aNY = aNorm->y(), aNZ = aNorm->z();
// update sketch plane
updateArguments(theFeature);
- //theFeature->attributeChanged("External"); // to recompute origin, direction and normal
+ theFeature->attributeChanged("External"); // to recompute origin, direction and normal
// check it is updated, so all must be changed
if (anOrigin->x() != anOX || anOrigin->y() != anOY || anOrigin->z() != anOZ ||
aDir->x() != aDX || aDir->y() != aDY || aDir->z() != aDZ ||