From 4cbfb073803b0c753a8a31e677a5b786974cf983 Mon Sep 17 00:00:00 2001 From: azv Date: Tue, 31 Mar 2015 18:54:47 +0300 Subject: [PATCH] SketchSolver library refactoring 1. Implemented Radius constraint 2. Implemented Equal constraint 3. Implemented Tangent constraint --- src/SketchSolver/CMakeLists.txt | 4 + src/SketchSolver/SketchSolver_Builder.cpp | 8 +- src/SketchSolver/SketchSolver_Constraint.cpp | 2 + src/SketchSolver/SketchSolver_Constraint.h | 23 +++++ .../SketchSolver_ConstraintEqual.cpp | 62 ++++++++++++++ .../SketchSolver_ConstraintEqual.h | 35 ++++++++ .../SketchSolver_ConstraintLength.h | 3 - .../SketchSolver_ConstraintTangent.cpp | 84 +++++++++++++++++++ .../SketchSolver_ConstraintTangent.h | 35 ++++++++ src/SketchSolver/SketchSolver_Error.h | 6 ++ .../SketchSolver_FeatureStorage.cpp | 28 +++++-- .../SketchSolver_FeatureStorage.h | 3 + src/SketchSolver/SketchSolver_Group.cpp | 4 +- src/SketchSolver/SketchSolver_Storage.cpp | 11 +++ src/SketchSolver/SketchSolver_Storage.h | 4 + 15 files changed, 300 insertions(+), 12 deletions(-) create mode 100644 src/SketchSolver/SketchSolver_ConstraintEqual.cpp create mode 100644 src/SketchSolver/SketchSolver_ConstraintEqual.h create mode 100644 src/SketchSolver/SketchSolver_ConstraintTangent.cpp create mode 100644 src/SketchSolver/SketchSolver_ConstraintTangent.h diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index 334ee0451..bc1b78af7 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -10,8 +10,10 @@ SET(PROJECT_HEADERS SketchSolver_Constraint.h SketchSolver_ConstraintCoincidence.h SketchSolver_ConstraintDistance.h + SketchSolver_ConstraintEqual.h SketchSolver_ConstraintLength.h SketchSolver_ConstraintRigid.h + SketchSolver_ConstraintTangent.h SketchSolver_Builder.h SketchSolver_Group.h SketchSolver_ConstraintManager.h @@ -24,8 +26,10 @@ SET(PROJECT_SOURCES SketchSolver_Constraint.cpp SketchSolver_ConstraintCoincidence.cpp SketchSolver_ConstraintDistance.cpp + SketchSolver_ConstraintEqual.cpp SketchSolver_ConstraintLength.cpp SketchSolver_ConstraintRigid.cpp + SketchSolver_ConstraintTangent.cpp SketchSolver_Builder.cpp SketchSolver_Group.cpp SketchSolver_ConstraintManager.cpp diff --git a/src/SketchSolver/SketchSolver_Builder.cpp b/src/SketchSolver/SketchSolver_Builder.cpp index 4f0d05ab1..6bf3a61c0 100644 --- a/src/SketchSolver/SketchSolver_Builder.cpp +++ b/src/SketchSolver/SketchSolver_Builder.cpp @@ -7,8 +7,10 @@ #include "SketchSolver_Builder.h" #include #include +#include #include #include +#include #include #include @@ -61,7 +63,7 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) { -//// return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint)); + return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) { //// return SolverConstraintPtr(new SketchSolver_ConstraintFillet(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintHorizontal::ID()) { @@ -75,9 +77,9 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintPerpendicular(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintRadius::ID()) { -//// return SolverConstraintPtr(new SketchSolver_ConstraintRadius(theConstraint)); + return SolverConstraintPtr(new SketchSolver_ConstraintRadius(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID()) { -//// return SolverConstraintPtr(new SketchSolver_ConstraintTangent(theConstraint)); + return SolverConstraintPtr(new SketchSolver_ConstraintTangent(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintVertical::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintVertical(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) { diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index 2cdd24eb7..c382cdeb3 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -160,6 +160,8 @@ bool SketchSolver_Constraint::remove(ConstraintPtr theConstraint) cleanErrorMsg(); if (theConstraint && theConstraint != myBaseConstraint) return false; + if (mySlvsConstraints.empty()) + return true; bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints.front()); if (isFullyRemoved) { myFeatureMap.clear(); diff --git a/src/SketchSolver/SketchSolver_Constraint.h b/src/SketchSolver/SketchSolver_Constraint.h index 6a57f6b21..3640d881d 100644 --- a/src/SketchSolver/SketchSolver_Constraint.h +++ b/src/SketchSolver/SketchSolver_Constraint.h @@ -177,4 +177,27 @@ public: { return SLVS_C_VERTICAL; } }; + +/** \class SketchSolver_ConstraintRadius + * \ingroup Plugins + * \brief Convert Radius constraint to SolveSpace structure + */ +class SketchSolver_ConstraintRadius : public SketchSolver_Constraint +{ +public: + SketchSolver_ConstraintRadius(ConstraintPtr theConstraint) : + SketchSolver_Constraint(theConstraint) + {} + + virtual int getType() const + { return SLVS_C_DIAMETER; } + + virtual void adjustConstraint() + { + Slvs_Constraint aConstraint = myStorage->getConstraint(mySlvsConstraints.front()); + aConstraint.valA *= 2.0; + myStorage->updateConstraint(aConstraint); + } +}; + #endif diff --git a/src/SketchSolver/SketchSolver_ConstraintEqual.cpp b/src/SketchSolver/SketchSolver_ConstraintEqual.cpp new file mode 100644 index 000000000..23ff40407 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintEqual.cpp @@ -0,0 +1,62 @@ +#include +#include +#include + + +void SketchSolver_ConstraintEqual::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 anEntities; + getAttributes(aValue, anEntities); + if (!myErrorMsg.empty()) + return; + + // Check the quantity of entities of each type + int aNbLines = 0; + int aNbArcs = 0; + int aNbCircs = 0; + std::vector::iterator anEntIter = anEntities.begin(); + for (; anEntIter != anEntities.end(); anEntIter++) { + Slvs_Entity anEnt = myStorage->getEntity(*anEntIter); + if (anEnt.type == SLVS_E_LINE_SEGMENT) + aNbLines++; + else if (anEnt.type == SLVS_E_CIRCLE) + aNbCircs++; + else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) + aNbArcs++; + } + + if (aNbLines + aNbArcs + aNbCircs != 2 || + (aNbLines == aNbCircs && aNbArcs == 0)) { + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); + return; + } + + switch (aNbLines) { + case 0: + myType = SLVS_C_EQUAL_RADIUS; + break; + case 1: + myType = SLVS_C_EQUAL_LINE_ARC_LEN; + break; + default: + myType = SLVS_C_EQUAL_LENGTH_LINES; + break; + } + + Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), + getType(), myGroup->getWorkplaneId(), aValue, + anEntities[0], anEntities[1], anEntities[2], anEntities[3]); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + adjustConstraint(); +} + diff --git a/src/SketchSolver/SketchSolver_ConstraintEqual.h b/src/SketchSolver/SketchSolver_ConstraintEqual.h new file mode 100644 index 000000000..c48477954 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintEqual.h @@ -0,0 +1,35 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintEqual.h +// Created: 1 Apr 2015 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintEqual_H_ +#define SketchSolver_ConstraintEqual_H_ + +#include "SketchSolver.h" +#include + +/** \class SketchSolver_ConstraintEqual + * \ingroup Plugins + * \brief Convert equality constraint to SolveSpace structure + */ +class SketchSolver_ConstraintEqual : public SketchSolver_Constraint +{ +public: + SketchSolver_ConstraintEqual(ConstraintPtr theConstraint) : + SketchSolver_Constraint(theConstraint) + {} + + virtual int getType() const + { return myType; } + +protected: + /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints + virtual void process(); + +private: + int myType; ///< type of constraint (applicable: SLVS_C_EQUAL_LENGTH_LINES, SLVS_C_EQUAL_RADIUS, SLVS_C_EQUAL_LINE_ARC_LEN) +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_ConstraintLength.h b/src/SketchSolver/SketchSolver_ConstraintLength.h index 176c6948e..5d0583752 100644 --- a/src/SketchSolver/SketchSolver_ConstraintLength.h +++ b/src/SketchSolver/SketchSolver_ConstraintLength.h @@ -27,9 +27,6 @@ public: 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 diff --git a/src/SketchSolver/SketchSolver_ConstraintTangent.cpp b/src/SketchSolver/SketchSolver_ConstraintTangent.cpp new file mode 100644 index 000000000..37b59fab2 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintTangent.cpp @@ -0,0 +1,84 @@ +#include +#include +#include + + +void SketchSolver_ConstraintTangent::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 anEntID; + getAttributes(aValue, anEntID); + if (!myErrorMsg.empty()) + return; + // Check the quantity of entities of each type and their order (arcs first) + int aNbLines = 0; + int aNbArcs = 0; + Slvs_Entity anEntities[2]; + myType = SLVS_C_CURVE_CURVE_TANGENT; + std::vector::iterator anEntIter = anEntID.begin(); + for (; anEntIter != anEntID.end(); anEntIter++) { + Slvs_Entity anEnt = myStorage->getEntity(*anEntIter); + if (anEnt.type == SLVS_E_LINE_SEGMENT) { + if (aNbLines == 0) + anEntities[1 + aNbLines] = anEnt; + aNbLines++; + myType = SLVS_C_ARC_LINE_TANGENT; + } + else if (anEnt.type == SLVS_E_ARC_OF_CIRCLE) { + if (aNbArcs < 2) + anEntities[aNbArcs] = anEnt; + aNbArcs++; + } + } + + if (aNbLines + aNbArcs != 2) { + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); + return; + } else if (aNbArcs < 1) { + myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE(); + return; + } + + // It is necessary to identify which points of entities are coincident + int aSlvsOtherFlag = 0; + int aSlvsOther2Flag = 0; + // Obtain start and end points of entities + Slvs_hEntity aPointsToFind[4]; + for (int i = 0; i < 2; i++) { + int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0; + aPointsToFind[2*i] = anEntities[i].point[aShift]; + aPointsToFind[2*i+1]= anEntities[i].point[aShift+1]; + } + // Search coincident points + bool isPointFound = false; + for (int i = 0; i < 2 && !isPointFound; i++) + for (int j = 2; j < 4 && !isPointFound; j++) + if (myStorage->isCoincident(aPointsToFind[i], aPointsToFind[j])) { + aSlvsOtherFlag = i; + aSlvsOther2Flag = j - 2; + isPointFound = true; + } + if (!isPointFound) { + // There is no coincident points between tangential objects. Generate error message + myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS(); + return; + } + + Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), + getType(), myGroup->getWorkplaneId(), aValue, + SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, anEntities[0].h, anEntities[1].h); + aConstraint.other = aSlvsOtherFlag; + aConstraint.other2 = aSlvsOther2Flag; + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + adjustConstraint(); +} + diff --git a/src/SketchSolver/SketchSolver_ConstraintTangent.h b/src/SketchSolver/SketchSolver_ConstraintTangent.h new file mode 100644 index 000000000..7f7e30d0c --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintTangent.h @@ -0,0 +1,35 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintTangent.h +// Created: 1 Apr 2015 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintTangent_H_ +#define SketchSolver_ConstraintTangent_H_ + +#include "SketchSolver.h" +#include + +/** \class SketchSolver_ConstraintTangent + * \ingroup Plugins + * \brief Convert tangency constraint to SolveSpace structure + */ +class SketchSolver_ConstraintTangent : public SketchSolver_Constraint +{ +public: + SketchSolver_ConstraintTangent(ConstraintPtr theConstraint) : + SketchSolver_Constraint(theConstraint) + {} + + virtual int getType() const + { return myType; } + +protected: + /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints + virtual void process(); + +private: + int myType; ///< type of constraint (applicable: SLVS_C_ARC_LINE_TANGENT, SLVS_C_CURVE_CURVE_TANGENT) +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_Error.h b/src/SketchSolver/SketchSolver_Error.h index dfae098bf..b05cb554e 100644 --- a/src/SketchSolver/SketchSolver_Error.h +++ b/src/SketchSolver/SketchSolver_Error.h @@ -41,6 +41,12 @@ class SketchSolver_Error static const std::string MY_ERROR_VALUE("Incorrect attribute"); return MY_ERROR_VALUE; } + /// Tangency constraint has wrong attributes + inline static const std::string& INCORRECT_TANGENCY_ATTRIBUTE() + { + static const std::string MY_ERROR_VALUE("An arc should be an attribute of tangency constraint"); + return MY_ERROR_VALUE; + } }; #endif diff --git a/src/SketchSolver/SketchSolver_FeatureStorage.cpp b/src/SketchSolver/SketchSolver_FeatureStorage.cpp index 9b8f133f4..5e112078d 100644 --- a/src/SketchSolver/SketchSolver_FeatureStorage.cpp +++ b/src/SketchSolver/SketchSolver_FeatureStorage.cpp @@ -313,11 +313,11 @@ bool SketchSolver_FeatureStorage::isConsistent() const for (; aFIter != myFeatures.end(); aFIter++) if (!aFIter->first->data() || !aFIter->first->data()->isValid()) return false; - // Check the attributes are valid - MapAttributeFeature::const_iterator aTIter = myAttributes.begin(); - for (; aTIter != myAttributes.end(); aTIter++) - if (!aTIter->first->isInitialized()) - return false; +//// // Check the attributes are valid +//// MapAttributeFeature::const_iterator aTIter = myAttributes.begin(); +//// for (; aTIter != myAttributes.end(); aTIter++) +//// if (!aTIter->first->isInitialized()) +//// return false; return true; } @@ -370,3 +370,21 @@ std::set SketchSolver_FeatureStorage::getConstraints(AttributePtr return aResult; } +void SketchSolver_FeatureStorage::blockEvents(bool isBlocked) const +{ + std::set::iterator aCIter = myConstraints.begin(); + for (; aCIter != myConstraints.end(); aCIter++) + if ((*aCIter)->data() && (*aCIter)->data()->isValid()) + (*aCIter)->data()->blockSendAttributeUpdated(isBlocked); + + MapFeatureConstraint::const_iterator aFIter = myFeatures.begin(); + for (; aFIter != myFeatures.end(); aFIter++) + if (aFIter->first->data() && aFIter->first->data()->isValid()) + aFIter->first->data()->blockSendAttributeUpdated(isBlocked); + + MapAttributeFeature::const_iterator anAtIter = myAttributes.begin(); + for (; anAtIter != myAttributes.end(); anAtIter++) + if (anAtIter->first->owner() && anAtIter->first->owner()->data() && + anAtIter->first->owner()->data()->isValid()) + anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked); +} diff --git a/src/SketchSolver/SketchSolver_FeatureStorage.h b/src/SketchSolver/SketchSolver_FeatureStorage.h index 287be5a57..2cb36ba81 100644 --- a/src/SketchSolver/SketchSolver_FeatureStorage.h +++ b/src/SketchSolver/SketchSolver_FeatureStorage.h @@ -64,6 +64,9 @@ public: /// \brief Prepares list of constraints, which using specified attribute std::set getConstraints(AttributePtr theAttribute) const; + /// \brief Block/unblock events of changing attributes of the features + void blockEvents(bool isBlocked) const; + private: std::set myConstraints; ///< list of SketchPlugin constraints used in the current group MapFeatureConstraint myFeatures; ///< list of features used in the group and corresponding constraints which use the feature diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 493fdbf37..0a250d8c2 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -1397,16 +1397,18 @@ bool SketchSolver_Group::resolveConstraints() int aResult = myConstrSolver.solve(); if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes + myFeatureStorage->blockEvents(true); ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin(); for (; aConstrIter != myConstraints.end(); aConstrIter++) aConstrIter->second->refresh(); + myFeatureStorage->blockEvents(false); } else if (!myConstraints.empty()) Events_Error::send(SketchSolver_Error::CONSTRAINTS(), this); - myStorage->setNeedToResolve(false); aResolved = true; } removeTemporaryConstraints(); + myStorage->setNeedToResolve(false); return aResolved; } diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index 687e6ea11..eabf3a5fa 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -381,6 +381,17 @@ void SketchSolver_Storage::removeCoincidentPoint(const Slvs_hEntity& thePoint) } } +bool SketchSolver_Storage::isCoincident( + const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const +{ + std::vector< std::set >::const_iterator aCIter = myCoincidentPoints.begin(); + for (; aCIter != myCoincidentPoints.end(); aCIter++) + if (aCIter->find(thePoint1) != aCIter->end() && aCIter->find(thePoint2) != aCIter->end()) + return true; + return false; +} + + // ======================================================== diff --git a/src/SketchSolver/SketchSolver_Storage.h b/src/SketchSolver/SketchSolver_Storage.h index fe206107e..70f2622b1 100644 --- a/src/SketchSolver/SketchSolver_Storage.h +++ b/src/SketchSolver/SketchSolver_Storage.h @@ -109,6 +109,10 @@ private: /// \brief Remove point from lists of coincidence void removeCoincidentPoint(const Slvs_hEntity& thePoint); +public: + /// \brief Check two points are coincident + bool isCoincident(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const; + private: Slvs_hParam myParamMaxID; ///< current parameter index (may differs with the number of parameters) std::vector myParameters; ///< list of parameters used in the current group of constraints (sorted by the identifier) -- 2.39.2