X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_Constraint.cpp;h=690cc087c6ea0983f530e1709b24acc06e4c27f9;hb=745c72679f6346375d5e886b25cc3865f3c4daae;hp=3c5b4be1b8cb72478c378cd2b538b7154043a825;hpb=a24b7e6f4d112d5e7889fd76f030298fc428cd01;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index 3c5b4be1b..690cc087c 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -1,22 +1,42 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: SketchSolver_Constraint.cpp -// Created: 27 May 2014 -// Author: Artem ZHIDKOV - -#include "SketchSolver_Constraint.h" -#include +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +#include +#include + +#include +#include +#include +#include #include #include -#include -#include + +#include #include +#include +#include #include #include -#include #include #include +#include #include #include #include @@ -25,329 +45,202 @@ #include #include -#include -#include -#include -#include -#include -#include - +#include #include #include -#include -#include - -/// Possible types of attributes (used to determine constraint type) -enum AttrType -{ - UNKNOWN, // Something wrong during type determination - POINT2D, - POINT3D, - LINE, - CIRCLE, - ARC -}; +#include +#include -/// Calculate type of the attribute -static AttrType typeOfAttribute(std::shared_ptr theAttribute); +#include -SketchSolver_Constraint::SketchSolver_Constraint() - : myConstraint(std::shared_ptr()), - myType(SLVS_C_UNKNOWN), - myAttributesList() +SketchSolver_Constraint::SketchSolver_Constraint( + ConstraintPtr theConstraint) + : myBaseConstraint(theConstraint), + myType(CONSTRAINT_UNKNOWN) { } -SketchSolver_Constraint::SketchSolver_Constraint( - std::shared_ptr theConstraint) - : myConstraint(theConstraint), - myAttributesList() +void SketchSolver_Constraint::process(StoragePtr theStorage, bool theEvensBlocked) { - myType = getType(myConstraint); + myStorage = theStorage; + blockEvents(theEvensBlocked); + // Process constraint according to its type + process(); } -const int& SketchSolver_Constraint::getType( - std::shared_ptr theConstraint) +void SketchSolver_Constraint::blockEvents(bool isBlocked) { - myType = SLVS_C_UNKNOWN; - if (!theConstraint) - return getType(); - - DataPtr aConstrData = theConstraint->data(); - if (!aConstrData || !aConstrData->isValid()) - return getType(); + myBaseConstraint->data()->blockSendAttributeUpdated(isBlocked); +} - // 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(SketchPlugin_ConstraintCoincidence::ID()) == 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++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - if (!anAttr) - continue; - switch (typeOfAttribute(anAttr)) { - case POINT2D: // the attribute is a 2D point - aPt2d |= (1 << indAttr); - myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - break; - case POINT3D: // the attribute is a 3D point - aPt3d |= (1 << indAttr); - myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - break; - default: - // 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(); - } - - // Constraint for distance between point and another entity - if (aConstraintKind.compare(SketchPlugin_ConstraintDistance::ID()) == 0) { - int aNbPoints = 0; - int aNbEntities = 0; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - switch (typeOfAttribute(anAttr)) { - case POINT2D: - case POINT3D: - myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - break; - case LINE: - // entities are placed starting from SketchPlugin_Constraint::ENTITY_C() attribute - myAttributesList[2 + aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - myType = SLVS_C_PT_LINE_DISTANCE; - break; - } - } - // 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(); - } - - // Constraint for the given length of a line - if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0) { - int aNbLines = 0; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - if (typeOfAttribute(anAttr) == LINE) - myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - if (aNbLines == 1) - myType = SLVS_C_PT_PT_DISTANCE; - return getType(); - } +SketchSolver_ConstraintType SketchSolver_Constraint::TYPE(ConstraintPtr theConstraint) +{ + const std::string& aType = theConstraint->getKind(); + if (aType == SketchPlugin_ConstraintCoincidence::ID() || + aType == SketchPlugin_ConstraintCoincidenceInternal::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; + else if (aType == SketchPlugin_ConstraintCollinear::ID()) + return CONSTRAINT_COLLINEAR; + else if (aType == SketchPlugin_ConstraintMiddle::ID()) + return CONSTRAINT_MIDDLE_POINT; + return CONSTRAINT_UNKNOWN; +} - // Constraint for two parallel/perpendicular lines - bool isParallel = (aConstraintKind.compare(SketchPlugin_ConstraintParallel::ID()) == 0); - bool isPerpendicular = (aConstraintKind.compare(SketchPlugin_ConstraintPerpendicular::ID()) == 0); - if (isParallel || isPerpendicular) { - int aNbEntities = 2; // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - if (typeOfAttribute(anAttr) == LINE) - myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - if (aNbEntities == 4) - myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR; - return getType(); +void SketchSolver_Constraint::process() +{ + cleanErrorMsg(); + if (!myBaseConstraint || !myStorage) { + // Not enough parameters are assigned + return; } - // Constraint for radius of a circle or an arc of circle - if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0) { - int aNbEntities = 2; // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - AttrType aType = typeOfAttribute(anAttr); - if (aType == CIRCLE || aType == ARC) - myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - if (aNbEntities == 3) - myType = SLVS_C_DIAMETER; - return getType(); + SketchSolver_ConstraintType aConstrType = getType(); + EntityWrapperPtr aValue; + std::vector anAttributes; + getAttributes(aValue, anAttributes); + if (!myErrorMsg.empty()) + return; + if (anAttributes.empty()) { + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); + return; } - - // Constraint for fixed entity - if (aConstraintKind.compare(SketchPlugin_ConstraintRigid::ID()) == 0) { - // Verify that only one entity is filled - int aNbAttrs = 0; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - AttrType aType = typeOfAttribute(anAttr); - if (aType != UNKNOWN) - myAttributesList[aNbAttrs++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - if (aNbAttrs == 1) - myType = SLVS_C_WHERE_DRAGGED; - return getType(); + if (aConstrType == CONSTRAINT_UNKNOWN) + aConstrType = getType(); + + ConstraintWrapperPtr aNewConstraint = PlaneGCSSolver_Tools::createConstraint( + myBaseConstraint, aConstrType, + aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]); + if (!aNewConstraint) { + myErrorMsg = SketchSolver_Error::WRONG_CONSTRAINT_TYPE(); + return; } + myStorage->addConstraint(myBaseConstraint, aNewConstraint); - // Constraint for horizontal/vertical line - bool isHorizontal = (aConstraintKind.compare(SketchPlugin_ConstraintHorizontal::ID()) == 0); - bool isVertical = (aConstraintKind.compare(SketchPlugin_ConstraintVertical::ID()) == 0); - if (isHorizontal || isVertical) { - int aNbEntities = 2; // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - if (typeOfAttribute(anAttr) == LINE) - myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - if (aNbEntities == 3) - myType = isHorizontal ? SLVS_C_HORIZONTAL : SLVS_C_VERTICAL; - return getType(); - } + adjustConstraint(); +} - if (aConstraintKind.compare(SketchPlugin_ConstraintEqual::ID()) == 0) { - static const int aConstrType[3] = { - SLVS_C_EQUAL_RADIUS, - SLVS_C_EQUAL_LINE_ARC_LEN, - SLVS_C_EQUAL_LENGTH_LINES - }; - int aNbLines = 0; - int aNbEntities = 2; // lines and circles in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - AttrType aType = typeOfAttribute(anAttr); - if (aType == LINE) { - myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - aNbLines++; +void SketchSolver_Constraint::update() +{ + cleanErrorMsg(); + + // Get list of attributes of the constraint and compare it with previously stored. + // If the lists are different, fully rebuild constraint + std::set anAttributes; + for (int anEntIndex = 0; anEntIndex < 4; ++anEntIndex) { + AttributePtr anAttr = + myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(anEntIndex)); + if (!anAttr) + continue; + + if (myBaseConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast(anAttr); + FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object()); + if (aFeat) { + // Workaround for the Length constraint: add points of line, not line itself + anAttributes.insert(myStorage->entity(aFeat->attribute(SketchPlugin_Line::START_ID()))); + anAttributes.insert(myStorage->entity(aFeat->attribute(SketchPlugin_Line::END_ID()))); } - else if (aType == CIRCLE || aType == ARC) - myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - if (aNbEntities == 4) - myType = aConstrType[aNbLines]; - return getType(); + } else + anAttributes.insert(myStorage->entity(anAttr)); } - if (aConstraintKind.compare(SketchPlugin_ConstraintTangent::ID()) == 0) { - static const int anArcPosDefault = 2; - static const int aLinePosDefault = 3; - int anArcPos = anArcPosDefault; // arc in tangency constraint should be placed before line - int aLinePos = aLinePosDefault; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - AttrType aType = typeOfAttribute(anAttr); - if (aType == LINE && aLinePos < CONSTRAINT_ATTR_SIZE) - myAttributesList[aLinePos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - else if (aType == ARC) - myAttributesList[anArcPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - if (anArcPos - anArcPosDefault + aLinePos - aLinePosDefault == 2) - myType = aLinePos > 3 ? SLVS_C_ARC_LINE_TANGENT : SLVS_C_CURVE_CURVE_TANGENT; - return getType(); - } + std::set::iterator aFound; + std::list::const_iterator anAttrIt = myAttributes.begin(); + for (; anAttrIt != myAttributes.end() && !anAttributes.empty(); ++anAttrIt) + anAttributes.erase(*anAttrIt); - if (aConstraintKind.compare(SketchPlugin_ConstraintMirror::ID()) == 0) { - int aNbAttrs = 0; - bool hasMirrorLine = false; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - AttributeRefListPtr anAttrRefList = std::dynamic_pointer_cast( - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr))); - if (anAttrRefList) { - aNbAttrs++; - myAttributesList[aNbAttrs] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - else { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - if (typeOfAttribute(anAttr) == LINE) { - hasMirrorLine = !hasMirrorLine; - myAttributesList[0] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - } - } - if (aNbAttrs == 2 && hasMirrorLine) - myType = SLVS_C_SYMMETRIC_LINE; - return getType(); + if (!anAttributes.empty()) { + remove(); + process(); + return; } - if (aConstraintKind.compare(SketchPlugin_ConstraintFillet::ID()) == 0) { - int aNbAttrs = 0; - for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { - AttributeRefListPtr anAttrRefList = std::dynamic_pointer_cast( - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr))); - if (anAttrRefList) - myAttributesList[aNbAttrs++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - else { - std::shared_ptr anAttr = - aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)); - AttrType aType = typeOfAttribute(anAttr); - if (aType == LINE || aType == ARC) - myAttributesList[aNbAttrs++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr); - } - } - if (aNbAttrs == 3) - myType = SLVS_C_FILLET; - return getType(); - } + AttributePtr aValueAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()); + if (aValueAttr) + myStorage->update(aValueAttr); - /// \todo Implement other kind of constraints + adjustConstraint(); +} - return getType(); +bool SketchSolver_Constraint::remove() +{ + cleanErrorMsg(); + myType = CONSTRAINT_UNKNOWN; + myStorage->unsubscribeUpdates(this); + return myStorage->removeConstraint(myBaseConstraint); } -// ================= Auxiliary functions ============================== -AttrType typeOfAttribute(std::shared_ptr theAttribute) +void SketchSolver_Constraint::getAttributes( + EntityWrapperPtr& theValue, + std::vector& theAttributes) { - std::shared_ptr anAttrRef = std::dynamic_pointer_cast< - ModelAPI_AttributeRefAttr>(theAttribute); - if (!anAttrRef) - return UNKNOWN; + static const int anInitNbOfAttr = 4; + theAttributes.assign(anInitNbOfAttr, EntityWrapperPtr()); + myAttributes.clear(); - if (anAttrRef->isObject()) { - ResultConstructionPtr aRC = std::dynamic_pointer_cast( - anAttrRef->object()); - if (!aRC || !aRC->shape()) - return UNKNOWN; + DataPtr aData = myBaseConstraint->data(); - if (aRC->shape()->isVertex()) - return POINT3D; - else if (aRC->shape()->isEdge()) { - std::shared_ptr anEdge = std::dynamic_pointer_cast( - aRC->shape()); - if (anEdge->isLine()) - return LINE; - else if (anEdge->isCircle()) - return CIRCLE; - else if (anEdge->isArc()) - return ARC; + myType = TYPE(myBaseConstraint); + + AttributePtr aValueAttr = aData->attribute(SketchPlugin_Constraint::VALUE()); + if (aValueAttr) { + PlaneGCSSolver_AttributeBuilder aValueBuilder; + theValue = aValueBuilder.createAttribute(aValueAttr); + myStorage->addEntity(aValueAttr, theValue); + } + + 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; } - } else { - if (anAttrRef->attr().get() != NULL) { - const std::string aType = anAttrRef->attr()->attributeType(); - if (aType == GeomDataAPI_Point2D::typeId()) - return POINT2D; - if (aType == GeomDataAPI_Point2D::typeId()) - return POINT2D; + + myStorage->update(*anIter, true); + EntityWrapperPtr anEntity = myStorage->entity(*anIter); + myAttributes.push_back(anEntity); + + SketchSolver_EntityType aType = anEntity->type(); + if (aType == ENTITY_UNKNOWN) + continue; + else if (aType == ENTITY_POINT || aType == ENTITY_POINT_ARRAY) + 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++; } } - - return UNKNOWN; } -