X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSketchSolver%2FSketchSolver_Group.cpp;h=4c005e9d318e52134c9fc4afe3acd0564d699821;hb=3ea24ee33413ac77fdc8cd3ad63c0fde5da00c11;hp=709407ee5d79cb9594f433db8f3ab60a75102aea;hpb=a2ab2dc339b560c7309540e1f10b6ad60e5ed0af;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 709407ee5..4c005e9d3 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -1,8 +1,22 @@ -// Copyright (C) 2014-20xx CEA/DEN, EDF R&D - -// File: SketchSolver_Group.cpp -// Created: 27 May 2014 -// Author: Artem ZHIDKOV +// Copyright (C) 2014-2017 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 "SketchSolver_Group.h" #include @@ -15,7 +29,10 @@ #include #include #include +#include #include +#include +#include static void sendMessage(const char* theMessageName) @@ -34,7 +51,9 @@ static void sendMessage(const char* theMessageName, const std::set& t Events_Loop::loop()->send(aMessage); } -static void sendMessage(const char* theMessageName, const CompositeFeaturePtr& theSketch, const int theDOF) +static void sendMessage(const char* theMessageName, + const CompositeFeaturePtr& theSketch, + const int theDOF) { std::shared_ptr aMessage = std::shared_ptr( @@ -51,14 +70,15 @@ static void sendMessage(const char* theMessageName, const CompositeFeaturePtr& t // ======================================================== -// ========= SketchSolver_Group =============== +// ========= SketchSolver_Group =============== // ======================================================== SketchSolver_Group::SketchSolver_Group(const CompositeFeaturePtr& theWorkplane) : mySketch(theWorkplane), myPrevResult(PlaneGCSSolver_Solver::STATUS_UNKNOWN), myDOF(0), - myIsEventsBlocked(false) + myIsEventsBlocked(false), + myMultiConstraintUpdateStack(0) { mySketchSolver = SolverPtr(new PlaneGCSSolver_Solver); myStorage = StoragePtr(new PlaneGCSSolver_Storage(mySketchSolver)); @@ -98,6 +118,9 @@ bool SketchSolver_Group::changeConstraint( } else myConstraints[theConstraint]->update(); + + // constraint is created/updated => reset stack of "multi" constraints updates + myMultiConstraintUpdateStack = 0; return true; } @@ -106,24 +129,56 @@ 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 std::shared_ptr& theFrom, + const std::shared_ptr& theTo) { - if (myDOF == 0) { + bool isEntityExists = (theStorage->entity(theFeatureOrPoint).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 - SolverConstraintPtr aConstraint = PlaneGCSSolver_Tools::createMovementConstraint(theFeature); - if (!aConstraint) - return false; - aConstraint->process(myStorage, myIsEventsBlocked); - if (aConstraint->error().empty()) - setTemporary(aConstraint); - else - myStorage->notify(theFeature); + std::shared_ptr aConstraint = + PlaneGCSSolver_Tools::createMovementConstraint(theFeatureOrPoint); + if (aConstraint) { + SolverConstraintPtr(aConstraint)->process(theStorage, theEventsBlocked); + if (aConstraint->error().empty()) { + aConstraint->startPoint(theFrom); + theSketchSolver->initialize(); + aConstraint->moveTo(theTo); + theStorage->setNeedToResolve(true); + } else + theStorage->notify(aConstraint->movedFeature()); + } + + return aConstraint; +} +bool SketchSolver_Group::moveFeature(FeaturePtr theFeature, + const std::shared_ptr& theFrom, + const std::shared_ptr& theTo) +{ + SolverConstraintPtr aConstraint = + move(myStorage, mySketchSolver, myDOF, myIsEventsBlocked, theFeature, theFrom, theTo); + setTemporary(aConstraint); + return true; +} + +bool SketchSolver_Group::movePoint(AttributePtr theAttribute, + const std::shared_ptr& theFrom, + const std::shared_ptr& theTo) +{ + SolverConstraintPtr aConstraint = + move(myStorage, mySketchSolver, myDOF, myIsEventsBlocked, theAttribute, theFrom, theTo); + setTemporary(aConstraint); return true; } @@ -134,6 +189,18 @@ bool SketchSolver_Group::moveFeature(FeaturePtr theFeature) // ============================================================================ bool SketchSolver_Group::resolveConstraints() { + static const int MAX_STACK_SIZE = 5; + // check the "Multi" constraints do not drop sketch into infinite loop + if (myMultiConstraintUpdateStack > MAX_STACK_SIZE) { + myMultiConstraintUpdateStack = 0; + myPrevResult = PlaneGCSSolver_Solver::STATUS_FAILED; + // generate error message due to loop update of the sketch + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR()) + ->setValue(SketchSolver_Error::INFINITE_LOOP()); + sendMessage(EVENT_SOLVER_FAILED, myConflictingConstraints); + return false; + } + bool aResolved = false; bool isGroupEmpty = isEmpty() && myStorage->isEmpty(); if (myStorage->isNeedToResolve() && @@ -144,6 +211,12 @@ bool SketchSolver_Group::resolveConstraints() try { if (!isGroupEmpty) aResult = mySketchSolver->solve(); + if (aResult == PlaneGCSSolver_Solver::STATUS_FAILED && + !myTempConstraints.empty()) { + mySketchSolver->undo(); + removeTemporaryConstraints(); + aResult = mySketchSolver->solve(); + } } catch (...) { getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR()) ->setValue(SketchSolver_Error::SOLVESPACE_CRASH()); @@ -161,19 +234,26 @@ bool SketchSolver_Group::resolveConstraints() aResult == PlaneGCSSolver_Solver::STATUS_EMPTYSET) { myStorage->setNeedToResolve(false); myStorage->refresh(); -//// updateMultiConstraints(myConstraints); -//// // multi-constraints updated some parameters, need to store them -//// if (myStorage->isNeedToResolve()) -//// resolveConstraints(); - if (myPrevResult != PlaneGCSSolver_Solver::STATUS_OK || - myPrevResult == PlaneGCSSolver_Solver::STATUS_UNKNOWN) { - getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(""); - std::set aConflicting = myConflictingConstraints; - myConflictingConstraints.clear(); - myPrevResult = PlaneGCSSolver_Solver::STATUS_OK; - // the error message should be changed before sending the message - sendMessage(EVENT_SOLVER_REPAIRED, aConflicting); + // additional check that copied entities used in Mirror and other "Multi" constraints + // is not connected with their originals by constraints. + myMultiConstraintUpdateStack += 1; + aResolved = true; + if (myStorage->isNeedToResolve()) + aResolved = resolveConstraints(); + + if (aResolved) { + myMultiConstraintUpdateStack -= 1; + + if (myPrevResult != PlaneGCSSolver_Solver::STATUS_OK || + myPrevResult == PlaneGCSSolver_Solver::STATUS_UNKNOWN) { + getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(""); + std::set aConflicting = myConflictingConstraints; + myConflictingConstraints.clear(); + myPrevResult = PlaneGCSSolver_Solver::STATUS_OK; + // the error message should be changed before sending the message + sendMessage(EVENT_SOLVER_REPAIRED, aConflicting); + } } // show degrees of freedom @@ -207,18 +287,6 @@ bool SketchSolver_Group::resolveConstraints() } } - aResolved = true; - } else if (!isGroupEmpty) { - // Check if the group contains only constraints Fixed, update parameters by stored values - aResolved = true; - ConstraintConstraintMap::iterator aCIt = myConstraints.begin(); - for (; aCIt != myConstraints.end(); ++aCIt) - if (aCIt->first->getKind() != SketchPlugin_ConstraintRigid::ID()) { - aResolved = false; - break; - } - if (aCIt == myConstraints.end()) - myStorage->refresh(); } else if (isGroupEmpty && isWorkplaneValid()) computeDoF(); removeTemporaryConstraints(); @@ -235,6 +303,8 @@ void SketchSolver_Group::computeDoF() { std::ostringstream aDoFMsg; 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 @@ -243,7 +313,7 @@ void SketchSolver_Group::computeDoF() 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); @@ -258,7 +328,7 @@ void SketchSolver_Group::computeDoF() // ============================================================================ void SketchSolver_Group::repairConsistency() { - if (!myStorage->isConsistent()) { + if (!areConstraintsValid() || !myStorage->areFeaturesValid()) { // remove invalid constraints std::set anInvalidConstraints; ConstraintConstraintMap::iterator aCIter = myConstraints.begin(); @@ -310,6 +380,9 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) for (; aCIter != myConstraints.end(); aCIter++) if (aCIter->first == theConstraint) { aCIter->second->remove(); // the constraint is not fully removed + + // constraint is removed => reset stack of "multi" constraints updates + myMultiConstraintUpdateStack = 0; break; } if (aCIter != myConstraints.end()) @@ -323,7 +396,8 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) // ============================================================================ void SketchSolver_Group::setTemporary(SolverConstraintPtr theConstraint) { - myTempConstraints.insert(theConstraint); + if (theConstraint) + myTempConstraints.insert(theConstraint); } // ============================================================================ @@ -346,3 +420,13 @@ void SketchSolver_Group::blockEvents(bool isBlocked) myIsEventsBlocked = isBlocked; } + +bool SketchSolver_Group::areConstraintsValid() const +{ + // Check the constraints are valid + ConstraintConstraintMap::const_iterator aCIter = myConstraints.begin(); + for (; aCIter != myConstraints.end(); ++aCIter) + if (!aCIter->first->data() || !aCIter->first->data()->isValid()) + return false; + return true; +}