From 6534ec23cbbcf075080dde61be55628c4814a793 Mon Sep 17 00:00:00 2001 From: azv Date: Mon, 29 Feb 2016 16:54:35 +0300 Subject: [PATCH] Collinear and coinciding point constraints problem (issue #1318) Improve working with coincident points. --- src/SketchSolver/CMakeLists.txt | 2 + src/SketchSolver/SketchSolver_Builder.cpp | 4 ++ src/SketchSolver/SketchSolver_Constraint.cpp | 2 + src/SketchSolver/SketchSolver_Constraint.h | 9 ++++ .../SketchSolver_ConstraintCollinear.cpp | 54 +++++++++++++++++++ .../SketchSolver_ConstraintCollinear.h | 28 ++++++++++ src/SketchSolver/SketchSolver_Group.cpp | 15 ++++++ src/SketchSolver/SketchSolver_Group.h | 4 ++ 8 files changed, 118 insertions(+) create mode 100644 src/SketchSolver/SketchSolver_ConstraintCollinear.cpp create mode 100644 src/SketchSolver/SketchSolver_ConstraintCollinear.h diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index e8ebc506c..b2eb54738 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -8,6 +8,7 @@ SET(PROJECT_HEADERS SketchSolver_Constraint.h SketchSolver_ConstraintAngle.h SketchSolver_ConstraintCoincidence.h + SketchSolver_ConstraintCollinear.h SketchSolver_ConstraintDistance.h SketchSolver_ConstraintEqual.h SketchSolver_ConstraintLength.h @@ -33,6 +34,7 @@ SET(PROJECT_SOURCES SketchSolver_Constraint.cpp SketchSolver_ConstraintAngle.cpp SketchSolver_ConstraintCoincidence.cpp + SketchSolver_ConstraintCollinear.cpp SketchSolver_ConstraintDistance.cpp SketchSolver_ConstraintEqual.cpp SketchSolver_ConstraintLength.cpp diff --git a/src/SketchSolver/SketchSolver_Builder.cpp b/src/SketchSolver/SketchSolver_Builder.cpp index dece279ca..4709e6833 100644 --- a/src/SketchSolver/SketchSolver_Builder.cpp +++ b/src/SketchSolver/SketchSolver_Builder.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include +#include #include #include #include @@ -77,6 +79,8 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintCoincidence(theConstraint)); + } else if (theConstraint->getKind() == SketchPlugin_ConstraintCollinear::ID()) { + return SolverConstraintPtr(new SketchSolver_ConstraintCollinear(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintDistance(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) { diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index 1d765142e..fcb2a1fc1 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -201,6 +201,7 @@ void SketchSolver_Constraint::getAttributes( { static const int anInitNbOfAttr = 4; theAttributes.assign(anInitNbOfAttr, EntityWrapperPtr()); + myAttributes.clear(); DataPtr aData = myBaseConstraint->data(); BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder(); @@ -225,6 +226,7 @@ void SketchSolver_Constraint::getAttributes( myStorage->update(*anIter/*, myGroupID*/); EntityWrapperPtr anEntity = myStorage->entity(*anIter); + myAttributes.push_back(anEntity); SketchSolver_EntityType aType = anEntity->type(); if (aType == ENTITY_UNKNOWN) diff --git a/src/SketchSolver/SketchSolver_Constraint.h b/src/SketchSolver/SketchSolver_Constraint.h index 3f6e0f281..dbb647623 100644 --- a/src/SketchSolver/SketchSolver_Constraint.h +++ b/src/SketchSolver/SketchSolver_Constraint.h @@ -57,11 +57,19 @@ public: virtual SketchSolver_ConstraintType getType() const { return myType; } + /// \brief Returns list of attributes of constraint + const std::list& attributes() const + { return myAttributes; } + /// \brief Verify the feature or any its attribute is used by constraint virtual bool isUsed(FeaturePtr theFeature) const; /// \brief Verify the attribute is used by constraint virtual bool isUsed(AttributePtr theAttribute) const; + /// \brief Notify constraint, that coincidence appears or removed + virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1, EntityWrapperPtr theCoincAttr2) + { /* implement in derived class */ } + /// \brief Shows error message const std::string& error() const { return myErrorMsg; } @@ -90,6 +98,7 @@ protected: ConstraintPtr myBaseConstraint; ///< base SketchPlugin constraint StoragePtr myStorage; ///< storage, which contains all information about entities and constraints SketchSolver_ConstraintType myType; ///< type of constraint + std::list myAttributes; ///< attributes of constraint std::string myErrorMsg; ///< error message }; diff --git a/src/SketchSolver/SketchSolver_ConstraintCollinear.cpp b/src/SketchSolver/SketchSolver_ConstraintCollinear.cpp new file mode 100644 index 000000000..682782624 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintCollinear.cpp @@ -0,0 +1,54 @@ +#include +#include + +#include + +SketchSolver_ConstraintCollinear::SketchSolver_ConstraintCollinear(ConstraintPtr theConstraint) + : SketchSolver_Constraint(theConstraint) +{ +} + +void SketchSolver_ConstraintCollinear::notifyCoincidenceChanged( + EntityWrapperPtr theCoincAttr1, + EntityWrapperPtr theCoincAttr2) +{ + bool used = true; + + // obtain IDs of all boundary points of lines + EntityID aPointIDs[4]; + for (int i = 0; i < 2; ++i) { + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i))); + if (!aRefAttr->object()) + continue; + FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object()); + AttributePtr aLinePt = aLine->attribute(SketchPlugin_Line::START_ID()); + aPointIDs[2*i] = myStorage->entity(aLinePt)->id(); + aLinePt = aLine->attribute(SketchPlugin_Line::END_ID()); + aPointIDs[2*i + 1] = myStorage->entity(aLinePt)->id(); + } + + EntityWrapperPtr anAttrs[2] = {theCoincAttr1, theCoincAttr2}; + for (int i = 0; i < 2 && used; ++i) { + if (anAttrs[i]->baseAttribute()) + used = used && isUsed(anAttrs[i]->baseAttribute()); + else + used = used && isUsed(anAttrs[i]->baseFeature()); + + if (!used) { + if (anAttrs[i]->type() == ENTITY_POINT) { + EntityID anID = anAttrs[i]->id(); + for (int j = 0; j < 4; ++j) + if (anID == aPointIDs[j]) { + used = true; + break; + } + } + } + } + + if (used) { + remove(); + process(); + } +} diff --git a/src/SketchSolver/SketchSolver_ConstraintCollinear.h b/src/SketchSolver/SketchSolver_ConstraintCollinear.h new file mode 100644 index 000000000..6299740dd --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintCollinear.h @@ -0,0 +1,28 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintCollinear.h +// Created: 27 May 2014 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintCollinear_H_ +#define SketchSolver_ConstraintCollinear_H_ + +#include + +/** \class SketchSolver_ConstraintCollinear + * \ingroup Plugins + * \brief Converts collinear constraint to the constraint applicable for solver + */ +class SketchSolver_ConstraintCollinear : public SketchSolver_Constraint +{ +public: + /// Constructor based on SketchPlugin constraint + SKETCHSOLVER_EXPORT SketchSolver_ConstraintCollinear(ConstraintPtr theConstraint); + + virtual ~SketchSolver_ConstraintCollinear() {} + + /// \brief Notify constraint, that coincidence appears or removed + virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1, EntityWrapperPtr theCoincAttr2); +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index c2034c157..6a2dc0a00 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -169,6 +169,9 @@ bool SketchSolver_Group::changeConstraint( Events_Error::send(aConstraint->error(), this); } myConstraints[theConstraint] = aConstraint; + + if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) + notifyCoincidenceChanged(myConstraints[theConstraint]); } else myConstraints[theConstraint]->update(); @@ -561,6 +564,8 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) for (; aCIter != myConstraints.end(); aCIter++) if (aCIter->first == theConstraint) { aCIter->second->remove(); // the constraint is not fully removed + if (aCIter->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) + notifyCoincidenceChanged(aCIter->second); break; } if (aCIter != myConstraints.end()) @@ -674,3 +679,13 @@ std::list SketchSolver_Group::selectApplicableFeatures(const std::se return aResult; } +void SketchSolver_Group::notifyCoincidenceChanged(SolverConstraintPtr theCoincidence) +{ + const std::list& aCoincident = theCoincidence->attributes(); + EntityWrapperPtr anAttr1 = aCoincident.front(); + EntityWrapperPtr anAttr2 = aCoincident.back(); + + ConstraintConstraintMap::iterator anIt = myConstraints.begin(); + for (; anIt != myConstraints.end(); ++anIt) + anIt->second->notifyCoincidenceChanged(anAttr1, anAttr2); +} diff --git a/src/SketchSolver/SketchSolver_Group.h b/src/SketchSolver/SketchSolver_Group.h index f814dda84..89a14f490 100644 --- a/src/SketchSolver/SketchSolver_Group.h +++ b/src/SketchSolver/SketchSolver_Group.h @@ -155,6 +155,10 @@ private: /// \brief Verifies is the feature valid bool checkFeatureValidity(FeaturePtr theFeature); + /// \brief Notify all interested constraints that coincidence appears or removed + /// \param[in] theCoincidence coincidence constraint + void notifyCoincidenceChanged(SolverConstraintPtr theCoincidence); + private: GroupID myID; ///< Index of the group EntityID myWorkplaneID; ///< Index of workplane, the group is based on -- 2.39.2