X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FSketchSolver%2FSketchSolver_ConstraintMirror.cpp;h=6ce1ab65d69907dc56bb577202aeb03a2b565396;hb=9ddba1caf0817c1e95c55d4c5b8ae6de23cbe6d5;hp=8ed85ff49cbfc140c1e1b57065a9040ce602c8eb;hpb=041e61bc73a3917195bb1f32d9375baefdfdad77;p=modules%2Fshaper.git diff --git a/src/SketchSolver/SketchSolver_ConstraintMirror.cpp b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp index 8ed85ff49..6ce1ab65d 100644 --- a/src/SketchSolver/SketchSolver_ConstraintMirror.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp @@ -10,6 +10,7 @@ #include #include +#include void SketchSolver_ConstraintMirror::getAttributes( Slvs_Entity& theMirrorLine, @@ -57,7 +58,13 @@ void SketchSolver_ConstraintMirror::getAttributes( continue; anEntity = changeEntity(aFeature, aType); - aList->push_back(myStorage->getEntity(anEntity)); + // Sort entities by their type + std::vector::iterator anIt = aList->begin(); + for (; anIt != aList->end(); anIt++) + if (aType < anIt->type) + break; +// aList->push_back(myStorage->getEntity(anEntity)); + aList->insert(anIt, myStorage->getEntity(anEntity)); } } @@ -186,15 +193,6 @@ void SketchSolver_ConstraintMirror::process() } } } - - // Set the mirror line unchanged during constraint recalculation - for (int i = 0; i < 2; i++) { - aConstraint = Slvs_MakeConstraint( - SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_WHERE_DRAGGED, myGroup->getWorkplaneId(), 0.0, - aMirrorLine.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); - aConstraint.h = myStorage->addConstraint(aConstraint); - mySlvsConstraints.push_back(aConstraint.h); - } } @@ -224,6 +222,10 @@ bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint) isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved; mySlvsConstraints.clear(); + std::map::iterator aFeatIt = myFeatureMap.begin(); + for (; aFeatIt != myFeatureMap.end(); aFeatIt++) + myStorage->removeEntity(aFeatIt->second); + if (isFullyRemoved) { myFeatureMap.clear(); myAttributeMap.clear(); @@ -233,6 +235,39 @@ bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint) return true; } +bool SketchSolver_ConstraintMirror::checkAttributesChanged(ConstraintPtr theConstraint) +{ + // First of all, check the mirror line is changed. + // It may be changed to one of mirrored lines, which is already in this constraint + // (this case is not marked as attribute changing) + ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint; + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + if (!aRefAttr || !aRefAttr->isObject() || !aRefAttr->object()) + return true; + FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aRefAttr->object()); + if (!aMirrorLine) + return true; + + std::map::iterator aMirrorIter = myFeatureMap.find(aMirrorLine); + if (aMirrorIter == myFeatureMap.end()) + return true; + + // Check the entity is not used as mirror line + std::vector::iterator aCIter = mySlvsConstraints.begin(); + for (; aCIter != mySlvsConstraints.end(); aCIter++) { + Slvs_Constraint aMirrorConstr = myStorage->getConstraint(*aCIter); + if (aMirrorConstr.type != SLVS_C_SYMMETRIC_LINE) + continue; + if (aMirrorConstr.entityA != aMirrorIter->second) + return true; + else break; // check just one symmetric constraint + } + + // Base verification + return SketchSolver_Constraint::checkAttributesChanged(theConstraint); +} + void SketchSolver_ConstraintMirror::makeMirrorEntity( const Slvs_Entity& theBase, const Slvs_Entity& theMirror, @@ -248,6 +283,7 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity( Slvs_hEntity aTmp = aMirrorPoint[2]; aMirrorPoint[2] = aMirrorPoint[1]; aMirrorPoint[1] = aTmp; + adjustArcPoints(theBase); } if (theBase.type == SLVS_E_POINT_IN_2D || theBase.type == SLVS_E_POINT_IN_3D) { aBasePoint[0] = theBase.h; @@ -265,9 +301,14 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity( // orthogonal direction aDir = std::shared_ptr(new GeomAPI_Dir2d(aDir->y(), -aDir->x())); + Slvs_hConstraint aFixed; // transient variable for (int i = 0; i < 4; i++) { if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN) continue; + // check the mirror point is not fixed + if (myStorage->isPointFixed(aMirrorPoint[i], aFixed, true)) + continue; + Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]); double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val; double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val; @@ -286,13 +327,41 @@ void SketchSolver_ConstraintMirror::makeMirrorEntity( } } -void SketchSolver_ConstraintMirror::adjustConstraint() +void SketchSolver_ConstraintMirror::adjustArcPoints(const Slvs_Entity& theArc) const { - // 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; + Slvs_Param aParam; + Slvs_Entity aPoint; + double anArcParams[3][2]; + for (int i = 0; i < 3; i++) { + aPoint = myStorage->getEntity(theArc.point[i]); + for (int j = 0; j < 2; j++) { + aParam = myStorage->getParameter(aPoint.param[j]); + anArcParams[i][j] = aParam.val; + if (i > 0) + anArcParams[i][j] -= anArcParams[0][j]; + } + } + double aRad2 = anArcParams[1][0] * anArcParams[1][0] + anArcParams[1][1] * anArcParams[1][1]; + double aDist2 = anArcParams[2][0] * anArcParams[2][0] + anArcParams[2][1] * anArcParams[2][1]; + if (std::fabs(aRad2 - aDist2) < tolerance) + return; // nothing to update (last point already on the arc) + if (aDist2 < tolerance) + return; // unable to update + double aCoeff = std::sqrt(aRad2 / aDist2); + anArcParams[2][0] *= aCoeff; + anArcParams[2][1] *= aCoeff; + + // Update last point + aPoint = myStorage->getEntity(theArc.point[2]); + for (int i = 0; i < 2; i++) { + aParam = Slvs_MakeParam(aPoint.param[i], myGroup->getId(), + anArcParams[0][i] + anArcParams[2][i]); + myStorage->updateParameter(aParam); + } +} +void SketchSolver_ConstraintMirror::adjustConstraint() +{ AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast( myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) { @@ -308,6 +377,7 @@ void SketchSolver_ConstraintMirror::adjustConstraint() return; Slvs_Entity aMirrorLine = myStorage->getEntity(aMirLineIter->second); + Slvs_Constraint aMirror; double aStartEnd[4]; for (int i = 0; i < 2; i++) { Slvs_Entity aPoint = myStorage->getEntity(aMirrorLine.point[i]); @@ -315,12 +385,17 @@ void SketchSolver_ConstraintMirror::adjustConstraint() aStartEnd[2*i+j] = myStorage->getParameter(aPoint.param[j]).val; } - Slvs_Constraint aMirror; + // Search mirror between middle points on the arcs and recompute their coordinates + std::map aPointsOnCircles; + std::list aMirrorPonCirc; + std::list aPonCirc = myStorage->getConstraintsByType(SLVS_C_PT_ON_CIRCLE); std::vector::iterator aConstrIter = mySlvsConstraints.begin(); for (; aConstrIter != mySlvsConstraints.end(); aConstrIter++) { aMirror = myStorage->getConstraint(*aConstrIter); if (aMirror.type != SLVS_C_SYMMETRIC_LINE) continue; + if (aMirror.entityA != aMirrorLine.h) + continue; // don't update another Mirror constraints Slvs_Constraint aPonCircA, aPonCircB; aPonCircA.h = SLVS_E_UNKNOWN; aPonCircB.h = SLVS_E_UNKNOWN; @@ -333,24 +408,47 @@ void SketchSolver_ConstraintMirror::adjustConstraint() } if (aPonCircA.h == SLVS_E_UNKNOWN || aPonCircB.h == SLVS_E_UNKNOWN) continue; + aMirrorPonCirc.push_back(aMirror); + // Store point IDs to avoid their recalculation twice + aPointsOnCircles[aPonCircA.ptA] = aPonCircA.entityA; + aPointsOnCircles[aPonCircB.ptA] = aPonCircB.entityA; + } + + // Recalculate positions of mirroring points + std::list aMirrorList = myStorage->getConstraintsByType(SLVS_C_SYMMETRIC_LINE); + std::list::iterator aMirIter = aMirrorList.begin(); + for (; aMirIter != aMirrorList.end(); aMirIter++) { + if (aMirIter->entityA != aMirrorLine.h) + continue; // don't update another Mirror constraints + if (aPointsOnCircles.find(aMirIter->ptA) != aPointsOnCircles.end()) + continue; // Avoid mirroring points on circles + Slvs_Entity aBase = myStorage->getEntity(aMirIter->ptA); + Slvs_Entity aMirror = myStorage->getEntity(aMirIter->ptB); + makeMirrorEntity(aBase, aMirror, aStartEnd); + } - bool aNeedToResolve = myStorage->isNeedToResolve(); + bool aNeedToResolve = myStorage->isNeedToResolve(); + for (aMirIter = aMirrorPonCirc.begin(); aMirIter != aMirrorPonCirc.end(); aMirIter++) { + // Make centers of arcs symmetric + Slvs_Entity aBaseArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptA]); + Slvs_Entity aBasePoint = myStorage->getEntity(aBaseArc.point[0]); + Slvs_Entity aMirrorArc = myStorage->getEntity(aPointsOnCircles[aMirIter->ptB]); + Slvs_Entity aMirrorPoint = myStorage->getEntity(aMirrorArc.point[0]); + makeMirrorEntity(aBasePoint, aMirrorPoint, aStartEnd); // 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); + aBasePoint = myStorage->getEntity(aMirIter->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 aMirrorArc = myStorage->getEntity(aPonCircB.entityA); - Slvs_Entity aMirrorPoint = myStorage->getEntity(aPonCircB.ptA); + aMirrorPoint = myStorage->getEntity(aMirIter->ptB); aParamX = myStorage->getParameter(aMirrorPoint.param[0]); aParamY = myStorage->getParameter(aMirrorPoint.param[1]); calculateMiddlePoint(aMirrorArc, 0.5, aParamX.val, aParamY.val); myStorage->updateParameter(aParamX); myStorage->updateParameter(aParamY); - // To avoid looped recalculations of sketch - myStorage->setNeedToResolve(aNeedToResolve); } + // Restore previous value to avoid looped recalculations of sketch + myStorage->setNeedToResolve(aNeedToResolve); }