X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_Group.cpp;h=2b2df9856d5da54cad0fd6f12110bb9bf5b78244;hb=a74fbd0025bc36fc76b5559d960857f419446ecb;hp=f437103ac38527035421f86396b2fe5c6c0d26fd;hpb=5c59bf6725e7e4855b5ca956475d705e2d5b014c;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index f437103ac..2b2df9856 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// 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 @@ -12,10 +12,9 @@ // // 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 +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "SketchSolver_Group.h" @@ -34,6 +33,8 @@ #include #include +#include + static void sendMessage(const char* theMessageName) { @@ -70,18 +71,18 @@ static void sendMessage(const char* theMessageName, // ======================================================== -// ========= SketchSolver_Group =============== +// ========= SketchSolver_Group =============== // ======================================================== SketchSolver_Group::SketchSolver_Group(const CompositeFeaturePtr& theWorkplane) - : mySketch(theWorkplane), - myPrevResult(PlaneGCSSolver_Solver::STATUS_UNKNOWN), - myDOF(0), + : myPrevResult(PlaneGCSSolver_Solver::STATUS_UNKNOWN), + myDOF(-1), myIsEventsBlocked(false), myMultiConstraintUpdateStack(0) { mySketchSolver = SolverPtr(new PlaneGCSSolver_Solver); myStorage = StoragePtr(new PlaneGCSSolver_Storage(mySketchSolver)); + updateSketch(theWorkplane); } SketchSolver_Group::~SketchSolver_Group() @@ -124,37 +125,102 @@ bool SketchSolver_Group::changeConstraint( return true; } +bool SketchSolver_Group::updateSketch(CompositeFeaturePtr theSketch) +{ + static const double THE_TOLERANCE = 1.e-7; + bool isChanged = theSketch != mySketch; + + AttributePointPtr anOrigin = std::dynamic_pointer_cast( + theSketch->attribute(SketchPlugin_Sketch::ORIGIN_ID())); + AttributeDirPtr aNorm = std::dynamic_pointer_cast( + theSketch->attribute(SketchPlugin_Sketch::NORM_ID())); + AttributeDirPtr aDirX = std::dynamic_pointer_cast( + theSketch->attribute(SketchPlugin_Sketch::DIRX_ID())); + + isChanged = isChanged + || (mySketchOrigin && anOrigin && anOrigin->pnt()->distance(mySketchOrigin) > THE_TOLERANCE) + || (mySketchNormal && aNorm && aNorm->xyz()->distance(mySketchNormal->xyz()) > THE_TOLERANCE) + || (mySketchXDir && aDirX && aDirX->xyz()->distance(mySketchXDir->xyz()) > THE_TOLERANCE); + + if (isChanged) { + mySketch = theSketch; + mySketchOrigin = anOrigin->pnt(); + mySketchNormal = aNorm->dir(); + mySketchXDir = aDirX->dir(); + + myStorage->notify(theSketch); + } + return true; +} + bool SketchSolver_Group::updateFeature(FeaturePtr theFeature) { return myStorage->update(theFeature); } -bool SketchSolver_Group::moveFeature(FeaturePtr theFeature) +template +static SolverConstraintPtr move(StoragePtr theStorage, + SolverPtr theSketchSolver, + int theSketchDOF, + bool theEventsBlocked, + Type theFeatureOrPoint, + const EntityWrapperPtr& theSolverEntity, + const std::shared_ptr& theFrom, + const std::shared_ptr& theTo) { - bool isFeatureExists = (myStorage->entity(theFeature).get() != 0); - if (myDOF == 0 && isFeatureExists) { + bool isEntityExists = (theSolverEntity.get() != 0); + if (theSketchDOF == 0 && isEntityExists) { // avoid moving elements of fully constrained sketch - myStorage->refresh(); - return true; + theStorage->refresh(); + return SolverConstraintPtr(); } // Create temporary Fixed constraint - std::shared_ptr aConstraint = - PlaneGCSSolver_Tools::createMovementConstraint(theFeature); - if (!aConstraint) - return false; - SolverConstraintPtr(aConstraint)->process(myStorage, myIsEventsBlocked); - if (aConstraint->error().empty()) { - setTemporary(aConstraint); - if (!myStorage->isEmpty()) - myStorage->setNeedToResolve(true); - - mySketchSolver->initialize(); - aConstraint->moveFeature(); + std::shared_ptr aConstraint = + PlaneGCSSolver_Tools::createMovementConstraint(theFeatureOrPoint); + if (aConstraint) { + SolverConstraintPtr(aConstraint)->process(theStorage, theEventsBlocked); + if (aConstraint->error().empty()) { + aConstraint->startPoint(theFrom); + theStorage->adjustParametrizationOfArcs(); + theSketchSolver->initialize(); + aConstraint->moveTo(theTo); + theStorage->setNeedToResolve(true); + } else + theStorage->notify(aConstraint->movedFeature()); } - // notify all observers that theFeature has been changed - myStorage->notify(theFeature); + return aConstraint; +} + +bool SketchSolver_Group::moveFeature(FeaturePtr theFeature, + const std::shared_ptr& theFrom, + const std::shared_ptr& theTo) +{ + EntityWrapperPtr anEntity = myStorage->entity(theFeature); + SolverConstraintPtr aConstraint = move(myStorage, mySketchSolver, myDOF, myIsEventsBlocked, + theFeature, anEntity, theFrom, theTo); + setTemporary(aConstraint); + return true; +} + +bool SketchSolver_Group::movePoint(AttributePtr theAttribute, + const int thePointIndex, + const std::shared_ptr& theFrom, + const std::shared_ptr& theTo) +{ + EntityWrapperPtr anEntity = myStorage->entity(theAttribute); + SolverConstraintPtr aConstraint; + if (thePointIndex < 0) { + aConstraint = move(myStorage, mySketchSolver, myDOF, myIsEventsBlocked, + theAttribute, anEntity, theFrom, theTo); + } + else { + aConstraint = move(myStorage, mySketchSolver, myDOF, myIsEventsBlocked, + std::pair(theAttribute, thePointIndex), anEntity, + theFrom, theTo); + } + setTemporary(aConstraint); return true; } @@ -185,14 +251,19 @@ bool SketchSolver_Group::resolveConstraints() PlaneGCSSolver_Solver::SolveStatus aResult = PlaneGCSSolver_Solver::STATUS_OK; try { - if (!isGroupEmpty) + if (!isGroupEmpty) { + myStorage->adjustParametrizationOfArcs(); aResult = mySketchSolver->solve(); + } if (aResult == PlaneGCSSolver_Solver::STATUS_FAILED && !myTempConstraints.empty()) { mySketchSolver->undo(); removeTemporaryConstraints(); aResult = mySketchSolver->solve(); } + // check degenerated geometry after constraints resolving + if (aResult == PlaneGCSSolver_Solver::STATUS_OK) + aResult = myStorage->checkDegeneratedGeometry(); } catch (...) { getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR()) ->setValue(SketchSolver_Error::SOLVESPACE_CRASH()); @@ -238,8 +309,10 @@ bool SketchSolver_Group::resolveConstraints() mySketchSolver->undo(); if (!myConstraints.empty()) { // the error message should be changed before sending the message - getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR()) - ->setValue(SketchSolver_Error::CONSTRAINTS()); + const std::string& aErrorMsg = aResult == PlaneGCSSolver_Solver::STATUS_DEGENERATED ? + SketchSolver_Error::DEGENERATED_GEOMETRY() : + SketchSolver_Error::CONSTRAINTS(); + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(aErrorMsg); if (myPrevResult != aResult || myPrevResult == PlaneGCSSolver_Solver::STATUS_UNKNOWN || myPrevResult == PlaneGCSSolver_Solver::STATUS_FAILED) { @@ -261,10 +334,26 @@ bool SketchSolver_Group::resolveConstraints() myPrevResult = aResult; } } + + // show degrees of freedom only if the degenerated geometry appears, + // or if DoF is not computed yet + if (aResult == PlaneGCSSolver_Solver::STATUS_DEGENERATED || myDOF < 0) + computeDoF(); + } + + } + else if (isGroupEmpty && isWorkplaneValid()) { + // clear error related to previously degenerated entities + if (myPrevResult == PlaneGCSSolver_Solver::STATUS_DEGENERATED) { + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(""); + myPrevResult = PlaneGCSSolver_Solver::STATUS_OK; + // the error message should be changed before sending the message + myConflictingConstraints.clear(); + sendMessage(EVENT_SOLVER_REPAIRED, myConflictingConstraints); } - } else if (isGroupEmpty && isWorkplaneValid()) computeDoF(); + } removeTemporaryConstraints(); myStorage->setNeedToResolve(false); return aResolved; @@ -277,19 +366,33 @@ bool SketchSolver_Group::resolveConstraints() // ============================================================================ void SketchSolver_Group::computeDoF() { - std::ostringstream aDoFMsg; + std::string aDoFMsg; + static const std::string aMsgContext("Sketch"); int aDoF = mySketchSolver->dof(); /// "DoF = 0" content of string value is used in PartSet by Sketch edit /// If it is changed, it should be corrected also there - if (aDoF == 0) - aDoFMsg << "Sketch is fully fixed (DoF = 0)"; - else - aDoFMsg << "DoF (degrees of freedom) = " << aDoF; - mySketch->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aDoFMsg.str()); - - if (aDoF > 0 && myDOF == 0) + //if (aDoF == 0) { + // static const std::string aMsgDoF("Sketch is fully fixed (DoF = 0)"); + // aDoFMsg = Config_Translator::translate(aMsgContext, aMsgDoF); + //} else { + // static const std::string aMsgDoF("DoF (degrees of freedom) = %1"); + // Events_InfoMessage aMsg(aMsgContext, aMsgDoF); + // aMsg.addParameter(aDoF); + // aDoFMsg = Config_Translator::translate(aMsg); + //} + //// store Unicode value for translated message about DoF + //size_t aLen = aDoFMsg.size(); + //std::wstring aWStr(aLen, L'#'); + //mbstowcs(&aWStr[0], aDoFMsg.c_str(), aLen); + //mySketch->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aWStr); + + std::ostringstream aStr; + aStr << aDoF; + mySketch->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aStr.str()); + + if (aDoF > 0 && myDOF <= 0) sendMessage(EVENT_SKETCH_UNDER_CONSTRAINED, mySketch, aDoF); - else if (aDoF == 0 && myDOF > 0) + else if (aDoF == 0 && myDOF != 0) sendMessage(EVENT_SKETCH_FULLY_CONSTRAINED, mySketch, aDoF); else if (aDoF < 0) sendMessage(EVENT_SKETCH_OVER_CONSTRAINED, mySketch, aDoF); @@ -372,7 +475,8 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) // ============================================================================ void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint) { - myTempConstraints.insert(theConstraint); + if (theConstraint) + myTempConstraints.insert(theConstraint); } // ============================================================================ @@ -405,3 +509,8 @@ bool SketchSolver_Group::areConstraintsValid() const return false; return true; } + +void SketchSolver_Group::underconstrainedFeatures(std::set& theFeatures) const +{ + myStorage->getUnderconstrainedGeometry(theFeatures); +}