From: azv Date: Mon, 14 Sep 2015 15:35:44 +0000 (+0300) Subject: There is implemented fixed constraint for the points which coordinates are given... X-Git-Tag: V_1.4.0~71 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=b1b810161662f4976b2ed5aafe8cfdc1e6112002;p=modules%2Fshaper.git There is implemented fixed constraint for the points which coordinates are given by parametric expression (issues #966, #967) --- diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index 97441526b..126fb212e 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -21,6 +21,7 @@ SET(PROJECT_HEADERS SketchSolver_ConstraintMultiRotation.h SketchSolver_ConstraintMultiTranslation.h SketchSolver_ConstraintMovement.h + SketchSolver_ConstraintParametric.h SketchSolver_Builder.h SketchSolver_Group.h SketchSolver_ConstraintManager.h @@ -43,6 +44,7 @@ SET(PROJECT_SOURCES SketchSolver_ConstraintMulti.cpp SketchSolver_ConstraintMultiRotation.cpp SketchSolver_ConstraintMultiTranslation.cpp + SketchSolver_ConstraintParametric.cpp SketchSolver_ConstraintMovement.cpp SketchSolver_Builder.cpp SketchSolver_Group.cpp diff --git a/src/SketchSolver/SketchSolver_Builder.cpp b/src/SketchSolver/SketchSolver_Builder.cpp index f491471df..78bfc59bb 100644 --- a/src/SketchSolver/SketchSolver_Builder.cpp +++ b/src/SketchSolver/SketchSolver_Builder.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -151,6 +152,11 @@ SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr th return SolverConstraintPtr(new SketchSolver_ConstraintMovement(theFixedFeature)); } +SolverConstraintPtr SketchSolver_Builder::createParametricConstraint(AttributePtr theAttribute) +{ + return SolverConstraintPtr(new SketchSolver_ConstraintParametric(theAttribute)); +} + bool SketchSolver_Builder::createWorkplane( diff --git a/src/SketchSolver/SketchSolver_Builder.h b/src/SketchSolver/SketchSolver_Builder.h index 1fd353f85..21beac319 100644 --- a/src/SketchSolver/SketchSolver_Builder.h +++ b/src/SketchSolver/SketchSolver_Builder.h @@ -38,6 +38,9 @@ public: /// \brief Creates temporary constraint to fix the feature after movement SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature); + /// \brief Creates constraint for parametrically given attribute + SolverConstraintPtr createParametricConstraint(AttributePtr theAttribute); + /// \brief Converts sketch parameters to the list of SolveSpace entities. /// Identifiers of entities and parameters are local. They should be changed while adding into storage. /// The sketch entity goes last. diff --git a/src/SketchSolver/SketchSolver_ConstraintParametric.cpp b/src/SketchSolver/SketchSolver_ConstraintParametric.cpp new file mode 100644 index 000000000..29147d76f --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintParametric.cpp @@ -0,0 +1,166 @@ +#include +#include +#include + +#include + +SketchSolver_ConstraintParametric::SketchSolver_ConstraintParametric(AttributePtr theAttribute) + : SketchSolver_ConstraintRigid(ConstraintPtr()), + myBaseAttribute(theAttribute) +{ + process(); +} + +void SketchSolver_ConstraintParametric::process() +{ + cleanErrorMsg(); + if (!myBaseAttribute || !myStorage || myGroup == 0) { + /// TODO: Put error message here + return; + } + if (!mySlvsConstraints.empty()) // some data is changed, update constraint + update(myBaseConstraint); + + Slvs_hEntity anAttrID; + getAttributes(anAttrID); + if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty())) + return; + + myHorizLineID = SLVS_E_UNKNOWN; + myVertLineID = SLVS_E_UNKNOWN; + + std::shared_ptr aPoint = + std::dynamic_pointer_cast(myBaseAttribute); + if (!aPoint) + return; + if (!aPoint->textX().empty()) { + // Create vertical line with fixed boundary point + Slvs_Param aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), aPoint->x()); + Slvs_Param aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), -10000.0); + aParX.h = myStorage->addParameter(aParX); + aParY.h = myStorage->addParameter(aParY); + Slvs_Entity aStartPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(), + myGroup->getWorkplaneId(), aParX.h, aParY.h); + aStartPoint.h = myStorage->addEntity(aStartPoint); + Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(), + myGroup->getWorkplaneId(), aStartPoint.h, anAttrID); + aLine.h = myStorage->addEntity(aLine); + + // Fix start point + fixPoint(aStartPoint.h); + // Add vertical constraint + Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), + SLVS_C_VERTICAL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, + aLine.h, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + myVertLineID = aLine.h; + myX = aPoint->x(); + } + if (!aPoint->textY().empty()) { + // Create horizontal line with fixed boundary point + Slvs_Param aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), -10000.0); + Slvs_Param aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), aPoint->y()); + aParX.h = myStorage->addParameter(aParX); + aParY.h = myStorage->addParameter(aParY); + Slvs_Entity aStartPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(), + myGroup->getWorkplaneId(), aParX.h, aParY.h); + aStartPoint.h = myStorage->addEntity(aStartPoint); + Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(), + myGroup->getWorkplaneId(), aStartPoint.h, anAttrID); + aLine.h = myStorage->addEntity(aLine); + + // Fix start point + fixPoint(aStartPoint.h); + // Add horizontal constraint + Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), + SLVS_C_HORIZONTAL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, + aLine.h, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + myHorizLineID = aLine.h; + myY = aPoint->y(); + } +} + + +void SketchSolver_ConstraintParametric::getAttributes(Slvs_hEntity& theAttributeID) +{ + int aType = SLVS_E_UNKNOWN; // type of created entity + theAttributeID = SLVS_E_UNKNOWN; + theAttributeID = myGroup->getAttributeId(myBaseAttribute); + if (theAttributeID == SLVS_E_UNKNOWN) { + theAttributeID = changeEntity(myBaseAttribute, aType); + if (theAttributeID == SLVS_E_UNKNOWN) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; + } + } + else + myAttributeMap[myBaseAttribute] = theAttributeID; +} + + +void SketchSolver_ConstraintParametric::update(ConstraintPtr theConstraint) +{ + cleanErrorMsg(); + if (!theConstraint || theConstraint == myBaseConstraint) { + std::shared_ptr aPoint = + std::dynamic_pointer_cast(myBaseAttribute); + if (aPoint && ((!aPoint->textX().empty() && myVertLineID != SLVS_E_UNKNOWN) || + (!aPoint->textY().empty() && myHorizLineID != SLVS_E_UNKNOWN))) { + remove(); + process(); + return; + } + } + adjustConstraint(); +} + +void SketchSolver_ConstraintParametric::refresh() +{ + Slvs_hEntity aBasePointID = myAttributeMap[myBaseAttribute]; + const Slvs_Entity& aBasePoint = myStorage->getEntity(aBasePointID); + double aXY[2]; + aXY[0] = myVertLineID != SLVS_E_UNKNOWN ? myX : myStorage->getParameter(aBasePoint.param[0]).val; + aXY[1] = myHorizLineID != SLVS_E_UNKNOWN ? myY : myStorage->getParameter(aBasePoint.param[1]).val; + + std::list aCoincidence = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT); + std::list::const_iterator aCIt = aCoincidence.begin(); + for (; aCIt != aCoincidence.end(); ++aCIt) { + if (aCIt->ptA != aBasePointID && aCIt->ptB != aBasePointID) + continue; + Slvs_hEntity anOtherPointID = aCIt->ptA == aBasePointID ? aCIt->ptB : aCIt->ptA; + const Slvs_Entity& aPoint = myStorage->getEntity(anOtherPointID); + for (int i = 0; i < 2; i++) { + Slvs_Param aParam = myStorage->getParameter(aPoint.param[i]); + aParam.val = aXY[i]; + myStorage->updateParameter(aParam); + } + } +} + +void SketchSolver_ConstraintParametric::adjustConstraint() +{ + std::shared_ptr aPoint = + std::dynamic_pointer_cast(myBaseAttribute); + if (!aPoint) + return; + + if (!aPoint->textX().empty()) { + const Slvs_Entity& aLine = myStorage->getEntity(myVertLineID); + const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]); + Slvs_Param aParX = myStorage->getParameter(aStartPoint.param[0]); + aParX.val = aPoint->x(); + myStorage->updateParameter(aParX); + myX = aParX.val; + } + if (!aPoint->textY().empty()) { + const Slvs_Entity& aLine = myStorage->getEntity(myHorizLineID); + const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]); + Slvs_Param aParY = myStorage->getParameter(aStartPoint.param[1]); + aParY.val = aPoint->y(); + myStorage->updateParameter(aParY); + myY = aParY.val; + } +} diff --git a/src/SketchSolver/SketchSolver_ConstraintParametric.h b/src/SketchSolver/SketchSolver_ConstraintParametric.h new file mode 100644 index 000000000..61eb3e72e --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintParametric.h @@ -0,0 +1,54 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintParametric.h +// Created: 15 Jun 2015 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintParametric_H_ +#define SketchSolver_ConstraintParametric_H_ + +#include "SketchSolver.h" +#include + +/** \class SketchSolver_ConstraintParametric + * \ingroup Plugins + * \brief Stores data of Rigid (Fixed) constraint for the attribute + * which coordinates are given by parametric expression + */ +class SketchSolver_ConstraintParametric : public SketchSolver_ConstraintRigid +{ +private: + /// Creates constraint to manage the given constraint from plugin + SketchSolver_ConstraintParametric() + : SketchSolver_ConstraintRigid(ConstraintPtr()) + {} + +public: + /// Creates temporary constraint based on feature + SketchSolver_ConstraintParametric(AttributePtr theAttribute); + + /// \brief Update constraint + virtual void update(ConstraintPtr theConstraint = ConstraintPtr()); + + /// \brief Update points coincident with parametric one + virtual void refresh(); + +protected: + /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints + virtual void process(); + + /// \brief Convert attribute to the entity + /// \param[out] theAttributeID identifier of the entity related to the attribute + virtual void getAttributes(Slvs_hEntity& theAttributeID); + + /// \brief This method is used in derived objects to check consistence of constraint. + virtual void adjustConstraint(); + +private: + AttributePtr myBaseAttribute; ///< attribute given by expression + Slvs_hEntity myHorizLineID; ///< identifier of horizontal line, containing the point + Slvs_hEntity myVertLineID; ///< identifier of vertical line, containing the point + double myX, myY; +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 8b4026ef2..0e636f7df 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -209,7 +209,7 @@ bool SketchSolver_Group::changeConstraint( if (myWorkplaneID == SLVS_E_UNKNOWN) return false; - if (!theConstraint) + if (!theConstraint || !theConstraint->data()) return false; if (!checkFeatureValidity(theConstraint)) @@ -298,6 +298,34 @@ bool SketchSolver_Group::changeConstraint( myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage); myFeatureStorage->changeConstraint(theConstraint); + // Check the attributes of constraint are given by parametric expression + std::list anAttributes = + theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + std::list::iterator anAttrIt = anAttributes.begin(); + for (; anAttrIt != anAttributes.end(); ++anAttrIt) { + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(*anAttrIt); + if (!aRefAttr || aRefAttr->isObject()) + continue; + std::shared_ptr aPoint = + std::dynamic_pointer_cast(aRefAttr->attr()); + if (!aPoint || (aPoint->textX().empty() && aPoint->textY().empty())) + continue; + + std::map::iterator aFound = + myParametricConstraints.find(aRefAttr->attr()); + if (aFound == myParametricConstraints.end()) { + SolverConstraintPtr aConstraint = + SketchSolver_Builder::getInstance()->createParametricConstraint(aRefAttr->attr()); + if (!aConstraint) + continue; + aConstraint->setGroup(this); + aConstraint->setStorage(myStorage); + myParametricConstraints[aRefAttr->attr()] = aConstraint; + } else + aFound->second->update(); + } + return true; } @@ -345,6 +373,20 @@ bool SketchSolver_Group::updateFeature(std::shared_ptr the aSolConIter->second->addFeature(theFeature); myChangedConstraints.insert(aSolConIter->first); } + + // Search attributes of the feature in the set of parametric constraints and update them + std::list anAttrList = + theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + std::list::iterator anAttrIt = anAttrList.begin(); + for (; anAttrIt != anAttrList.end(); ++anAttrIt) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(*anAttrIt); + if (!aRefAttr || aRefAttr->isObject()) + continue; + std::map::iterator aFound = + myParametricConstraints.find(aRefAttr->attr()); + if (aFound != myParametricConstraints.end()) + aFound->second->update(); + } return true; } @@ -525,8 +567,13 @@ bool SketchSolver_Group::resolveConstraints() } if (aResult == SLVS_RESULT_OKAY) { // solution succeeded, store results into correspondent attributes myFeatureStorage->blockEvents(true); + // First refresh parametric constraints to satisfy parameters + std::map::iterator aParIter = myParametricConstraints.begin(); + for (; aParIter != myParametricConstraints.end(); ++aParIter) + aParIter->second->refresh(); + // Update all other constraints ConstraintConstraintMap::iterator aConstrIter = myConstraints.begin(); - for (; aConstrIter != myConstraints.end(); aConstrIter++) + for (; aConstrIter != myConstraints.end(); ++aConstrIter) aConstrIter->second->refresh(); myFeatureStorage->blockEvents(false); if (!myPrevSolved) { diff --git a/src/SketchSolver/SketchSolver_Group.h b/src/SketchSolver/SketchSolver_Group.h index 79181c382..6c842caef 100644 --- a/src/SketchSolver/SketchSolver_Group.h +++ b/src/SketchSolver/SketchSolver_Group.h @@ -175,6 +175,7 @@ private: CompositeFeaturePtr mySketch; ///< Sketch is equivalent to workplane ConstraintConstraintMap myConstraints; ///< List of constraints std::set myTempConstraints; ///< List of temporary constraints + std::map myParametricConstraints; ///< List of parametric constraints std::set myChangedConstraints; ///< List of just updated constraints StoragePtr myStorage; ///< Container for the set of SolveSpace constraints and their entities