SketchSolver_Solver.h
SketchSolver_Constraint.h
SketchSolver_ConstraintCoincidence.h
+ SketchSolver_ConstraintDistance.h
+ SketchSolver_ConstraintLength.h
SketchSolver_ConstraintRigid.h
SketchSolver_Builder.h
SketchSolver_Group.h
SketchSolver_Solver.cpp
SketchSolver_Constraint.cpp
SketchSolver_ConstraintCoincidence.cpp
+ SketchSolver_ConstraintDistance.cpp
+ SketchSolver_ConstraintLength.cpp
SketchSolver_ConstraintRigid.cpp
SketchSolver_Builder.cpp
SketchSolver_Group.cpp
#include "SketchSolver_Builder.h"
#include <SketchSolver_ConstraintCoincidence.h>
+#include <SketchSolver_ConstraintDistance.h>
+#include <SketchSolver_ConstraintLength.h>
#include <SketchSolver_ConstraintRigid.h>
#include <GeomAPI_Edge.h>
} else if (theConstraint->getKind() == SketchPlugin_ConstraintHorizontal::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintHorizontal(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
-//// return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
+ return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
//// return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintParallel::ID()) {
mySlvsConstraints.push_back(anID);
else
mySlvsConstraints[0] = anID;
+ adjustConstraint();
}
void SketchSolver_Constraint::update(ConstraintPtr theConstraint)
process();
}
+ // Update all attributes
int aType;
+ std::map<Slvs_hEntity, Slvs_hEntity> aRelocationMap;
std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIter = myFeatureMap.begin();
- for (; aFeatIter != myFeatureMap.end(); aFeatIter++)
+ for (; aFeatIter != myFeatureMap.end(); aFeatIter++) {
+ Slvs_hEntity aPrevID = aFeatIter->second;
aFeatIter->second = changeEntity(aFeatIter->first, aType);
+ if (aFeatIter->second != aPrevID)
+ aRelocationMap[aPrevID] = aFeatIter->second;
+ }
std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
- for (; anAttrIter != myAttributeMap.end(); anAttrIter++)
+ for (; anAttrIter != myAttributeMap.end(); anAttrIter++) {
+ Slvs_hEntity aPrevID = anAttrIter->second;
anAttrIter->second = changeEntity(anAttrIter->first, aType);
+ if (anAttrIter->second != aPrevID)
+ aRelocationMap[aPrevID] = anAttrIter->second;
+ }
+
+ // Value if exists
+ AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ myBaseConstraint->data()->attribute(SketchPlugin_Constraint::VALUE()));
+ double aValue = aValueAttr ? aValueAttr->value() : 0.0;
+
+ // Update constraint
+ std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+ Slvs_Constraint aConstraint = myStorage->getConstraint(*aCIter);
+ aConstraint.valA = aValue;
+ Slvs_hEntity* aCoeffs[6] = {
+ &aConstraint.ptA, &aConstraint.ptB,
+ &aConstraint.entityA, &aConstraint.entityB,
+ &aConstraint.entityC, &aConstraint.entityD};
+ for (int i = 0; i < 6; i++) {
+ if (*(aCoeffs[i]) == SLVS_E_UNKNOWN)
+ continue;
+ std::map<Slvs_hEntity, Slvs_hEntity>::iterator aFound = aRelocationMap.find(*(aCoeffs[i]));
+ if (aFound != aRelocationMap.end())
+ *(aCoeffs[i]) = aFound->second;
+ }
+ *aCIter = myStorage->addConstraint(aConstraint);
+ }
+ adjustConstraint();
}
bool SketchSolver_Constraint::remove(ConstraintPtr theConstraint)
int anAttrType;
// Line
- if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) {
+ if (aFeatureKind == SketchPlugin_Line::ID()) {
anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID());
if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
aResult = myStorage->addEntity(aCurrentEntity);
}
// Circle
- else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) {
+ else if (aFeatureKind == SketchPlugin_Circle::ID()) {
anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID());
if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
aResult = myStorage->addEntity(aCurrentEntity);
}
// Arc
- else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) {
+ else if (aFeatureKind == SketchPlugin_Arc::ID()) {
anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID());
if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
aResult = myStorage->addEntity(aCurrentEntity);
}
// Point (it has low probability to be an attribute of constraint, so it is checked at the end)
- else if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) {
+ else if (aFeatureKind == SketchPlugin_Point::ID()) {
anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID());
if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
// Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
}
}
- myFeatureMap[theEntity] = aResult;
- theType = aCurrentEntity.type;
+ if (aResult != SLVS_E_UNKNOWN) {
+ myFeatureMap[theEntity] = aResult;
+ theType = aCurrentEntity.type;
+ }
return aResult;
}
/// \param[out] theAttributes list of attributes to be filled
virtual void getAttributes(double& theValue, std::vector<Slvs_hEntity>& theAttributes);
+ /// \brief This method is used in derived objects to check consistence of constraint.
+ /// E.g. the distance between line and point may be signed.
+ virtual void adjustConstraint()
+ {}
+
/// \brief Create or change SlveSpace entity according to the given attribute
/// \param[in] theAttribute reference to the entity to be changed
/// \param[out] theType type of created entity
-/** \class SketchSolver_ConstraintDistance
- * \ingroup Plugins
- * \brief Convert distance constraint to SolveSpace structure
- */
-class SketchSolver_ConstraintDistance : public SketchSolver_Constraint
-{
-public:
- SketchSolver_ConstraintDistance(ConstraintPtr theConstraint) :
- SketchSolver_Constraint(theConstraint)
- {}
-
- virtual int getType() const
- { return SLVS_C_PT_PT_DISTANCE; }
-};
-
-
/** \class SketchSolver_ConstraintParallel
* \ingroup Plugins
* \brief Convert Parallel constraint to SolveSpace structure
--- /dev/null
+#include <SketchSolver_ConstraintDistance.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+#include <GeomAPI_XY.h>
+
+
+void SketchSolver_ConstraintDistance::process()
+{
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
+ return;
+ }
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ double aValue;
+ std::vector<Slvs_hEntity> anEntities;
+ getAttributes(aValue, anEntities);
+ if (!myErrorMsg.empty())
+ return;
+
+ // Obtain entities to identify the type of distance
+ static const int aNbPoints = 2;
+ Slvs_hEntity aPoint[aNbPoints] = {SLVS_E_UNKNOWN, SLVS_E_UNKNOWN};
+ Slvs_hEntity aLine = SLVS_E_UNKNOWN;
+ myType = SLVS_C_PT_PT_DISTANCE;
+ int aPtPos = 0;
+ std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
+ for (; anEntIter != anEntities.end(); anEntIter++) {
+ if (*anEntIter == SLVS_E_UNKNOWN)
+ continue;
+ Slvs_Entity anEnt = myStorage->getEntity(*anEntIter);
+ if (anEnt.type == SLVS_E_POINT_IN_2D || anEnt.type == SLVS_E_POINT_IN_3D) {
+ if (aPtPos >= aNbPoints) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+ aPoint[aPtPos++] = *anEntIter;
+ }
+ else if (anEnt.type == SLVS_E_LINE_SEGMENT) {
+ if (myType == SLVS_C_PT_LINE_DISTANCE) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+ aLine = *anEntIter;
+ myType = SLVS_C_PT_LINE_DISTANCE;
+ }
+ }
+
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ getType(), myGroup->getWorkplaneId(), aValue, aPoint[0], aPoint[1], aLine, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ adjustConstraint();
+}
+
+void SketchSolver_ConstraintDistance::adjustConstraint()
+{
+ if (getType() != SLVS_C_PT_LINE_DISTANCE)
+ return;
+
+ // Get constraint parameters and check the sign of constraint value
+ std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
+ for (; aCIter != mySlvsConstraints.end(); aCIter++) {
+ Slvs_Constraint aConstraint = myStorage->getConstraint(*aCIter);
+ Slvs_Entity aLine = myStorage->getEntity(aConstraint.entityA);
+ // Obtain point and line coordinates
+ Slvs_hEntity aPointID[3] = {aConstraint.ptA, aLine.point[0], aLine.point[1]};
+ std::shared_ptr<GeomAPI_XY> aPoints[3];
+ for (int i = 0; i < 3; i++) {
+ Slvs_Entity aPoint = myStorage->getEntity(aPointID[i]);
+ Slvs_Param aParams[2] = {
+ myStorage->getParameter(aPoint.param[0]),
+ myStorage->getParameter(aPoint.param[1])};
+ aPoints[i] = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(aParams[0].val, aParams[1].val));
+ }
+ std::shared_ptr<GeomAPI_XY> aLineVec = aPoints[2]->decreased(aPoints[1]);
+ std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoints[0]->decreased(aPoints[1]);
+ if (aPtLineVec->cross(aLineVec) * aConstraint.valA < 0.0) {
+ aConstraint.valA *= -1.0;
+ myStorage->updateConstraint(aConstraint);
+ }
+ }
+}
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintDistance.h
+// Created: 31 Mar 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintDistance_H_
+#define SketchSolver_ConstraintDistance_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class SketchSolver_ConstraintDistance
+ * \ingroup Plugins
+ * \brief Convert distance constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintDistance : public SketchSolver_Constraint
+{
+public:
+ SketchSolver_ConstraintDistance(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint), myType(SLVS_C_UNKNOWN)
+ {}
+
+ virtual int getType() const
+ {return myType; }
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+ /// \brief Verifies the sign of the distance between line and point and change it if necessary
+ virtual void adjustConstraint();
+
+private:
+ int myType; ///< type of constraint (applicable: SLVS_C_PT_PT_DISTANCE, SLVS_C_PT_LINE_DISTANCE)
+};
+
+#endif
--- /dev/null
+#include <SketchSolver_ConstraintLength.h>
+#include <SketchSolver_Group.h>
+#include <SketchSolver_Error.h>
+
+
+void SketchSolver_ConstraintLength::process()
+{
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage || myGroup == 0) {
+ /// TODO: Put error message here
+ return;
+ }
+ if (!mySlvsConstraints.empty()) // some data is changed, update constraint
+ update(myBaseConstraint);
+
+ double aValue;
+ std::vector<Slvs_hEntity> anEntities;
+ getAttributes(aValue, anEntities);
+ if (!myErrorMsg.empty())
+ return;
+
+ // Check the entity is a line
+ Slvs_Entity aLine = myStorage->getEntity(anEntities[2]);
+ if (aLine.type != SLVS_E_LINE_SEGMENT){
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ getType(), myGroup->getWorkplaneId(), aValue,
+ aLine.point[0], aLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ adjustConstraint();
+}
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: SketchSolver_ConstraintLength.h
+// Created: 31 Mar 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchSolver_ConstraintLength_H_
+#define SketchSolver_ConstraintLength_H_
+
+#include "SketchSolver.h"
+#include <SketchSolver_Constraint.h>
+
+/** \class SketchSolver_ConstraintLength
+ * \ingroup Plugins
+ * \brief Convert length constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintLength : public SketchSolver_Constraint
+{
+public:
+ SketchSolver_ConstraintLength(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint)
+ {}
+
+ virtual int getType() const
+ { return SLVS_C_PT_PT_DISTANCE; }
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process();
+
+private:
+ int myType; ///< type of constraint (applicable: SLVS_C_PT_PT_DISTANCE, SLVS_C_PT_LINE_DISTANCE)
+};
+
+#endif
for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
if ((*aGroupIter)->getId() == aGroupId) {
// If the group is empty, the feature is not added (the constraint only)
-//// if (!aConstraint && !(*aGroupIter)->isEmpty())
+ if (!aConstraint && !(*aGroupIter)->isEmpty())
+ return (*aGroupIter)->updateFeature(theFeature);
//// return (*aGroupIter)->changeEntityFeature(theFeature) != SLVS_E_UNKNOWN;
return (*aGroupIter)->changeConstraint(aConstraint);
}
if (aConstraint)
return (*aFirstGroupIter)->changeConstraint(aConstraint);
+ return (*aFirstGroupIter)->updateFeature(theFeature);
//// return (*aFirstGroupIter)->changeEntityFeature(theFeature) != SLVS_E_UNKNOWN;
}
bool isEmpty = aConstrIter == mySlvsConstraints.end();
std::vector<Slvs_hEntity>::const_iterator anEntIter = anEntities.begin();
for (; anEntIter != anEntities.end(); anEntIter++) {
- if (isEmpty) { // create new constraint
+ if (*anEntIter == SLVS_E_UNKNOWN)
+ continue;
+ Slvs_hConstraint aConstrID = myStorage->isPointFixed(*anEntIter);
+ bool isForceUpdate = (aConstrID != SLVS_E_UNKNOWN && !myBaseConstraint);
+ if (isEmpty && !isForceUpdate) { // create new constraint
+ if (aConstrID != SLVS_E_UNKNOWN)
+ continue; // the coincident point is already fixed
aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(),
aValue, *anEntIter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
aConstraint.h = myStorage->addConstraint(aConstraint);
if (!myBaseConstraint)
myStorage->addTemporaryConstraint(aConstraint.h);
} else { // update already existent constraint
- aConstraint = myStorage->getConstraint(*aConstrIter);
+ if (aConstrID == SLVS_E_UNKNOWN || myBaseConstraint)
+ aConstrID = *aConstrIter;
+ aConstraint = myStorage->getConstraint(aConstrID);
aConstraint.ptA = *anEntIter;
myStorage->addConstraint(aConstraint);
- aConstrIter++;
- isEmpty = aConstrIter == mySlvsConstraints.end();
+ if (!myBaseConstraint)
+ myStorage->addTemporaryConstraint(aConstraint.h);
+ if (!isEmpty) {
+ aConstrIter++;
+ isEmpty = aConstrIter == mySlvsConstraints.end();
+ }
}
}
}
// Get the attribute of constraint
AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
myBaseConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A()));
- if (!aRefAttr) {
+ if (!aRefAttr || !aRefAttr->isInitialized()) {
myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
return;
}
static const std::string MY_ERROR_VALUE("Attribute is not initialized");
return MY_ERROR_VALUE;
}
+ /// Constraint has wrong attributes
+ inline static const std::string& INCORRECT_ATTRIBUTE()
+ {
+ static const std::string MY_ERROR_VALUE("Incorrect attribute");
+ return MY_ERROR_VALUE;
+ }
};
#endif
return aCIter->second->getId(theAttribute);
}
-
-////// ============================================================================
-////// Function: checkConstraintConsistence
-////// Class: SketchSolver_Group
-////// Purpose: verifies and changes parameters of the constraint
-////// ============================================================================
-////void SketchSolver_Group::checkConstraintConsistence(Slvs_Constraint& theConstraint)
-////{
-//// if (theConstraint.type == SLVS_C_PT_LINE_DISTANCE) {
-//// // Get constraint parameters and check the sign of constraint value
-////
-//// // point coordinates
-//// int aPtPos = Search(theConstraint.ptA, myEntities);
-//// int aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
-//// std::shared_ptr<GeomAPI_XY> aPoint(
-//// new GeomAPI_XY(myParams[aPtParamPos].val, myParams[aPtParamPos + 1].val));
-////
-//// // line coordinates
-//// int aLnPos = Search(theConstraint.entityA, myEntities);
-//// aPtPos = Search(myEntities[aLnPos].point[0], myEntities);
-//// aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
-//// std::shared_ptr<GeomAPI_XY> aStart(
-//// new GeomAPI_XY(-myParams[aPtParamPos].val, -myParams[aPtParamPos + 1].val));
-//// aPtPos = Search(myEntities[aLnPos].point[1], myEntities);
-//// aPtParamPos = Search(myEntities[aPtPos].param[0], myParams);
-//// std::shared_ptr<GeomAPI_XY> aEnd(
-//// new GeomAPI_XY(myParams[aPtParamPos].val, myParams[aPtParamPos + 1].val));
-////
-//// aEnd = aEnd->added(aStart);
-//// aPoint = aPoint->added(aStart);
-//// if (aPoint->cross(aEnd) * theConstraint.valA < 0.0)
-//// theConstraint.valA *= -1.0;
-//// }
-////}
-
// ============================================================================
// Function: changeConstraint
// Class: SketchSolver_Group
return true;
}
-void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
+
+bool SketchSolver_Group::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
{
std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(theFeature);
+ if (aConstraints.empty())
+ return false;
std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
for (; aCIter != aConstraints.end(); aCIter++) {
ConstraintConstraintMap::iterator aSolConIter = myConstraints.find(*aCIter);
aSolConIter->second->update();
}
+ return true;
+}
+void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
+{
+ updateFeature(theFeature);
// Temporary rigid constraint
SolverConstraintPtr aConstraint =
SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature);
// ============================================================================
bool SketchSolver_Group::resolveConstraints()
{
- if (!myStorage->isNeedToResolve() || isEmpty())
- return false;
+ bool aResolved = false;
+ if (myStorage->isNeedToResolve() && !isEmpty()) {
+ myConstrSolver.setGroupID(myID);
+ myStorage->initializeSolver(myConstrSolver);
- myConstrSolver.setGroupID(myID);
- myStorage->initializeSolver(myConstrSolver);
-
-//// theSolver.setDraggedParameters(myTempPointWhereDragged);
-////
- int aResult = myConstrSolver.solve();
- if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes
- ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
- for (; aConstrIter != myConstraints.end(); aConstrIter++)
- aConstrIter->second->refresh();
-
-//// // Obtain result into the same list of parameters
-//// if (!myConstrSolver.getResult(myParams))
-//// return true;
-////
-//// // We should go through the attributes map, because only attributes have valued parameters
-//// std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::iterator anEntIter =
-//// myEntityAttrMap.begin();
-//// for (; anEntIter != myEntityAttrMap.end(); anEntIter++) {
-//// if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get())
-//// anEntIter->first->owner()->data()->blockSendAttributeUpdated(true);
-//// if (updateAttribute(anEntIter->first, anEntIter->second))
-//// updateRelatedConstraints(anEntIter->first);
-//// }
-//// updateFilletConstraints();
-//// // unblock all features then
-//// for (anEntIter = myEntityAttrMap.begin(); anEntIter != myEntityAttrMap.end(); anEntIter++) {
-//// if (anEntIter->first->owner().get() && anEntIter->first->owner()->data().get())
-//// anEntIter->first->owner()->data()->blockSendAttributeUpdated(false);
-//// }
- } else if (!myConstraints.empty())
- Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this);
+ int aResult = myConstrSolver.solve();
+ if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes
+ ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); aConstrIter++)
+ aConstrIter->second->refresh();
+ } else if (!myConstraints.empty())
+ Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this);
+ myStorage->setNeedToResolve(false);
+ aResolved = true;
+ }
removeTemporaryConstraints();
-//// myNeedToSolve = false;
- myStorage->setNeedToResolve(false);
- return true;
+ return aResolved;
}
// ============================================================================
//// */
//// bool changeFilletConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
+ /** \brief Updates the data corresponding the specified feature
+ * \param[in] theFeature the feature to be updated
+ */
+ bool updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
+
/** \brief Updates the data corresponding the specified feature moved in GUI.
* Additional Fixed constraints are created.
* \param[in] theFeature the feature to be updated
//// */
//// bool addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2);
////
-//// /** \brief Verifies and changes parameters of constriant,
-//// * e.g. sign of the distance between line and point
-//// * \param[in,out] theConstraint SolveSpace constraint to be verified
-//// */
-//// void checkConstraintConsistence(Slvs_Constraint& theConstraint);
-////
//// /** \brief Change entities parameters to make them symmetric relating to the mirror line
//// * \param[in] theBase entity to be mirrored
//// * \param[in] theMirror a mirrored object
SketchSolver_Solver::~SketchSolver_Solver()
{
+ if (myEquationsSystem.constraint)
+ delete[] myEquationsSystem.constraint;
if (myEquationsSystem.failed)
delete[] myEquationsSystem.failed;
}
void SketchSolver_Solver::setConstraints(Slvs_Constraint* theConstraints, int theSize)
{
- myEquationsSystem.constraint = theConstraints;
- myEquationsSystem.constraints = theSize;
+ if (!myEquationsSystem.constraint) {
+ myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+ myEquationsSystem.constraints = theSize;
+ }
+ else if (myEquationsSystem.constraints != theSize) {
+ delete[] myEquationsSystem.constraint;
+ myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+ myEquationsSystem.constraints = theSize;
+ }
+ memcpy(myEquationsSystem.constraint, theConstraints, theSize * sizeof(Slvs_Constraint));
}
: myParamMaxID(SLVS_E_UNKNOWN),
myEntityMaxID(SLVS_E_UNKNOWN),
myConstrMaxID(SLVS_C_UNKNOWN),
+ myFixed(SLVS_E_UNKNOWN),
myNeedToResolve(false)
{
}
}
// Remove parameter
myParameters.erase(myParameters.begin() + aPos);
+ myParamMaxID = myParameters.empty() ? SLVS_E_UNKNOWN : myParameters.back().h;
myNeedToResolve = true;
myRemovedParameters.insert(theParamID);
return true;
// The entity is not used, remove it and its parameters
Slvs_Entity anEntity = myEntities[aPos];
myEntities.erase(myEntities.begin() + aPos);
+ myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h;
if (anEntity.distance != SLVS_E_UNKNOWN)
aResult = aResult && removeParameter(anEntity.distance);
for (int i = 0; i < 4; i++)
aResult = removeEntity(anEntity.point[i]) && aResult;
myNeedToResolve = true;
myRemovedEntities.insert(theEntityID);
+ if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
+ removeCoincidentPoint(theEntityID);
}
return aResult;
}
return aDummy;
}
+Slvs_hConstraint SketchSolver_Storage::isPointFixed(const Slvs_hEntity& thePointID) const
+{
+ // Search the set of coincident points
+ std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
+ for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
+ if (aCPIter->find(thePointID) != aCPIter->end())
+ break;
+ if (aCPIter == myCoincidentPoints.end()) {
+ std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); aConstrIter++)
+ if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
+ aConstrIter->ptA == thePointID)
+ return aConstrIter->h;
+ return SLVS_E_UNKNOWN;
+ }
+
+ // Search the Rigid constraint
+ std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); aConstrIter++)
+ if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
+ aCPIter->find(aConstrIter->ptA) != aCPIter->end())
+ return aConstrIter->h;
+ return SLVS_E_UNKNOWN;
+}
+
Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
{
aConstraint.h = ++myConstrMaxID;
myConstraints.push_back(aConstraint);
myNeedToResolve = true;
+ if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
+ addCoincidentPoints(aConstraint.ptA, aConstraint.ptB);
return aConstraint.h;
}
if (aPos >= 0 && aPos < (int)myConstraints.size()) {
myNeedToResolve = myNeedToResolve || IsNotEqual(myConstraints[aPos], theConstraint);
myConstraints[aPos] = theConstraint;
+ if (theConstraint.type == SLVS_C_POINTS_COINCIDENT)
+ addCoincidentPoints(theConstraint.ptA, theConstraint.ptB);
return theConstraint.h;
}
}
if (aPos >= 0 && aPos < (int)myConstraints.size()) {
Slvs_Constraint aConstraint = myConstraints[aPos];
myConstraints.erase(myConstraints.begin() + aPos);
+ myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h;
myNeedToResolve = true;
myRemovedConstraints.insert(theConstraintID);
// Remove all entities
aConstraint.entityA, aConstraint.entityB,
aConstraint.entityC, aConstraint.entityD};
for (int i = 0; i < 6; i++)
- if (anEntities[i] != SLVS_E_UNKNOWN) {
+ if (anEntities[i] != SLVS_E_UNKNOWN)
aResult = removeEntity(anEntities[i]) && aResult;
- // remove temporary fixed points, if exists
- std::vector<Slvs_hEntity>::iterator aFPIt = myFixedPoints.begin();
- for (; aFPIt != myFixedPoints.end(); aFPIt++)
- if (*aFPIt == anEntities[i]) {
- myFixedPoints.erase(aFPIt);
- break;
- }
- }
+ // remove temporary fixed point, if available
+ if (myFixed == theConstraintID)
+ myFixed = SLVS_E_UNKNOWN;
}
return aResult;
}
void SketchSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
{
+ if (myFixed != SLVS_E_UNKNOWN)
+ return; // the point is already fixed
int aPos = Search(theConstraintID, myConstraints);
- myFixedPoints.push_back(myConstraints[aPos].ptA);
+ if (aPos >= 0 && aPos < (int)myConstraints.size())
+ myFixed = theConstraintID;
}
void SketchSolver_Storage::getRemoved(
{
theSolver.setParameters(myParameters.data(), (int)myParameters.size());
theSolver.setEntities(myEntities.data(), (int)myEntities.size());
- theSolver.setConstraints(myConstraints.data(), (int)myConstraints.size());
- // initialize fixed points
- if (!myFixedPoints.empty()) {
- int aPos = Search(myFixedPoints.front(), myEntities);
+ // Copy constraints excluding the fixed one
+ std::vector<Slvs_Constraint> aConstraints = myConstraints;
+ if (myFixed != SLVS_E_UNKNOWN) {
+ Slvs_hEntity aFixedPoint = SLVS_E_UNKNOWN;
+ std::vector<Slvs_Constraint>::iterator anIt = aConstraints.begin();
+ for (; anIt != aConstraints.end(); anIt++)
+ if (anIt->h == myFixed) {
+ aFixedPoint = anIt->ptA;
+ aConstraints.erase(anIt);
+ break;
+ }
+ // set dragged parameters
+ int aPos = Search(aFixedPoint, myEntities);
theSolver.setDraggedParameters(myEntities[aPos].param);
}
+ theSolver.setConstraints(aConstraints.data(), (int)aConstraints.size());
}
+void SketchSolver_Storage::addCoincidentPoints(
+ const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2)
+{
+ std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
+ std::vector< std::set<Slvs_hEntity> >::iterator aFoundIter = myCoincidentPoints.end(); // already found coincidence
+ bool isFound = false;
+ for (; aCIter != myCoincidentPoints.end(); aCIter++) {
+ bool isFirstFound = aCIter->find(thePoint1) != aCIter->end();
+ bool isSecondFound = aCIter->find(thePoint2) != aCIter->end();
+ isFound = isFound || isFirstFound || isSecondFound;
+ if (isFirstFound && isSecondFound)
+ break; // already coincident
+ else if (isFirstFound || isSecondFound) {
+ if (aFoundIter != myCoincidentPoints.end()) {
+ // merge two sets
+ aFoundIter->insert(aCIter->begin(), aCIter->end());
+ myCoincidentPoints.erase(aCIter);
+ break;
+ }
+ aCIter->insert(thePoint1);
+ aCIter->insert(thePoint2);
+ }
+ }
+ // coincident points not found
+ if (!isFound) {
+ std::set<Slvs_hEntity> aNewSet;
+ aNewSet.insert(thePoint1);
+ aNewSet.insert(thePoint2);
+ myCoincidentPoints.push_back(aNewSet);
+ }
+}
+
+void SketchSolver_Storage::removeCoincidentPoint(const Slvs_hEntity& thePoint)
+{
+ std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
+ for (; aCIter != myCoincidentPoints.end(); aCIter++)
+ if (aCIter->find(thePoint) != aCIter->end()) {
+ aCIter->erase(thePoint);
+ if (aCIter->size() <= 1)
+ myCoincidentPoints.erase(aCIter);
+ break;
+ }
+}
+
+
// ========================================================
// ========= Auxiliary functions ===============
/// \brief Returns the entity by its ID
const Slvs_Entity& getEntity(const Slvs_hEntity& theEntityID) const;
+ /// \brief Verifies the current point or another coincident one is fixed
+ /// \return the ID of the Fixed constraint or SLVS_E_UNKNOWN
+ Slvs_hConstraint isPointFixed(const Slvs_hEntity& thePointID) const;
+
/** \brief Add new constraint to the current group
- * \param[in] theConstraint SolveSpace constraint
+ * \param[in] theConstraint SolveSpace's constraint
* \return the ID of added constraint
*/
Slvs_hConstraint addConstraint(const Slvs_Constraint& theConstraint);
/// \brief Initialize constraint solver by the entities collected by current storage
void initializeSolver(SketchSolver_Solver& theSolver);
+private:
+ /// \brief Store coincident points
+ void addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2);
+ /// \brief Remove point from lists of coincidence
+ void removeCoincidentPoint(const Slvs_hEntity& thePoint);
+
private:
Slvs_hParam myParamMaxID; ///< current parameter index (may differs with the number of parameters)
- std::vector<Slvs_Param> myParameters; ///< list of parameters used in the current group of constraints
+ std::vector<Slvs_Param> myParameters; ///< list of parameters used in the current group of constraints (sorted by the identifier)
Slvs_hEntity myEntityMaxID; ///< current entity index (may differs with the number of entities)
- std::vector<Slvs_Entity> myEntities; ///< list of entities used in the current group of constraints
+ std::vector<Slvs_Entity> myEntities; ///< list of entities used in the current group of constraints (sorted by the identifier)
Slvs_hConstraint myConstrMaxID; ///< current constraint index (may differs with the number of constraints)
- std::vector<Slvs_Constraint> myConstraints; ///< list of constraints used in the current group
+ std::vector<Slvs_Constraint> myConstraints; ///< list of constraints used in the current group (sorted by the identifier)
- std::vector<Slvs_hEntity> myFixedPoints; ///< identifiers of entities which relate to temporary constraints
+ std::vector< std::set<Slvs_hEntity> > myCoincidentPoints; ///< lists of coincident points
+ Slvs_hConstraint myFixed; ///< identifier of one of temporary constraints to fix separate point
bool myNeedToResolve; ///< parameters are changed and group needs to be resolved