--- /dev/null
+#include <SketchSolver_ConstraintParametric.h>
+#include <SketchSolver_Error.h>
+#include <SketchSolver_Group.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+SketchSolver_ConstraintParametric::SketchSolver_ConstraintParametric(AttributePtr theAttribute)
+ : SketchSolver_ConstraintRigid(ConstraintPtr()),
+ myBaseAttribute(theAttribute)
+{
+ process();
+}
+
+void SketchSolver_ConstraintParametric::process()
+{
+ cleanErrorMsg();
+ if (!myBaseAttribute || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
+ return;
+ }
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ Slvs_hEntity anAttrID;
+ getAttributes(anAttrID);
+ if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
+ return;
+
+ myHorizLineID = SLVS_E_UNKNOWN;
+ myVertLineID = SLVS_E_UNKNOWN;
+
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+ if (!aPoint)
+ return;
+ if (!aPoint->textX().empty()) {
+ // Create vertical line with fixed boundary point
+ Slvs_Param aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), aPoint->x());
+ Slvs_Param aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), -10000.0);
+ aParX.h = myStorage->addParameter(aParX);
+ aParY.h = myStorage->addParameter(aParY);
+ Slvs_Entity aStartPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aParX.h, aParY.h);
+ aStartPoint.h = myStorage->addEntity(aStartPoint);
+ Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aStartPoint.h, anAttrID);
+ aLine.h = myStorage->addEntity(aLine);
+
+ // Fix start point
+ fixPoint(aStartPoint.h);
+ // Add vertical constraint
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ SLVS_C_VERTICAL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+ aLine.h, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ myVertLineID = aLine.h;
+ myX = aPoint->x();
+ }
+ if (!aPoint->textY().empty()) {
+ // Create horizontal line with fixed boundary point
+ Slvs_Param aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), -10000.0);
+ Slvs_Param aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), aPoint->y());
+ aParX.h = myStorage->addParameter(aParX);
+ aParY.h = myStorage->addParameter(aParY);
+ Slvs_Entity aStartPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aParX.h, aParY.h);
+ aStartPoint.h = myStorage->addEntity(aStartPoint);
+ Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
+ myGroup->getWorkplaneId(), aStartPoint.h, anAttrID);
+ aLine.h = myStorage->addEntity(aLine);
+
+ // Fix start point
+ fixPoint(aStartPoint.h);
+ // Add horizontal constraint
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ SLVS_C_HORIZONTAL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
+ aLine.h, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ myHorizLineID = aLine.h;
+ myY = aPoint->y();
+ }
+}
+
+
+void SketchSolver_ConstraintParametric::getAttributes(Slvs_hEntity& theAttributeID)
+{
+ int aType = SLVS_E_UNKNOWN; // type of created entity
+ theAttributeID = SLVS_E_UNKNOWN;
+ theAttributeID = myGroup->getAttributeId(myBaseAttribute);
+ if (theAttributeID == SLVS_E_UNKNOWN) {
+ theAttributeID = changeEntity(myBaseAttribute, aType);
+ if (theAttributeID == SLVS_E_UNKNOWN) {
+ myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ return;
+ }
+ }
+ else
+ myAttributeMap[myBaseAttribute] = theAttributeID;
+}
+
+
+void SketchSolver_ConstraintParametric::update(ConstraintPtr theConstraint)
+{
+ cleanErrorMsg();
+ if (!theConstraint || theConstraint == myBaseConstraint) {
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+ if (aPoint && ((!aPoint->textX().empty() && myVertLineID != SLVS_E_UNKNOWN) ||
+ (!aPoint->textY().empty() && myHorizLineID != SLVS_E_UNKNOWN))) {
+ remove();
+ process();
+ return;
+ }
+ }
+ adjustConstraint();
+}
+
+void SketchSolver_ConstraintParametric::refresh()
+{
+ Slvs_hEntity aBasePointID = myAttributeMap[myBaseAttribute];
+ const Slvs_Entity& aBasePoint = myStorage->getEntity(aBasePointID);
+ double aXY[2];
+ aXY[0] = myVertLineID != SLVS_E_UNKNOWN ? myX : myStorage->getParameter(aBasePoint.param[0]).val;
+ aXY[1] = myHorizLineID != SLVS_E_UNKNOWN ? myY : myStorage->getParameter(aBasePoint.param[1]).val;
+
+ std::list<Slvs_Constraint> aCoincidence = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
+ std::list<Slvs_Constraint>::const_iterator aCIt = aCoincidence.begin();
+ for (; aCIt != aCoincidence.end(); ++aCIt) {
+ if (aCIt->ptA != aBasePointID && aCIt->ptB != aBasePointID)
+ continue;
+ Slvs_hEntity anOtherPointID = aCIt->ptA == aBasePointID ? aCIt->ptB : aCIt->ptA;
+ const Slvs_Entity& aPoint = myStorage->getEntity(anOtherPointID);
+ for (int i = 0; i < 2; i++) {
+ Slvs_Param aParam = myStorage->getParameter(aPoint.param[i]);
+ aParam.val = aXY[i];
+ myStorage->updateParameter(aParam);
+ }
+ }
+}
+
+void SketchSolver_ConstraintParametric::adjustConstraint()
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
+ if (!aPoint)
+ return;
+
+ if (!aPoint->textX().empty()) {
+ const Slvs_Entity& aLine = myStorage->getEntity(myVertLineID);
+ const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]);
+ Slvs_Param aParX = myStorage->getParameter(aStartPoint.param[0]);
+ aParX.val = aPoint->x();
+ myStorage->updateParameter(aParX);
+ myX = aParX.val;
+ }
+ if (!aPoint->textY().empty()) {
+ const Slvs_Entity& aLine = myStorage->getEntity(myHorizLineID);
+ const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]);
+ Slvs_Param aParY = myStorage->getParameter(aStartPoint.param[1]);
+ aParY.val = aPoint->y();
+ myStorage->updateParameter(aParY);
+ myY = aParY.val;
+ }
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintParametric.h
+// Created: 15 Jun 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintParametric_H_
+#define SketchSolver_ConstraintParametric_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_ConstraintRigid.h>
+
+/** \class SketchSolver_ConstraintParametric
+ * \ingroup Plugins
+ * \brief Stores data of Rigid (Fixed) constraint for the attribute
+ * which coordinates are given by parametric expression
+ */
+class SketchSolver_ConstraintParametric : public SketchSolver_ConstraintRigid
+{
+private:
+ /// Creates constraint to manage the given constraint from plugin
+ SketchSolver_ConstraintParametric()
+ : SketchSolver_ConstraintRigid(ConstraintPtr())
+ {}
+
+public:
+ /// Creates temporary constraint based on feature
+ SketchSolver_ConstraintParametric(AttributePtr theAttribute);
+
+ /// \brief Update constraint
+ virtual void update(ConstraintPtr theConstraint = ConstraintPtr());
+
+ /// \brief Update points coincident with parametric one
+ virtual void refresh();
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Convert attribute to the entity
+ /// \param[out] theAttributeID identifier of the entity related to the attribute
+ virtual void getAttributes(Slvs_hEntity& theAttributeID);
+
+ /// \brief This method is used in derived objects to check consistence of constraint.
+ virtual void adjustConstraint();
+
+private:
+ AttributePtr myBaseAttribute; ///< attribute given by expression
+ Slvs_hEntity myHorizLineID; ///< identifier of horizontal line, containing the point
+ Slvs_hEntity myVertLineID; ///< identifier of vertical line, containing the point
+ double myX, myY;
+};
+
+#endif
if (myWorkplaneID == SLVS_E_UNKNOWN)
return false;
- if (!theConstraint)
+ if (!theConstraint || !theConstraint->data())
return false;
if (!checkFeatureValidity(theConstraint))
myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
myFeatureStorage->changeConstraint(theConstraint);
+ // Check the attributes of constraint are given by parametric expression
+ std::list<AttributePtr> anAttributes =
+ theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+ std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
+ for (; anAttrIt != anAttributes.end(); ++anAttrIt) {
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
+ if (!aRefAttr || aRefAttr->isObject())
+ continue;
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
+ if (!aPoint || (aPoint->textX().empty() && aPoint->textY().empty()))
+ continue;
+
+ std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
+ myParametricConstraints.find(aRefAttr->attr());
+ if (aFound == myParametricConstraints.end()) {
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createParametricConstraint(aRefAttr->attr());
+ if (!aConstraint)
+ continue;
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
+ myParametricConstraints[aRefAttr->attr()] = aConstraint;
+ } else
+ aFound->second->update();
+ }
+
return true;
}
aSolConIter->second->addFeature(theFeature);
myChangedConstraints.insert(aSolConIter->first);
}
+
+ // Search attributes of the feature in the set of parametric constraints and update them
+ std::list<AttributePtr> anAttrList =
+ theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+ std::list<AttributePtr>::iterator anAttrIt = anAttrList.begin();
+ for (; anAttrIt != anAttrList.end(); ++anAttrIt) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
+ if (!aRefAttr || aRefAttr->isObject())
+ continue;
+ std::map<AttributePtr, SolverConstraintPtr>::iterator aFound =
+ myParametricConstraints.find(aRefAttr->attr());
+ if (aFound != myParametricConstraints.end())
+ aFound->second->update();
+ }
return true;
}
}
if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes
myFeatureStorage->blockEvents(true);
+ // First refresh parametric constraints to satisfy parameters
+ std::map<AttributePtr, SolverConstraintPtr>::iterator aParIter = myParametricConstraints.begin();
+ for (; aParIter != myParametricConstraints.end(); ++aParIter)
+ aParIter->second->refresh();
+ // Update all other constraints
ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
- for (; aConstrIter != myConstraints.end(); aConstrIter++)
+ for (; aConstrIter != myConstraints.end(); ++aConstrIter)
aConstrIter->second->refresh();
myFeatureStorage->blockEvents(false);
if (!myPrevSolved) {