reference(SKETCH_ID())->setValue(ObjectPtr());
}
-//=================================================================================================
-void FeaturesPlugin_CompositeSketch::erase()
-{
- if(data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid
- FeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_Feature>(reference(SKETCH_ID())->value());
- if(aSketch.get() && aSketch->data()->isValid()) {
- document()->removeFeature(aSketch);
- }
- }
-
- ModelAPI_CompositeFeature::erase();
-}
-
//=================================================================================================
void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
const bool theIsMakeShells)
/// structures of the owner (the remove from the document will be done outside just after).
FEATURESPLUGIN_EXPORT virtual void removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature);
- /// Removes also all sub-sketch.
- FEATURESPLUGIN_EXPORT virtual void erase();
-
protected:
enum InitFlags {
InitSketchLauncher = 1 << 0,
std::list<std::shared_ptr<GeomAPI_Shape> > GeomAPI_PlanarEdges::getEdges()
{
TopoDS_Shape& aShape = const_cast<TopoDS_Shape&>(impl<TopoDS_Shape>());
- //BRepTools_WireExplorer aWireExp(TopoDS::Wire(aShape));
TopExp_Explorer aWireExp(aShape, TopAbs_EDGE);
std::list<std::shared_ptr<GeomAPI_Shape> > aResult;
for (; aWireExp.More(); aWireExp.Next()) {
const std::shared_ptr<GeomAPI_Dir>& theNorm)
{
myPlane = std::shared_ptr<GeomAPI_Ax3>(new GeomAPI_Ax3(theOrigin, theDirX, theNorm));
-}
\ No newline at end of file
+}
+
+bool GeomAPI_PlanarEdges::isEqual(const std::shared_ptr<GeomAPI_Shape> theShape) const
+{
+ if (!theShape.get())
+ return false;
+ TopoDS_Shape& aMyShape = const_cast<TopoDS_Shape&>(impl<TopoDS_Shape>());
+ TopoDS_Shape aTheShape = theShape->impl<TopoDS_Shape>();
+ TopExp_Explorer aMyExp(aMyShape, TopAbs_EDGE);
+ TopExp_Explorer aTheExp(aTheShape, TopAbs_EDGE);
+ for (; aMyExp.More() && aTheExp.More(); aMyExp.Next(), aTheExp.Next()) {
+ // check that edge by edge all geometrically matches
+ std::shared_ptr<GeomAPI_Edge> aMyEdge(new GeomAPI_Edge);
+ aMyEdge->setImpl<TopoDS_Shape>(new TopoDS_Shape(aMyExp.Current()));
+ std::shared_ptr<GeomAPI_Edge> aTheEdge(new GeomAPI_Edge);
+ aTheEdge->setImpl<TopoDS_Shape>(new TopoDS_Shape(aTheExp.Current()));
+ if (!aMyEdge->isEqual(aTheEdge))
+ return false;
+ }
+ return !(aMyExp.More() || aTheExp.More());
+}
const std::shared_ptr<GeomAPI_Dir>& theDirX,
const std::shared_ptr<GeomAPI_Dir>& theNorm);
+ /// Returns whether the shapes are equal
+ GEOMAPI_EXPORT
+ virtual bool isEqual(const std::shared_ptr<GeomAPI_Shape> theShape) const;
+
private:
std::shared_ptr<GeomAPI_Ax3> myPlane;
isPlanesCoincident = true;
} else if(aFromShape.get() && aToShape.get()) {
std::shared_ptr<GeomAPI_Face> aFromFace(new GeomAPI_Face(aFromShape));
+ if (aFromFace->isNull()) {
+ theError = "From face selection is invalid.";
+ return false;
+ }
std::shared_ptr<GeomAPI_Pln> aFromPln = aFromFace->getPlane();
std::shared_ptr<GeomAPI_Face> aToFace(new GeomAPI_Face(aToShape));
+ if (aToFace->isNull()) {
+ theError = "To face selection is invalid.";
+ return false;
+ }
std::shared_ptr<GeomAPI_Pln> aToPln = aToFace->getPlane();
if(aFromPln.get()) {
std::shared_ptr<GeomAPI_Face> aFace;
if(aFromShape.get()) {
aFace.reset(new GeomAPI_Face(aFromShape));
+ if (aFace->isNull()) {
+ theError = "From face selection is invalid.";
+ return false;
+ }
} else {
aFace.reset(new GeomAPI_Face(aToShape));
+ if (aFace->isNull()) {
+ theError = "To face selection is invalid.";
+ return false;
+ }
}
std::shared_ptr<GeomAPI_Pln> aPln = aFace->getPlane();
if(aPln.get()) {
}
Model_AttributeReference::~Model_AttributeReference()
-{
- std::shared_ptr<Model_Document> aDoc =
- std::dynamic_pointer_cast<Model_Document>(owner()->document());
- TDF_Label aLab = myRef->Get();
-}
+{}
void Model_Data::erase()
{
- if (!myLab.IsNull())
+ if (!myLab.IsNull()) {
+ // remove in order to clear back references in other objects
+ std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+ referencesToObjects(aRefs);
+ std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator anAttrIter = aRefs.begin();
+ for(; anAttrIter != aRefs.end(); anAttrIter++) {
+ std::list<ObjectPtr>::iterator aReferenced = anAttrIter->second.begin();
+ for(; aReferenced != anAttrIter->second.end(); aReferenced++) {
+ if (aReferenced->get() && (*aReferenced)->data()->isValid()) {
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>((*aReferenced)->data());
+ aData->removeBackReference(myAttrs[anAttrIter->first]);
+ }
+ }
+ }
+ myAttrs.clear();
myLab.ForgetAllAttributes();
+ }
}
// indexes in the state array
for (; aSubIter != aSubs.end(); aSubIter++)
subDoc(*aSubIter)->abortOperation();
// references may be changed because they are set in attributes on the fly
- myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot());
+ myObjs->synchronizeFeatures(aDeltaLabels, true, false, isRoot());
}
bool Model_Document::isOperation() const
}
// after undo of all sub-documents to avoid updates on not-modified data (issue 370)
if (theSynchronize) {
- myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot());
+ myObjs->synchronizeFeatures(aDeltaLabels, true, false, isRoot());
// update the current features status
setCurrentFeature(currentFeature(false), false);
}
subDoc(*aSubIter)->redo();
// after redo of all sub-documents to avoid updates on not-modified data (issue 370)
- myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot());
+ myObjs->synchronizeFeatures(aDeltaLabels, true, false, isRoot());
// update the current features status
setCurrentFeature(currentFeature(false), false);
}
myDoc = theDoc;
// update all fields and recreate features and result objects if needed
TDF_LabelList aNoUpdated;
- synchronizeFeatures(aNoUpdated, true, true);
+ synchronizeFeatures(aNoUpdated, true, true, true);
myHistory.clear();
}
for(; aRefIter != aRefs.end(); aRefIter++) {
std::shared_ptr<ModelAPI_CompositeFeature> aComposite =
std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
- if (aComposite.get() && aComposite->data()->isValid()) {
+ if (aComposite.get()) {
aComposite->removeFeature(theFeature);
}
}
}
void Model_Objects::synchronizeFeatures(
- const TDF_LabelList& theUpdated, const bool theUpdateReferences, const bool theFlush)
+ const TDF_LabelList& theUpdated, const bool theUpdateReferences,
+ const bool theOpen, const bool theFlush)
{
Model_Document* anOwner = std::dynamic_pointer_cast<Model_Document>(myDoc).get();
if (!anOwner) // this may happen on creation of document: nothing there, so nothing to synchronize
myHistory.clear();
}
- anOwner->executeFeatures() = false;
+ if (theOpen)
+ anOwner->executeFeatures() = false;
aLoop->activateFlushes(isActive);
if (theFlush) {
aLoop->flush(aRedispEvent);
aLoop->flush(aToHideEvent);
}
- anOwner->executeFeatures() = true;
+ if (theOpen)
+ anOwner->executeFeatures() = true;
}
/// synchronises back references for the given object basing on the collected data
//! Synchronizes myFeatures list with the updated document
//! \param theUpdated list of labels that are marked as modified, so featrues must be also
//! \param theUpdateReferences causes the update of back-references
+ //! \param theOpen - on open nothing must be reexecuted, except not persistent results
//! \param theFlush makes flush all events in the end of all modifications of this method
void synchronizeFeatures(const TDF_LabelList& theUpdated, const bool theUpdateReferences,
- const bool theFlush);
+ const bool theOpen, const bool theFlush);
//! Synchronizes the BackReferences list in Data of Features and Results
void synchronizeBackRefs();
bool aWasChecked = myCheckTransactions;
setCheckTransactions(false);
TDF_LabelList anEmptyUpdated;
- aDoc->objects()->synchronizeFeatures(anEmptyUpdated, true, true);
+ aDoc->objects()->synchronizeFeatures(anEmptyUpdated, true, true, true);
if (aWasChecked)
setCheckTransactions(true);
}
TDF_CopyTool::Copy(aDS, aRT);
TDF_LabelList anEmptyUpdated;
- aNew->objects()->synchronizeFeatures(anEmptyUpdated, true, true);
+ aNew->objects()->synchronizeFeatures(anEmptyUpdated, true, true, true);
return aNew;
}
myIsProcessed = false;
}
-void Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
+bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
+
if (!theFeature->data()->isValid())
- return; // delete an extrusion created on the sketch
+ return false; // delete an extrusion created on the sketch
+
+ if (theFeature->isPersistentResult()) {
+ if (!std::dynamic_pointer_cast<Model_Document>((theFeature)->document())->executeFeatures())
+ return false;
+ }
+
if (!theFeature->isPreviewNeeded() && !myIsFinish) {
myProcessOnFinish.insert(theFeature);
#ifdef DEB_UPDATE
static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
aFactory->validate(theFeature); // need to be validated to update the "Apply" state if not previewed
}
- return;
+ return true;
}
if (myModified.find(theFeature) != myModified.end()) {
if (theReason.get()) {
#endif
myModified[theFeature].insert(theReason);
}
- return; // already is marked as modified, so, nothing to do, it will be processed
+ return true;
}
// do not add the disabled, but possibly the sub-elements are not disabled
bool aIsDisabled = theFeature->isDisabled();
if (theFeature->data()->execState() == ModelAPI_StateDone)
theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
else
- return; // do not need iteration deeply if it is already marked as modified or so
+ return true; // do not need iteration deeply if it is already marked as modified or so
#ifdef DEB_UPDATE
std::cout<<"*** Set modified state "<<theFeature->name()<<std::endl;
#endif
if (aPart.get())
addModified(aPart, theFeature);
}
- return;
+ return true;
}
void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessage)
myIsParamUpdated = true;
}
// on undo/redo, abort do not update persisten features
- bool anUpdateOnlyNotPersistent =
- !std::dynamic_pointer_cast<Model_Document>((*anObjIter)->document())->executeFeatures();
FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIter);
if (anUpdated.get()) {
- if (!anUpdateOnlyNotPersistent || !anUpdated->isPersistentResult()) {
- addModified(anUpdated, FeaturePtr());
+ if (addModified(anUpdated, FeaturePtr()))
aSomeModified = true;
- }
} else { // process the updated result as update of features that refers to this result
const std::set<std::shared_ptr<ModelAPI_Attribute> >& aRefs = (*anObjIter)->data()->refsToMe();
std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator aRefIter = aRefs.cbegin();
if (!(*aRefIter)->owner()->data()->isValid())
continue;
FeaturePtr anUpdated = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRefIter)->owner());
- if (anUpdated.get() && (!anUpdateOnlyNotPersistent || !anUpdated->isPersistentResult())) {
- addModified(anUpdated, FeaturePtr());
- aSomeModified = true;
+ if (anUpdated.get()) {
+ if (addModified(anUpdated, FeaturePtr()))
+ aSomeModified = true;
}
}
}
return false;
}
+ if (theFeature->isPersistentResult()) {
+ if (!std::dynamic_pointer_cast<Model_Document>((theFeature)->document())->executeFeatures())
+ return false;
+ }
+
// check this feature is not yet checked or processed
bool aIsModified = myModified.find(theFeature) != myModified.end();
if (!aIsModified && myIsFinish) { // get info about the modification for features without preview
// this checking must be after the composite feature sub-elements processing:
// composite feature status may depend on it's subelements
if (theFeature->data()->execState() == ModelAPI_StateInvalidArgument) {
+ #ifdef DEB_UPDATE
+ std::cout<<"Invalid args "<<theFeature->name()<<std::endl;
+ #endif
theFeature->eraseResults();
redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
return true; // so, feature is modified (results are erased)
}
- // On abort, undo or redo execute is not needed: results in document are updated automatically
- // But redisplay is needed: results are updated, must be also updated in the viewer.
- if (!std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures()) {
- if (!theFeature->isPersistentResult()) { // not persistent must be re-executed on abort, etc.
- ModelAPI_ExecState aState = theFeature->data()->execState();
- if (aFactory->validate(theFeature)) {
- executeFeature(theFeature);
- } else {
- theFeature->eraseResults();
- redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
- }
- } else {
- redisplayWithResults(theFeature, ModelAPI_StateNothing);
- if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) { // it is done (in the tree)
- theFeature->data()->execState(ModelAPI_StateDone);
- }
+ // execute feature if it must be updated
+ ModelAPI_ExecState aState = theFeature->data()->execState();
+ if (aFactory->validate(theFeature)) {
+ if (!isPostponedMain) {
+ executeFeature(theFeature);
}
} else {
- // execute feature if it must be updated
- ModelAPI_ExecState aState = theFeature->data()->execState();
- if (aFactory->validate(theFeature)) {
- if (!isPostponedMain) {
- executeFeature(theFeature);
- }
- } else {
- #ifdef DEB_UPDATE
- std::cout<<"Feature is not valid, erase results "<<theFeature->name()<<std::endl;
- #endif
- theFeature->eraseResults();
- redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
- }
+ #ifdef DEB_UPDATE
+ std::cout<<"Feature is not valid, erase results "<<theFeature->name()<<std::endl;
+ #endif
+ theFeature->eraseResults();
+ redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
}
return true;
}
void Model_Update::updateStability(void* theSender)
{
+ static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
if (theSender) {
bool added = false; // object may be was crated
ModelAPI_Object* aSender = static_cast<ModelAPI_Object*>(theSender);
aSender->data()->referencesToObjects(aRefs);
std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRefIt = aRefs.begin();
for(; aRefIt != aRefs.end(); aRefIt++) {
+ if (!aFactory->isConcealed(aFeatureSender->getKind(), aRefIt->first))
+ continue; // take into account only concealed references (do not remove the sketch constraint and the edge on constraint edit)
std::list<ObjectPtr>& aRefFeaturesList = aRefIt->second;
std::list<ObjectPtr>::iterator aReferenced = aRefFeaturesList.begin();
for(; aReferenced != aRefFeaturesList.end(); aReferenced++) {
/// Appends the new modified feature to the myModified, clears myProcessed if needed
/// Returns true if some feature really was marked as modified
/// theReason is the object that causes modification of this feature
- void addModified(
+ /// returns true if something reallsy was added to the modified and must be processed
+ bool addModified(
std::shared_ptr<ModelAPI_Feature> theFeature, std::shared_ptr<ModelAPI_Feature> theReason);
/// Recoursively checks and updates features if needed (calls the execute method)
{
// by default nothing is in the implementation
}
+
+void ModelAPI_CompositeFeature::erase()
+{
+ // erase all sub-features
+ for(int a = numberOfSubs(); a > 0; a--) {
+ FeaturePtr aFeature = subFeature(a - 1);
+ if (aFeature.get()) {
+ // subs are referenced from sketch, but must be removed for sure, so not checkings
+ aFeature->document()->removeFeature(aFeature);
+ }
+ }
+ ModelAPI_Feature::erase();
+}
/// Exchanges IDs of two given features: needed for more correct naming in some cases (issue 769)
MODELAPI_EXPORT virtual void exchangeIDs(std::shared_ptr<ModelAPI_Feature> theFeature1,
std::shared_ptr<ModelAPI_Feature> theFeature2);
+
+ /// in addition removes all subs
+ MODELAPI_EXPORT virtual void erase();
};
//! Pointer on the composite feature object
}
-void SketchPlugin_Sketch::erase()
-{
- std::shared_ptr<ModelAPI_AttributeRefList> aRefList = std::dynamic_pointer_cast<
- ModelAPI_AttributeRefList>(data()->attribute(SketchPlugin_Sketch::FEATURES_ID()));
- std::list<ObjectPtr> aFeatures = aRefList->list();
- std::list<ObjectPtr>::const_iterator anIt = aFeatures.begin();
- for (; anIt != aFeatures.end(); anIt++) {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
- if (aFeature) {
- // subs are referenced from sketch, but must be removed for sure, so not checkings
- document()->removeFeature(aFeature);
- }
- }
- ModelAPI_CompositeFeature::erase();
-}
-
void SketchPlugin_Sketch::attributeChanged(const std::string& theID) {
if (theID == SketchPlugin_SketchEntity::EXTERNAL_ID()) {
std::shared_ptr<GeomAPI_Shape> aSelection =
}
- /// removes also all sub-sketch elements
- SKETCHPLUGIN_EXPORT virtual void erase();
-
/// appends a feature to the sketch sub-elements container
SKETCHPLUGIN_EXPORT virtual std::shared_ptr<ModelAPI_Feature> addFeature(std::string theID);