From ecbff108f921874403c20972be1c654d2168b81c Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 3 Mar 2016 14:59:04 +0300 Subject: [PATCH] Fix conflict on middle-point constraint when the point is already on the line (issue #1315) --- src/SketchSolver/CMakeLists.txt | 2 + .../PlaneGCSSolver_ConstraintWrapper.h | 3 ++ .../PlaneGCSSolver/PlaneGCSSolver_Storage.cpp | 40 +++++++++++++++++- src/SketchSolver/SketchSolver_Builder.cpp | 4 ++ .../SketchSolver_ConstraintMiddle.cpp | 41 +++++++++++++++++++ .../SketchSolver_ConstraintMiddle.h | 28 +++++++++++++ .../SolveSpaceSolver_Storage.cpp | 23 +++++++++++ 7 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 src/SketchSolver/SketchSolver_ConstraintMiddle.cpp create mode 100644 src/SketchSolver/SketchSolver_ConstraintMiddle.h diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index b2eb54738..ac4117627 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -12,6 +12,7 @@ SET(PROJECT_HEADERS SketchSolver_ConstraintDistance.h SketchSolver_ConstraintEqual.h SketchSolver_ConstraintLength.h + SketchSolver_ConstraintMiddle.h SketchSolver_ConstraintMirror.h SketchSolver_ConstraintFixed.h SketchSolver_ConstraintFixedArcRadius.h @@ -38,6 +39,7 @@ SET(PROJECT_SOURCES SketchSolver_ConstraintDistance.cpp SketchSolver_ConstraintEqual.cpp SketchSolver_ConstraintLength.cpp + SketchSolver_ConstraintMiddle.cpp SketchSolver_ConstraintMirror.cpp SketchSolver_ConstraintFixed.cpp SketchSolver_ConstraintFixedArcRadius.cpp diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h index db2972db1..ebf65ea65 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_ConstraintWrapper.h @@ -28,6 +28,9 @@ public: /// \brief Return list of constraints const std::list& constraints() const { return myGCSConstraints; } + /// \brief Change list of constraints + void setConstraints(const std::list& theConstraints) + { myGCSConstraints = theConstraints; } /// \brief Return ID of current entity virtual ConstraintID id() const diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp index b79fd0dc8..3e9b00b75 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Storage.cpp @@ -67,9 +67,45 @@ bool PlaneGCSSolver_Storage::update(ConstraintWrapperPtr theConstraint) for (; anIt != anEntities.end(); ++anIt) isUpdated = update(*anIt) || isUpdated; - // Change ID of constraints - if (aConstraint->id() == CID_UNKNOWN) + if (aConstraint->id() == CID_UNKNOWN) { + const std::list& aSubs = aConstraint->entities(); + // check middle-point constraint conflicts with point-on-line + if (aConstraint->type() == CONSTRAINT_MIDDLE_POINT) { + std::map >::const_iterator + anIt = myConstraintMap.begin(); + for (; anIt != myConstraintMap.end(); ++anIt) { + EntityWrapperPtr aPoint, aLine; + ConstraintWrapperPtr aCurrentConstr = anIt->second.front(); + if (aCurrentConstr->type() != CONSTRAINT_PT_ON_LINE) + continue; + const std::list& aCurSubs = aCurrentConstr->entities(); + std::list::const_iterator aSIt1, aSIt2; + for (aSIt1 = aSubs.begin(); aSIt1 != aSubs.end(); ++aSIt1) { + if ((*aSIt1)->type() == ENTITY_POINT) + aPoint = *aSIt1; + else if((*aSIt1)->type() == ENTITY_LINE) + aLine = *aSIt1; + else + continue; + for (aSIt2 = aCurSubs.begin(); aSIt2 != aCurSubs.end(); ++aSIt2) + if ((*aSIt1)->id() == (*aSIt2)->id()) + break; + if (aSIt2 == aCurSubs.end()) + break; + } + // point-on-line found, change it to bisector + if (aSIt1 == aSubs.end()) { + std::list aConstrList = aConstraint->constraints(); + aConstrList.pop_front(); + aConstraint->setConstraints(aConstrList); + break; + } + } + } + + // Change ID of constraints aConstraint->setId(++myConstraintLastID); + } return isUpdated; } diff --git a/src/SketchSolver/SketchSolver_Builder.cpp b/src/SketchSolver/SketchSolver_Builder.cpp index 4709e6833..ba7074e50 100644 --- a/src/SketchSolver/SketchSolver_Builder.cpp +++ b/src/SketchSolver/SketchSolver_Builder.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -87,6 +89,8 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint)); + } else if (theConstraint->getKind() == SketchPlugin_ConstraintMiddle::ID()) { + return SolverConstraintPtr(new SketchSolver_ConstraintMiddle(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintTangent::ID()) { diff --git a/src/SketchSolver/SketchSolver_ConstraintMiddle.cpp b/src/SketchSolver/SketchSolver_ConstraintMiddle.cpp new file mode 100644 index 000000000..826a429af --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintMiddle.cpp @@ -0,0 +1,41 @@ +#include + +SketchSolver_ConstraintMiddle::SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint) + : SketchSolver_Constraint(theConstraint) +{ +} + +void SketchSolver_ConstraintMiddle::notifyCoincidenceChanged( + EntityWrapperPtr theCoincAttr1, + EntityWrapperPtr theCoincAttr2) +{ + // Check the coincidence between point and line has been changed + AttributePtr aPoint; + FeaturePtr aLine; + EntityWrapperPtr anEntities[2] = {theCoincAttr1, theCoincAttr2}; + for (int i = 0; i < 2; ++i) { + if (anEntities[i]->type() == ENTITY_POINT) + aPoint = anEntities[i]->baseAttribute(); + else if (anEntities[i]->type() == ENTITY_LINE) + aLine = anEntities[i]->baseFeature(); + } + if (!aPoint || !aLine) + return; + + // Check the attributes of middle-point constraint are the same point and line + bool isSameAttr = true; + for (int i = 0; i < 2 && isSameAttr; ++i) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i))); + if (aRefAttr->isObject()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + isSameAttr = (aFeature == aLine); + } else + isSameAttr = (aRefAttr->attr() == aPoint); + } + + if (isSameAttr) { + remove(); + process(); + } +} diff --git a/src/SketchSolver/SketchSolver_ConstraintMiddle.h b/src/SketchSolver/SketchSolver_ConstraintMiddle.h new file mode 100644 index 000000000..b86e714f5 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintMiddle.h @@ -0,0 +1,28 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintMiddle.h +// Created: 03 March 2016 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintMiddle_H_ +#define SketchSolver_ConstraintMiddle_H_ + +#include + +/** \class SketchSolver_ConstraintMiddle + * \ingroup Plugins + * \brief Converts middle-point constraint to the constraint applicable for solver + */ +class SketchSolver_ConstraintMiddle : public SketchSolver_Constraint +{ +public: + /// Constructor based on SketchPlugin constraint + SKETCHSOLVER_EXPORT SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint); + + virtual ~SketchSolver_ConstraintMiddle() {} + + /// \brief Notify constraint, that coincidence appears or removed + virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1, EntityWrapperPtr theCoincAttr2); +}; + +#endif diff --git a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp index c1bd90b6e..d796f7964 100644 --- a/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp +++ b/src/SketchSolver/SolveSpaceSolver/SolveSpaceSolver_Storage.cpp @@ -798,6 +798,29 @@ Slvs_hConstraint SolveSpaceSolver_Storage::updateConstraint(const Slvs_Constrain // Constraint is not found, add new one Slvs_Constraint aConstraint = theConstraint; aConstraint.h = 0; + + // Firstly, check middle-point constraint conflicts with point-on-line + if (aConstraint.type == SLVS_C_AT_MIDPOINT) { + std::vector::const_iterator anIt = myConstraints.begin(); + for (; anIt != myConstraints.end(); ++anIt) + if (anIt->type == SLVS_C_PT_ON_LINE && + anIt->ptA == aConstraint.ptA && + anIt->entityA == aConstraint.entityA) + break; + if (anIt != myConstraints.end()) { + // change the constraint to the lengths equality to avoid conflicts + Slvs_Entity aLine = getEntity(aConstraint.entityA); + Slvs_Entity aNewLine1 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroupID, + myWorkplaneID, aLine.point[0], aConstraint.ptA); + aNewLine1.h = addEntity(aNewLine1); + Slvs_Entity aNewLine2 = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroupID, + myWorkplaneID, aLine.point[1], aConstraint.ptA); + aNewLine2.h = addEntity(aNewLine2); + aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroupID, SLVS_C_EQUAL_LENGTH_LINES, + myWorkplaneID, 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aNewLine1.h, aNewLine2.h); + } + } + return addConstraint(aConstraint); } -- 2.39.2