+ else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
+ // Do not add point-point coincidence, because it is already made by setting
+ // the same parameters for both points
+ std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
+ for (; aCIt != theSolverConstraints.end(); ++aCIt)
+ update(*aCIt);
+ }
+
+ if (!theSolverConstraints.empty() || aFound == myConstraintMap.end())
+ myConstraintMap[theConstraint] = theSolverConstraints;
+ // block events if necessary
+ if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
+ theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
+}
+
+static std::list<AttributePtr> pointAttributes(FeaturePtr theFeature)
+{
+ std::list<AttributePtr> aPoints;
+ if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
+ aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
+ aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::START_ID()));
+ aPoints.push_back(theFeature->attribute(SketchPlugin_Arc::END_ID()));
+ }
+ else if (theFeature->getKind() == SketchPlugin_Circle::ID())
+ aPoints.push_back(theFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
+ else if (theFeature->getKind() == SketchPlugin_Line::ID()) {
+ aPoints.push_back(theFeature->attribute(SketchPlugin_Line::START_ID()));
+ aPoints.push_back(theFeature->attribute(SketchPlugin_Line::END_ID()));
+ }
+ else if (theFeature->getKind() == SketchPlugin_Point::ID() ||
+ theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
+ aPoints.push_back(theFeature->attribute(SketchPlugin_Point::COORD_ID()));
+ return aPoints;
+}
+
+void SketchSolver_Storage::addEntity(FeaturePtr theFeature,
+ EntityWrapperPtr theSolverEntity)
+{
+ std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
+ if (aFound == myFeatureMap.end() || !aFound->second ||
+ (theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
+ setNeedToResolve(true); // the entity is new or modified
+
+ if (!theSolverEntity) {
+ // feature links to the empty entity, add its attributes
+ std::list<AttributePtr> aPntAttrs = pointAttributes(theFeature);
+ std::list<AttributePtr>::const_iterator anAttrIt = aPntAttrs.begin();
+ for (; anAttrIt != aPntAttrs.end(); ++anAttrIt)
+ addEntity(*anAttrIt, EntityWrapperPtr());
+ if (aFound == myFeatureMap.end())
+ myFeatureMap[theFeature] = theSolverEntity;
+ } else
+ myFeatureMap[theFeature] = theSolverEntity;
+
+ // block events if necessary
+ if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
+ theFeature->data()->blockSendAttributeUpdated(myEventsBlocked);
+}
+
+void SketchSolver_Storage::addEntity(AttributePtr theAttribute,
+ EntityWrapperPtr theSolverEntity)
+{
+ std::map<AttributePtr, EntityWrapperPtr>::const_iterator aFound = myAttributeMap.find(theAttribute);
+ if (aFound == myAttributeMap.end() || !aFound->second ||
+ (theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
+ setNeedToResolve(true); // the entity is new or modified
+
+ if (theSolverEntity || aFound == myAttributeMap.end())
+ myAttributeMap[theAttribute] = theSolverEntity;
+ // block events if necessary
+ if (myEventsBlocked && theAttribute->owner() &&
+ theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
+ theAttribute->owner()->data()->blockSendAttributeUpdated(myEventsBlocked);
+}
+
+
+bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup)
+{
+ bool isUpdated = false;
+ EntityWrapperPtr aRelated = entity(theFeature);
+ if (!aRelated) { // Feature is not exist, create it
+ std::list<EntityWrapperPtr> aSubs;
+ // Reserve the feature in the map of features (do not want to add several copies of it)
+ myFeatureMap[theFeature] = aRelated;
+ // Firstly, create/update its attributes
+ std::list<AttributePtr> anAttrs = pointAttributes(theFeature);
+ std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
+ for (; anIt != anAttrs.end(); ++anIt) {
+ isUpdated = update(*anIt, theGroup) || isUpdated;
+ aSubs.push_back(entity(*anIt));
+ }
+ // If the feature is a circle, add its radius as a sub
+ if (theFeature->getKind() == SketchPlugin_Circle::ID()) {
+ AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
+ isUpdated = update(aRadius, theGroup) || isUpdated;
+ aSubs.push_back(entity(aRadius));
+ }
+ // If the feature if circle or arc, we need to add normal of the sketch to the list of subs
+ if (theFeature->getKind() == SketchPlugin_Arc::ID() ||
+ theFeature->getKind() == SketchPlugin_Circle::ID()) {
+ EntityWrapperPtr aNormal = getNormal();
+ if (aNormal) aSubs.push_back(aNormal);
+ }
+ // Secondly, convert feature
+ BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+ GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
+ // Check external feature
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
+ if (aSketchFeature && aSketchFeature->isExternal())
+ aGroup = GID_OUTOFGROUP;
+ aRelated = aBuilder->createFeature(theFeature, aSubs, aGroup);
+ if (!aRelated)
+ return false;
+ addEntity(theFeature, aRelated);
+ } else if (theGroup != GID_UNKNOWN)
+ changeGroup(aRelated, theGroup);
+ return update(aRelated) || isUpdated;
+}
+
+bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup)
+{
+ AttributePtr anAttribute = theAttribute;
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
+ if (aRefAttr) {
+ if (aRefAttr->isObject()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ return update(aFeature, theGroup);
+ } else
+ anAttribute = aRefAttr->attr();
+ }
+
+ EntityWrapperPtr aRelated = entity(anAttribute);
+ if (!aRelated) { // Attribute is not exist, create it
+ // verify the attribute is a point of arc and add whole arc
+ if (anAttribute->owner()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
+ if (aFeature->getKind() == SketchPlugin_Arc::ID() &&
+ myFeatureMap.find(aFeature) == myFeatureMap.end()) {
+ // Additional checking that all attributes are initialized
+ if (aFeature->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() &&
+ aFeature->attribute(SketchPlugin_Arc::START_ID())->isInitialized() &&
+ aFeature->attribute(SketchPlugin_Arc::END_ID())->isInitialized()) {
+ return SketchSolver_Storage::update(aFeature);
+ } else {
+ myFeatureMap[aFeature] = EntityWrapperPtr();
+ myExistArc = true;
+ }
+ }
+ }
+ BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+ GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
+ // Check attribute of external features
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theAttribute->owner());
+ if (aSketchFeature && aSketchFeature->isExternal())
+ aGroup = GID_OUTOFGROUP;
+ aRelated = aBuilder->createAttribute(anAttribute, aGroup);
+ if (!aRelated)
+ return false;
+ addEntity(anAttribute, aRelated);
+ } else if (theGroup != GID_UNKNOWN)
+ changeGroup(aRelated, theGroup);
+ return update(aRelated);