From: azv Date: Wed, 2 Sep 2015 09:22:33 +0000 (+0300) Subject: Code optimization of multi-rotation and multi-translation in SketchSolver X-Git-Tag: V_1.4.0_beta4~152 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=d4c4c30796ce288f2e81205e0555457542f2e5be;p=modules%2Fshaper.git Code optimization of multi-rotation and multi-translation in SketchSolver --- diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index eedad7a0f..7c4c8c29e 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -17,6 +17,7 @@ SET(PROJECT_HEADERS SketchSolver_ConstraintMirror.h SketchSolver_ConstraintRigid.h SketchSolver_ConstraintTangent.h + SketchSolver_ConstraintMulti.h SketchSolver_ConstraintMultiRotation.h SketchSolver_ConstraintMultiTranslation.h SketchSolver_ConstraintMovement.h @@ -39,6 +40,7 @@ SET(PROJECT_SOURCES SketchSolver_ConstraintMirror.cpp SketchSolver_ConstraintRigid.cpp SketchSolver_ConstraintTangent.cpp + SketchSolver_ConstraintMulti.cpp SketchSolver_ConstraintMultiRotation.cpp SketchSolver_ConstraintMultiTranslation.cpp SketchSolver_ConstraintMovement.cpp diff --git a/src/SketchSolver/SketchSolver_ConstraintMulti.cpp b/src/SketchSolver/SketchSolver_ConstraintMulti.cpp new file mode 100644 index 000000000..92a79eb04 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintMulti.cpp @@ -0,0 +1,235 @@ +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +void SketchSolver_ConstraintMulti::processEntities(const std::vector< std::vector >& theEntAndCopies) +{ + // Keep all objects unchanged (only initial object may be changed by user) + myCircsAndCopies.clear(); + std::vector >::const_iterator anEntIt = theEntAndCopies.begin(); + std::vector::const_iterator aCpIt; + for (; anEntIt != theEntAndCopies.end(); ++anEntIt) { + std::vector aCircs; + aCpIt = anEntIt->begin(); + // Obtain initial points + Slvs_Entity anInitial = myStorage->getEntity(*aCpIt); + if (anInitial.type == SLVS_E_POINT_IN_2D || anInitial.type == SLVS_E_POINT_IN_3D) + myInitialPoints.insert(anInitial.h); + else { + for (int i = 0; i < 4 && anInitial.point[i] != SLVS_E_UNKNOWN; i++) + myInitialPoints.insert(anInitial.point[i]); + } + + // Fix the copies + for (++aCpIt; aCpIt != anEntIt->end(); ++aCpIt) { + const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt); + std::vector aNewConstr; + if (anEntity.type == SLVS_E_CIRCLE) { + aCircs.push_back(anEntity.distance); + // for circles we fix only center + aNewConstr = myStorage->fixEntity(anEntity.point[0]); + } else + aNewConstr = myStorage->fixEntity(*aCpIt); + if (anEntity.type == SLVS_E_ARC_OF_CIRCLE) + aCircs.push_back(anEntity.h); + mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end()); + } + + if (!aCircs.empty()) { + if (anInitial.type == SLVS_E_CIRCLE) + aCircs.insert(aCircs.begin(), anInitial.distance); + else + aCircs.insert(aCircs.begin(), anInitial.h); + myCircsAndCopies.push_back(aCircs); + } + } +} + +void SketchSolver_ConstraintMulti::update(ConstraintPtr theConstraint) +{ + cleanErrorMsg(); + if (!theConstraint || theConstraint == myBaseConstraint) { + AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(nameNbCopies()); + if (anInitialRefList->size() != myNumberOfObjects || aNbCopies->value() != myNumberOfCopies) { + remove(myBaseConstraint); + process(); + return; + } + } + + updateLocal(); + SketchSolver_Constraint::update(); +} + +bool SketchSolver_ConstraintMulti::remove(ConstraintPtr theConstraint) +{ + cleanErrorMsg(); + if (theConstraint && theConstraint != myBaseConstraint) + return false; + bool isFullyRemoved = true; + std::vector::iterator aCIter = mySlvsConstraints.begin(); + for (; aCIter != mySlvsConstraints.end(); aCIter++) + isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved; + mySlvsConstraints.clear(); + + std::map::iterator aFeatIt = myFeatureMap.begin(); + for (; aFeatIt != myFeatureMap.end(); aFeatIt++) + myStorage->removeEntity(aFeatIt->second); + myStorage->removeUnusedEntities(); + + std::map aFeatureMapCopy = myFeatureMap; + + if (isFullyRemoved) { + myFeatureMap.clear(); + myAttributeMap.clear(); + myValueMap.clear(); + } else + cleanRemovedEntities(); + + // Restore initial features + std::map::iterator aFIter = aFeatureMapCopy.begin(); + for (; aFIter != aFeatureMapCopy.end(); ++aFIter) + { + if (myFeatureMap.find(aFIter->first) != myFeatureMap.end()) + continue; // the feature was not removed + Slvs_hEntity anEntity = myGroup->getFeatureId(aFIter->first); + if (anEntity != SLVS_E_UNKNOWN) + myFeatureMap[aFIter->first] = anEntity; + } + + // Clear list of rotated points + myPointsAndCopies.clear(); + myInitialPoints.clear(); + + return true; +} + +void SketchSolver_ConstraintMulti::addFeature(FeaturePtr theFeature) +{ + SketchSolver_Constraint::addFeature(theFeature); + + std::map::iterator aFeatIt = myFeatureMap.find(theFeature); + if (aFeatIt == myFeatureMap.end()) + return; + + // store list of points of the feature + const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second); + for (int i = 0; i < 4; i++) + if (theEntity.point[i] != SLVS_E_UNKNOWN) + myPointsJustUpdated.insert(theEntity.point[i]); +} + +void SketchSolver_ConstraintMulti::adjustConstraint() +{ + double aRelCoord[2] = {0.0, 0.0}; // relative coordinates of point + double anAbsCoord[2] = {0.0, 0.0}; // absolute coordinates of point + + std::list aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT); + std::list::const_iterator aCoIt; + + // Update positions of all points to satisfy angles + std::vector< std::vector >::const_iterator aPointsIter = myPointsAndCopies.begin(); + std::vector::const_iterator aCopyIter; + for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) { + aCopyIter = aPointsIter->begin(); + const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); + for (int i = 0; i < 2; i++) + anAbsCoord[i] = myStorage->getParameter(anInitial.param[i]).val; + getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]); + + // if the point is coincident with another one which is temporary fixed (moved by user), + // we will update its position correspondingly + Slvs_hConstraint aFixed; + for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) { + if ((aCoIt->ptA == anInitial.h && myInitialPoints.find(aCoIt->ptB) != myInitialPoints.end()) || + (aCoIt->ptB == anInitial.h && myInitialPoints.find(aCoIt->ptA) != myInitialPoints.end())) { + Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA; + if (!myStorage->isTemporary(aFixed) && + myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end()) + continue; // nothing to change + + const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId); + for (int i = 0; i < 2; i++) { + Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]); + const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]); + anInitParam.val = anOtherParam.val; + myStorage->updateParameter(anInitParam); + anAbsCoord[i] = anOtherParam.val; + } + getRelative(anAbsCoord[0], anAbsCoord[1], aRelCoord[0], aRelCoord[1]); + } + } + + // update copied points + aCopyIter = aPointsIter->begin(); + for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { + // transform coordinates + transformRelative(aRelCoord[0], aRelCoord[1]); + getAbsolute(aRelCoord[0], aRelCoord[1], anAbsCoord[0], anAbsCoord[1]); + + const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter); + for (int i = 0; i < 2; i++) { + Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]); + aParam.val = anAbsCoord[i]; + myStorage->updateParameter(aParam); + } + } + } + + std::list aDiamConstr; + for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) { + aCopyIter = aPointsIter->begin(); + const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); + if (anInitial.type == SLVS_E_DISTANCE) { + const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]); + for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { + const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter); + Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]); + aCopyRad.val = anInitRad.val; + myStorage->updateParameter(aCopyRad); + } + } else if (anInitial.type == SLVS_E_ARC_OF_CIRCLE) { + const Slvs_Entity& aCenterEnt = myStorage->getEntity(anInitial.point[0]); + const Slvs_Entity& aStartEnt = myStorage->getEntity(anInitial.point[1]); + + if (aDiamConstr.empty()) + aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER); + // Calculate diameter of initial arc + double aDiam = 0.0; + for (int i = 0; i < 2; i++) { + double d = myStorage->getParameter(aStartEnt.param[i]).val - + myStorage->getParameter(aCenterEnt.param[i]).val; + aDiam += d * d; + } + aDiam = sqrt(aDiam) * 2.0; + // Update the Diameter constraints of copied arcs + for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { + std::list::iterator aDCIt = aDiamConstr.begin(); + for (; aDCIt != aDiamConstr.end(); ++aDCIt) + if (aDCIt->entityA == *aCopyIter) { + aDCIt->valA = aDiam; + myStorage->updateConstraint(*aDCIt); + aDiamConstr.erase(aDCIt); + break; + } + } + } + } + + myPointsJustUpdated.clear(); +} diff --git a/src/SketchSolver/SketchSolver_ConstraintMulti.h b/src/SketchSolver/SketchSolver_ConstraintMulti.h new file mode 100644 index 000000000..cf2f16d94 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintMulti.h @@ -0,0 +1,83 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintMulti.h +// Created: 2 Sep 2015 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintMulti_H_ +#define SketchSolver_ConstraintMulti_H_ + +#include "SketchSolver.h" +#include + +#include + +/** \class SketchSolver_ConstraintMulti + * \ingroup Plugins + * \brief Common base class for the Multi constraints + */ +class SketchSolver_ConstraintMulti : public SketchSolver_Constraint +{ +public: + SketchSolver_ConstraintMulti(ConstraintPtr theConstraint) : + SketchSolver_Constraint(theConstraint), + myNumberOfObjects(0), + myNumberOfCopies(0) + {} + + virtual int getType() const + { return SLVS_C_UNKNOWN; } + + /// \brief Update constraint + virtual void update(ConstraintPtr theConstraint = ConstraintPtr()); + + /// \brief Tries to remove constraint + /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence) + virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr()); + + /// \brief Adds a feature to constraint and create its analogue in SolveSpace + virtual void addFeature(FeaturePtr theFeature); + +protected: + /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints + virtual void process() + { /* do nothing here */ } + + /// \brief Collect entities and their copies, like circles and arcs + void processEntities(const std::vector< std::vector >& theEntAndCopies); + + /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints + /// \param[out] theValue numerical characteristic of constraint (e.g. distance) + /// \param[out] theAttributes list of attributes to be filled + virtual void getAttributes(double& theValue, std::vector& theAttributes) + { /* do nothing here */ } + + /// \brief This method is used in derived objects to check consistence of constraint. + virtual void adjustConstraint(); + + /// \brief Update parameters of derived classes + virtual void updateLocal() = 0; + + /// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature + virtual const std::string& nameNbCopies() = 0; + +protected: + /// \brief Convert absolute coordinates to relative coordinates + virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY) = 0; + /// \brief Convert relative coordinates to absolute coordinates + virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY) = 0; + /// \brief Apply transformation for relative coordinates + virtual void transformRelative(double& theX, double& theY) = 0; + +protected: + size_t myNumberOfObjects; ///< number of previous initial objects + size_t myNumberOfCopies; ///< number of previous copies of initial objects + + std::vector< std::vector > myPointsAndCopies; ///< list of initial points and their copies + std::vector< std::vector > myCircsAndCopies; ///< list of circles and their copies (to change their radii together) + + std::set myPointsJustUpdated; ///< list of points touched by user + std::set myInitialPoints; ///< list of points containing initial objects +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp index ea4372fa6..da083caf7 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.cpp @@ -16,18 +16,6 @@ #include -static double squareDistance( - StoragePtr theStorage, const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) -{ - Slvs_Entity aPoint1 = theStorage->getEntity(thePoint1); - Slvs_Entity aPoint2 = theStorage->getEntity(thePoint2); - double x1 = theStorage->getParameter(aPoint1.param[0]).val; - double y1 = theStorage->getParameter(aPoint1.param[1]).val; - double x2 = theStorage->getParameter(aPoint2.param[0]).val; - double y2 = theStorage->getParameter(aPoint2.param[1]).val; - return (x1-x2) * (x1-x2) + (y1-y2) * (y1-y2); -} - void SketchSolver_ConstraintMultiRotation::getAttributes( Slvs_hEntity& theCenter, double& theAngle, std::vector< std::vector >& thePoints, @@ -138,131 +126,20 @@ void SketchSolver_ConstraintMultiRotation::process() mySlvsConstraints.push_back(aConstraint.h); } - // Keep all objects unchanged (only initial object may be changed by user) - myCircsAndCopies.clear(); - std::vector >::const_iterator anEntIt = anEntitiesAndCopies.begin(); - std::vector::const_iterator aCpIt; - for (; anEntIt != anEntitiesAndCopies.end(); ++anEntIt) { - std::vector aCircs; - aCpIt = anEntIt->begin(); - // Obtain initial points - Slvs_Entity anInitial = myStorage->getEntity(*aCpIt); - if (anInitial.type == SLVS_E_POINT_IN_2D || anInitial.type == SLVS_E_POINT_IN_3D) - myInitialPoints.insert(anInitial.h); - else { - for (int i = 0; i < 4 && anInitial.point[i] != SLVS_E_UNKNOWN; i++) - myInitialPoints.insert(anInitial.point[i]); - } - - // Fix the copies - for (++aCpIt; aCpIt != anEntIt->end(); ++aCpIt) { - const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt); - std::vector aNewConstr; - if (anEntity.type == SLVS_E_CIRCLE) { - aCircs.push_back(anEntity.distance); - // for circles we fix only center - aNewConstr = myStorage->fixEntity(anEntity.point[0]); - } else - aNewConstr = myStorage->fixEntity(*aCpIt); - if (anEntity.type == SLVS_E_ARC_OF_CIRCLE) - aCircs.push_back(anEntity.h); - mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end()); - } - - if (!aCircs.empty()) { - if (anInitial.type == SLVS_E_CIRCLE) - aCircs.insert(aCircs.begin(), anInitial.distance); - else - aCircs.insert(aCircs.begin(), anInitial.h); - myCircsAndCopies.push_back(aCircs); - } - } - + processEntities(anEntitiesAndCopies); adjustConstraint(); } -void SketchSolver_ConstraintMultiRotation::update(ConstraintPtr theConstraint) +void SketchSolver_ConstraintMultiRotation::updateLocal() { - cleanErrorMsg(); - if (!theConstraint || theConstraint == myBaseConstraint) { - AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast( - myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID()); - if (anInitialRefList->size() != myNumberOfObjects || aNbCopies->value() != myNumberOfCopies) { - remove(myBaseConstraint); - process(); - return; - } - } - // update angle value myAngle = std::dynamic_pointer_cast( myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value(); - - SketchSolver_Constraint::update(); -} - -bool SketchSolver_ConstraintMultiRotation::remove(ConstraintPtr theConstraint) -{ - cleanErrorMsg(); - if (theConstraint && theConstraint != myBaseConstraint) - return false; - bool isFullyRemoved = true; - std::vector::iterator aCIter = mySlvsConstraints.begin(); - for (; aCIter != mySlvsConstraints.end(); aCIter++) - isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved; - mySlvsConstraints.clear(); - - std::map::iterator aFeatIt = myFeatureMap.begin(); - for (; aFeatIt != myFeatureMap.end(); aFeatIt++) - myStorage->removeEntity(aFeatIt->second); - myStorage->removeUnusedEntities(); - - std::map aFeatureMapCopy = myFeatureMap; - - if (isFullyRemoved) { - myFeatureMap.clear(); - myAttributeMap.clear(); - myValueMap.clear(); - } else - cleanRemovedEntities(); - - // Restore initial features - std::map::iterator aFIter = aFeatureMapCopy.begin(); - for (; aFIter != aFeatureMapCopy.end(); ++aFIter) - { - if (myFeatureMap.find(aFIter->first) != myFeatureMap.end()) - continue; // the feature was not removed - Slvs_hEntity anEntity = myGroup->getFeatureId(aFIter->first); - if (anEntity != SLVS_E_UNKNOWN) - myFeatureMap[aFIter->first] = anEntity; - } - - // Clear list of rotated points - myPointsAndCopies.clear(); - myInitialPoints.clear(); - - return true; -} - -void SketchSolver_ConstraintMultiRotation::addFeature(FeaturePtr theFeature) -{ - SketchSolver_Constraint::addFeature(theFeature); - - std::map::iterator aFeatIt = myFeatureMap.find(theFeature); - if (aFeatIt == myFeatureMap.end()) - return; - - // store list of points of the feature - const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second); - for (int i = 0; i < 4; i++) - if (theEntity.point[i] != SLVS_E_UNKNOWN) - myPointsJustUpdated.insert(theEntity.point[i]); } void SketchSolver_ConstraintMultiRotation::adjustConstraint() { - if (abs(myAngle) < tolerance) { + if (fabs(myAngle) < tolerance) { myStorage->setNeedToResolve(false); return; } @@ -290,102 +167,39 @@ void SketchSolver_ConstraintMultiRotation::adjustConstraint() // Obtain coordinates of rotation center Slvs_Entity aRotCenter = myStorage->getEntity(myRotationCenter); - double aCenterXY[2]; - for (int i = 0; i < 2; i++) - aCenterXY[i] = myStorage->getParameter(aRotCenter.param[i]).val; - - double cosA = cos(myAngle * PI / 180.0); - double sinA = sin(myAngle * PI / 180.0); - - double aVec[2]; // coordinates of vector defining a direction from rotation center to a point - - // Update positions of all points to satisfy angles - std::vector< std::vector >::const_iterator aPointsIter = myPointsAndCopies.begin(); - std::vector::const_iterator aCopyIter; - for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) { - aCopyIter = aPointsIter->begin(); - const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); - for (int i = 0; i < 2; i++) - aVec[i] = myStorage->getParameter(anInitial.param[i]).val - aCenterXY[i]; - - // if the point is coincident with another one which is temporary fixed (moved by user), - // we will update its position correspondingly - Slvs_hConstraint aFixed; - for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) { - if ((aCoIt->ptA == anInitial.h && myInitialPoints.find(aCoIt->ptB) != myInitialPoints.end()) || - (aCoIt->ptB == anInitial.h && myInitialPoints.find(aCoIt->ptA) != myInitialPoints.end())) { - Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA; - if (!myStorage->isTemporary(aFixed) && - myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end()) - continue; // nothing to change + myCenterCoord[0] = myStorage->getParameter(aRotCenter.param[0]).val; + myCenterCoord[1] = myStorage->getParameter(aRotCenter.param[1]).val; - const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId); - for (int i = 0; i < 2; i++) { - Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]); - const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]); - anInitParam.val = anOtherParam.val; - myStorage->updateParameter(anInitParam); - aVec[i] = anOtherParam.val - aCenterXY[i]; - } - } - } + myRotationVal[0] = sin(myAngle * PI / 180.0); + myRotationVal[1] = cos(myAngle * PI / 180.0); - // update copied points - aCopyIter = aPointsIter->begin(); - for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { - // rotate direction - double aTemp = aVec[0] * cosA - aVec[1] * sinA; - aVec[1] = aVec[0] * sinA + aVec[1] * cosA; - aVec[0] = aTemp; + SketchSolver_ConstraintMulti::adjustConstraint(); +} - const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter); - for (int i = 0; i < 2; i++) { - Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]); - aParam.val = aCenterXY[i] + aVec[i]; - myStorage->updateParameter(aParam); - } - } - } +void SketchSolver_ConstraintMultiRotation::getRelative( + double theAbsX, double theAbsY, double& theRelX, double& theRelY) +{ + theRelX = theAbsX - myCenterCoord[0]; + theRelY = theAbsY - myCenterCoord[1]; +} - std::list aDiamConstr; - for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) { - aCopyIter = aPointsIter->begin(); - const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); - if (anInitial.type == SLVS_E_DISTANCE) { - const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]); - for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { - const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter); - Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]); - aCopyRad.val = anInitRad.val; - myStorage->updateParameter(aCopyRad); - } - } else if (anInitial.type == SLVS_E_ARC_OF_CIRCLE) { - const Slvs_Entity& aCenterEnt = myStorage->getEntity(anInitial.point[0]); - const Slvs_Entity& aStartEnt = myStorage->getEntity(anInitial.point[1]); +void SketchSolver_ConstraintMultiRotation::getAbsolute( + double theRelX, double theRelY, double& theAbsX, double& theAbsY) +{ + theAbsX = theRelX + myCenterCoord[0]; + theAbsY = theRelY + myCenterCoord[1]; +} - if (aDiamConstr.empty()) - aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER); - // Calculate diameter of initial arc - double aDiam = 0.0; - for (int i = 0; i < 2; i++) { - double d = myStorage->getParameter(aStartEnt.param[i]).val - - myStorage->getParameter(aCenterEnt.param[i]).val; - aDiam += d * d; - } - aDiam = sqrt(aDiam) * 2.0; - // Update the Diameter constraints of copied arcs - for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { - std::list::iterator aDCIt = aDiamConstr.begin(); - for (; aDCIt != aDiamConstr.end(); ++aDCIt) - if (aDCIt->entityA == *aCopyIter) { - aDCIt->valA = aDiam; - myStorage->updateConstraint(*aDCIt); - aDiamConstr.erase(aDCIt); - break; - } - } - } - } +void SketchSolver_ConstraintMultiRotation::transformRelative(double& theX, double& theY) +{ + // rotate direction + // myRotationVal[0] = sinA, myRotationVal[1] = cosA + double aTemp = theX * myRotationVal[1] - theY * myRotationVal[0]; + theY = theX * myRotationVal[0] + theY * myRotationVal[1]; + theX = aTemp; +} - myPointsJustUpdated.clear(); +const std::string& SketchSolver_ConstraintMultiRotation::nameNbCopies() +{ + return SketchPlugin_MultiRotation::NUMBER_OF_COPIES_ID(); } diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.h b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.h index 3294112dd..94355ba5b 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiRotation.h +++ b/src/SketchSolver/SketchSolver_ConstraintMultiRotation.h @@ -8,46 +8,26 @@ #define SketchSolver_ConstraintMultiRotation_H_ #include "SketchSolver.h" -#include - -#include +#include /** \class SketchSolver_ConstraintMultiRotation * \ingroup Plugins * \brief Convert rotated features to the list of SolveSpace constraints */ -class SketchSolver_ConstraintMultiRotation : public SketchSolver_Constraint +class SketchSolver_ConstraintMultiRotation : public SketchSolver_ConstraintMulti { public: SketchSolver_ConstraintMultiRotation(ConstraintPtr theConstraint) : - SketchSolver_Constraint(theConstraint), - myNumberOfObjects(0), - myNumberOfCopies(0) + SketchSolver_ConstraintMulti(theConstraint) {} virtual int getType() const { return SLVS_C_MULTI_ROTATION; } - /// \brief Update constraint - virtual void update(ConstraintPtr theConstraint = ConstraintPtr()); - - /// \brief Tries to remove constraint - /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence) - virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr()); - - /// \brief Adds a feature to constraint and create its analogue in SolveSpace - virtual void addFeature(FeaturePtr theFeature); - protected: /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints virtual void process(); - /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints - /// \param[out] theValue numerical characteristic of constraint (e.g. distance) - /// \param[out] theAttributes list of attributes to be filled - virtual void getAttributes(double& theValue, std::vector& theAttributes) - { /* do nothing here */ } - /// \brief Generate list of rotated entities /// \param[out] theCenter ID of central point of rotation /// \param[out] theAngle rotation angle @@ -60,16 +40,27 @@ protected: /// \brief This method is used in derived objects to check consistence of constraint. virtual void adjustConstraint(); + /// \brief Update parameters (called from base class) + virtual void updateLocal(); + +private: + /// \brief Convert absolute coordinates to relative coordinates + virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY); + /// \brief Convert relative coordinates to absolute coordinates + virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY); + /// \brief Apply transformation for relative coordinates + virtual void transformRelative(double& theX, double& theY); + +private: + /// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature + virtual const std::string& nameNbCopies(); + private: - size_t myNumberOfObjects; ///< number of previous initial objects - size_t myNumberOfCopies; ///< number of previous copies of initial objects Slvs_hEntity myRotationCenter; ///< ID of center of rotation - double myAngle; ///< angle of rotation - std::vector< std::vector > myPointsAndCopies; ///< list of initial points and their rotated copies - std::vector< std::vector > myCircsAndCopies; ///< list of circles and their copies (to change their radii together) + double myAngle; ///< angle of rotation - std::set myPointsJustUpdated; ///< list of points touched by user - std::set myInitialPoints; ///< list of points containig initial objects + double myCenterCoord[2]; ///< coordinates of rotation center + double myRotationVal[2]; ///< sinus and cosinus of rotation angle }; #endif diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp index eb6b61e43..816aa8fcc 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp @@ -138,119 +138,10 @@ void SketchSolver_ConstraintMultiTranslation::process() } } - // Keep all objects unchanged (only initial object may be changed by user) - myCircsAndCopies.clear(); - std::vector >::const_iterator anEntIt = anEntitiesAndCopies.begin(); - std::vector::const_iterator aCpIt; - for (; anEntIt != anEntitiesAndCopies.end(); ++anEntIt) { - std::vector aCircs; - aCpIt = anEntIt->begin(); - // Obtain initial points - Slvs_Entity anInitial = myStorage->getEntity(*aCpIt); - if (anInitial.type == SLVS_E_POINT_IN_2D || anInitial.type == SLVS_E_POINT_IN_3D) - myInitialPoints.insert(anInitial.h); - else { - for (int i = 0; i < 4 && anInitial.point[i] != SLVS_E_UNKNOWN; i++) - myInitialPoints.insert(anInitial.point[i]); - } - - // Fix the copies - for (++aCpIt; aCpIt != anEntIt->end(); ++aCpIt) { - const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt); - std::vector aNewConstr; - if (anEntity.type == SLVS_E_CIRCLE) { - aCircs.push_back(anEntity.distance); - // for circles we fix only center - aNewConstr = myStorage->fixEntity(anEntity.point[0]); - } else - aNewConstr = myStorage->fixEntity(*aCpIt); - if (anEntity.type == SLVS_E_ARC_OF_CIRCLE) - aCircs.push_back(anEntity.h); - mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end()); - } - - if (!aCircs.empty()) { - if (anInitial.type == SLVS_E_CIRCLE) - aCircs.insert(aCircs.begin(), anInitial.distance); - else - aCircs.insert(aCircs.begin(), anInitial.h); - myCircsAndCopies.push_back(aCircs); - } - } - + processEntities(anEntitiesAndCopies); adjustConstraint(); } -void SketchSolver_ConstraintMultiTranslation::update(ConstraintPtr theConstraint) -{ - cleanErrorMsg(); - if (!theConstraint || theConstraint == myBaseConstraint) { - AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast( - myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); - AttributeIntegerPtr aNbCopies = myBaseConstraint->integer(SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID()); - if (anInitialRefList->size() != myNumberOfObjects || - (size_t)aNbCopies->value() != myNumberOfCopies) { - remove(myBaseConstraint); - process(); - return; - } - } - SketchSolver_Constraint::update(); -} - -bool SketchSolver_ConstraintMultiTranslation::remove(ConstraintPtr theConstraint) -{ - cleanErrorMsg(); - if (theConstraint && theConstraint != myBaseConstraint) - return false; - bool isFullyRemoved = true; - std::vector::iterator aCIter = mySlvsConstraints.begin(); - for (; aCIter != mySlvsConstraints.end(); aCIter++) - isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved; - mySlvsConstraints.clear(); - - std::map::iterator aFeatIt = myFeatureMap.begin(); - for (; aFeatIt != myFeatureMap.end(); aFeatIt++) - myStorage->removeEntity(aFeatIt->second); - - std::map aFeatureMapCopy = myFeatureMap; - - if (isFullyRemoved) { - myFeatureMap.clear(); - myAttributeMap.clear(); - myValueMap.clear(); - } else - cleanRemovedEntities(); - - // Restore initial features - std::map::iterator aFIter = aFeatureMapCopy.begin(); - for (; aFIter != aFeatureMapCopy.end(); ++aFIter) - { - if (myFeatureMap.find(aFIter->first) != myFeatureMap.end()) - continue; // the feature was not removed - Slvs_hEntity anEntity = myGroup->getFeatureId(aFIter->first); - if (anEntity != SLVS_E_UNKNOWN) - myFeatureMap[aFIter->first] = anEntity; - } - - return true; -} - -void SketchSolver_ConstraintMultiTranslation::addFeature(FeaturePtr theFeature) -{ - SketchSolver_Constraint::addFeature(theFeature); - - std::map::iterator aFeatIt = myFeatureMap.find(theFeature); - if (aFeatIt == myFeatureMap.end()) - return; - - // store list of points of the feature - const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second); - for (int i = 0; i < 4; i++) - if (theEntity.point[i] != SLVS_E_UNKNOWN) - myPointsJustUpdated.insert(theEntity.point[i]); -} - void SketchSolver_ConstraintMultiTranslation::adjustConstraint() { Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine); @@ -273,103 +164,38 @@ void SketchSolver_ConstraintMultiTranslation::adjustConstraint() aXY[2*i] = myStorage->getParameter(aPnt.param[0]).val; aXY[2*i+1] = myStorage->getParameter(aPnt.param[1]).val; } - double aDelta[2] = {aXY[2] - aXY[0], aXY[3] - aXY[1]}; - if (fabs(aDelta[0]) + fabs(aDelta[1]) < tolerance) { + myDelta[0] = aXY[2] - aXY[0]; + myDelta[1] = aXY[3] - aXY[1]; + if (fabs(myDelta[0]) + fabs(myDelta[1]) < tolerance) { myStorage->setNeedToResolve(false); return; } - std::list aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT); - std::list::const_iterator aCoIt; - - double aCoord[2]; - - // Update positions of all points to satisfy distances - std::vector< std::vector >::const_iterator aPointsIter = myPointsAndCopies.begin(); - std::vector::const_iterator aCopyIter; - for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) { - aCopyIter = aPointsIter->begin(); - const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); - for (int i = 0; i < 2; i++) - aCoord[i] = myStorage->getParameter(anInitial.param[i]).val; - - // if the point is coincident with another one which is temporary fixed (moved by user), - // we will update its position correspondingly - Slvs_hConstraint aFixed; - for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) { - if ((aCoIt->ptA == anInitial.h && myInitialPoints.find(aCoIt->ptB) != myInitialPoints.end()) || - (aCoIt->ptB == anInitial.h && myInitialPoints.find(aCoIt->ptA) != myInitialPoints.end())) { - Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA; - if (!myStorage->isTemporary(aFixed) && - myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end()) - continue; // nothing to change - - const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId); - for (int i = 0; i < 2; i++) { - Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]); - const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]); - anInitParam.val = anOtherParam.val; - myStorage->updateParameter(anInitParam); - aCoord[i] = anOtherParam.val; - } - } - } - - // update copied points - aCopyIter = aPointsIter->begin(); - for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { - // update position - aCoord[0] += aDelta[0]; - aCoord[1] += aDelta[1]; + SketchSolver_ConstraintMulti::adjustConstraint(); +} - const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter); - for (int i = 0; i < 2; i++) { - Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]); - aParam.val = aCoord[i]; - myStorage->updateParameter(aParam); - } - } - } +void SketchSolver_ConstraintMultiTranslation::getRelative( + double theAbsX, double theAbsY, double& theRelX, double& theRelY) +{ + theRelX = theAbsX; + theRelY = theAbsY; +} - std::list aDiamConstr; - for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) { - aCopyIter = aPointsIter->begin(); - const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); - if (anInitial.type == SLVS_E_DISTANCE) { - const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]); - for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { - const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter); - Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]); - aCopyRad.val = anInitRad.val; - myStorage->updateParameter(aCopyRad); - } - } else if (anInitial.type == SLVS_E_ARC_OF_CIRCLE) { - const Slvs_Entity& aCenterEnt = myStorage->getEntity(anInitial.point[0]); - const Slvs_Entity& aStartEnt = myStorage->getEntity(anInitial.point[1]); +void SketchSolver_ConstraintMultiTranslation::getAbsolute( + double theRelX, double theRelY, double& theAbsX, double& theAbsY) +{ + theAbsX = theRelX; + theAbsY = theRelY; +} - if (aDiamConstr.empty()) - aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER); - // Calculate diameter of initial arc - double aDiam = 0.0; - for (int i = 0; i < 2; i++) { - double d = myStorage->getParameter(aStartEnt.param[i]).val - - myStorage->getParameter(aCenterEnt.param[i]).val; - aDiam += d * d; - } - aDiam = sqrt(aDiam) * 2.0; - // Update the Diameter constraints of copied arcs - for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { - std::list::iterator aDCIt = aDiamConstr.begin(); - for (; aDCIt != aDiamConstr.end(); ++aDCIt) - if (aDCIt->entityA == *aCopyIter) { - aDCIt->valA = aDiam; - myStorage->updateConstraint(*aDCIt); - aDiamConstr.erase(aDCIt); - break; - } - } - } - } +void SketchSolver_ConstraintMultiTranslation::transformRelative(double& theX, double& theY) +{ + // translate coordinates + theX += myDelta[0]; + theY += myDelta[1]; +} - myPointsJustUpdated.clear(); +const std::string& SketchSolver_ConstraintMultiTranslation::nameNbCopies() +{ + return SketchPlugin_MultiTranslation::NUMBER_OF_COPIES_ID(); } diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h index 10d44dbf1..68c4fbcb8 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h +++ b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h @@ -8,45 +8,27 @@ #define SketchSolver_ConstraintMultiTranslation_H_ #include "SketchSolver.h" -#include +#include /** \class SketchSolver_ConstraintMultiTranslation * \ingroup Plugins * \brief Convert translated features to the list of SolveSpace constraints */ -class SketchSolver_ConstraintMultiTranslation : public SketchSolver_Constraint +class SketchSolver_ConstraintMultiTranslation : public SketchSolver_ConstraintMulti { public: SketchSolver_ConstraintMultiTranslation(ConstraintPtr theConstraint) : - SketchSolver_Constraint(theConstraint), - myNumberOfObjects(0), - myNumberOfCopies(0), + SketchSolver_ConstraintMulti(theConstraint), myTranslationLine(SLVS_E_UNKNOWN) {} virtual int getType() const { return SLVS_C_MULTI_TRANSLATION; } - /// \brief Update constraint - virtual void update(ConstraintPtr theConstraint = ConstraintPtr()); - - /// \brief Tries to remove constraint - /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence) - virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr()); - - /// \brief Adds a feature to constraint and create its analogue in SolveSpace - virtual void addFeature(FeaturePtr theFeature); - protected: /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints virtual void process(); - /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints - /// \param[out] theValue numerical characteristic of constraint (e.g. distance) - /// \param[out] theAttributes list of attributes to be filled - virtual void getAttributes(double& theValue, std::vector& theAttributes) - { /* do nothing here */ } - /// \brief Generate list of translated entities /// \param[out] theStartPoint ID of start point of translation /// \param[out] theEndPoint ID of final point of translation @@ -59,15 +41,26 @@ protected: /// \brief This method is used in derived objects to check consistence of constraint. virtual void adjustConstraint(); + /// \brief Update parameters (called from base class) + virtual void updateLocal() + {} + +private: + /// \brief Convert absolute coordinates to relative coordinates + virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY); + /// \brief Convert relative coordinates to absolute coordinates + virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY); + /// \brief Apply transformation for relative coordinates + virtual void transformRelative(double& theX, double& theY); + +private: + /// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature + virtual const std::string& nameNbCopies(); + private: - size_t myNumberOfObjects; ///< number of previous initial objects - size_t myNumberOfCopies; ///< number of previous copies of initial objects Slvs_hEntity myTranslationLine; ///< ID of translation line - std::vector< std::vector > myPointsAndCopies; ///< list of initial points and their translated copies - std::vector< std::vector > myCircsAndCopies; ///< list of circles and their copies (to change their radii together) - std::set myPointsJustUpdated; ///< list of points touched by user - std::set myInitialPoints; ///< list of points containig initial objects + double myDelta[2]; ///< increment of translation }; #endif