From 25121bdeff44b30c89d08469d683b8707cf3ce66 Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 26 Mar 2015 15:08:51 +0300 Subject: [PATCH] Fillet updated to create necessary constraints (tangent, coincidence etc) in data model --- src/GeomAPI/GeomAPI_XY.cpp | 11 +- src/GeomAPI/GeomAPI_XY.h | 2 + .../SketchPlugin_ConstraintFillet.cpp | 247 +++++++++++++++++- .../SketchSolver_ConstraintGroup.cpp | 110 ++------ .../SketchSolver_ConstraintManager.cpp | 12 +- 5 files changed, 286 insertions(+), 96 deletions(-) diff --git a/src/GeomAPI/GeomAPI_XY.cpp b/src/GeomAPI/GeomAPI_XY.cpp index ebe52e065..5cfeff6ba 100644 --- a/src/GeomAPI/GeomAPI_XY.cpp +++ b/src/GeomAPI/GeomAPI_XY.cpp @@ -37,7 +37,16 @@ void GeomAPI_XY::setY(const double theY) const std::shared_ptr GeomAPI_XY::added(const std::shared_ptr& theArg) { - std::shared_ptr aResult(new GeomAPI_XY(MY_XY->X() + theArg->x(), MY_XY->Y() + theArg->y())); + std::shared_ptr aResult(new GeomAPI_XY( + MY_XY->X() + theArg->x(), MY_XY->Y() + theArg->y())); + return aResult; +} + +const std::shared_ptr GeomAPI_XY::decreased( + const std::shared_ptr& theArg) +{ + std::shared_ptr aResult(new GeomAPI_XY( + MY_XY->X() - theArg->x(), MY_XY->Y() - theArg->y())); return aResult; } diff --git a/src/GeomAPI/GeomAPI_XY.h b/src/GeomAPI/GeomAPI_XY.h index 3649db87d..0438b3c38 100644 --- a/src/GeomAPI/GeomAPI_XY.h +++ b/src/GeomAPI/GeomAPI_XY.h @@ -33,6 +33,8 @@ class GEOMAPI_EXPORT GeomAPI_XY : public GeomAPI_Interface /// result is sum of coordinates of this and the given argument const std::shared_ptr added(const std::shared_ptr& theArg); + /// result is difference between coordinates of this and the given argument + const std::shared_ptr decreased(const std::shared_ptr& theArg); /// result is coordinates multiplied by the argument const std::shared_ptr multiplied(const double theArg); diff --git a/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp b/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp index 22bc2541a..23d1858b6 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintFillet.cpp @@ -6,19 +6,34 @@ #include "SketchPlugin_ConstraintFillet.h" +#include +#include +#include +#include #include -#include -#include #include #include +#include +#include +#include #include #include +#include #include +#include +#include +#include #include #include +#include + +/// \brief Attract specified point on theNewArc to the attribute of theFeature +static void recalculateAttributes(FeaturePtr theNewArc, const std::string& theNewArcAttribute, + FeaturePtr theFeature, const std::string& theFeatureAttribute); + SketchPlugin_ConstraintFillet::SketchPlugin_ConstraintFillet() { @@ -38,6 +53,8 @@ void SketchPlugin_ConstraintFillet::execute() { std::shared_ptr aData = data(); // Check the base objects are initialized + double aFilletRadius = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::VALUE()))->value(); AttributeRefAttrPtr aBaseA = std::dynamic_pointer_cast( aData->attribute(SketchPlugin_Constraint::ENTITY_A())); AttributeRefAttrPtr aBaseB = std::dynamic_pointer_cast( @@ -62,20 +79,186 @@ void SketchPlugin_ConstraintFillet::execute() // Create list of objects composing a fillet // copy aFeatureA - FeaturePtr aNewFeature = sketch()->addFeature(aFeatureA->getKind()); - aFeatureA->data()->copyTo(aNewFeature->data()); - aRefListOfFillet->append(aNewFeature); + FeaturePtr aNewFeatureA = sketch()->addFeature(aFeatureA->getKind()); + aFeatureA->data()->copyTo(aNewFeatureA->data()); + aNewFeatureA->execute(); + aRefListOfFillet->append(aNewFeatureA); // copy aFeatureB - aNewFeature = sketch()->addFeature(aFeatureB->getKind()); - aFeatureB->data()->copyTo(aNewFeature->data()); - aRefListOfFillet->append(aNewFeature); + FeaturePtr aNewFeatureB = sketch()->addFeature(aFeatureB->getKind()); + aFeatureB->data()->copyTo(aNewFeatureB->data()); + aNewFeatureB->execute(); + aRefListOfFillet->append(aNewFeatureB); // create filleting arc - aNewFeature = sketch()->addFeature(SketchPlugin_Arc::ID()); - aNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())->setInitialized(); - aNewFeature->attribute(SketchPlugin_Arc::START_ID())->setInitialized(); - aNewFeature->attribute(SketchPlugin_Arc::END_ID())->setInitialized(); - aRefListOfFillet->append(aNewFeature); + FeaturePtr aNewArc = sketch()->addFeature(SketchPlugin_Arc::ID()); + aRefListOfFillet->append(aNewArc); aRefListOfFillet->setInitialized(); + + // Wait all constraints being created, then send update events + static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); + bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent); + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, false); + + // Calculate arc attributes + static const int aNbFeatures = 2; + FeaturePtr aFeature[aNbFeatures] = {aNewFeatureA, aNewFeatureB}; + std::shared_ptr aTangentDir[aNbFeatures]; // tangent directions of the features in coincident point + bool isStart[aNbFeatures]; // indicates which point the features share + std::shared_ptr aStartEndPnt[aNbFeatures * 2]; // first pair of points relate to first feature, second pair - to second + std::string aFeatAttributes[aNbFeatures * 2]; // attributes of features + for (int i = 0; i < aNbFeatures; i++) { + std::string aStartAttr, aEndAttr; + if (aFeature[i]->getKind() == SketchPlugin_Line::ID()) { + aStartAttr = SketchPlugin_Line::START_ID(); + aEndAttr = SketchPlugin_Line::END_ID(); + } else if (aFeature[i]->getKind() == SketchPlugin_Arc::ID()) { + aStartAttr = SketchPlugin_Arc::START_ID(); + aEndAttr = SketchPlugin_Arc::END_ID(); + } else { // wrong argument + aRefListOfFillet->remove(aNewFeatureA); + aRefListOfFillet->remove(aNewFeatureB); + aRefListOfFillet->remove(aNewArc); + return; + } + aFeatAttributes[2*i] = aStartAttr; + aStartEndPnt[2*i] = std::dynamic_pointer_cast( + aFeature[i]->attribute(aStartAttr))->pnt(); + aFeatAttributes[2*i+1] = aEndAttr; + aStartEndPnt[2*i+1] = std::dynamic_pointer_cast( + aFeature[i]->attribute(aEndAttr))->pnt(); + } + for (int i = 0; i < aNbFeatures; i++) { + int j = aNbFeatures; + for (; j < 2 * aNbFeatures; j++) + if (aStartEndPnt[i]->distance(aStartEndPnt[j]) < 1.e-10) { + isStart[0] = i==0; + isStart[1] = j==aNbFeatures; + break; + } + if (j < 2 * aNbFeatures) + break; + } + // tangent directions of the features + for (int i = 0; i < aNbFeatures; i++) { + std::shared_ptr aDir; + if (aFeature[i]->getKind() == SketchPlugin_Line::ID()) { + aDir = aStartEndPnt[2*i+1]->xy()->decreased(aStartEndPnt[2*i]->xy()); + if (!isStart[i]) + aDir = aDir->multiplied(-1.0); + } else if (aFeature[i]->getKind() == SketchPlugin_Arc::ID()) { + std::shared_ptr aCenterPoint = + std::dynamic_pointer_cast( + aFeature[i]->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt(); + aDir = isStart[i] ? aStartEndPnt[2*i]->xy() : aStartEndPnt[2*i+1]->xy(); + aDir = aDir->decreased(aCenterPoint->xy()); + + double x = aDir->x(); + double y = aDir->y(); + aDir->setX(-y); + aDir->setY(x); + if (!isStart[i]) + aDir = aDir->multiplied(-1.0); + } + aTangentDir[i] = std::shared_ptr(new GeomAPI_Dir2d(aDir)); + } + // By default, the start point of fillet arc is connected to FeatureA, + // and the end point - to FeatureB. But when the angle between TangentDirA and + // TangentDirB greater 180 degree, the sequaence of features need to be reversed. + double cosBA = aTangentDir[0]->cross(aTangentDir[1]); // cos(B-A), where A and B - angles between corresponding tanget direction and the X axis + bool isReversed = cosBA > 0.0; + + std::shared_ptr aSharedPoint = aStartEndPnt[isStart[0] ? 0 : 1]; + std::shared_ptr aBisect(new GeomAPI_Dir2d( + aTangentDir[0]->xy()->added(aTangentDir[1]->xy()))); + std::shared_ptr aStep = aBisect->xy()->multiplied(aFilletRadius); + std::shared_ptr aCenter = aSharedPoint->xy()->added(aStep); + std::dynamic_pointer_cast( + aNewArc->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue( + aCenter->x(), aCenter->y()); + std::dynamic_pointer_cast( + aNewArc->attribute(SketchPlugin_Arc::START_ID()))->setValue( + aCenter->x() - aStep->y(), aCenter->y() + aStep->x()); + std::dynamic_pointer_cast( + aNewArc->attribute(SketchPlugin_Arc::END_ID()))->setValue( + aCenter->x() + aStep->y(), aCenter->y() - aStep->x()); + aNewArc->execute(); + + // Create list of additional constraints: + // 1. Coincidence of boundary points of features and fillet arc + // 1.1. coincidence + FeaturePtr aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID()); + AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + aRefAttr->setAttr(aNewArc->attribute(SketchPlugin_Arc::START_ID())); + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); + int aFeatInd = isReversed ? 1 : 0; + int anAttrInd = (isReversed ? 2 : 0) + (isStart[isReversed ? 1 : 0] ? 0 : 1); + aRefAttr->setAttr(aFeature[aFeatInd]->attribute(aFeatAttributes[anAttrInd])); + recalculateAttributes(aNewArc, SketchPlugin_Arc::START_ID(), aFeature[aFeatInd], aFeatAttributes[anAttrInd]); + aConstraint->execute(); + ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); + // 1.2. coincidence + aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID()); + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + aRefAttr->setAttr(aNewArc->attribute(SketchPlugin_Arc::END_ID())); + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); + aFeatInd = isReversed ? 0 : 1; + anAttrInd = (isReversed ? 0 : 2) + (isStart[isReversed ? 0 : 1] ? 0 : 1); + aRefAttr->setAttr(aFeature[aFeatInd]->attribute(aFeatAttributes[anAttrInd])); + recalculateAttributes(aNewArc, SketchPlugin_Arc::END_ID(), aFeature[aFeatInd], aFeatAttributes[anAttrInd]); + aConstraint->execute(); + ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); + // recalculate center of fillet arc + std::shared_ptr aStartPoint = std::dynamic_pointer_cast( + aNewArc->attribute(SketchPlugin_Arc::START_ID()))->pnt(); + std::shared_ptr aEndPoint = std::dynamic_pointer_cast( + aNewArc->attribute(SketchPlugin_Arc::END_ID()))->pnt(); + aCenter = aStartPoint->xy()->added(aEndPoint->xy())->multiplied(0.5); + std::dynamic_pointer_cast( + aNewArc->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue( + aCenter->x(), aCenter->y()); + // 2. Fillet arc radius + aConstraint = sketch()->addFeature(SketchPlugin_ConstraintRadius::ID()); + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + aRefAttr->setObject(aNewArc->lastResult()); + std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::VALUE()))->setValue(aFilletRadius); + std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()))->setValue( + isStart[0] ? aStartEndPnt[0] : aStartEndPnt[1]); + aConstraint->execute(); + ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); + // 3. Tangency of fillet arc and features + for (int i = 0; i < aNbFeatures; i++) { + aConstraint = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID()); + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + aRefAttr->setObject(aNewArc->lastResult()); + aRefAttr = std::dynamic_pointer_cast( + aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); + bool isArc = aFeature[i]->getKind() == SketchPlugin_Arc::ID(); + aRefAttr->setObject(isArc ? aFeature[i]->lastResult() : aFeature[i]->firstResult()); + aConstraint->execute(); + ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent); + } + + // send events + ModelAPI_EventCreator::get()->sendUpdated(FeaturePtr(this), anUpdateEvent); + if (isUpdateFlushed) + Events_Loop::loop()->setFlushed(anUpdateEvent, true); + Events_Loop::loop()->flush(anUpdateEvent); + + // make base features auxiliary + static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + aFeatureA->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true); + aFeatureB->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true); + ModelAPI_EventCreator::get()->sendUpdated(aFeatureA, aRedisplayEvent); + ModelAPI_EventCreator::get()->sendUpdated(aFeatureB, aRedisplayEvent); + Events_Loop::loop()->flush(aRedisplayEvent); } AISObjectPtr SketchPlugin_ConstraintFillet::getAISObject(AISObjectPtr thePrevious) @@ -89,3 +272,41 @@ AISObjectPtr SketchPlugin_ConstraintFillet::getAISObject(AISObjectPtr thePreviou } + +// ========= Auxiliary functions ================= +void recalculateAttributes(FeaturePtr theNewArc, const std::string& theNewArcAttribute, + FeaturePtr theFeature, const std::string& theFeatureAttribute) +{ + std::shared_ptr anArcPoint = std::dynamic_pointer_cast( + theNewArc->attribute(theNewArcAttribute))->pnt(); + if (theFeature->getKind() == SketchPlugin_Line::ID()) { + std::shared_ptr aStartPoint = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt(); + std::shared_ptr aEndPoint = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt(); + std::shared_ptr aLineDir(new GeomAPI_Dir2d( + aEndPoint->xy()->decreased(aStartPoint->xy()))); + std::shared_ptr aVec = anArcPoint->xy()->decreased(aStartPoint->xy()); + double aDot = aVec->dot(aLineDir->xy()); + aVec = aStartPoint->xy()->added(aLineDir->xy()->multiplied(aDot)); + anArcPoint->setX(aVec->x()); + anArcPoint->setY(aVec->y()); + } else if (theFeature->getKind() == SketchPlugin_Arc::ID()) { + std::shared_ptr aStartPoint = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt(); + std::shared_ptr aCenterPoint = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt(); + double aRadius = aStartPoint->distance(aCenterPoint); + std::shared_ptr aDir(new GeomAPI_Dir2d( + anArcPoint->xy()->decreased(aCenterPoint->xy()))); + std::shared_ptr aPoint = aCenterPoint->xy()->added(aDir->xy()->multiplied(aRadius)); + anArcPoint->setX(aPoint->x()); + anArcPoint->setY(aPoint->y()); + } else + return; + + std::dynamic_pointer_cast( + theNewArc->attribute(theNewArcAttribute))->setValue(anArcPoint->x(), anArcPoint->y()); + std::dynamic_pointer_cast( + theFeature->attribute(theFeatureAttribute))->setValue(anArcPoint->x(), anArcPoint->y()); +} diff --git a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp index 05171749b..776be57bd 100644 --- a/src/SketchSolver/SketchSolver_ConstraintGroup.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintGroup.cpp @@ -894,6 +894,8 @@ bool SketchSolver_ConstraintGroup::changeFilletConstraint( if (!aFilletFeature) return false; aFilletEnt[indEnt] = changeEntityFeature(aFilletFeature); + if (aFilletEnt[indEnt] == SLVS_E_UNKNOWN) + return false; // not all attributes are initialized yet aFilletObjInd[indEnt] = Search(aFilletEnt[indEnt], myEntities); } // At first time, for correct result, move floating points of fillet on the middle points of base objects @@ -934,34 +936,14 @@ bool SketchSolver_ConstraintGroup::changeFilletConstraint( } } - // Check the fillet arc which point to be connected to - bool isArcInversed = false; // indicates that start and end points of arc should be connected to second and first object respectively - Slvs_hEntity hEnt = myEntities[aFilletObjInd[2]].point[1]; - int aPos = Search(hEnt, myEntities); - Slvs_hParam anArcStartPoint = myEntities[aPos].param[0]; - aPos = Search(anArcStartPoint, myParams); - double anArcPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val}; - double aSqDistances[2]; - int aPtInd; - for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) { - aPtInd = aBaseCoincInd[indEnt]+aShift[indEnt]; - hEnt = myEntities[aFilletObjInd[indEnt]].point[aPtInd]; - aPos = Search(hEnt, myEntities); - Slvs_hParam anObjectPoint = myEntities[aPos].param[0]; - aPos = Search(anObjectPoint, myParams); - double aPtCoord[2] = {myParams[aPos].val, myParams[aPos+1].val}; - aSqDistances[indEnt] = - (anArcPtCoord[0] - aPtCoord[0]) * (anArcPtCoord[0] - aPtCoord[0]) + - (anArcPtCoord[1] - aPtCoord[1]) * (anArcPtCoord[1] - aPtCoord[1]); - } - if (aSqDistances[1] < aSqDistances[0]) - isArcInversed = true; - // Create list of constraints to generate fillet + int aPtInd; std::vector aConstrList; bool isExists = myConstraintMap.find(theConstraint) != myConstraintMap.end(); // constraint already exists std::vector::iterator aCMapIter = isExists ? myConstraintMap[theConstraint].begin() : aConstrList.begin(); + std::vector::iterator aCMapEnd = + isExists ? myConstraintMap[theConstraint].end() : aConstrList.end(); int aCurConstrPos = isExists ? Search(*aCMapIter, myConstraints) : 0; for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) { // one point of fillet object should be coincident with the point on base, non-coincident with another base object @@ -973,7 +955,7 @@ bool SketchSolver_ConstraintGroup::changeFilletConstraint( myConstraints[aCurConstrPos].ptB = aPtFillet; aCMapIter++; aCurConstrPos = Search(*aCMapIter, myConstraints); - } else { + } else if (addCoincidentPoints(aPtBase, aPtFillet)) { // the points are not connected by coincidence yet Slvs_Constraint aCoincConstr = Slvs_MakeConstraint( ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h, 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); @@ -992,8 +974,9 @@ bool SketchSolver_ConstraintGroup::changeFilletConstraint( myConstraints[aCurConstrPos].ptA = aPtBase; myConstraints[aCurConstrPos].ptB = aPtFillet; aCMapIter++; - aCurConstrPos = Search(*aCMapIter, myConstraints); - } else { + if (aCMapIter != aCMapEnd) + aCurConstrPos = Search(*aCMapIter, myConstraints); + } else if (addCoincidentPoints(aPtBase, aPtFillet)) { // the points are not connected by coincidence yet aPonCurveConstr = Slvs_MakeConstraint( ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h, 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); @@ -1006,7 +989,8 @@ bool SketchSolver_ConstraintGroup::changeFilletConstraint( if (isExists) { myConstraints[aCurConstrPos].ptA = aPtFillet; aCMapIter++; - aCurConstrPos = Search(*aCMapIter, myConstraints); + if (aCMapIter != aCMapEnd) + aCurConstrPos = Search(*aCMapIter, myConstraints); } else { aPonCurveConstr = Slvs_MakeConstraint( ++myConstrMaxID, myID, SLVS_C_PT_ON_LINE, myWorkplane.h, @@ -1018,56 +1002,13 @@ bool SketchSolver_ConstraintGroup::changeFilletConstraint( myConstraints.push_back(aPonCurveConstr); aConstrList.push_back(aPonCurveConstr.h); } - - // Bound point of fillet arc should be tangently coincident with a bound point of fillet object - aPtInd = 1 + (isArcInversed ? 1-indEnt : indEnt); - Slvs_hEntity aPtArc = myEntities[aFilletObjInd[2]].point[aPtInd]; - if (isExists) { - myConstraints[aCurConstrPos].ptA = aPtArc; - myConstraints[aCurConstrPos].ptB = aPtFillet; - aCMapIter++; - aCurConstrPos = Search(*aCMapIter, myConstraints); - myConstraints[aCurConstrPos].entityA = aFilletEnt[2]; - myConstraints[aCurConstrPos].entityB = aFilletEnt[indEnt]; - myConstraints[aCurConstrPos].other = (isArcInversed ? 1-indEnt : indEnt); - aCMapIter++; - aCurConstrPos = Search(*aCMapIter, myConstraints); - } else { - Slvs_Constraint aCoincConstr = Slvs_MakeConstraint( - ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h, - 0, aPtArc, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); - myConstraints.push_back(aCoincConstr); - aConstrList.push_back(aCoincConstr.h); - Slvs_Constraint aTangency = Slvs_MakeConstraint( - ++myConstrMaxID, myID, aTangentType, myWorkplane.h, - 0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], aFilletEnt[indEnt]); - aTangency.other = (isArcInversed ? 1-indEnt : indEnt); - aTangency.other2 = aTangentType == SLVS_C_CURVE_CURVE_TANGENT ? aBaseCoincInd[indEnt] : 0; - myConstraints.push_back(aTangency); - aConstrList.push_back(aTangency.h); - } } - // Additional constraint for fillet diameter - double aRadius = 0.0; // scalar value of the constraint - AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast( - aConstrData->attribute(SketchPlugin_Constraint::VALUE())); - aRadius = aDistAttr->value(); - if (isExists) { - myConstraints[aCurConstrPos].entityA = aFilletEnt[2]; - myConstraints[aCurConstrPos].valA = aRadius * 2.0; - aCMapIter++; - } else { - Slvs_Constraint aDiamConstr = Slvs_MakeConstraint( - ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, aRadius * 2.0, - SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aFilletEnt[2], SLVS_E_UNKNOWN); - myConstraints.push_back(aDiamConstr); - aConstrList.push_back(aDiamConstr.h); - + if (!isExists) myConstraintMap[theConstraint] = aConstrList; - } // Additional temporary constraints for base objects to be fixed + int aNbArcs = 0; for (unsigned int indAttr = 0; indAttr < 2; indAttr++) { if (!aBaseFeature[indAttr]) { AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast( @@ -1075,17 +1016,24 @@ bool SketchSolver_ConstraintGroup::changeFilletConstraint( addTemporaryConstraintWhereDragged(aConstrAttr->attr()); continue; } - std::list anAttributes = - aBaseFeature[indAttr]->data()->attributes(GeomDataAPI_Point2D::typeId()); - std::list::iterator anIt = anAttributes.begin(); - for ( ; anIt != anAttributes.end(); anIt++) { - // Arc should be fixed by center and start points only (to avoid "conflicting constraints" message) - if (aBaseFeature[indAttr]->getKind() == SketchPlugin_Arc::ID() && - (*anIt)->id() == SketchPlugin_Arc::END_ID()) - continue; - addTemporaryConstraintWhereDragged(*anIt); + if (aBaseFeature[indAttr]->getKind() == SketchPlugin_Line::ID()) { + addTemporaryConstraintWhereDragged( + aBaseFeature[indAttr]->attribute(SketchPlugin_Line::START_ID())); + addTemporaryConstraintWhereDragged( + aBaseFeature[indAttr]->attribute(SketchPlugin_Line::END_ID())); + } else if (aBaseFeature[indAttr]->getKind() == SketchPlugin_Arc::ID()) { + // Arc should be fixed by its center only (to avoid "conflicting constraints" message) + // If the fillet is made on two arc, the shared point should be fixed too + aNbArcs++; + addTemporaryConstraintWhereDragged( + aBaseFeature[indAttr]->attribute(SketchPlugin_Arc::CENTER_ID())); } } + if (aNbArcs == 2) { + addTemporaryConstraintWhereDragged(aBaseCoincInd[0] == 0 ? + aBaseFeature[0]->attribute(SketchPlugin_Arc::START_ID()) : + aBaseFeature[0]->attribute(SketchPlugin_Arc::END_ID())); + } return true; } diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index 72cb9f214..1fafcf506 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintManager.cpp @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -104,10 +105,19 @@ void SketchSolver_ConstraintManager::processEvent( } } // then get anything but not the sketch + // at first, add coincidence constraints, because they may be used by other constraints for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { std::shared_ptr aFeature = std::dynamic_pointer_cast(*aFeatIter); - if (!aFeature) + if (!aFeature || aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) + continue; + changeConstraintOrEntity(aFeature); + } + // after that, add all features except coincidence + for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { + std::shared_ptr aFeature = + std::dynamic_pointer_cast(*aFeatIter); + if (!aFeature || aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) continue; changeConstraintOrEntity(aFeature); } -- 2.39.2