myPointsJustUpdated.clear();
myAdjusted = true;
}
+
+void SketchSolver_ConstraintMulti::checkCoincidence()
+{
+ std::vector< std::vector<Slvs_hEntity> > aFilteredPoints; // points are filtered by their positions
+
+ std::vector< std::vector<Slvs_hEntity> >::const_iterator aPCIt = myPointsAndCopies.begin();
+ std::vector<Slvs_hEntity>::const_iterator aCIt;
+ for (; aPCIt != myPointsAndCopies.end(); ++aPCIt) {
+ aCIt = aPCIt->begin();
+ // Skip first element, focus the copies only
+ for (++aCIt; aCIt != aPCIt->end(); ++aCIt) {
+ std::vector< std::vector<Slvs_hEntity> >::iterator aFilterIt = aFilteredPoints.begin();
+ for (; aFilterIt != aFilteredPoints.end(); ++aFilterIt)
+ if (myStorage->isEqual(*aCIt, aFilterIt->front())) {
+ aFilterIt->push_back(*aCIt);
+ break;
+ }
+ if (aFilterIt == aFilteredPoints.end()) {
+ std::vector<Slvs_hEntity> aNewFilter(1, *aCIt);
+ aFilteredPoints.push_back(aNewFilter);
+ }
+ }
+ }
+
+ // Check the coicidence of filtered points and remove extra fixation.
+ // Also check separated points which are not fixed.
+ std::vector< std::vector<Slvs_hEntity> >::iterator aFPIt = aFilteredPoints.begin();
+ for (; aFPIt != aFilteredPoints.end(); ++aFPIt) {
+ if (aFPIt->size() <= 1)
+ continue;
+ std::vector<Slvs_hEntity>::iterator anIt1, anIt2;
+ for (anIt1 = aFPIt->begin(); anIt1 != aFPIt->end(); ++anIt1) {
+ for (anIt2 = anIt1 + 1; anIt2 != aFPIt->end(); ++anIt2) {
+ Slvs_hConstraint aFixed1, aFixed2;
+ bool isFixed1 = myStorage->isPointFixed(*anIt1, aFixed1);
+ bool isFixed2 = myStorage->isPointFixed(*anIt2, aFixed2);
+ if (myStorage->isCoincident(*anIt1, *anIt2)) {
+ if (!isFixed1 && isFixed2) {
+ Slvs_hEntity aTmp = *anIt1;
+ *anIt1 = *anIt2;
+ *anIt2 = aTmp;
+ } else if (isFixed1 && isFixed2) {
+ // remove fixing of the second point
+ myStorage->removeConstraint(aFixed2);
+ std::vector<Slvs_hConstraint>::iterator aRemoveIt = mySlvsConstraints.begin();
+ for (; aRemoveIt != mySlvsConstraints.end(); ++aRemoveIt)
+ if (*aRemoveIt == aFixed2) {
+ mySlvsConstraints.erase(aRemoveIt);
+ break;
+ }
+ }
+ } else {
+ bool isFixed[2] = {isFixed1, isFixed2};
+ Slvs_hEntity aPoint[2] = {*anIt1, *anIt2};
+ for (int i = 0; i < 2; i++)
+ if (!isFixed[i]) {
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
+ SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0,
+ aPoint[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aConstraint.h = myStorage->addConstraint(aConstraint);
+ mySlvsConstraints.push_back(aConstraint.h);
+ }
+ }
+ }
+ }
+ }
+}
SketchSolver_Constraint::refresh();
}
+ /// \brief Verifies, the coincidence between points of copied entities appears or disappears,
+ /// and removes or adds fixing of corresponding points.
+ void checkCoincidence();
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
#include <SketchSolver_Builder.h>
#include <SketchSolver_Constraint.h>
#include <SketchSolver_ConstraintCoincidence.h>
+#include <SketchSolver_ConstraintMulti.h>
#include <SketchSolver_Error.h>
#include <Events_Error.h>
// Additional verification of coincidence of several points
if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ bool hasMultiCoincidence = false;
ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
- for (; aCIter != myConstraints.end(); aCIter++) {
+ for (; aCIter != myConstraints.end(); ++aCIter) {
std::shared_ptr<SketchSolver_ConstraintCoincidence> aCoincidence =
std::dynamic_pointer_cast<SketchSolver_ConstraintCoincidence>(aCIter->second);
if (!aCoincidence)
if (anIt->second == aCIter->second)
anIt->second = aCoinc2;
aCIter->second = aCoinc2;
+ hasMultiCoincidence = true;
}
}
+
+ if (hasMultiCoincidence)
+ notifyMultiConstraints();
}
myConstraints[theConstraint] = aConstraint;
}
std::list<ConstraintPtr>::iterator anIt = aMultiCoinc.begin();
for (; anIt != aMultiCoinc.end(); ++anIt)
changeConstraint(*anIt);
+
+ notifyMultiConstraints();
}
}
return aFactory->validate(theFeature);
}
+// ============================================================================
+// Function: notifyMultiConstraints
+// Class: SketchSolver_Group
+// Purpose: Update Multi-Translation/-Rotation constraints due to multi coincidence appears/disappears
+// ============================================================================
+void SketchSolver_Group::notifyMultiConstraints()
+{
+ ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
+ for (; aCIter != myConstraints.end(); ++aCIter) {
+ if (aCIter->first->getKind() == SketchPlugin_MultiRotation::ID() ||
+ aCIter->first->getKind() == SketchPlugin_MultiTranslation::ID()) {
+ std::shared_ptr<SketchSolver_ConstraintMulti> aMulti =
+ std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIter->second);
+ aMulti->checkCoincidence();
+ }
+ }
+}
/// \brief Update just changed constraints
void updateConstraints();
+ /// \brief Update Multi-Translation/-Rotation constraints due to multi coincidence appears/disappears
+ void notifyMultiConstraints();
+
private:
Slvs_hGroup myID; ///< Index of the group
Slvs_hEntity myWorkplaneID; ///< Index of workplane, the group is based on
}
// Search the Rigid constraint
+ theFixed = SLVS_C_UNKNOWN;
std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
for (; aConstrIter != myConstraints.end(); aConstrIter++)
if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
theFixed = aConstrIter->h;
- return true;
+ if (aConstrIter->ptA == thePointID)
+ return true;
}
+ if (theFixed != SLVS_C_UNKNOWN)
+ return true;
if (theAccurate) {
// Try to find the fixed entity which uses such point or its coincidence
myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h;
myNeedToResolve = true;
myRemovedConstraints.insert(theConstraintID);
+ if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
+ removeCoincidence(aConstraint);
+
// Remove all entities
Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB,
aConstraint.entityA, aConstraint.entityB,
}
}
+void SketchSolver_Storage::removeCoincidence(const Slvs_Constraint& theCoincidence)
+{
+ // Find set of coincident points
+ std::vector< std::set<Slvs_hEntity> >::iterator aCIt = myCoincidentPoints.begin();
+ for (; aCIt != myCoincidentPoints.end(); ++aCIt)
+ if (aCIt->find(theCoincidence.ptA) != aCIt->end() ||
+ aCIt->find(theCoincidence.ptB) != aCIt->end())
+ break;
+ if (aCIt == myCoincidentPoints.end())
+ return;
+
+ // Leave only the points which are still coincident
+ std::set<Slvs_hEntity> aRemainCoincidence;
+ std::vector<Slvs_Constraint>::const_iterator aConstrIt = myConstraints.begin();
+ for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
+ if (aConstrIt->type != SLVS_C_POINTS_COINCIDENT)
+ continue;
+ if (aCIt->find(aConstrIt->ptA) != aCIt->end() ||
+ aCIt->find(aConstrIt->ptB) != aCIt->end()) {
+ aRemainCoincidence.insert(aConstrIt->ptA);
+ aRemainCoincidence.insert(aConstrIt->ptB);
+ }
+ }
+ if (aRemainCoincidence.size() <= 1)
+ myCoincidentPoints.erase(aCIt);
+ else
+ aCIt->swap(aRemainCoincidence);
+}
+
bool SketchSolver_Storage::isCoincident(
const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
{
void addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2);
/// \brief Remove point from lists of coincidence
void removeCoincidentPoint(const Slvs_hEntity& thePoint);
+ /// \brief Remove point-point coincidence
+ void removeCoincidence(const Slvs_Constraint& theCoincidence);
public:
/// \brief Check two points are coincident