X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_ConstraintMovement.cpp;h=d9f46de4a0c2fc21f63b24ddf97957983508a07a;hb=88ee9b2b81cf93a6324336b57e30cc8a3a487499;hp=b97d1a754fde25fbc659b8bfa8e0e771e1502c48;hpb=868158fe6d39b25e60ac528295b1c908821e4af5;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintMovement.cpp b/src/SketchSolver/SketchSolver_ConstraintMovement.cpp index b97d1a754..d9f46de4a 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMovement.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMovement.cpp @@ -1,176 +1,327 @@ +// Copyright (C) 2017-2022 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 + +static GCS::Point createGCSPoint(double* x, double* y) +{ + GCS::Point aPoint; + aPoint.x = x; + aPoint.y = y; + return aPoint; +} + + SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature) - : SketchSolver_ConstraintRigid(theFeature) + : SketchSolver_ConstraintFixed(ConstraintPtr()), + myMovedFeature(theFeature), + mySimpleMove(true) +{ +} + +SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(AttributePtr theAttribute, + const int thePointIndex) + : SketchSolver_ConstraintFixed(ConstraintPtr()), + myDraggedAttribute(theAttribute), + myDraggedPointIndex(thePointIndex), + mySimpleMove(true) { - process(); + myMovedFeature = ModelAPI_Feature::feature(theAttribute->owner()); +} + +void SketchSolver_ConstraintMovement::blockEvents(bool isBlocked) +{ + if (myMovedFeature) + myMovedFeature->data()->blockSendAttributeUpdated(isBlocked); } void SketchSolver_ConstraintMovement::process() { cleanErrorMsg(); - if (!myBaseFeature || !myStorage || myGroup == 0) { - /// TODO: Put error message here + if (!myMovedFeature || !myStorage) { + // Not enough parameters are initialized return; } - if (!mySlvsConstraints.empty()) // some data is changed, update constraint - update(myBaseConstraint); - - double aValue; - std::vector anEntities; - bool isFullyMoved; - getAttributes(aValue, anEntities, isFullyMoved); - if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty())) - return; - if (isFullyMoved) - fixFeature(); - else { - std::vector::iterator anEntIt = anEntities.begin(); - for (; anEntIt != anEntities.end(); ++anEntIt) - fixPoint(*anEntIt); + mySolverConstraint = initMovement(); + if (!myErrorMsg.empty() || !mySolverConstraint) { + // Nothing to move, clear the feature to avoid changing its group + // after removing the Movement constraint. + myMovedFeature = FeaturePtr(); + return; } + myStorage->addMovementConstraint(mySolverConstraint); } -void SketchSolver_ConstraintMovement::getAttributes( - double& theValue, - std::vector& theAttributes, - bool& theIsFullyMoved) +static bool isSimpleMove(FeaturePtr theMovedFeature, AttributePtr theDraggedPoint) { - bool isComplexFeature = false; - theValue = 0.0; - theIsFullyMoved = true; - int aType = SLVS_E_UNKNOWN; // type of created entity - Slvs_hEntity anEntityID = SLVS_E_UNKNOWN; - Slvs_hEntity anEntMaxID = myStorage->entityMaxID(); - anEntityID = myGroup->getFeatureId(myBaseFeature); - if (anEntityID == SLVS_E_UNKNOWN) { - anEntityID = changeEntity(myBaseFeature, aType); - if (anEntityID == SLVS_E_UNKNOWN) { - myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); - return; - } - - // Check the entity is complex - Slvs_Entity anEntity = myStorage->getEntity(anEntityID); - if (anEntity.point[0] != SLVS_E_UNKNOWN) - isComplexFeature = true; - else // simple entity - theAttributes.push_back(anEntityID); + bool isSimple = true; +#ifdef CHANGE_RADIUS_WHILE_MOVE + if (theMovedFeature->getKind() == SketchPlugin_Circle::ID() || + theMovedFeature->getKind() == SketchPlugin_Ellipse::ID()) + isSimple = (theDraggedPoint.get() != 0); + else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID() || + theMovedFeature->getKind() == SketchPlugin_EllipticArc::ID()) { + isSimple = (theDraggedPoint.get() != 0 && + (theDraggedPoint->id() == SketchPlugin_Arc::CENTER_ID() || + theDraggedPoint->id() == SketchPlugin_EllipticArc::CENTER_ID())); } - else { - myFeatureMap[myBaseFeature] = anEntityID; - isComplexFeature = true; +#endif + return isSimple; +} + +ConstraintWrapperPtr SketchSolver_ConstraintMovement::initMovement() +{ + ConstraintWrapperPtr aConstraint; + + // if the feature is copy, do not move it + std::shared_ptr aSketchFeature = + std::dynamic_pointer_cast(myMovedFeature); + if (!aSketchFeature || aSketchFeature->isCopy()) { + myStorage->setNeedToResolve(true); + return aConstraint; } - int aNbOutOfGroup = 0; - if (isComplexFeature) { - std::list aPoints = - myBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list::iterator anIt = aPoints.begin(); - for (; anIt != aPoints.end(); ++anIt) { - std::map::const_iterator aFound = myAttributeMap.find(*anIt); - Slvs_hEntity anAttr = aFound != myAttributeMap.end() ? - aFound->second : myGroup->getAttributeId(*anIt); - Slvs_Entity anAttrEnt = myStorage->getEntity(anAttr); - - // Check the attribute changes coordinates - std::shared_ptr aPt = - std::dynamic_pointer_cast(*anIt); - // Check the entity is not lying in the current group or it is not moved - if (anAttr == SLVS_E_UNKNOWN || anAttrEnt.group != myGroup->getId() || - (anAttr <= anEntMaxID && !isMoved(aPt, anAttrEnt))) { - if (anAttrEnt.group == SLVS_G_OUTOFGROUP) - ++aNbOutOfGroup; - theIsFullyMoved = false; - } - else { - theAttributes.push_back(anAttr); - // update point coordinates - Slvs_Entity anAttrEnt = myStorage->getEntity(anAttr); - double aNewPos[2] = {aPt->x(), aPt->y()}; - for (int i = 0; i < 2; i++) { - Slvs_Param aParam = myStorage->getParameter(anAttrEnt.param[i]); - aParam.val = aNewPos[i]; - myStorage->updateParameter(aParam); - } - } - } + EntityWrapperPtr anEntity = myDraggedAttribute ? myStorage->entity(myDraggedAttribute) + : myStorage->entity(myMovedFeature); + if (!anEntity) { + myStorage->update(myMovedFeature, true); + anEntity = myDraggedAttribute ? myStorage->entity(myDraggedAttribute) + : myStorage->entity(myMovedFeature); + if (!anEntity) + return aConstraint; } - // Additional checking, which leads to fix whole feature, if it has fixed points - if (!theIsFullyMoved) { - Slvs_Entity aFeature = myStorage->getEntity(anEntityID); - int aNbPoints = 4; - while (aNbPoints > 0 && aFeature.point[aNbPoints-1] == SLVS_E_UNKNOWN) - --aNbPoints; - if (aNbPoints == aNbOutOfGroup + (int)theAttributes.size()) { - theIsFullyMoved = true; - return; + mySimpleMove = isSimpleMove(myMovedFeature, myDraggedAttribute); + + if (mySimpleMove) { + if (anEntity->type() == ENTITY_POINT_ARRAY) { + anEntity = std::dynamic_pointer_cast(anEntity) + ->value(myDraggedPointIndex); } + aConstraint = fixFeature(anEntity); } - - // Leave only points which are used in constraints - if (myStorage->isUsedByConstraints(anEntityID)) - return; - std::vector::iterator anIt = theAttributes.begin(); - while (anIt != theAttributes.end()) { - if (myStorage->isUsedByConstraints(*anIt)) - ++anIt; - else { - int aShift = anIt - theAttributes.begin(); - theAttributes.erase(anIt); - anIt = theAttributes.begin() + aShift; + else { + if (myDraggedAttribute) // start or end point of arc has been moved + aConstraint = fixArcExtremity(anEntity); + else if (anEntity->type() == ENTITY_CIRCLE || anEntity->type() == ENTITY_ARC) { + // arc or circle has been moved + aConstraint = fixPointOnCircle(anEntity); + } + else if (anEntity->type() == ENTITY_ELLIPSE || anEntity->type() == ENTITY_ELLIPTIC_ARC) { + // ellipse or elliptic arc has been moved + aConstraint = fixPointOnEllipse(anEntity); } } + + return aConstraint; } -bool SketchSolver_ConstraintMovement::isMoved( - std::shared_ptr thePoint, const Slvs_Entity& theEntity) +ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixArcExtremity( + const EntityWrapperPtr& theArcExtremity) { - double aDeltaX = myStorage->getParameter(theEntity.param[0]).val; - double aDeltaY = myStorage->getParameter(theEntity.param[1]).val; - aDeltaX -= thePoint->x(); - aDeltaY -= thePoint->y(); - return aDeltaX * aDeltaX + aDeltaY * aDeltaY >= tolerance * tolerance; + static const int nbParams = 4; + myFixedValues.reserve(nbParams); // moved point and center of arc + + EdgeWrapperPtr aCircularEntity = std::dynamic_pointer_cast( + myStorage->entity(myMovedFeature)); + std::shared_ptr anArc = + std::dynamic_pointer_cast(aCircularEntity->entity()); + std::shared_ptr anEllArc = + std::dynamic_pointer_cast(aCircularEntity->entity()); + + PointWrapperPtr aPoint = + std::dynamic_pointer_cast(theArcExtremity); + + double* aParams[nbParams] = { aPoint->point()->x, aPoint->point()->y, 0, 0 }; + if (anArc) { + aParams[2] = anArc->center.x; + aParams[3] = anArc->center.y; + } + else if (anEllArc) { + aParams[2] = anEllArc->center.x; + aParams[3] = anEllArc->center.y; + } + + std::list aConstraints; + for (int i = 0; i < nbParams; ++i) { + myFixedValues.push_back(*aParams[i]); + GCSConstraintPtr aNewConstraint(new GCS::ConstraintEqual(&myFixedValues[i], aParams[i])); + aNewConstraint->rescale(0.01); + aConstraints.push_back(aNewConstraint); + } + + return ConstraintWrapperPtr( + new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType())); } -void SketchSolver_ConstraintMovement::fixFeature() +ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnCircle( + const EntityWrapperPtr& theCircular) { - Slvs_hEntity anEntID = fixedEntity(); - - std::string aKind; - std::map::const_iterator aFIt = myFeatureMap.begin(); - for (; aFIt != myFeatureMap.end() && aKind.empty(); ++aFIt) - if (aFIt->second == anEntID) - aKind = aFIt->first->getKind(); - std::map::const_iterator anAtIt = myAttributeMap.begin(); - for (; anAtIt != myAttributeMap.end() && aKind.empty(); ++anAtIt) - if (anAtIt->second == anEntID) - aKind = anAtIt->first->attributeType(); - - if (aKind == SketchPlugin_Line::ID()) { - Slvs_Entity aLine = myStorage->getEntity(anEntID); - fixLine(aLine); - } - else if (aKind == SketchPlugin_Arc::ID()) { - Slvs_Entity anArc = myStorage->getEntity(anEntID); - fixArc(anArc); + static const double scale = 0.01; + static const int nbParams = 4; + myFixedValues.reserve(nbParams); // moved point and center of arc/circle + + EdgeWrapperPtr aCircularEntity = + std::dynamic_pointer_cast(theCircular); + std::shared_ptr aCircular = + std::dynamic_pointer_cast(aCircularEntity->entity()); + + // initialize fixed values + myFixedValues.push_back(*aCircular->center.x + *aCircular->rad); + myFixedValues.push_back(*aCircular->center.y); + myFixedValues.push_back(*aCircular->center.x); + myFixedValues.push_back(*aCircular->center.y); + + // create a moved point + GCS::Point aPointOnCircle = createGCSPoint(&myFixedValues[0], &myFixedValues[1]); + + std::list aConstraints; + // point-on-circle + GCSConstraintPtr aNewConstraint( + new GCS::ConstraintP2PDistance(aPointOnCircle, aCircular->center, aCircular->rad)); + aNewConstraint->rescale(scale); + aConstraints.push_back(aNewConstraint); + // fixed center (x) + aNewConstraint = GCSConstraintPtr( + new GCS::ConstraintEqual(&myFixedValues[2], aCircular->center.x)); + aNewConstraint->rescale(scale); + aConstraints.push_back(aNewConstraint); + // fixed center (y) + aNewConstraint = GCSConstraintPtr( + new GCS::ConstraintEqual(&myFixedValues[3], aCircular->center.y)); + aNewConstraint->rescale(scale); + aConstraints.push_back(aNewConstraint); + + return ConstraintWrapperPtr( + new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType())); +} + +ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnEllipse( + const EntityWrapperPtr& theConic) +{ + static const double scale = 0.01; + static const int nbParams = 6; + myFixedValues.reserve(nbParams); // moved point; center and focus of ellipse + + EdgeWrapperPtr anEdge = std::dynamic_pointer_cast(theConic); + std::shared_ptr aConic = std::dynamic_pointer_cast(anEdge->entity()); + + // major axis direction + double dx = *aConic->focus1.x - *aConic->center.x; + double dy = *aConic->focus1.y - *aConic->center.y; + double norm = sqrt(dx * dx + dy* dy); + if (norm < tolerance) { + dx = 1.0; + dy = 0.0; } - else if (aKind == SketchPlugin_Circle::ID()) { - Slvs_Entity aCirc = myStorage->getEntity(anEntID); - fixCircle(aCirc); + else { + dx /= norm; + dy /= norm; } - else if (aKind == SketchPlugin_Point::ID() || aKind == GeomDataAPI_Point2D::typeId()) { - fixPoint(anEntID); + + double aMajorRad = aConic->getRadMaj(); + + // initialize fixed values + myFixedValues.push_back(*aConic->center.x + dx * aMajorRad); + myFixedValues.push_back(*aConic->center.y + dy * aMajorRad); + myFixedValues.push_back(*aConic->center.x); + myFixedValues.push_back(*aConic->center.y); + myFixedValues.push_back(*aConic->focus1.x); + myFixedValues.push_back(*aConic->focus1.y); + + // create a moved point + GCS::Point aPointOnEllipse = createGCSPoint(&myFixedValues[0], &myFixedValues[1]); + + std::list aConstraints; + // point-on-circle + GCSConstraintPtr aNewConstraint( + new GCS::ConstraintPointOnEllipse(aPointOnEllipse, *aConic)); + aNewConstraint->rescale(scale); + aConstraints.push_back(aNewConstraint); + // fixed center (x) + aNewConstraint = GCSConstraintPtr( + new GCS::ConstraintEqual(&myFixedValues[2], aConic->center.x)); + aNewConstraint->rescale(scale); + aConstraints.push_back(aNewConstraint); + // fixed center (y) + aNewConstraint = GCSConstraintPtr( + new GCS::ConstraintEqual(&myFixedValues[3], aConic->center.y)); + aNewConstraint->rescale(scale); + aConstraints.push_back(aNewConstraint); + // focus on the major axis + GCS::Point aStartPoint = createGCSPoint(&myFixedValues[2], &myFixedValues[3]); + GCS::Point aEndPoint = createGCSPoint(&myFixedValues[4], &myFixedValues[5]); + aNewConstraint = GCSConstraintPtr( + new GCS::ConstraintPointOnLine(aConic->focus1, aStartPoint, aEndPoint)); + aNewConstraint->rescale(scale); + aConstraints.push_back(aNewConstraint); + + return ConstraintWrapperPtr( + new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType())); +} + +void SketchSolver_ConstraintMovement::startPoint( + const std::shared_ptr& theStartPoint) +{ + myStartPoint = theStartPoint; + if (!mySimpleMove) { + myFixedValues[0] = myStartPoint->x(); + myFixedValues[1] = myStartPoint->y(); } } +void SketchSolver_ConstraintMovement::moveTo( + const std::shared_ptr& theDestinationPoint) +{ + if (!myMovedFeature) + return; // nothing to move + + double aDelta[2] = { theDestinationPoint->x() - myStartPoint->x(), + theDestinationPoint->y() - myStartPoint->y() }; + +#ifdef CHANGE_RADIUS_WHILE_MOVE + int aMaxSize = mySimpleMove ? (int)myFixedValues.size() : 2; +#else + int aMaxSize = + myMovedFeature->getKind() == SketchPlugin_Line::ID() && !myDraggedAttribute ? 4 : 2; +#endif + for (int i = 0; i < aMaxSize; ++i) + myFixedValues[i] += aDelta[i % 2]; +}