From 33079643b5c49725368969aa1b1d7218a4291cf1 Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 13 Aug 2015 14:51:19 +0300 Subject: [PATCH] Update behavior of calculation of Multi-Translation constraint --- ...ketchSolver_ConstraintMultiTranslation.cpp | 225 ++++++++++-------- .../SketchSolver_ConstraintMultiTranslation.h | 16 +- 2 files changed, 137 insertions(+), 104 deletions(-) diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp index 8dba38189..5b7b27538 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.cpp @@ -20,8 +20,8 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes( Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint, - std::vector >& thePoints, - std::vector >& theCircular) + std::vector< std::vector >& thePoints, + std::vector< std::vector >& theEntities) { DataPtr aData = myBaseConstraint->data(); AttributePtr aStartPointAttr = aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID()); @@ -59,20 +59,22 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes( // Also all circles and arc collected too, because they will be constrained by equal radii. FeaturePtr aFeature; ResultConstructionPtr aRC; - std::vector aPoints[2]; // lists of points of features - std::vector aCircs; // list of circular objects + static const size_t MAX_POINTS = 3; + std::vector aPoints[MAX_POINTS]; // lists of points of features + std::vector anEntities; // list of translated entities std::list anObjectList = aRefList->list(); std::list::iterator anObjectIter = anObjectList.begin(); while (anObjectIter != anObjectList.end()) { - aPoints[0].clear(); - aPoints[1].clear(); - aCircs.clear(); + for (size_t i = 0; i < MAX_POINTS; i++) + aPoints[i].clear(); + anEntities.clear(); for (size_t i = 0; i <= myNumberOfCopies && anObjectIter != anObjectList.end(); i++, anObjectIter++) { aFeature = ModelAPI_Feature::feature(*anObjectIter); if (!aFeature) continue; anEntityID = changeEntity(aFeature, aType); + anEntities.push_back(anEntityID); Slvs_Entity anEntity = myStorage->getEntity(anEntityID); switch (aType) { case SLVS_E_POINT_IN_2D: @@ -85,12 +87,11 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes( break; case SLVS_E_CIRCLE: aPoints[0].push_back(anEntity.point[0]); // center of circle - aCircs.push_back(anEntityID); break; case SLVS_E_ARC_OF_CIRCLE: - aPoints[0].push_back(anEntity.point[1]); // start point of arc - aPoints[1].push_back(anEntity.point[2]); // end point of arc - aCircs.push_back(anEntityID); + aPoints[0].push_back(anEntity.point[0]); // center of arc + aPoints[1].push_back(anEntity.point[1]); // start point of arc + aPoints[2].push_back(anEntity.point[2]); // end point of arc break; default: myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); @@ -98,12 +99,11 @@ void SketchSolver_ConstraintMultiTranslation::getAttributes( } } - if (!aPoints[0].empty()) - thePoints.push_back(aPoints[0]); - if (!aPoints[1].empty()) - thePoints.push_back(aPoints[1]); - if (!aCircs.empty()) - theCircular.push_back(aCircs); + for (size_t i = 0; i < MAX_POINTS; ++i) + if (!aPoints[i].empty()) + thePoints.push_back(aPoints[i]); + if (!anEntities.empty()) + theEntities.push_back(anEntities); } } @@ -118,50 +118,46 @@ void SketchSolver_ConstraintMultiTranslation::process() update(myBaseConstraint); Slvs_hEntity aStartPoint, aEndPoint; - std::vector > aPointsAndCopies; - std::vector > aCircsAndCopies; - getAttributes(aStartPoint, aEndPoint, aPointsAndCopies, aCircsAndCopies); + std::vector > anEntitiesAndCopies; + getAttributes(aStartPoint, aEndPoint, myPointsAndCopies, anEntitiesAndCopies); if (!myErrorMsg.empty()) return; - // Create lines between neighbor translated points and make them parallel to the translation line. - // Also these lines should have equal lengths. - Slvs_Constraint aConstraint; - Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(), - myGroup->getWorkplaneId(), aStartPoint, aEndPoint); - aTranslationLine.h = myStorage->addEntity(aTranslationLine); - myTranslationLine = aTranslationLine.h; - std::vector >::iterator aCopyIter = aPointsAndCopies.begin(); - for (; aCopyIter != aPointsAndCopies.end(); aCopyIter++) { - size_t aSize = aCopyIter->size(); - for (size_t i = 0; i < aSize - 1; i++) { - Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(), - myGroup->getWorkplaneId(), (*aCopyIter)[i], (*aCopyIter)[i+1]); - aLine.h = myStorage->addEntity(aLine); - // Equal length constraint - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), - SLVS_C_EQUAL_LENGTH_LINES, myGroup->getWorkplaneId(), 0.0, - SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aTranslationLine.h, aLine.h); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - // Parallel constraint - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), - SLVS_C_PARALLEL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, - aTranslationLine.h, aLine.h); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); + // Create translation line + if (myTranslationLine == SLVS_E_UNKNOWN) { + Slvs_Entity aTranslationLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(), + myGroup->getWorkplaneId(), aStartPoint, aEndPoint); + aTranslationLine.h = myStorage->addEntity(aTranslationLine); + myTranslationLine = aTranslationLine.h; + } else { + Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine); + if (aTranslationLine.point[0] != aStartPoint || aTranslationLine.point[1] != aEndPoint) { + aTranslationLine.point[0] = aStartPoint; + aTranslationLine.point[1] = aEndPoint; + myStorage->updateEntity(aTranslationLine); } } - // Equal radii constraints - for (aCopyIter = aCircsAndCopies.begin(); aCopyIter != aCircsAndCopies.end(); aCopyIter++) { - size_t aSize = aCopyIter->size(); - for (size_t i = 0; i < aSize - 1; i++) { - aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), - SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, - (*aCopyIter)[i], (*aCopyIter)[i+1]); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); + + // Set all objects unchanged (only initial object may be changed by user) + myCircsAndCopies.clear(); + std::vector >::const_iterator anEntIt = anEntitiesAndCopies.begin(); + std::vector::const_iterator aCpIt; + for (; anEntIt != anEntitiesAndCopies.end(); ++anEntIt) { + std::vector aCircs; + for (aCpIt = anEntIt->begin(); aCpIt != anEntIt->end(); ++aCpIt) { + const Slvs_Entity& anEntity = myStorage->getEntity(*aCpIt); + std::vector aNewConstr; + if (anEntity.type == SLVS_E_CIRCLE) { + aCircs.push_back(anEntity.distance); + // for circles we fix only center + aNewConstr = myStorage->fixEntity(anEntity.point[0]); + } else + aNewConstr = myStorage->fixEntity(*aCpIt); + mySlvsConstraints.insert(mySlvsConstraints.end(), aNewConstr.begin(), aNewConstr.end()); } + + if (!aCircs.empty()) + myCircsAndCopies.push_back(aCircs); } adjustConstraint(); @@ -222,6 +218,21 @@ bool SketchSolver_ConstraintMultiTranslation::remove(ConstraintPtr theConstraint return true; } +void SketchSolver_ConstraintMultiTranslation::addFeature(FeaturePtr theFeature) +{ + SketchSolver_Constraint::addFeature(theFeature); + + std::map::iterator aFeatIt = myFeatureMap.find(theFeature); + if (aFeatIt == myFeatureMap.end()) + return; + + // store list of points of the feature + const Slvs_Entity& theEntity = myStorage->getEntity(aFeatIt->second); + for (int i = 0; i < 4; i++) + if (theEntity.point[i] != SLVS_E_UNKNOWN) + myPointsJustUpdated.insert(theEntity.point[i]); +} + void SketchSolver_ConstraintMultiTranslation::adjustConstraint() { Slvs_Entity aTranslationLine = myStorage->getEntity(myTranslationLine); @@ -250,55 +261,69 @@ void SketchSolver_ConstraintMultiTranslation::adjustConstraint() return; } + std::list aCoincident = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT); + std::list::const_iterator aCoIt; + + double aCoord[2]; + // Update positions of all points to satisfy distances - std::list aParallel = myStorage->getConstraintsByType(SLVS_C_PARALLEL); - std::list::iterator aParIt = aParallel.begin(); - std::vector::iterator aCIt; - for (; aParIt != aParallel.end(); aParIt++) { - for (aCIt = mySlvsConstraints.begin(); aCIt != mySlvsConstraints.end(); aCIt++) - if (aParIt->h == *aCIt) - break; - if (aCIt == mySlvsConstraints.end()) - continue; - Slvs_Entity aLine = myStorage->getEntity(aParIt->entityB); - if (myStorage->isPointFixed(aLine.point[1], aFixed)) - continue; - Slvs_Entity aStart = myStorage->getEntity(aLine.point[0]); - Slvs_Entity aEnd = myStorage->getEntity(aLine.point[1]); - for (int i = 0; i < 2; i++) { - Slvs_Param aFrom = myStorage->getParameter(aStart.param[i]); - Slvs_Param aTo = myStorage->getParameter(aEnd.param[i]); - aTo.val = aFrom.val + aDelta[i]; - myStorage->updateParameter(aTo); + std::vector< std::vector >::const_iterator aPointsIter = myPointsAndCopies.begin(); + std::vector::const_iterator aCopyIter; + for (; aPointsIter != myPointsAndCopies.end(); ++aPointsIter) { + aCopyIter = aPointsIter->begin(); + const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); + for (int i = 0; i < 2; i++) + aCoord[i] = myStorage->getParameter(anInitial.param[i]).val; + + // if the point is coincident with another one which is temporary fixed (moved by user), + // we will update its position correspondingly + Slvs_hConstraint aFixed; + for (aCoIt = aCoincident.begin(); aCoIt != aCoincident.end(); ++aCoIt) { + if ((aCoIt->ptA == anInitial.h && myStorage->isPointFixed(aCoIt->ptB, aFixed, true)) || + (aCoIt->ptB == anInitial.h && myStorage->isPointFixed(aCoIt->ptA, aFixed, true))) { + Slvs_hEntity anOtherId = aCoIt->ptA == anInitial.h ? aCoIt->ptB : aCoIt->ptA; + if (!myStorage->isTemporary(aFixed) && + myPointsJustUpdated.find(anOtherId) == myPointsJustUpdated.end()) + continue; // nothing to change + + const Slvs_Entity& anOtherPnt = myStorage->getEntity(anOtherId); + for (int i = 0; i < 2; i++) { + Slvs_Param anInitParam = myStorage->getParameter(anInitial.param[i]); + const Slvs_Param& anOtherParam = myStorage->getParameter(anOtherPnt.param[i]); + anInitParam.val = anOtherParam.val; + myStorage->updateParameter(anInitParam); + aCoord[i] = anOtherParam.val; + } + } } - } - // update positions of centers of arcs for correct radius calculation - std::list aRadii = myStorage->getConstraintsByType(SLVS_C_EQUAL_RADIUS); - std::map::iterator aFeatIt; - for (aParIt = aRadii.begin(); aParIt != aRadii.end(); aParIt++) { - int aNbFound = 0; // number of arcs used in translation - for (aFeatIt = myFeatureMap.begin(); aFeatIt != myFeatureMap.end(); aFeatIt++) - if (aFeatIt->second == aParIt->entityA || aFeatIt->second == aParIt->entityB) { - if (aFeatIt->first->getKind() == SketchPlugin_Arc::ID()) - aNbFound++; - else - break; + // update copied points + aCopyIter = aPointsIter->begin(); + for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { + // update position + aCoord[0] += aDelta[0]; + aCoord[1] += aDelta[1]; + + const Slvs_Entity& aTarget = myStorage->getEntity(*aCopyIter); + for (int i = 0; i < 2; i++) { + Slvs_Param aParam = myStorage->getParameter(aTarget.param[i]); + aParam.val = aCoord[i]; + myStorage->updateParameter(aParam); } - if (aNbFound != 2) - continue; - // two arcs were found, update their centers - Slvs_Entity anArcA = myStorage->getEntity(aParIt->entityA); - Slvs_Entity anArcB = myStorage->getEntity(aParIt->entityB); - if (myStorage->isPointFixed(anArcB.point[0], aFixed)) - continue; - Slvs_Entity aCenterA = myStorage->getEntity(anArcA.point[0]); - Slvs_Entity aCenterB = myStorage->getEntity(anArcB.point[0]); - for (int i = 0; i < 2; i++) { - Slvs_Param aFrom = myStorage->getParameter(aCenterA.param[i]); - Slvs_Param aTo = myStorage->getParameter(aCenterB.param[i]); - aTo.val = aFrom.val + aDelta[i]; - myStorage->updateParameter(aTo); } } + + for (aPointsIter = myCircsAndCopies.begin(); aPointsIter != myCircsAndCopies.end(); ++aPointsIter) { + aCopyIter = aPointsIter->begin(); + const Slvs_Entity& anInitial = myStorage->getEntity(*aCopyIter); + const Slvs_Param& anInitRad = myStorage->getParameter(anInitial.param[0]); + for (++aCopyIter; aCopyIter != aPointsIter->end(); ++aCopyIter) { + const Slvs_Entity& aCopy = myStorage->getEntity(*aCopyIter); + Slvs_Param aCopyRad = myStorage->getParameter(aCopy.param[0]); + aCopyRad.val = anInitRad.val; + myStorage->updateParameter(aCopyRad); + } + } + + myPointsJustUpdated.clear(); } diff --git a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h index b02551f07..bed7df229 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h +++ b/src/SketchSolver/SketchSolver_ConstraintMultiTranslation.h @@ -20,7 +20,8 @@ public: SketchSolver_ConstraintMultiTranslation(ConstraintPtr theConstraint) : SketchSolver_Constraint(theConstraint), myNumberOfObjects(0), - myNumberOfCopies(0) + myNumberOfCopies(0), + myTranslationLine(SLVS_E_UNKNOWN) {} virtual int getType() const @@ -33,6 +34,9 @@ public: /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence) virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr()); + /// \brief Adds a feature to constraint and create its analogue in SolveSpace + virtual void addFeature(FeaturePtr theFeature); + protected: /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints virtual void process(); @@ -47,10 +51,10 @@ protected: /// \param[out] theStartPoint ID of start point of translation /// \param[out] theEndPoint ID of final point of translation /// \param[out] thePoints list of IDs of initial points and their translated copies - /// \param[out] theCircular list of IDs of arcs and circles and their copies + /// \param[out] theEntities list of IDs of entities and their translated copies void getAttributes(Slvs_hEntity& theStartPoint, Slvs_hEntity& theEndPoint, - std::vector >& thePoints, - std::vector >& theCircular); + std::vector< std::vector >& thePoints, + std::vector< std::vector >& theEntities); /// \brief This method is used in derived objects to check consistence of constraint. virtual void adjustConstraint(); @@ -59,6 +63,10 @@ private: size_t myNumberOfObjects; ///< number of previous initial objects size_t myNumberOfCopies; ///< number of previous copies of initial objects Slvs_hEntity myTranslationLine; ///< ID of translation line + std::vector< std::vector > myPointsAndCopies; ///< list of initial points and their translated copies + std::vector< std::vector > myCircsAndCopies; ///< list of circles and their copies (to change their radii together) + + std::set myPointsJustUpdated; ///< list of points touched by user }; #endif -- 2.39.2