From ba81013956da94b9d03a21931bc40fa2c985e27a Mon Sep 17 00:00:00 2001 From: azv Date: Fri, 3 Apr 2015 16:21:21 +0300 Subject: [PATCH] Issue #424: Avoid conflicting constraint message. Implemented correction for moving the mirror --- .../SketchSolver_ConstraintMirror.cpp | 68 ++++++++++++++++++- .../SketchSolver_ConstraintMirror.h | 4 ++ .../SketchSolver_ConstraintRigid.cpp | 22 ++++-- src/SketchSolver/SketchSolver_Storage.cpp | 25 +++++++ src/SketchSolver/SketchSolver_Storage.h | 3 + 5 files changed, 114 insertions(+), 8 deletions(-) diff --git a/src/SketchSolver/SketchSolver_ConstraintMirror.cpp b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp index 6ea42d13e..f3ded1d30 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMirror.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp @@ -137,8 +137,8 @@ void SketchSolver_ConstraintMirror::process() aBaseIter->point[2], SLVS_E_UNKNOWN}; Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point - aBaseIter->point[2], - aBaseIter->point[1], + aMirrorIter->point[2], + aMirrorIter->point[1], SLVS_E_UNKNOWN}; Slvs_Entity aBothArcs[2] = {*aBaseIter, *aMirrorIter}; @@ -234,6 +234,10 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity( aMirrorPoint[2] = aMirrorPoint[1]; aMirrorPoint[1] = aTmp; } + if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) { + aBasePoint[0] = theBase.h; + aMirrorPoint[0] = theMirror.h; + } // Mirror line parameters std::shared_ptr aLinePoints[2]; @@ -267,3 +271,63 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity( } } +void SketchSolver_ConstraintMirror::adjustConstraint() +{ + // Search mirror between middle points on the arcs and recompute their coordinates + std::list aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE); + if (aPonCirc.empty()) + return; + + AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; + } + ResultConstructionPtr aRC = + std::dynamic_pointer_cast(aMirLineAttr->object()); + FeaturePtr aFeature = aRC ? aRC->document()->feature(aRC) : + std::dynamic_pointer_cast(aMirLineAttr->object()); + std::map::iterator aMirLineIter = myFeatureMap.find(aFeature); + if (aMirLineIter == myFeatureMap.end()) + return; + Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second); + + double aStartEnd[4]; + for (int i = 0; i < 2; i++) { + Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]); + for (int j = 0; j < 2; j++) + aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val; + } + + Slvs_Constraint aMirror; + std::vector::iterator aConstrIter = mySlvsConstraints.begin(); + for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) { + aMirror = myStorage->getConstraint(*aConstrIter); + if (aMirror.type != SLVS_C_SYMMETRIC_LINE) + continue; + Slvs_Constraint aPonCircA, aPonCircB; + aPonCircA.h = SLVS_E_UNKNOWN; + aPonCircB.h = SLVS_E_UNKNOWN; + std::list::iterator aPtIter = aPonCirc.begin(); + for (; aPtIter != aPonCirc.end(); aPtIter++) { + if (aMirror.ptA == aPtIter->ptA) + aPonCircA = *aPtIter; + if (aMirror.ptB == aPtIter->ptA) + aPonCircB = *aPtIter; + } + if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN) + continue; + + // Calculate middle point for base arc and mirrored point on mirror arc + Slvs_Entity aBaseArc = myStorage->getEntity(aPonCircA.entityA); + Slvs_Entity aBasePoint = myStorage->getEntity(aPonCircA.ptA); + Slvs_Param aParamX = myStorage->getParameter(aBasePoint.param[0]); + Slvs_Param aParamY = myStorage->getParameter(aBasePoint.param[1]); + calculateMiddlePoint(aBaseArc, 0.5, aParamX.val, aParamY.val); + myStorage->updateParameter(aParamX); + myStorage->updateParameter(aParamY); + Slvs_Entity aMirrorPoint = myStorage->getEntity(aPonCircB.ptA); + makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd); + } +} diff --git a/src/SketchSolver/SketchSolver_ConstraintMirror.h b/src/SketchSolver/SketchSolver_ConstraintMirror.h index 092e4dff6..eb3af1fb3 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMirror.h +++ b/src/SketchSolver/SketchSolver_ConstraintMirror.h @@ -50,6 +50,10 @@ protected: std::vector& theBaseEntities, std::vector& theMirrorEntities); + /// \brief This method is used in derived objects to check consistence of constraint. + /// E.g. the distance between line and point may be signed. + virtual void adjustConstraint(); + private: /// \brief Change parameters of entities to be symmetric relative a line, /// given by array of parameters (coordinates of first and last points) diff --git a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp index 75cf0d0d0..a1deb96cc 100644 --- a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp @@ -113,6 +113,8 @@ void SketchSolver_ConstraintRigid::getAttributes( anEntityID = myGroup->getFeatureId(myBaseFeature); if (anEntityID == SLVS_E_UNKNOWN) anEntityID = changeEntity(myBaseFeature, aType); + else + myFeatureMap[myBaseFeature] = anEntityID; } // Check the entity is complex @@ -223,11 +225,19 @@ void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc) } // Fix radius of the arc - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(), - aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, myFeatureMap.begin()->second, SLVS_E_UNKNOWN); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - if (!myBaseConstraint) - myStorage->addTemporaryConstraint(aConstraint.h); + bool isExists = false; + std::list aDiamConstraints = myStorage->getConstraintsByType(SLVS_C_DIAMETER); + std::list::iterator anIt = aDiamConstraints.begin(); + for (; anIt != aDiamConstraints.end() && !isExists; anIt) + if (anIt->entityA == myFeatureMap.begin()->second) + isExists = true; + if (!isExists) { + aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(), + aRadius * 2.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, myFeatureMap.begin()->second, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + if (!myBaseConstraint) + myStorage->addTemporaryConstraint(aConstraint.h); + } } diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index 9dbf54f0c..d4a517132 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -226,6 +226,20 @@ Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theC } Slvs_Constraint aConstraint = theConstraint; + + // Find a constraint with same type uses same arguments + std::vector::iterator aCIt = myConstraints.begin(); + for (; aCIt != myConstraints.end(); aCIt++) { + if (aConstraint.type != aCIt->type) + continue; + if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB && + aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB && + aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD) { + aConstraint.h = aCIt->h; + return updateConstraint(aConstraint); + } + } + if (aConstraint.h > myConstrMaxID) myConstrMaxID = aConstraint.h; else @@ -293,6 +307,17 @@ const Slvs_Constraint& SketchSolver_Storage::getConstraint(const Slvs_hConstrain return aDummy; } +std::list SketchSolver_Storage::getConstraintsByType(int theConstraintType) const +{ + std::list aResult; + std::vector::const_iterator aCIter = myConstraints.begin(); + for (; aCIter != myConstraints.end(); aCIter++) + if (aCIter->type == theConstraintType) + aResult.push_back(*aCIter); + return aResult; +} + + void SketchSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID) { if (myFixed != SLVS_E_UNKNOWN) diff --git a/src/SketchSolver/SketchSolver_Storage.h b/src/SketchSolver/SketchSolver_Storage.h index 70f2622b1..cf04f47ab 100644 --- a/src/SketchSolver/SketchSolver_Storage.h +++ b/src/SketchSolver/SketchSolver_Storage.h @@ -10,6 +10,7 @@ #include "SketchSolver.h" #include +#include #include #include #include @@ -83,6 +84,8 @@ public: bool removeConstraint(const Slvs_hConstraint& theConstraintID); /// \brief Returns the constraint by its ID const Slvs_Constraint& getConstraint(const Slvs_hConstraint& theConstraintID) const; + /// \brief Returns list of constraints of specified type + std::list getConstraintsByType(int theConstraintType) const; /// \brief Attach temporary constraint to this storage. It need to make precise calculations void addTemporaryConstraint(const Slvs_hConstraint& theConstraintID); -- 2.39.2