BOPCol_IndexedDataMapOfShapeListOfShape aMapVE; // map between vertexes and edges
BOPTools::MapShapesAndAncestors(aFeaturesCompound, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
+ if (aMapVE.IsEmpty()) // in case of not-initialized circle
+ return;
gp_Dir aDirX = theDirX->impl<gp_Dir>();
gp_Dir aDirY = theDirY->impl<gp_Dir>();
Model_AttributeRefList.h
Model_AttributeBoolean.h
Model_Events.h
+ Model_Update.h
)
SET(PROJECT_SOURCES
Model_AttributeRefList.cpp
Model_AttributeBoolean.cpp
Model_Events.cpp
+ Model_Update.cpp
)
+
SET(PROJECT_LIBRARIES
ModelAPI
Events
return myRef->Extent();
}
-list<FeaturePtr > Model_AttributeRefList::list()
+list<FeaturePtr> Model_AttributeRefList::list()
{
std::list< FeaturePtr > aResult;
boost::shared_ptr<Model_Document> aDoc =
{if (theFeature) myFeatures.insert(theFeature);}
/// Returns the feature that has been updated
- std::set<FeaturePtr > features() const {return myFeatures;}
+ std::set<FeaturePtr> features() const {return myFeatures;}
//! Creates a new empty group (to store it in the loop before flush)
virtual Events_MessageGroup* newEmpty() {
--- /dev/null
+// File: Model_Update.cxx
+// Created: 25 Jun 2014
+// Author: Mikhail PONIKAROV
+
+#include <Model_Update.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <Model_Events.h>
+#include <ModelAPI_AttributeReference.h>
+#include <ModelAPI_AttributeRefList.h>
+
+using namespace std;
+
+Model_Update MY_INSTANCE; /// the only one instance initialized on load of the library
+
+Model_Update::Model_Update()
+{
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED));
+}
+
+void Model_Update::processEvent(const Events_Message* theMessage)
+{
+ const Model_FeatureUpdatedMessage* aMsg =
+ dynamic_cast<const Model_FeatureUpdatedMessage*>(theMessage);
+ myInitial = aMsg->features();
+ // collect all documents involved into the update
+ set<boost::shared_ptr<ModelAPI_Document> > aDocs;
+ set<boost::shared_ptr<ModelAPI_Feature> >::iterator aFIter = myInitial.begin();
+ for(; aFIter != myInitial.end(); aFIter++) {
+ aDocs.insert((*aFIter)->document());
+ }
+ // iterate all features of features-documents to update them
+ set<boost::shared_ptr<ModelAPI_Document> >::iterator aDIter = aDocs.begin();
+ for(; aDIter != aDocs.end(); aDIter++) {
+ int aNbFeatures = (*aDIter)->size(FEATURES_GROUP);
+ for(int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) {
+ boost::shared_ptr<ModelAPI_Feature> aFeature = (*aDIter)->feature(FEATURES_GROUP, aFIndex);
+ if (aFeature)
+ updateFeature(aFeature);
+ }
+ }
+ myUpdated.clear();
+}
+
+bool Model_Update::updateFeature(boost::shared_ptr<ModelAPI_Feature> theFeature)
+{
+ // check it is already processed
+ if (myUpdated.find(theFeature) != myUpdated.end())
+ return myUpdated[theFeature];
+ // check all features this feature depended on (recursive call of updateFeature)
+ bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end();
+ // references
+ list<boost::shared_ptr<ModelAPI_Attribute> > aRefs =
+ theFeature->data()->attributes(ModelAPI_AttributeReference::type());
+ list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
+ for(; aRefsIter != aRefs.end(); aRefsIter++) {
+ boost::shared_ptr<ModelAPI_Feature> aSub =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRefsIter)->value();
+ if (aSub && aSub != theFeature && updateFeature(aSub))
+ aMustbeUpdated = true;
+ }
+ // lists of references
+ aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type());
+ for(aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) {
+ list<FeaturePtr> aListRef =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)->list();
+ list<FeaturePtr>::iterator aListIter = aListRef.begin();
+ for(; aListIter != aListRef.end(); aListIter++) {
+ boost::shared_ptr<ModelAPI_Feature> aSub = *aListIter;
+ if (aSub && updateFeature(aSub))
+ aMustbeUpdated = true;
+ }
+ }
+ // execute feature if it must be updated
+ bool anExecute = aMustbeUpdated || myInitial.find(theFeature) != myInitial.end();
+ if (anExecute) {
+ theFeature->execute();
+ }
+ myUpdated[theFeature] = anExecute;
+ return anExecute;
+}
--- /dev/null
+// File: Model_Update.hxx
+// Created: 25 Jun 2014
+// Author: Mikhail PONIKAROV
+
+#ifndef Model_Update_HeaderFile
+#define Model_Update_HeaderFile
+
+#include "Model.h"
+#include "Events_Listener.h"
+#include <boost/shared_ptr.hpp>
+#include <set>
+#include <map>
+
+class ModelAPI_Feature;
+
+/**\class Model_Update
+ * \ingroup DataModel
+ * \brief Updates the results of features when it is needed.
+ */
+class Model_Update : public Events_Listener
+{
+ ///< initial set of updated features that must be processed
+ std::set<boost::shared_ptr<ModelAPI_Feature> > myInitial;
+ ///< already updated and processed features and modificated feature flag
+ std::map<boost::shared_ptr<ModelAPI_Feature>, bool> myUpdated;
+public:
+ /// Is called only once, on startup of the application
+ Model_Update();
+
+ /// Processes the feature argument update: executes the results
+ MODEL_EXPORT virtual void processEvent(const Events_Message* theMessage);
+
+protected:
+ /// Recoursively checks and updates the feature if needed
+ /// Returns true if feature was updated.
+ bool updateFeature(boost::shared_ptr<ModelAPI_Feature> theFeature);
+};
+
+#endif
{
boost::shared_ptr<ModelAPI_AttributeDocRef> aDocRef = data()->docRef(PART_ATTR_DOC_REF);
if (!aDocRef->value()) { // create a document if not yet created
- boost::shared_ptr<ModelAPI_Document> aPartSetDoc = ModelAPI_PluginManager::get()->rootDocument();
+ boost::shared_ptr<ModelAPI_Document> aPartSetDoc =
+ ModelAPI_PluginManager::get()->rootDocument();
aDocRef->setValue(aPartSetDoc->subDocument(data()->getName()));
}
}
// compute a circle point in 3D view
boost::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CIRCLE_ATTR_CENTER));
- if (aCenterAttr->isInitialized()) {
+ AttributeDoublePtr aRadiusAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(CIRCLE_ATTR_RADIUS));
+ if (aCenterAttr->isInitialized() && aRadiusAttr->isInitialized()) {
boost::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
// make a visible point
boost::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
if (aHasPlane) {
boost::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
// compute the circle radius
- AttributeDoublePtr aRadiusAttr =
- boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(CIRCLE_ATTR_RADIUS));
double aRadius = aRadiusAttr->value();
boost::shared_ptr<GeomAPI_Shape> aCircleShape =
aFeaturesPreview.push_back(aPreview);
}
+ if (aFeaturesPreview.empty())
+ return ;
std::list< boost::shared_ptr<GeomAPI_Shape> > aLoops;
std::list< boost::shared_ptr<GeomAPI_Shape> > aWires;
GeomAlgoAPI_SketchBuilder::createFaces(anOrigin->pnt(), aDirX->dir(), aDirY->dir(), aNorm->dir(),
${SLVS_LIBRARIES}
Events
ModelAPI
- Model
)
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/src/SketchPlugin
${PROJECT_SOURCE_DIR}/src/ModelAPI
- ${PROJECT_SOURCE_DIR}/src/Model
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/GeomDataAPI
${PROJECT_SOURCE_DIR}/src/Events