From b7576839d8982c8e08513b8d3d214a7e5d09e310 Mon Sep 17 00:00:00 2001 From: azv Date: Fri, 22 Jan 2016 14:41:42 +0300 Subject: [PATCH] Movement of arc in ward of sketch solver (improvement #730, issue #1172) --- src/SketchPlugin/SketchPlugin_Arc.cpp | 59 +----------------- src/SketchSolver/CMakeLists.txt | 2 + .../PlaneGCSSolver/PlaneGCSSolver_Storage.cpp | 2 +- src/SketchSolver/SketchSolver_Builder.cpp | 9 +++ src/SketchSolver/SketchSolver_Builder.h | 3 + .../SketchSolver_ConstraintFixed.cpp | 2 +- .../SketchSolver_ConstraintFixedArcRadius.cpp | 61 +++++++++++++++++++ .../SketchSolver_ConstraintFixedArcRadius.h | 39 ++++++++++++ src/SketchSolver/SketchSolver_Group.cpp | 14 ++++- src/SketchSolver/SketchSolver_Manager.cpp | 13 +++- src/SketchSolver/SketchSolver_Storage.cpp | 2 +- src/SketchSolver/SketchSolver_Storage.h | 6 ++ 12 files changed, 150 insertions(+), 62 deletions(-) create mode 100644 src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.cpp create mode 100644 src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.h diff --git a/src/SketchPlugin/SketchPlugin_Arc.cpp b/src/SketchPlugin/SketchPlugin_Arc.cpp index 261e70b95..9ec13a320 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@ -94,13 +94,11 @@ void SketchPlugin_Arc::execute() // compute and change the arc end point std::shared_ptr anEndAttr = std::dynamic_pointer_cast< GeomDataAPI_Point2D>(data()->attribute(END_ID())); - /* must be automatically done in attributeChanged std::shared_ptr aCircleForArc( new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); std::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) anEndAttr->setValue(aProjection); - */ std::shared_ptr aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y())); AttributeBooleanPtr isInversed = std::dynamic_pointer_cast(attribute(INVERSED_ID())); @@ -249,64 +247,11 @@ void SketchPlugin_Arc::attributeChanged(const std::string& theID) } return; } - if (!aCenterAttr->isInitialized()) - return; - if (!aStartAttr->isInitialized()) - return; - if (!anEndAttr->isInitialized()) + if (!isFeatureValid()) return; // update the points in accordance to the changed point changes - if (theID == END_ID() && !myEndUpdate) { - myEndUpdate = true; - // compute and change the arc end point - std::shared_ptr aCircleForArc( - new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); - std::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); - if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) { - if (!isStable()) { // issue #855: trying to update only not-updated coordinate if it is possible - if (fabs(myXEndBefore - anEndAttr->x()) < 1.e-10) { // keep Y unchanged - double aVy = aCenterAttr->y() - anEndAttr->y(); - double aVy2 = aVy * aVy; - double aR2 = aCircleForArc->radius() * aCircleForArc->radius(); - if (aVy2 <= aR2) { - double aDX = sqrt(aR2 - aVy * aVy); - if (anEndAttr->x() > aCenterAttr->x()) - aProjection->setX(aCenterAttr->x() + aDX); - else - aProjection->setX(aCenterAttr->x() - aDX); - aProjection->setY(anEndAttr->y()); - } - } else if (fabs(myYEndBefore - anEndAttr->y()) < 1.e-10) { // keep X unchanged - double aVx = aCenterAttr->x() - anEndAttr->x(); - double aVx2 = aVx * aVx; - double aR2 = aCircleForArc->radius() * aCircleForArc->radius(); - if (aVx2 <= aR2) { - double aDY = sqrt(aR2 - aVx * aVx); - if (anEndAttr->y() > aCenterAttr->y()) - aProjection->setY(aCenterAttr->y() + aDY); - else - aProjection->setY(aCenterAttr->y() - aDY); - aProjection->setX(anEndAttr->x()); - } - } - } - - anEndAttr->setValue(aProjection); - } - myXEndBefore = anEndAttr->x(); - myYEndBefore = anEndAttr->y(); - myEndUpdate = false; - } else if (theID == START_ID() && !myStartUpdate) { - myStartUpdate = true; - // compute and change the arc start point - std::shared_ptr aCircleForArc( - new GeomAPI_Circ2d(aCenterAttr->pnt(), anEndAttr->pnt())); - std::shared_ptr aProjection = aCircleForArc->project(aStartAttr->pnt()); - if (aProjection && aStartAttr->pnt()->distance(aProjection) > tolerance) - aStartAttr->setValue(aProjection); - myStartUpdate = false; - } else if (theID == CENTER_ID() && !myEndUpdate) { + if (theID == CENTER_ID() && !myEndUpdate) { myEndUpdate = true; // compute and change the arc end point std::shared_ptr aCircleForArc( diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index 91cfe6c82..8e18f16da 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -13,6 +13,7 @@ SET(PROJECT_HEADERS SketchSolver_ConstraintLength.h SketchSolver_ConstraintMirror.h SketchSolver_ConstraintFixed.h + SketchSolver_ConstraintFixedArcRadius.h SketchSolver_ConstraintTangent.h SketchSolver_ConstraintMulti.h SketchSolver_ConstraintMultiRotation.h @@ -37,6 +38,7 @@ SET(PROJECT_SOURCES SketchSolver_ConstraintLength.cpp SketchSolver_ConstraintMirror.cpp SketchSolver_ConstraintFixed.cpp + SketchSolver_ConstraintFixedArcRadius.cpp SketchSolver_ConstraintTangent.cpp SketchSolver_ConstraintMulti.cpp SketchSolver_ConstraintMultiRotation.cpp diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp index 33a04b7f3..5d0578c06 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp @@ -178,7 +178,7 @@ bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint) if (aConstraint->valueParameter()) isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved; - if (!isFullyRemoved && + if (!isFullyRemoved && aConstraint->baseConstraint() && (!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid())) isFullyRemoved = true; setNeedToResolve(true); diff --git a/src/SketchSolver/SketchSolver_Builder.cpp b/src/SketchSolver/SketchSolver_Builder.cpp index ff3413649..dece279ca 100644 --- a/src/SketchSolver/SketchSolver_Builder.cpp +++ b/src/SketchSolver/SketchSolver_Builder.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,14 @@ SolverConstraintPtr SketchSolver_Builder::createFixedConstraint(FeaturePtr theFi return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theFixedFeature)); } +SolverConstraintPtr SketchSolver_Builder::createFixedArcRadiusConstraint(FeaturePtr theArc) const +{ + DataPtr aData = theArc->data(); + if (!aData || !aData->isValid()) + return SolverConstraintPtr(); + return SolverConstraintPtr(new SketchSolver_ConstraintFixedArcRadius(theArc)); +} + SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theFixedFeature) const { DataPtr aData = theFixedFeature->data(); diff --git a/src/SketchSolver/SketchSolver_Builder.h b/src/SketchSolver/SketchSolver_Builder.h index e7e6f5cf0..86a395bc2 100644 --- a/src/SketchSolver/SketchSolver_Builder.h +++ b/src/SketchSolver/SketchSolver_Builder.h @@ -32,6 +32,9 @@ public: /// \brief Creates temporary constraint to fix the placement of the feature SolverConstraintPtr createFixedConstraint(FeaturePtr theFixedFeature) const; + /// \brief Creates temporary constraint to fix radius of the arc + SolverConstraintPtr createFixedArcRadiusConstraint(FeaturePtr theArc) const; + /// \brief Creates temporary constraint to fix the feature after movement SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature) const; diff --git a/src/SketchSolver/SketchSolver_ConstraintFixed.cpp b/src/SketchSolver/SketchSolver_ConstraintFixed.cpp index ee1700d22..13c2fa50d 100644 --- a/src/SketchSolver/SketchSolver_ConstraintFixed.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintFixed.cpp @@ -69,7 +69,7 @@ void SketchSolver_ConstraintFixed::getAttributes( EntityWrapperPtr aSolverEntity; if (myBaseFeature) { // The feature is fixed. - myStorage->update(myBaseFeature, myGroupID); + myStorage->update(myBaseFeature/*, myGroupID*/); aSolverEntity = myStorage->entity(myBaseFeature); } else if (myBaseConstraint) { // Constraint Fixed is added by user. diff --git a/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.cpp b/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.cpp new file mode 100644 index 000000000..e45137149 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.cpp @@ -0,0 +1,61 @@ +#include +#include +#include + +#include +#include + +SketchSolver_ConstraintFixedArcRadius::SketchSolver_ConstraintFixedArcRadius(FeaturePtr theFeature) + : SketchSolver_ConstraintFixed(theFeature) +{ + myType = CONSTRAINT_RADIUS; + process(); +} + +void SketchSolver_ConstraintFixedArcRadius::process() +{ + cleanErrorMsg(); + if (!myBaseFeature || !myStorage || myGroupID == GID_UNKNOWN) { + // Not enough parameters are assigned + return; + } + + if (myBaseFeature->getKind() != SketchPlugin_Arc::ID()) { + myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); + return; + } + + ParameterWrapperPtr aValue; + std::vector anEntities; + getAttributes(aValue, anEntities); + if (!myErrorMsg.empty() || anEntities.empty()) + return; + fixFeature(anEntities.front()); +} + +void SketchSolver_ConstraintFixedArcRadius::fixFeature(EntityWrapperPtr theFeature) +{ + BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); + + // Calculate radius of the arc + std::list aSubs = theFeature->subEntities(); + std::list::const_iterator aSubIt = aSubs.begin(); + std::shared_ptr aCenter = aBuilder->point(*aSubIt++); + std::shared_ptr aStart = aBuilder->point(*aSubIt++); + double aRadius = aCenter->distance(aStart); + + // Create constraint + std::list aConstrList = aBuilder->createConstraint(ConstraintPtr(), + myGroupID, mySketchID, myType, aRadius, EntityWrapperPtr(), EntityWrapperPtr(), theFeature); + myRadiusConstraint = aConstrList.front(); + myStorage->addConstraint(ConstraintPtr(), myRadiusConstraint); +} + +bool SketchSolver_ConstraintFixedArcRadius::remove() +{ + bool isFullyRemoved = SketchSolver_ConstraintFixed::remove(); + if (myRadiusConstraint) + isFullyRemoved = myStorage->removeConstraint(ConstraintPtr()) && + myStorage->remove(myRadiusConstraint) && isFullyRemoved; + return isFullyRemoved; +} diff --git a/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.h b/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.h new file mode 100644 index 000000000..f4fc805c3 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintFixedArcRadius.h @@ -0,0 +1,39 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintFixedArcRadiusArcRadius.h +// Created: 22 Jan 2016 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintFixedArcRadius_H_ +#define SketchSolver_ConstraintFixedArcRadius_H_ + +#include "SketchSolver.h" +#include + +/** \class SketchSolver_ConstraintFixedArcRadius + * \ingroup Plugins + * \brief Fix radius of the arc. Temporary constraint. Based on an arc, sharp! + */ +class SketchSolver_ConstraintFixedArcRadius : public SketchSolver_ConstraintFixed +{ +public: + /// Creates temporary constraint based on feature + SketchSolver_ConstraintFixedArcRadius(FeaturePtr theFeature); + + /// \brief Tries to remove constraint + /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence) + virtual bool remove(); + +protected: + /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints + virtual void process(); + + /// \brief Fix radius of arc + /// \param theFeature [in] feature, converted to solver specific format + virtual void fixFeature(EntityWrapperPtr theFeature); + +private: + ConstraintWrapperPtr myRadiusConstraint; +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 34fb4d17b..950004104 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -222,6 +223,17 @@ void SketchSolver_Group::moveFeature(FeaturePtr theFeature) // Secondly, search attributes of the feature in the list of the Multi constraints and update them updateMultiConstraints(myConstraints, theFeature); + + // Workaround to process arcs. + // When move unconstrained arc, add temporary constraint to fix radius. + if (theFeature->getKind() == SketchPlugin_Arc::ID()) { + SolverConstraintPtr aFixedRadius = aBuilder->createFixedArcRadiusConstraint(theFeature); + if (aFixedRadius) { + aFixedRadius->process(myStorage, getId(), getWorkplaneId()); + if (aFixedRadius->error().empty()) + setTemporary(aFixedRadius); + } + } } // ============================================================================ @@ -270,7 +282,7 @@ bool SketchSolver_Group::updateWorkplane() bool SketchSolver_Group::resolveConstraints() { bool aResolved = false; - bool isGroupEmpty = isEmpty(); + bool isGroupEmpty = isEmpty() && myStorage->isEmpty(); if (myStorage->isNeedToResolve() && !isGroupEmpty) { if (!mySketchSolver) mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver(); diff --git a/src/SketchSolver/SketchSolver_Manager.cpp b/src/SketchSolver/SketchSolver_Manager.cpp index ba8b2ea17..546186bb5 100644 --- a/src/SketchSolver/SketchSolver_Manager.cpp +++ b/src/SketchSolver/SketchSolver_Manager.cpp @@ -287,10 +287,21 @@ bool SketchSolver_Manager::changeFeature(std::shared_ptr t // ============================================================================ void SketchSolver_Manager::moveEntity(std::shared_ptr theFeature) { + bool isMoved = false; std::vector::iterator aGroupIt = myGroups.begin(); for (; aGroupIt != myGroups.end(); aGroupIt++) - if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature)) + if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature)) { (*aGroupIt)->moveFeature(theFeature); + isMoved = true; + } + + if (!isMoved && theFeature->getKind() == SketchPlugin_Arc::ID()) { + // Workaround to move arc. + // If the arc has not been constrained, we will push it into empty group and apply movement. + for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); aGroupIt++) + if ((*aGroupIt)->isEmpty()) + (*aGroupIt)->moveFeature(theFeature); + } } // ============================================================================ diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index e606f44c1..e75992823 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -76,7 +76,7 @@ void SketchSolver_Storage::addConstraint( if (!theSolverConstraints.empty() || aFound == myConstraintMap.end()) myConstraintMap[theConstraint] = theSolverConstraints; // block events if necessary - if (myEventsBlocked && theConstraint->data() && theConstraint->data()->isValid()) + if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid()) theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked); } diff --git a/src/SketchSolver/SketchSolver_Storage.h b/src/SketchSolver/SketchSolver_Storage.h index 7cd073f70..2be30dec3 100644 --- a/src/SketchSolver/SketchSolver_Storage.h +++ b/src/SketchSolver/SketchSolver_Storage.h @@ -19,6 +19,7 @@ #include class SketchSolver_ConstraintDistance; +class SketchSolver_ConstraintFixedArcRadius; typedef std::map > CoincidentPointsMap; @@ -113,6 +114,10 @@ public: /// \brief Check the features is not removed bool isConsistent() const; + /// \brief Check the storage has constraints + bool isEmpty() const + { return myConstraintMap.empty(); } + /// \brief Check the entity is fixed. /// If the point is under verification, all coincident points are checked too. SKETCHSOLVER_EXPORT bool isFixed(EntityWrapperPtr theEntity) const; @@ -216,6 +221,7 @@ protected: // to be able to update entities from constraints friend class SketchSolver_ConstraintDistance; + friend class SketchSolver_ConstraintFixedArcRadius; }; typedef std::shared_ptr StoragePtr; -- 2.39.2