#include <ModelAPI_ResultConstruction.h>
#include <SketchPlugin_Constraint.h>
+#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_ConstraintFillet.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_ConstraintTangent.h>
#include <SketchPlugin_Feature.h>
#include <SketchPlugin_Arc.h>
if (!theConstraint)
return false;
- if (myConstraints.find(theConstraint) == myConstraints.end()) {
+ bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end();
+ if (isNewConstraint) {
// Add constraint to the current group
SolverConstraintPtr aConstraint =
SketchSolver_Builder::getInstance()->createConstraint(theConstraint);
myConstraints[theConstraint]->update();
// Fix base features for fillet
- if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
+ if (isNewConstraint && theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
std::list<AttributePtr> anAttrList =
theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
continue;
aConstraint->setGroup(this);
aConstraint->setStorage(myStorage);
- myTempConstraints.insert(aConstraint);
+ setTemporary(aConstraint);
}
}
- // Fix base features for mirror
+ // Fix mirror line
if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
- AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_B()));
- fixFeaturesList(aRefList);
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A()));
+ if (aRefAttr && aRefAttr->isObject()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ if (aFeature) {
+ SolverConstraintPtr aConstraint =
+ SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+ if (aConstraint) {
+ aConstraint->setGroup(this);
+ aConstraint->setStorage(myStorage);
+ setTemporary(aConstraint);
+ }
+ }
+ }
}
if (!myFeatureStorage)
std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
for (; aCIter != aConstraints.end(); aCIter++) {
ConstraintConstraintMap::iterator aSolConIter = myConstraints.find(*aCIter);
+ if (aSolConIter == myConstraints.end() || !aSolConIter->first->data() ||
+ !aSolConIter->first->data()->isValid())
+ continue;
+ myFeatureStorage->changeFeature(theFeature, aSolConIter->first);
+ aSolConIter->second->addFeature(theFeature);
aSolConIter->second->update();
}
return true;
void SketchSolver_Group::moveFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
{
- updateFeature(theFeature);
- // Temporary rigid constraint
+ // Firstly, create temporary rigid constraint
SolverConstraintPtr aConstraint =
SketchSolver_Builder::getInstance()->createRigidConstraint(theFeature);
if (!aConstraint)
return;
aConstraint->setGroup(this);
aConstraint->setStorage(myStorage);
- myTempConstraints.insert(aConstraint);
+ if (aConstraint->error().empty())
+ setTemporary(aConstraint);
+ // Secondly, update the feature
+ updateFeature(theFeature);
}
// ============================================================================
{
std::list<ObjectPtr> aList = theList->list();
std::list<ObjectPtr>::iterator anIt = aList.begin();
+ std::list<FeaturePtr> aFeatures;
+ // Sort features, at begining there are features used by Equal constraint
for (; anIt != aList.end(); anIt++) {
if (!(*anIt))
continue;
FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+ std::set<ConstraintPtr> aConstraints = myFeatureStorage->getConstraints(aFeature);
+ std::set<ConstraintPtr>::iterator aCIter = aConstraints.begin();
+ for (; aCIter != aConstraints.end(); aCIter++)
+ if ((*aCIter)->getKind() == SketchPlugin_ConstraintEqual::ID())
+ break;
+ if (aCIter != aConstraints.end())
+ aFeatures.push_front(aFeature);
+ else
+ aFeatures.push_back(aFeature);
+ }
+
+ std::list<FeaturePtr>::iterator aFeatIter = aFeatures.begin();
+ for (; aFeatIter != aFeatures.end(); aFeatIter++) {
SolverConstraintPtr aConstraint =
- SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature);
+ SketchSolver_Builder::getInstance()->createRigidConstraint(*aFeatIter);
if (!aConstraint)
continue;
aConstraint->setGroup(this);
aConstraint->setStorage(myStorage);
- myTempConstraints.insert(aConstraint);
+ setTemporary(aConstraint);
}
}
myConstrSolver.setGroupID(myID);
myStorage->initializeSolver(myConstrSolver);
- int aResult = myConstrSolver.solve();
+ int aResult = SLVS_RESULT_OKAY;
+ try {
+ if (myStorage->hasDuplicatedConstraint())
+ aResult = SLVS_RESULT_INCONSISTENT;
+ else {
+ // To avoid overconstraint situation, we will remove temporary constraints one-by-one
+ // and try to find the case without overconstraint
+ int aNbTemp = myStorage->numberTemporary();
+ while (true) {
+ aResult = myConstrSolver.solve();
+ if (aResult == SLVS_RESULT_OKAY || aNbTemp <= 0)
+ break;
+ aNbTemp = myStorage->deleteTemporaryConstraint();
+ myStorage->initializeSolver(myConstrSolver);
+ }
+ }
+ } catch (...) {
+ Events_Error::send(SketchSolver_Error::SOLVESPACE_CRASH(), this);
+ return false;
+ }
if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes
myFeatureStorage->blockEvents(true);
ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin();
if (!myFeatureStorage)
myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage);
+ std::vector<ConstraintPtr> aComplexConstraints;
ConstraintConstraintMap::const_iterator aConstrIter = theGroup.myConstraints.begin();
+ // append simple constraints
for (; aConstrIter != theGroup.myConstraints.end(); aConstrIter++)
- changeConstraint(aConstrIter->first);
+ if (isComplexConstraint(aConstrIter->first))
+ aComplexConstraints.push_back(aConstrIter->first);
+ else
+ changeConstraint(aConstrIter->first);
+ // append complex constraints
+ std::vector<ConstraintPtr>::iterator aComplexIter = aComplexConstraints.begin();
+ for (; aComplexIter != aComplexConstraints.end(); aComplexIter++)
+ changeConstraint(*aComplexIter);
}
// ============================================================================
anUnusedConstraints.push_back(*anIter);
}
- std::vector<SketchSolver_Group*>::iterator aCutsIter;
+ // Check the unused constraints once again, because they may become interacted with new storage since adding constraints
std::vector<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
+ while (aUnuseIt != anUnusedConstraints.end()) {
+ if (aNewFeatStorage->isInteract(*aUnuseIt)) {
+ size_t aShift = aUnuseIt - anUnusedConstraints.begin();
+ anUnusedConstraints.erase(aUnuseIt);
+ aUnuseIt = anUnusedConstraints.begin() + aShift;
+ continue;
+ }
+ aUnuseIt++;
+ }
+
+ std::vector<SketchSolver_Group*>::iterator aCutsIter;
+ aUnuseIt = anUnusedConstraints.begin();
for ( ; aUnuseIt != anUnusedConstraints.end(); aUnuseIt++) {
// Remove unused constraints
removeConstraint(*aUnuseIt);
void SketchSolver_Group::removeTemporaryConstraints()
{
myTempConstraints.clear();
+ while (myStorage->numberTemporary())
+ myStorage->deleteTemporaryConstraint();
// Clean lists of removed entities in the storage
std::set<Slvs_hParam> aRemPar;
std::set<Slvs_hEntity> aRemEnt;
if (aCIter != myConstraints.end())
myConstraints.erase(aCIter);
}
+
+// ============================================================================
+// Function: isComplexConstraint
+// Class: SketchSolver_Group
+// Purpose: verifies the constraint is complex, i.e. it needs another constraints to be created before
+// ============================================================================
+bool SketchSolver_Group::isComplexConstraint(FeaturePtr theConstraint)
+{
+ return theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID() ||
+ theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID() ||
+ theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID();
+}
+
+// ============================================================================
+// Function: setTemporary
+// Class: SketchSolver_Group
+// Purpose: append given constraint to th group of temporary constraints
+// ============================================================================
+void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint)
+{
+ theConstraint->makeTemporary();
+ myTempConstraints.insert(theConstraint);
+}
+