X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_Constraint.cpp;h=96051c3d01128d11ef79f375f255acb67cfaaabd;hb=68a3f0934001109743353b6cc2ac42d8b92bd868;hp=67a177038088fffb546b35af925fa8483aab67e6;hpb=8dfbb935d2eac7b77029d1f090b84840ff27d612;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index 67a177038..96051c3d0 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -1,225 +1,225 @@ -// File: SketchSolver_Constraint.cpp -// Created: 27 May 2014 -// Author: Artem ZHIDKOV - -#include "SketchSolver_Constraint.h" -#include +#include +#include +#include +#include +#include +#include #include #include -#include -#include + +#include +#include #include +#include +#include #include +#include #include #include #include +#include +#include +#include -#include -#include - +#include #include #include +#include +#include +#include -SketchSolver_Constraint::SketchSolver_Constraint() - : myConstraint(boost::shared_ptr()), - myType(SLVS_C_UNKNOWN), - myAttributesList() +SketchSolver_Constraint::SketchSolver_Constraint( + ConstraintPtr theConstraint) + : myBaseConstraint(theConstraint), + myGroupID(GID_UNKNOWN), + myType(CONSTRAINT_UNKNOWN) { } -SketchSolver_Constraint::SketchSolver_Constraint( - boost::shared_ptr theConstraint) - : myConstraint(theConstraint), - myAttributesList() +void SketchSolver_Constraint::process(StoragePtr theStorage, + const GroupID& theGroupID, + const EntityID& theSketchID) +{ + myStorage = theStorage; + myGroupID = theGroupID; + mySketchID = theSketchID; + // Process constraint according to its type + process(); +} + + +SketchSolver_ConstraintType SketchSolver_Constraint::TYPE(ConstraintPtr theConstraint) { - myType = getType(myConstraint); + const std::string& aType = theConstraint->getKind(); + if (aType == SketchPlugin_ConstraintCoincidence::ID()) + return CONSTRAINT_COINCIDENCE; + else if (aType == SketchPlugin_ConstraintRigid::ID()) + return CONSTRAINT_FIXED; + else if (aType == SketchPlugin_ConstraintHorizontal::ID()) + return CONSTRAINT_HORIZONTAL; + else if (aType == SketchPlugin_ConstraintVertical::ID()) + return CONSTRAINT_VERTICAL; + else if (aType == SketchPlugin_ConstraintAngle::ID()) + return CONSTRAINT_ANGLE; + else if (aType == SketchPlugin_ConstraintDistance::ID()) + return CONSTRAINT_DISTANCE; + else if (aType == SketchPlugin_ConstraintEqual::ID()) + return CONSTRAINT_EQUAL; + else if (aType == SketchPlugin_ConstraintLength::ID()) + return CONSTRAINT_PT_PT_DISTANCE; + else if (aType == SketchPlugin_ConstraintMirror::ID()) + return CONSTRAINT_SYMMETRIC; + else if (aType == SketchPlugin_ConstraintParallel::ID()) + return CONSTRAINT_PARALLEL; + else if (aType == SketchPlugin_ConstraintPerpendicular::ID()) + return CONSTRAINT_PERPENDICULAR; + else if (aType == SketchPlugin_ConstraintRadius::ID()) + return CONSTRAINT_RADIUS; + else if (aType == SketchPlugin_ConstraintTangent::ID()) + return CONSTRAINT_TANGENT; + return CONSTRAINT_UNKNOWN; } -const int& SketchSolver_Constraint::getType(boost::shared_ptr theConstraint) +void SketchSolver_Constraint::process() { - myType = SLVS_C_UNKNOWN; - if (!theConstraint) - return getType(); - - // Assign empty names of attributes - myAttributesList.clear(); - for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++) - myAttributesList.push_back(std::string()); - - const std::string& aConstraintKind = theConstraint->getKind(); - // Constraint for coincidence of two points - if (aConstraintKind.compare("SketchConstraintCoincidence") == 0) - { - int anAttrPos = 0; - // Verify the constraint has only two attributes and they are points - int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point - int aPt3d = 0; // bit-mapped field, the same information for 3D points - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr) continue; - // Verify the attribute is a 2D point - boost::shared_ptr aPoint2D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint2D) - { - aPt2d |= (1 << indAttr); - myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - // Verify the attribute is a 3D point - boost::shared_ptr aPoint3D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint3D) - { - aPt3d |= (1 << indAttr); - myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - // Attribute neither 2D nor 3D point is not supported by this type of constraint - return getType(); - } - // The constrained points should be in first and second positions, - // so the expected value of aPt2d or aPt3d is 3 - if ((aPt2d == 3 && aPt3d == 0) || (aPt2d == 0 && aPt3d == 3)) - myType = SLVS_C_POINTS_COINCIDENT; - // Constraint parameters are wrong - return getType(); + cleanErrorMsg(); + if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) { + // Not enough parameters are assigned + return; } - // Constraint for distance between point and another entity - if (aConstraintKind.compare(SKETCH_CONSTRAINT_DISTANCE_KIND) == 0) - { - int aNbPoints = 0; - int aNbEntities = 0; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr) continue; - if (anAttr->isFeature() && anAttr->feature()) - { // verify posiible entities - const std::string& aKind = anAttr->feature()->getKind(); - if (aKind.compare(SKETCH_POINT_KIND) == 0) - { - myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - else if(aKind.compare(SKETCH_LINE_KIND) == 0) - { - // entities are placed starting from CONSTRAINT_ATTR_ENTITY_C attribute - myAttributesList[2 + aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; - myType = SLVS_C_PT_LINE_DISTANCE; - continue; - } - } - else - { // verify points - // Verify the attribute is a 2D point - boost::shared_ptr aPoint2D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint2D) - { - myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - // Verify the attribute is a 3D point - boost::shared_ptr aPoint3D = - boost::dynamic_pointer_cast(anAttr->attr()); - if (aPoint3D) - { - myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } - } - } - // Verify the correctness of constraint arguments - if (aNbPoints == 2 && aNbEntities ==0) - myType = SLVS_C_PT_PT_DISTANCE; - else if (aNbPoints == 1 && aNbEntities == 1) - myType = SLVS_C_UNKNOWN; - return getType(); + SketchSolver_ConstraintType aConstrType = getType(); + double aValue; + std::vector anAttributes; + getAttributes(aValue, anAttributes); + if (!myErrorMsg.empty()) + return; + if (anAttributes.empty()) { + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); + return; } + if (aConstrType == CONSTRAINT_UNKNOWN) + aConstrType = getType(); - // Constraint for the given length of a line - if (aConstraintKind.compare(SKETCH_CONSTRAINT_LENGTH_KIND) == 0) - { - int aNbLines = 0; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr) continue; - if (anAttr->isFeature() && anAttr->feature() && - anAttr->feature()->getKind().compare(SKETCH_LINE_KIND) == 0) - { - myAttributesList[aNbLines++] = CONSTRAINT_ATTRIBUTES[indAttr]; - break; - } - } - if (aNbLines == 1) - myType = SLVS_C_PT_PT_DISTANCE; - return getType(); + BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + std::list aNewConstraints = aBuilder->createConstraint( + myBaseConstraint, myGroupID, mySketchID, aConstrType, + aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]); + myStorage->addConstraint(myBaseConstraint, aNewConstraints); + + adjustConstraint(); +} + +void SketchSolver_Constraint::update() +{ + cleanErrorMsg(); + + std::list aWrapper = myStorage->constraint(myBaseConstraint); + AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE())); + if (aValueAttr) { + std::list::iterator aWIt = aWrapper.begin(); + for (; aWIt != aWrapper.end(); ++aWIt) + (*aWIt)->setValue(aValueAttr->value()); } + myStorage->addConstraint(myBaseConstraint, aWrapper); + + adjustConstraint(); +} + +bool SketchSolver_Constraint::remove() +{ + cleanErrorMsg(); + return myStorage->removeConstraint(myBaseConstraint); +} - // Constraint for two parallel/perpendicular lines - bool isParallel = (aConstraintKind.compare(SKETCH_CONSTRAINT_PARALLEL_KIND) == 0); - bool isPerpendicular = (aConstraintKind.compare(SKETCH_CONSTRAINT_PERPENDICULAR_KIND) == 0); - if (isParallel || isPerpendicular) - { - int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr || !anAttr->isFeature() || !anAttr->feature()) continue; - const std::string& aKind = anAttr->feature()->getKind(); - if (aKind.compare(SKETCH_LINE_KIND) == 0) - { - myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } +void SketchSolver_Constraint::getAttributes( + double& theValue, + std::vector& theAttributes) +{ + static const int anInitNbOfAttr = 4; + theAttributes.assign(anInitNbOfAttr, EntityWrapperPtr()); + + DataPtr aData = myBaseConstraint->data(); + BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + + myType = TYPE(myBaseConstraint); + + AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::VALUE())); + theValue = aValueAttr ? aValueAttr->value() : 0.0; + + int aPtInd = 0; // index of first point in the list of attributes + int aEntInd = 2; // index of first entity in the list of attributes + std::list aConstrAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId()); + std::list::iterator anIter = aConstrAttrs.begin(); + for (; anIter != aConstrAttrs.end(); anIter++) { + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(*anIter); + if (!aRefAttr || !aRefAttr->isInitialized()) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; } - if (aNbEntities == 4) - myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR; - return getType(); - } - // Constraint for radius of a circle or an arc of circle - if (aConstraintKind.compare(SKETCH_CONSTRAINT_RADIUS_KIND) == 0) - { - int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) - { - boost::shared_ptr anAttr = - boost::dynamic_pointer_cast( - theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr]) - ); - if (!anAttr || !anAttr->isFeature() || !anAttr->feature()) continue; - const std::string& aKind = anAttr->feature()->getKind(); - if (aKind.compare(SKETCH_CIRCLE_KIND) == 0 || aKind.compare(SKETCH_ARC_KIND) == 0) - { - myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr]; - continue; - } + myStorage->update(*anIter/*, myGroupID*/); + EntityWrapperPtr anEntity = myStorage->entity(*anIter); + + SketchSolver_EntityType aType = anEntity->type(); + if (aType == ENTITY_UNKNOWN) + continue; + else if (aType == ENTITY_POINT) + theAttributes[aPtInd++] = anEntity; // the point is created + else { // another entity (not a point) is created + if (aEntInd < anInitNbOfAttr) + theAttributes[aEntInd] = anEntity; + else + theAttributes.push_back(anEntity); + aEntInd++; } - if (aNbEntities == 3) - myType = SLVS_C_DIAMETER; - return getType(); } +} - /// \todo Implement other kind of constrtaints +bool SketchSolver_Constraint::isUsed(FeaturePtr theFeature) const +{ + const std::list& aCList = myStorage->constraint(myBaseConstraint); + std::list::const_iterator aCIt = aCList.begin(); + for (; aCIt != aCList.end(); ++aCIt) + if ((*aCIt)->isUsed(theFeature)) + return true; + + std::list anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); + std::list::const_iterator anAttrIt = anAttrList.begin(); + for (; anAttrIt != anAttrList.end(); ++ anAttrIt) + if (isUsed(*anAttrIt)) + return true; + + return false; +} + +bool SketchSolver_Constraint::isUsed(AttributePtr theAttribute) const +{ + AttributePtr anAttribute = theAttribute; + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(anAttribute); + if (aRefAttr) { + if (aRefAttr->isObject()) + return isUsed(ModelAPI_Feature::feature(aRefAttr->object())); + else + anAttribute = aRefAttr->attr(); + } - return getType(); + const std::list& aCList = myStorage->constraint(myBaseConstraint); + std::list::const_iterator aCIt = aCList.begin(); + for (; aCIt != aCList.end(); ++aCIt) + if ((*aCIt)->isUsed(theAttribute)) + return true; + return false; } + +void SketchSolver_Constraint::makeTemporary() const +{ + myStorage->setTemporary(myBaseConstraint); +} +