From ef017929d9fd0f90a8bc7513148e25ce833971ac Mon Sep 17 00:00:00 2001 From: azv Date: Thu, 2 Apr 2015 08:44:56 +0300 Subject: [PATCH] SketchSolver library refactoring 1. Implemented Fillet 2. Implemented Mirror constraint 3. Update Rigid constraint 4. Code clean up --- .../SketchPlugin_ConstraintMirror.cpp | 4 + src/SketchSolver/CMakeLists.txt | 4 + src/SketchSolver/SketchSolver_Builder.cpp | 6 +- src/SketchSolver/SketchSolver_Constraint.cpp | 269 ++- src/SketchSolver/SketchSolver_Constraint.h | 12 + .../SketchSolver_ConstraintFillet.cpp | 208 +++ .../SketchSolver_ConstraintFillet.h | 45 + .../SketchSolver_ConstraintManager.cpp | 65 +- .../SketchSolver_ConstraintMirror.cpp | 269 +++ .../SketchSolver_ConstraintMirror.h | 64 + .../SketchSolver_ConstraintRigid.cpp | 121 +- .../SketchSolver_ConstraintRigid.h | 10 + src/SketchSolver/SketchSolver_Error.h | 6 + .../SketchSolver_FeatureStorage.cpp | 5 - src/SketchSolver/SketchSolver_Group.cpp | 1578 +---------------- src/SketchSolver/SketchSolver_Group.h | 144 -- src/SketchSolver/SketchSolver_Storage.cpp | 2 + 17 files changed, 1000 insertions(+), 1812 deletions(-) create mode 100644 src/SketchSolver/SketchSolver_ConstraintFillet.cpp create mode 100644 src/SketchSolver/SketchSolver_ConstraintFillet.h create mode 100644 src/SketchSolver/SketchSolver_ConstraintMirror.cpp create mode 100644 src/SketchSolver/SketchSolver_ConstraintMirror.h diff --git a/src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp b/src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp index 5dc94ef4a..fd765dec9 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintMirror.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -90,6 +91,8 @@ void SketchPlugin_ConstraintMirror::execute() aMirrorIter++; } + static Events_ID aRedisplayEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); + // Check consistency of initial list and mirrored list anInitialList = aRefListOfShapes->list(); anInitIter = anInitialList.begin(); @@ -131,6 +134,7 @@ void SketchPlugin_ConstraintMirror::execute() FeaturePtr aNewFeature = sketch()->addFeature(aFeatureIn->getKind()); aFeatureIn->data()->copyTo(aNewFeature->data()); aNewFeature->execute(); + ModelAPI_EventCreator::get()->sendUpdated(aNewFeature, aRedisplayEvent); std::shared_ptr aShapeIn = aRCIn->shape(); const std::list& aResults = aNewFeature->results(); diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index bc1b78af7..d8070e05f 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -11,7 +11,9 @@ SET(PROJECT_HEADERS SketchSolver_ConstraintCoincidence.h SketchSolver_ConstraintDistance.h SketchSolver_ConstraintEqual.h + SketchSolver_ConstraintFillet.h SketchSolver_ConstraintLength.h + SketchSolver_ConstraintMirror.h SketchSolver_ConstraintRigid.h SketchSolver_ConstraintTangent.h SketchSolver_Builder.h @@ -27,7 +29,9 @@ SET(PROJECT_SOURCES SketchSolver_ConstraintCoincidence.cpp SketchSolver_ConstraintDistance.cpp SketchSolver_ConstraintEqual.cpp + SketchSolver_ConstraintFillet.cpp SketchSolver_ConstraintLength.cpp + SketchSolver_ConstraintMirror.cpp SketchSolver_ConstraintRigid.cpp SketchSolver_ConstraintTangent.cpp SketchSolver_Builder.cpp diff --git a/src/SketchSolver/SketchSolver_Builder.cpp b/src/SketchSolver/SketchSolver_Builder.cpp index 6bf3a61c0..a1823bd36 100644 --- a/src/SketchSolver/SketchSolver_Builder.cpp +++ b/src/SketchSolver/SketchSolver_Builder.cpp @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include #include @@ -65,13 +67,13 @@ SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theCons } else if (theConstraint->getKind() == SketchPlugin_ConstraintEqual::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintEqual(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) { -//// return SolverConstraintPtr(new SketchSolver_ConstraintFillet(theConstraint)); + return SolverConstraintPtr(new SketchSolver_ConstraintFillet(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintHorizontal::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintHorizontal(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintLength(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) { -//// return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint)); + return SolverConstraintPtr(new SketchSolver_ConstraintMirror(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintParallel::ID()) { return SolverConstraintPtr(new SketchSolver_ConstraintParallel(theConstraint)); } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) { diff --git a/src/SketchSolver/SketchSolver_Constraint.cpp b/src/SketchSolver/SketchSolver_Constraint.cpp index c382cdeb3..012c45c6e 100644 --- a/src/SketchSolver/SketchSolver_Constraint.cpp +++ b/src/SketchSolver/SketchSolver_Constraint.cpp @@ -169,6 +169,7 @@ bool SketchSolver_Constraint::remove(ConstraintPtr theConstraint) myValueMap.clear(); } else cleanRemovedEntities(); + mySlvsConstraints.clear(); return true; } @@ -278,7 +279,7 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributeRefAttrPtr theAttrib Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int& theType) { Slvs_hEntity aResult = SLVS_E_UNKNOWN; - if (!theEntity->isInitialized()) + if (!isInitialized(theEntity)) return SLVS_E_UNKNOWN; // If the entity is already in the group, try to find it @@ -373,7 +374,7 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int& Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& theType) { Slvs_hEntity aResult = SLVS_E_UNKNOWN; - if (!theEntity->data()->isValid()) + if (!theEntity->data() || !theEntity->data()->isValid()) return SLVS_E_UNKNOWN; // If the entity is already in the group, try to find it std::map::const_iterator anEntIter = myFeatureMap.find(theEntity); @@ -392,85 +393,82 @@ Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& th Slvs_hGroup aGroupID = myGroup->getId(); Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId(); + DataPtr aData = theEntity->data(); + // SketchPlugin features - std::shared_ptr aFeature = std::dynamic_pointer_cast< - SketchPlugin_Feature>(theEntity); - if (aFeature) { // Verify the feature by its kind - const std::string& aFeatureKind = aFeature->getKind(); - AttributePtr anAttribute; - int anAttrType; - - // Line - if (aFeatureKind == SketchPlugin_Line::ID()) { - anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID()); - if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; - Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType); - - anAttribute = aFeature->data()->attribute(SketchPlugin_Line::END_ID()); - if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; - Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType); + const std::string& aFeatureKind = theEntity->getKind(); + AttributePtr anAttribute; + int anAttrType; + // Line + if (aFeatureKind == SketchPlugin_Line::ID()) { + anAttribute = aData->attribute(SketchPlugin_Line::START_ID()); + if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN; + Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType); + + anAttribute = aData->attribute(SketchPlugin_Line::END_ID()); + if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN; + Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType); - if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity - aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd); - else { - aCurrentEntity.point[0] = aStart; - aCurrentEntity.point[1] = aEnd; - } - aResult = myStorage->addEntity(aCurrentEntity); - } - // Circle - else if (aFeatureKind == SketchPlugin_Circle::ID()) { - anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()); - if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; - Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType); - - anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()); - if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; - Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType); - - if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity - Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID); - aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, - aCenter, aWorkplane.normal, aRadius); - } else { - aCurrentEntity.point[0] = aCenter; - aCurrentEntity.distance = aRadius; - } - aResult = myStorage->addEntity(aCurrentEntity); + if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity + aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd); + else { + aCurrentEntity.point[0] = aStart; + aCurrentEntity.point[1] = aEnd; } - // Arc - else if (aFeatureKind == SketchPlugin_Arc::ID()) { - anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()); - if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; - Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType); - - anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::START_ID()); - if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; - Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType); - - anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::END_ID()); - if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; - Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType); - - if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity - Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID); - aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, - aWorkplane.normal, aCenter, aStart, aEnd); - } else { - aCurrentEntity.point[0] = aCenter; - aCurrentEntity.point[1] = aStart; - aCurrentEntity.point[2] = aEnd; - } - aResult = myStorage->addEntity(aCurrentEntity); + aResult = myStorage->addEntity(aCurrentEntity); + } + // Circle + else if (aFeatureKind == SketchPlugin_Circle::ID()) { + anAttribute = aData->attribute(SketchPlugin_Circle::CENTER_ID()); + if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN; + Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType); + + anAttribute = aData->attribute(SketchPlugin_Circle::RADIUS_ID()); + if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN; + Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType); + + if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity + Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID); + aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, + aCenter, aWorkplane.normal, aRadius); + } else { + aCurrentEntity.point[0] = aCenter; + aCurrentEntity.distance = aRadius; } - // Point (it has low probability to be an attribute of constraint, so it is checked at the end) - else if (aFeatureKind == SketchPlugin_Point::ID()) { - anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()); - if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; - // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier - aResult = changeEntity(anAttribute, anAttrType); - aCurrentEntity.type = SLVS_E_POINT_IN_3D; + aResult = myStorage->addEntity(aCurrentEntity); + } + // Arc + else if (aFeatureKind == SketchPlugin_Arc::ID()) { + anAttribute = aData->attribute(SketchPlugin_Arc::CENTER_ID()); + if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN; + Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType); + + anAttribute = aData->attribute(SketchPlugin_Arc::START_ID()); + if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN; + Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType); + + anAttribute = aData->attribute(SketchPlugin_Arc::END_ID()); + if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN; + Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType); + + if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity + Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID); + aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, + aWorkplane.normal, aCenter, aStart, aEnd); + } else { + aCurrentEntity.point[0] = aCenter; + aCurrentEntity.point[1] = aStart; + aCurrentEntity.point[2] = aEnd; } + aResult = myStorage->addEntity(aCurrentEntity); + } + // Point (it has low probability to be an attribute of constraint, so it is checked at the end) + else if (aFeatureKind == SketchPlugin_Point::ID()) { + anAttribute = aData->attribute(SketchPlugin_Point::COORD_ID()); + if (!isInitialized(anAttribute)) return SLVS_E_UNKNOWN; + // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier + aResult = changeEntity(anAttribute, anAttrType); + aCurrentEntity.type = SLVS_E_POINT_IN_3D; } if (aResult != SLVS_E_UNKNOWN) { @@ -501,19 +499,24 @@ void SketchSolver_Constraint::refresh() Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]); aXYZ[i] = aPar.val; } - aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]); + if (fabs(aPoint->x() - aXYZ[0]) > tolerance || + fabs(aPoint->y() - aXYZ[1]) > tolerance || + fabs(aPoint->z() - aXYZ[2]) > tolerance) + aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]); } else { // Point in 2D std::shared_ptr aPoint2D = std::dynamic_pointer_cast(anAttrIter->first); if (aPoint2D) { Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second); - double aXYZ[2]; + double aXY[2]; for (int i = 0; i < 2; i++) { Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]); - aXYZ[i] = aPar.val; + aXY[i] = aPar.val; } - aPoint2D->setValue(aXYZ[0], aXYZ[1]); + if (fabs(aPoint2D->x() - aXY[0]) > tolerance || + fabs(aPoint2D->y() - aXY[1]) > tolerance) + aPoint2D->setValue(aXY[0], aXY[1]); } else { // Scalar value (used for the distance entities) AttributeDoublePtr aScalar = @@ -521,7 +524,8 @@ void SketchSolver_Constraint::refresh() if (aScalar) { Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second); Slvs_Param aPar = myStorage->getParameter(anEntity.param[0]); - aScalar->setValue(aPar.val); + if (fabs(aScalar->value() - aPar.val) > tolerance) + aScalar->setValue(aPar.val); } } } @@ -554,3 +558,106 @@ Slvs_hEntity SketchSolver_Constraint::getId(AttributePtr theAttribute) const return anAttrIter->second; } +bool SketchSolver_Constraint::isInitialized(AttributePtr theAttribute) +{ + if (theAttribute->isInitialized()) + return true; + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return false; +} + + +void SketchSolver_Constraint::calculateMiddlePoint( + const Slvs_Entity& theEntity, double theCoeff, double& theX, double& theY) const +{ + if (theEntity.type == SLVS_E_LINE_SEGMENT) { + double aStartEndXY[2][2]; + Slvs_Entity aPoint; + for (int i = 0; i < 2; i++) { + aPoint = myStorage->getEntity(theEntity.point[i]); + for (int j = 0; j < 2; j++) + aStartEndXY[i][j] = myStorage->getParameter(aPoint.param[j]).val; + } + theX = (1.0 - theCoeff) * aStartEndXY[0][0] + theCoeff * aStartEndXY[1][0]; + theY = (1.0 - theCoeff) * aStartEndXY[0][1] + theCoeff * aStartEndXY[1][1]; + } else if (theEntity.type == SLVS_E_ARC_OF_CIRCLE) { + double anArcPoint[3][2]; + Slvs_Entity aPoint; + for (int i = 0; i < 3; i++) { + aPoint = myStorage->getEntity(theEntity.point[i]); + for (int j = 0; j < 2; j++) + anArcPoint[i][j] = myStorage->getParameter(aPoint.param[j]).val; + } + // project last point of arc on the arc + double x = anArcPoint[1][0] - anArcPoint[0][0]; + double y = anArcPoint[1][1] - anArcPoint[0][1]; + double aRad = sqrt(x*x + y*y); + x = anArcPoint[2][0] - anArcPoint[0][0]; + y = anArcPoint[2][1] - anArcPoint[0][1]; + double aNorm = sqrt(x*x + y*y); + if (aNorm >= tolerance) { + anArcPoint[2][0] = x * aRad / aNorm; + anArcPoint[2][1] = y * aRad / aNorm; + } + anArcPoint[1][0] -= anArcPoint[0][0]; + anArcPoint[1][1] -= anArcPoint[0][1]; + if (theCoeff < tolerance) { + theX = anArcPoint[0][0] + anArcPoint[1][0]; + theY = anArcPoint[0][1] + anArcPoint[1][1]; + return; + } else if (1 - theCoeff < tolerance) { + theX = anArcPoint[0][0] + anArcPoint[2][0]; + theY = anArcPoint[0][1] + anArcPoint[2][1]; + return; + } + + double xStart = anArcPoint[1][0] / aRad, xEnd = anArcPoint[2][0] / aRad; + double yStart = anArcPoint[1][1] / aRad, yEnd = anArcPoint[2][1] / aRad; + if (anArcPoint[1][0] * anArcPoint[2][0] < 0.0) { + if (anArcPoint[1][0] > 0.0) + yEnd = 2.0 - yEnd; + else + yStart = -2.0 - yStart; + } else { + if (yStart > yEnd) { + yStart = 2.0 - yStart; + yEnd = -2.0 - yEnd; + } else { + yStart = -2.0 - yStart; + yEnd = 2.0 - yEnd; + } + } + if (anArcPoint[1][1] * anArcPoint[2][1] < 0.0) { + if (anArcPoint[1][1] > 0.0) + xEnd = 2.0 - xEnd; + else + xStart = -2.0 - xStart; + } else { + if (xStart > xEnd) { + xStart = 2.0 - xStart; + xEnd = -2.0 - xEnd; + } else { + xStart = -2.0 - xStart; + xEnd = 2.0 - xEnd; + } + } + x = (1.0 - theCoeff) * xStart + theCoeff * xEnd; + y = (1.0 - theCoeff) * yStart + theCoeff * yEnd; + if (x > 1.0) x = 2.0 - x; + if (x < -1.0) x = -2.0 - x; + if (y > 1.0) y = 2.0 - y; + if (y < -1.0) y = -2.0 - y; + + aNorm = sqrt(x*x + y*y); + if (aNorm >= tolerance) { + x *= aRad / aNorm; + y *= aRad / aNorm; + } else { + x = -0.5 * (anArcPoint[2][1] + anArcPoint[1][1]); + y = -0.5 * (anArcPoint[2][0] + anArcPoint[1][0]); + } + theX = anArcPoint[0][0] + x; + theY = anArcPoint[0][1] + y; + } +} + diff --git a/src/SketchSolver/SketchSolver_Constraint.h b/src/SketchSolver/SketchSolver_Constraint.h index 3640d881d..6cfe355f8 100644 --- a/src/SketchSolver/SketchSolver_Constraint.h +++ b/src/SketchSolver/SketchSolver_Constraint.h @@ -91,6 +91,14 @@ protected: /// \brief Create or change SlveSpace entity according to the given feature Slvs_hEntity changeEntity(FeaturePtr theFeature, int& theType); + /// \brief Calculate middle point on the specified entity + /// \param[in] theEntity arc or line + /// \param[in] theCoeff is a value in [0.0, 1.0] which shows the position of the point on the entity (0.0 - start point, 1.0 - end point) + /// \param[out] theX X coordinate of middle point + /// \param[out] theY Y coordinate of middle point + void calculateMiddlePoint(const Slvs_Entity& theEntity, double theCoeff, + double& theX, double& theY) const; + /// \brief Removes the links to unused entities void cleanRemovedEntities(); @@ -98,6 +106,10 @@ protected: void cleanErrorMsg() { myErrorMsg.clear(); } +private: + /// \brief Sets error, if the attribute is not initialized + bool isInitialized(AttributePtr theAttribute); + protected: SketchSolver_Group* myGroup; ///< the group which contains current constraint ConstraintPtr myBaseConstraint; ///< SketchPlugin constraint diff --git a/src/SketchSolver/SketchSolver_ConstraintFillet.cpp b/src/SketchSolver/SketchSolver_ConstraintFillet.cpp new file mode 100644 index 000000000..a8b9bcf37 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintFillet.cpp @@ -0,0 +1,208 @@ +#include +#include +#include + +#include +#include +#include +#include + + +void SketchSolver_ConstraintFillet::getAttributes( + double& theValue, std::vector& theAttributes) +{ + theAttributes.clear(); + + DataPtr aData = myBaseConstraint->data(); + AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::VALUE())); + theValue = aValueAttr ? aValueAttr->value() : 0.0; + + std::list aBaseAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId()); + std::list::iterator anIter = aBaseAttrs.begin(); + for (; anIter != aBaseAttrs.end(); anIter++) { + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(*anIter); + if (!aRefAttr || !aRefAttr->isInitialized()) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; + } + + int aType = SLVS_E_UNKNOWN; // type of created entity + Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr); + if (anEntity == SLVS_E_UNKNOWN) + anEntity = changeEntity(aRefAttr, aType); + + if (aType == SLVS_E_UNKNOWN) + continue; + theAttributes.push_back(anEntity); + } + + // Fillet objects + AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast( + aData->attribute(SketchPlugin_Constraint::ENTITY_C())); + if (!aFilletRefList || !aFilletRefList->isInitialized()) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; + } + std::list aFilletList = aFilletRefList->list(); + if (aFilletList.size() < theAttributes.size() + 1) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; + } + FeaturePtr aFilletFeature; + ResultConstructionPtr aRC; + int aType; + std::list::iterator aFilIter = aFilletList.begin(); + for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) { + aRC = std::dynamic_pointer_cast(*aFilIter); + aFilletFeature = aRC ? aRC->document()->feature(aRC) : + std::dynamic_pointer_cast(*aFilIter); + if (!aFilletFeature) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; + } + Slvs_hEntity anEntity = changeEntity(aFilletFeature, aType); + theAttributes.push_back(anEntity); + } +} + +void SketchSolver_ConstraintFillet::process() +{ + cleanErrorMsg(); + if (!myBaseConstraint || !myStorage || myGroup == 0) { + /// TODO: Put error message here + return; + } + if (!mySlvsConstraints.empty()) // some data is changed, update constraint + update(myBaseConstraint); + + double aValue; + std::vector anEntID; + getAttributes(aValue, anEntID); + if (!myErrorMsg.empty()) + return; + + // Obtain the entities itself: + // First two are base entities + // Second two are trimmed them + // Last one is a fillet arc + std::vector anEntities; + std::vector::iterator anIt = anEntID.begin(); + for (; anIt != anEntID.end(); anIt++) + anEntities.push_back(myStorage->getEntity(*anIt)); + + // Check the base entities have a coincident point + Slvs_hEntity aPointsToFind[4]; + for (int i = 0; i < 2; i++) { + int aShift = anEntities[i].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0; + aPointsToFind[2*i] = anEntities[i].point[aShift]; + aPointsToFind[2*i+1]= anEntities[i].point[aShift+1]; + } + // Search coincident points + int aCoincInd[2]; // indices of coincident points on each entity (0 - first, 1 - last) + bool isPointFound = false; + for (int i = 0; i < 2 && !isPointFound; i++) + for (int j = 2; j < 4 && !isPointFound; j++) + if (myStorage->isCoincident(aPointsToFind[i], aPointsToFind[j])) { + aCoincInd[0] = i; + aCoincInd[1] = j - 2; + isPointFound = true; + } + if (!isPointFound) { + // There is no coincident points between tangential objects. Generate error message + myErrorMsg = SketchSolver_Error::NO_COINCIDENT_POINTS(); + return; + } + + // For correct result, move floating points of fillet on the middle points of base objects + Slvs_Entity aPoint; + Slvs_Param aParam; + double anArcPoints[3][2]; + for (int i = 0; i < 2; i++) { + calculateMiddlePoint(anEntities[i], 0.1 + 0.8 * aCoincInd[i], anArcPoints[i+1][0], anArcPoints[i+1][1]); + aPoint = myStorage->getEntity(anEntities[i+2].point[aCoincInd[i]]); + for (int j = 0; j < 2; j++) { + aParam = myStorage->getParameter(aPoint.param[j]); + aParam.val = anArcPoints[i+1][j]; + aPoint.param[j] = myStorage->updateParameter(aParam); + } + } + anArcPoints[0][0] = 0.5 * (anArcPoints[1][0] + anArcPoints[2][0]); + anArcPoints[0][1] = 0.5 * (anArcPoints[1][1] + anArcPoints[2][1]); + // Check the arc is need to be reversed + double aSharedPoint[2]; + aPoint = myStorage->getEntity(aPointsToFind[aCoincInd[0]]); + for (int j = 0; j < 2; j++) + aSharedPoint[j] = myStorage->getParameter(aPoint.param[j]).val; + double aCross = (anArcPoints[1][0] - anArcPoints[0][0]) * (aSharedPoint[1] - anArcPoints[0][1]) - + (anArcPoints[1][1] - anArcPoints[0][1]) * (aSharedPoint[0] - anArcPoints[0][0]); + if (aCross < 0.0) { // reverse fillet arc + double aTmp; + for (int j = 0; j < 2; j++) { + aTmp = anArcPoints[1][j]; + anArcPoints[1][j] = anArcPoints[2][j]; + anArcPoints[2][j] = aTmp; + } + } + // update fillet arc coordinates + for (int indArcPt = 0; indArcPt < 3; indArcPt++) { + aPoint = myStorage->getEntity(anEntities.back().point[indArcPt]); + for (int j = 0; j < 2; j++) { + aParam = myStorage->getParameter(aPoint.param[j]); + aParam.val = anArcPoints[indArcPt][j]; + aPoint.param[j] = myStorage->updateParameter(aParam); + } + } + + for (int indEnt = 0; indEnt < 2; indEnt++) { + int aShift = anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0; + // one point of fillet object should be coincident with the point on base, non-coincident with another base object + Slvs_hEntity aBaseID = anEntities[indEnt].point[1 - aCoincInd[indEnt] + aShift]; + Slvs_hEntity aFilletID = anEntities[2 + indEnt].point[1 - aCoincInd[indEnt] + aShift]; + Slvs_Constraint aCoincConstr = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), + 0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + aCoincConstr.h = myStorage->addConstraint(aCoincConstr); + mySlvsConstraints.push_back(aCoincConstr.h); + + // another point of fillet object should be placed on the base object + Slvs_Constraint aPonCurveConstr; + if (anEntities[indEnt].type == SLVS_E_ARC_OF_CIRCLE) { + // centers of arcs should be coincident + aBaseID = anEntities[indEnt].point[0]; + aFilletID = anEntities[2 + indEnt].point[0]; + aPonCurveConstr = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), + 0.0, aBaseID, aFilletID, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + } else { + aFilletID = anEntities[2 + indEnt].point[aCoincInd[indEnt]]; + aPonCurveConstr = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(), + 0.0, aFilletID, SLVS_E_UNKNOWN, anEntities[indEnt].h, SLVS_E_UNKNOWN); + } + aPonCurveConstr.h = myStorage->addConstraint(aPonCurveConstr); + mySlvsConstraints.push_back(aPonCurveConstr.h); + } +} + +bool SketchSolver_ConstraintFillet::remove(ConstraintPtr theConstraint) +{ + cleanErrorMsg(); + if (theConstraint && theConstraint != myBaseConstraint) + return false; + bool isFullyRemoved = true; + std::vector::iterator aCIter = mySlvsConstraints.begin(); + for (; aCIter != mySlvsConstraints.end(); aCIter++) + isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved; + mySlvsConstraints.clear(); + + if (isFullyRemoved) { + myFeatureMap.clear(); + myAttributeMap.clear(); + myValueMap.clear(); + } else + cleanRemovedEntities(); + return true; +} + diff --git a/src/SketchSolver/SketchSolver_ConstraintFillet.h b/src/SketchSolver/SketchSolver_ConstraintFillet.h new file mode 100644 index 000000000..126d46d37 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintFillet.h @@ -0,0 +1,45 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintFillet.h +// Created: 1 Apr 2015 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintFillet_H_ +#define SketchSolver_ConstraintFillet_H_ + +#include "SketchSolver.h" +#include + +/** \class SketchSolver_ConstraintFillet + * \ingroup Plugins + * \brief Convert fillet constraint to SolveSpace structure + */ +class SketchSolver_ConstraintFillet : public SketchSolver_Constraint +{ +public: + SketchSolver_ConstraintFillet(ConstraintPtr theConstraint) : + SketchSolver_Constraint(theConstraint) + {} + + virtual int getType() const + { return SLVS_C_FILLET; } + + /// \brief Tries to remove constraint + /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence) + virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr()); + +protected: + /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints + virtual void process(); + + /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints + /// \param[out] theValue numerical characteristic of constraint (e.g. distance) + /// \param[out] theAttributes list of attributes to be filled + /// + /// Parameter theAttributes contains 5 elements: + /// Two first entities in theAttributes list correspond to base features of fillet, + /// the next two entities represent trimmed base features and the last one is a fillet arc. + virtual void getAttributes(double& theValue, std::vector& theAttributes); +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_ConstraintManager.cpp b/src/SketchSolver/SketchSolver_ConstraintManager.cpp index 2dbd6c57d..d6094199f 100644 --- a/src/SketchSolver/SketchSolver_ConstraintManager.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintManager.cpp @@ -17,6 +17,9 @@ #include #include +#include +#include +#include #include #include @@ -104,19 +107,27 @@ void SketchSolver_ConstraintManager::processEvent( } } // then get anything but not the sketch - // at first, add coincidence constraints, because they may be used by other constraints + std::set aComplexConstraints; + // fillet and mirror an tangency constraints will be processed later for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { std::shared_ptr aFeature = std::dynamic_pointer_cast(*aFeatIter); - if (!aFeature || aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID()) + if (!aFeature) + continue; + if (aFeature->getKind() == SketchPlugin_ConstraintFillet::ID() || + aFeature->getKind() == SketchPlugin_ConstraintMirror::ID() || + aFeature->getKind() == SketchPlugin_ConstraintTangent::ID()) { + aComplexConstraints.insert(aFeature); continue; + } changeConstraintOrEntity(aFeature); } - // after that, add all features except coincidence - for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) { + // processing remain constraints + aFeatIter = aComplexConstraints.begin(); + for (; aFeatIter != aComplexConstraints.end(); aFeatIter++) { std::shared_ptr aFeature = std::dynamic_pointer_cast(*aFeatIter); - if (!aFeature /*|| aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()*/) + if (!aFeature) continue; changeConstraintOrEntity(aFeature); } @@ -226,7 +237,6 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity( // If the group is empty, the feature is not added (the constraint only) if (!aConstraint && !(*aGroupIter)->isEmpty()) return (*aGroupIter)->updateFeature(theFeature); -//// return (*aGroupIter)->changeEntityFeature(theFeature) != SLVS_E_UNKNOWN; return (*aGroupIter)->changeConstraint(aConstraint); } } else if (aGroups.size() > 1) { // Several groups applicable for this feature => need to merge them @@ -263,7 +273,6 @@ bool SketchSolver_ConstraintManager::changeConstraintOrEntity( if (aConstraint) return (*aFirstGroupIter)->changeConstraint(aConstraint); return (*aFirstGroupIter)->updateFeature(theFeature); -//// return (*aFirstGroupIter)->changeEntityFeature(theFeature) != SLVS_E_UNKNOWN; } // Something goes wrong @@ -282,48 +291,6 @@ void SketchSolver_ConstraintManager::moveEntity( for (; aGroupIt != myGroups.end(); aGroupIt++) if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature)) (*aGroupIt)->moveFeature(theFeature); - -//// // Create list of attributes depending on type of the feature -//// std::vector anAttrList; -//// const std::string& aFeatureKind = theFeature->getKind(); -//// // Point -//// if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) -//// anAttrList.push_back(SketchPlugin_Point::COORD_ID()); -//// // Line -//// else if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) { -//// anAttrList.push_back(SketchPlugin_Line::START_ID()); -//// anAttrList.push_back(SketchPlugin_Line::END_ID()); -//// } -//// // Circle -//// else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) { -//// anAttrList.push_back(SketchPlugin_Circle::CENTER_ID()); -//// anAttrList.push_back(SketchPlugin_Circle::RADIUS_ID()); -//// } -//// // Arc -//// else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) { -//// anAttrList.push_back(SketchPlugin_Arc::CENTER_ID()); -//// anAttrList.push_back(SketchPlugin_Arc::START_ID()); -//// anAttrList.push_back(SketchPlugin_Arc::END_ID()); -//// } -//// /// \todo Other types of features should be implemented -//// -//// // Check changing of feature's attributes (go through the groups and search usage of the attributes) -//// std::vector::const_iterator anAttrIter; -//// for (anAttrIter = anAttrList.begin(); anAttrIter != anAttrList.end(); anAttrIter++) { -//// std::vector::iterator aGroupIter; -//// for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) { -//// if ((*aGroupIter)->isEmpty()) -//// continue; -//// std::shared_ptr anAttribute = std::dynamic_pointer_cast< -//// ModelAPI_Attribute>(theFeature->data()->attribute(*anAttrIter)); -//// (*aGroupIter)->updateEntityIfPossible(anAttribute); -//// } -//// } -//// -//// std::vector::iterator aGroupIter; -//// for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) -//// if (!(*aGroupIter)->isEmpty()) -//// (*aGroupIter)->updateRelatedConstraintsFeature(theFeature); } // ============================================================================ diff --git a/src/SketchSolver/SketchSolver_ConstraintMirror.cpp b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp new file mode 100644 index 000000000..6ea42d13e --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintMirror.cpp @@ -0,0 +1,269 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + + +void SketchSolver_ConstraintMirror::getAttributes( + Slvs_Entity& theMirrorLine, + std::vector& theBaseEntities, + std::vector& theMirrorEntities) +{ + DataPtr aData = myBaseConstraint->data(); + AttributeRefAttrPtr aMirLineAttr = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A())); + if (!aMirLineAttr || !aMirLineAttr->isInitialized() || !aMirLineAttr->isObject()) { + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); + return; + } + int aType = SLVS_E_UNKNOWN; // type of created entity + Slvs_hEntity anEntity = myGroup->getAttributeId(aMirLineAttr); + if (anEntity == SLVS_E_UNKNOWN) + anEntity = changeEntity(aMirLineAttr, aType); + theMirrorLine = myStorage->getEntity(anEntity); + + // Create SolveSpace entity for all features + AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B())); + AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C())); + myNumberOfObjects = aMirroredRefList->size(); + if (!aBaseRefList || !aMirroredRefList) { + myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE(); + return; + } + + std::list aBaseList = aBaseRefList->list(); + std::list aMirroredList = aMirroredRefList->list(); + + FeaturePtr aFeature; + ResultConstructionPtr aRC; + for (int i = 0; i < 2; i++) { + std::list::iterator anIter = i == 0 ? aBaseList.begin() : aMirroredList.begin(); + std::list::iterator aEndIter = i == 0 ? aBaseList.end() : aMirroredList.end(); + std::vector* aList = i == 0 ? &theBaseEntities : & theMirrorEntities; + for ( ; anIter != aEndIter; anIter++) { + aRC = std::dynamic_pointer_cast(*anIter); + aFeature = aRC ? aRC->document()->feature(aRC) : + std::dynamic_pointer_cast(*anIter); + if (!aFeature) + continue; + + anEntity = changeEntity(aFeature, aType); + aList->push_back(myStorage->getEntity(anEntity)); + } + } + + if (theBaseEntities.size() > theMirrorEntities.size()) + myErrorMsg = SketchSolver_Error::NOT_INITIALIZED(); +} + +void SketchSolver_ConstraintMirror::process() +{ + cleanErrorMsg(); + if (!myBaseConstraint || !myStorage || myGroup == 0) { + /// TODO: Put error message here + return; + } + if (!mySlvsConstraints.empty()) // some data is changed, update constraint + update(myBaseConstraint); + + Slvs_Entity aMirrorLine; + std::vector aBaseList; + std::vector aMirrorList; + getAttributes(aMirrorLine, aBaseList, aMirrorList); + if (!myErrorMsg.empty()) + return; + + if (aBaseList.size() != aMirrorList.size()) { + myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE(); + return; + } + + Slvs_Constraint aConstraint; + // Get coordinates of mirror line points for speed up + 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; + } + + std::vector::iterator aBaseIter = aBaseList.begin(); + std::vector::iterator aMirrorIter = aMirrorList.begin(); + for (; aBaseIter != aBaseList.end(); aBaseIter++, aMirrorIter++) { + // Make aMirrorEnt parameters to be symmetric with aBaseEnt + makeMirrorEntity(*aBaseIter, *aMirrorIter, aStartEnd); + + if (aBaseIter->type == SLVS_E_POINT_IN_2D) { + aConstraint = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), + 0.0, aBaseIter->h, aMirrorIter->h, aMirrorLine.h, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + } else if (aBaseIter->type == SLVS_E_LINE_SEGMENT) { + for (int i = 0; i < 2; i++) { + aConstraint = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0, + aBaseIter->point[i], aMirrorIter->point[i], aMirrorLine.h, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + } + } else if (aBaseIter->type == SLVS_E_CIRCLE) { + aConstraint = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0, + aBaseIter->point[0], aMirrorIter->point[0], aMirrorLine.h, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + // Additional constraint for equal radii + Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_EQUAL_RADIUS, myGroup->getWorkplaneId(), + 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseIter->h, aMirrorIter->h); + anEqRadConstr.h = myStorage->addConstraint(anEqRadConstr); + mySlvsConstraints.push_back(anEqRadConstr.h); + } else if (aBaseIter->type == SLVS_E_ARC_OF_CIRCLE) { + // Workaround to avoid problems in SolveSpace. + // The symmetry of two arcs will be done using symmetry of three points on these arcs: + // start point, end point, and any other point on the arc + Slvs_hEntity aBaseArcPoints[3] = { + aBaseIter->point[1], + 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], + SLVS_E_UNKNOWN}; + + Slvs_Entity aBothArcs[2] = {*aBaseIter, *aMirrorIter}; + Slvs_hEntity aBothMiddlePoints[2]; + for (int i = 0; i < 2; i++) { + double x, y; + calculateMiddlePoint(aBothArcs[i], 0.5, x, y); + Slvs_Param aParamX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), x); + Slvs_Param aParamY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), y); + aParamX.h = myStorage->addParameter(aParamX); + aParamY.h = myStorage->addParameter(aParamY); + Slvs_Entity aPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(), + myGroup->getWorkplaneId(), aParamX.h, aParamY.h); + aBothMiddlePoints[i] = myStorage->addEntity(aPoint); + // additional constraint point-on-curve + Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_PT_ON_CIRCLE, myGroup->getWorkplaneId(), + 0.0, aBothMiddlePoints[i], SLVS_E_UNKNOWN, aBothArcs[i].h, SLVS_E_UNKNOWN); + aPonCircConstr.h = myStorage->addConstraint(aPonCircConstr); + mySlvsConstraints.push_back(aPonCircConstr.h); + } + + aBaseArcPoints[2] = aBothMiddlePoints[0]; + aMirrorArcPoints[2] = aBothMiddlePoints[1]; + for (int ind = 0; ind < 3; ind++) { + Slvs_Constraint aConstraint = Slvs_MakeConstraint( + SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), 0.0, + aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLine.h, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + } + } + } + + // 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); + } +} + + +void SketchSolver_ConstraintMirror::update(ConstraintPtr theConstraint) +{ + cleanErrorMsg(); + if (!theConstraint || theConstraint == myBaseConstraint) { + AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast( + myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C())); + if (aMirroredRefList->size() != myNumberOfObjects) { + remove(myBaseConstraint); + process(); + } + } + SketchSolver_Constraint::update(); +} + +bool SketchSolver_ConstraintMirror::remove(ConstraintPtr theConstraint) +{ + cleanErrorMsg(); + if (theConstraint && theConstraint != myBaseConstraint) + return false; + bool isFullyRemoved = true; + std::vector::iterator aCIter = mySlvsConstraints.begin(); + for (; aCIter != mySlvsConstraints.end(); aCIter++) + isFullyRemoved = myStorage->removeConstraint(*aCIter) && isFullyRemoved; + mySlvsConstraints.clear(); + + if (isFullyRemoved) { + myFeatureMap.clear(); + myAttributeMap.clear(); + myValueMap.clear(); + } else + cleanRemovedEntities(); + return true; +} + +void SketchSolver_ConstraintMirror::makeMirrorEntity( + const Slvs_Entity& theBase, + const Slvs_Entity& theMirror, + const double theMirrorLine[]) const +{ + Slvs_hEntity aBasePoint[4]; + Slvs_hEntity aMirrorPoint[4]; + for (int i = 0; i < 4; i++) { + aBasePoint[i] = theBase.point[i]; + aMirrorPoint[i] = theMirror.point[i]; + } + if (theBase.type == SLVS_E_ARC_OF_CIRCLE) { + Slvs_hEntity aTmp = aMirrorPoint[2]; + aMirrorPoint[2] = aMirrorPoint[1]; + aMirrorPoint[1] = aTmp; + } + + // Mirror line parameters + std::shared_ptr aLinePoints[2]; + for (int i = 0; i < 2; i++) + aLinePoints[i] = std::shared_ptr( + new GeomAPI_XY(theMirrorLine[2*i], theMirrorLine[2*i+1])); + // direction of a mirror line + std::shared_ptr aDir = std::shared_ptr( + new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0)))); + // orthogonal direction + aDir = std::shared_ptr(new GeomAPI_Dir2d(aDir->y(), -aDir->x())); + + for (int i = 0; i < 4; i++) { + if (aBasePoint[i] == SLVS_E_UNKNOWN || aMirrorPoint[i] == SLVS_E_UNKNOWN) + continue; + Slvs_Entity aPointEnt = myStorage->getEntity(aBasePoint[i]); + double aBaseX = myStorage->getParameter(aPointEnt.param[0]).val; + double aBaseY = myStorage->getParameter(aPointEnt.param[1]).val; + std::shared_ptr aPoint = std::shared_ptr(new GeomAPI_XY(aBaseX, aBaseY)); + + std::shared_ptr aVec = std::shared_ptr( + new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y())); + double aDist = aVec->dot(aDir->xy()); + aPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist)); + + Slvs_Entity aMirrorEnt = myStorage->getEntity(aMirrorPoint[i]); + Slvs_Param aParam = Slvs_MakeParam(aMirrorEnt.param[0], myGroup->getId(), aPoint->x()); + myStorage->updateParameter(aParam); + aParam = Slvs_MakeParam(aMirrorEnt.param[1], myGroup->getId(), aPoint->y()); + myStorage->updateParameter(aParam); + } +} + diff --git a/src/SketchSolver/SketchSolver_ConstraintMirror.h b/src/SketchSolver/SketchSolver_ConstraintMirror.h new file mode 100644 index 000000000..092e4dff6 --- /dev/null +++ b/src/SketchSolver/SketchSolver_ConstraintMirror.h @@ -0,0 +1,64 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +// File: SketchSolver_ConstraintMirror.h +// Created: 1 Apr 2015 +// Author: Artem ZHIDKOV + +#ifndef SketchSolver_ConstraintMirror_H_ +#define SketchSolver_ConstraintMirror_H_ + +#include "SketchSolver.h" +#include + +/** \class SketchSolver_ConstraintMirror + * \ingroup Plugins + * \brief Convert fillet constraint to SolveSpace structure + */ +class SketchSolver_ConstraintMirror : public SketchSolver_Constraint +{ +public: + SketchSolver_ConstraintMirror(ConstraintPtr theConstraint) : + SketchSolver_Constraint(theConstraint), + myNumberOfObjects(0) + {} + + virtual int getType() const + { return SLVS_C_SYMMETRIC_LINE; } + + /// \brief Update constraint + virtual void update(ConstraintPtr theConstraint = ConstraintPtr()); + + /// \brief Tries to remove constraint + /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence) + virtual bool remove(ConstraintPtr theConstraint = ConstraintPtr()); + +protected: + /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints + virtual void process(); + + /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints + /// \param[out] theValue numerical characteristic of constraint (e.g. distance) + /// \param[out] theAttributes list of attributes to be filled + virtual void getAttributes(double& theValue, std::vector& theAttributes) + { /* do nothing here */ } + + /// \brief Generate list of entities of mirror constraint + /// \param[out] theMirrorLine entity corresponding to mirror line + /// \param[out] theBaseEntities list of entities to mirror + /// \param[out] theMirrorEntities list of mirrored entities + void getAttributes(Slvs_Entity& theMirrorLine, + std::vector& theBaseEntities, + std::vector& theMirrorEntities); + +private: + /// \brief Change parameters of entities to be symmetric relative a line, + /// given by array of parameters (coordinates of first and last points) + void makeMirrorEntity(const Slvs_Entity& theBase, + const Slvs_Entity& theMirror, + const double theMirrorLine[]) const; + +private: + size_t myNumberOfObjects; ///< number of previously mirrored objects +}; + +#endif diff --git a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp index 12815acf3..75cf0d0d0 100644 --- a/src/SketchSolver/SketchSolver_ConstraintRigid.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintRigid.cpp @@ -2,8 +2,15 @@ #include #include +#include +#include #include +#include +#include +#include +#include + SketchSolver_ConstraintRigid::SketchSolver_ConstraintRigid(FeaturePtr theFeature) : SketchSolver_Constraint(), myBaseFeature(theFeature) @@ -24,10 +31,22 @@ void SketchSolver_ConstraintRigid::process() double aValue; std::vector anEntities; getAttributes(aValue, anEntities); + if (!myErrorMsg.empty()) + return; Slvs_Constraint aConstraint; std::vector::iterator aConstrIter = mySlvsConstraints.begin(); bool isEmpty = aConstrIter == mySlvsConstraints.end(); + + // Check the fixed entity is an arc + if (isEmpty) { + if (!myFeatureMap.empty() && myFeatureMap.begin()->first->getKind() == SketchPlugin_Arc::ID()) { + Slvs_Entity anArc = myStorage->getEntity(myFeatureMap.begin()->second); + fixArc(anArc); + return; + } + } + std::vector::const_iterator anEntIter = anEntities.begin(); for (; anEntIter != anEntities.end(); anEntIter++) { if (*anEntIter == SLVS_E_UNKNOWN) @@ -37,7 +56,7 @@ void SketchSolver_ConstraintRigid::process() if (isEmpty && !isForceUpdate) { // create new constraint if (aConstrID != SLVS_E_UNKNOWN) continue; // the coincident point is already fixed - aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), + aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), aValue, *anEntIter, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); aConstraint.h = myStorage->addConstraint(aConstraint); mySlvsConstraints.push_back(aConstraint.h); @@ -57,6 +76,18 @@ void SketchSolver_ConstraintRigid::process() } } } + + if (!myFeatureMap.empty() && myFeatureMap.begin()->first->getKind() == SketchPlugin_Circle::ID()) { + // Fix radius of a circle + AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast( + myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID())); + aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER, myGroup->getWorkplaneId(), + aRadiusAttr->value() * 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); + } } @@ -93,6 +124,39 @@ void SketchSolver_ConstraintRigid::getAttributes( theAttributes.push_back(anEntityID); } +void SketchSolver_ConstraintRigid::adjustConstraint() +{ + if (myFeatureMap.empty() || ( + myFeatureMap.begin()->first->getKind() != SketchPlugin_Arc::ID() && + myFeatureMap.begin()->first->getKind() != SketchPlugin_Circle::ID())) + return; + FeaturePtr aFeature = myFeatureMap.begin()->first; + + // Search radius constraints and update them + Slvs_Constraint aConstraint; + std::vector::iterator aCIter = mySlvsConstraints.begin(); + for (; aCIter != mySlvsConstraints.end(); aCIter++) { + aConstraint = myStorage->getConstraint(*aCIter); + if (aConstraint.type != SLVS_C_DIAMETER) + continue; + double aRadius = 0.0; + if (aFeature->getKind() == SketchPlugin_Arc::ID()) { + std::shared_ptr aCenter = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt(); + std::shared_ptr aStart = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt(); + aRadius = aCenter->distance(aStart); + } else { + aRadius = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Circle::RADIUS_ID()))->value(); + } + + aConstraint.valA = aRadius * 2.0; + *aCIter = myStorage->updateConstraint(aConstraint); + } +} + + bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint) { cleanErrorMsg(); @@ -112,3 +176,58 @@ bool SketchSolver_ConstraintRigid::remove(ConstraintPtr theConstraint) return true; } + +void SketchSolver_ConstraintRigid::fixArc(const Slvs_Entity& theArc) +{ + Slvs_Constraint aConstraint; + Slvs_hConstraint aConstrID = myStorage->isPointFixed(theArc.point[0]); + int aPointsToFix = 2; // number of fixed points for the arc + if (aConstrID != SLVS_E_UNKNOWN) + aPointsToFix--; + + // Radius of the arc + FeaturePtr aFeature = myFeatureMap.begin()->first; + std::shared_ptr aCenter = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt(); + std::shared_ptr aStart = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt(); + double aRadius = aCenter->distance(aStart); + + // Update end point of the arc to be on a curve + std::shared_ptr anEnd = std::dynamic_pointer_cast( + aFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt(); + double aDistance = anEnd->distance(aCenter); + std::shared_ptr aDir = anEnd->xy()->decreased(aCenter->xy()); + if (aDistance < tolerance) + aDir = aStart->xy()->decreased(aCenter->xy())->multiplied(-1.0); + else + aDir = aDir->multiplied(aRadius / aDistance); + double xy[2] = {aCenter->x() + aDir->x(), aCenter->y() + aDir->y()}; + Slvs_Entity aEndPoint = myStorage->getEntity(theArc.point[2]); + for (int i = 0; i < 2; i++) { + Slvs_Param aParam = myStorage->getParameter(aEndPoint.param[i]); + aParam.val = xy[i]; + myStorage->updateParameter(aParam); + } + + for (int i = 1; aPointsToFix > 0; i++, aPointsToFix--) { + aConstrID = myStorage->isPointFixed(theArc.point[i]); + if (aConstrID != SLVS_E_UNKNOWN) + continue; // the coincident point is already fixed + aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), getType(), myGroup->getWorkplaneId(), + 0.0, theArc.point[i], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); + aConstraint.h = myStorage->addConstraint(aConstraint); + mySlvsConstraints.push_back(aConstraint.h); + if (!myBaseConstraint) + myStorage->addTemporaryConstraint(aConstraint.h); + } + + // 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); +} + diff --git a/src/SketchSolver/SketchSolver_ConstraintRigid.h b/src/SketchSolver/SketchSolver_ConstraintRigid.h index 66f581638..dd1487782 100644 --- a/src/SketchSolver/SketchSolver_ConstraintRigid.h +++ b/src/SketchSolver/SketchSolver_ConstraintRigid.h @@ -44,6 +44,16 @@ protected: /// \param[out] theAttributes list of attributes to be filled virtual void getAttributes(double& theValue, std::vector& theAttributes); + /// \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 The arc is fixed differently to avoid SolveSpace problems (overconstraint) + /// + /// There will be fixed start and end points and the radius of the arc. + void fixArc(const Slvs_Entity& theArc); + protected: FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL) }; diff --git a/src/SketchSolver/SketchSolver_Error.h b/src/SketchSolver/SketchSolver_Error.h index b05cb554e..1a5718a8d 100644 --- a/src/SketchSolver/SketchSolver_Error.h +++ b/src/SketchSolver/SketchSolver_Error.h @@ -47,6 +47,12 @@ class SketchSolver_Error static const std::string MY_ERROR_VALUE("An arc should be an attribute of tangency constraint"); return MY_ERROR_VALUE; } + /// Mirror constraint has wrong attributes + inline static const std::string& INCORRECT_MIRROR_ATTRIBUTE() + { + static const std::string MY_ERROR_VALUE("Mirror constraint has wrong attributes"); + return MY_ERROR_VALUE; + } }; #endif diff --git a/src/SketchSolver/SketchSolver_FeatureStorage.cpp b/src/SketchSolver/SketchSolver_FeatureStorage.cpp index 5e112078d..610993a74 100644 --- a/src/SketchSolver/SketchSolver_FeatureStorage.cpp +++ b/src/SketchSolver/SketchSolver_FeatureStorage.cpp @@ -313,11 +313,6 @@ bool SketchSolver_FeatureStorage::isConsistent() const for (; aFIter != myFeatures.end(); aFIter++) if (!aFIter->first->data() || !aFIter->first->data()->isValid()) return false; -//// // Check the attributes are valid -//// MapAttributeFeature::const_iterator aTIter = myAttributes.begin(); -//// for (; aTIter != myAttributes.end(); aTIter++) -//// if (!aTIter->first->isInitialized()) -//// return false; return true; } diff --git a/src/SketchSolver/SketchSolver_Group.cpp b/src/SketchSolver/SketchSolver_Group.cpp index 0a250d8c2..1ad3646dd 100644 --- a/src/SketchSolver/SketchSolver_Group.cpp +++ b/src/SketchSolver/SketchSolver_Group.cpp @@ -63,13 +63,6 @@ private: Slvs_hGroup GroupIndexer::myGroupIndex = 0; -/** \brief Search the entity/parameter with specified ID in the list of elements - * \param[in] theEntityID unique ID of the element - * \param[in] theEntities list of elements - * \return position of the found element or -1 if the element is not found - */ -template -static int Search(const uint32_t& theEntityID, const std::vector& theEntities); // ======================================================== // ========= SketchSolver_Group =============== @@ -127,15 +120,22 @@ bool SketchSolver_Group::isInteract( // ============================================================================ Slvs_hEntity SketchSolver_Group::getFeatureId(FeaturePtr theFeature) const { + Slvs_hEntity aResult = SLVS_E_UNKNOWN; if (!myFeatureStorage) - return SLVS_E_UNKNOWN; + return aResult; std::set aConstraints = myFeatureStorage->getConstraints(theFeature); if (aConstraints.empty()) - return SLVS_E_UNKNOWN; - ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstraints.begin()); - if (aCIter == myConstraints.end()) - return SLVS_E_UNKNOWN; - return aCIter->second->getId(theFeature); + return aResult; + std::set::iterator aConstrIter = aConstraints.begin(); + for (; aConstrIter != aConstraints.end(); aConstrIter++) { + ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstrIter); + if (aCIter == myConstraints.end()) + continue; + aResult = aCIter->second->getId(theFeature); + if (aResult != SLVS_E_UNKNOWN) + return aResult; + } + return SLVS_E_UNKNOWN; } // ============================================================================ @@ -145,15 +145,22 @@ Slvs_hEntity SketchSolver_Group::getFeatureId(FeaturePtr theFeature) const // ============================================================================ Slvs_hEntity SketchSolver_Group::getAttributeId(AttributePtr theAttribute) const { + Slvs_hEntity aResult = SLVS_E_UNKNOWN; if (!myFeatureStorage) - return SLVS_E_UNKNOWN; + return aResult; std::set aConstraints = myFeatureStorage->getConstraints(theAttribute); if (aConstraints.empty()) - return SLVS_E_UNKNOWN; - ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstraints.begin()); - if (aCIter == myConstraints.end()) - return SLVS_E_UNKNOWN; - return aCIter->second->getId(theAttribute); + return aResult; + std::set::iterator aConstrIter = aConstraints.begin(); + for (; aConstrIter != aConstraints.end(); aConstrIter++) { + ConstraintConstraintMap::const_iterator aCIter = myConstraints.find(*aConstrIter); + if (aCIter == myConstraints.end()) + continue; + aResult = aCIter->second->getId(theAttribute); + if (aResult != SLVS_E_UNKNOWN) + return aResult; + } + return SLVS_E_UNKNOWN; } // ============================================================================ @@ -206,215 +213,31 @@ bool SketchSolver_Group::changeConstraint( else myConstraints[theConstraint]->update(); + // Fix base features for fillet + if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) { + std::list anAttrList = + theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId()); + std::list::iterator anAttrIter = anAttrList.begin(); + for (; anAttrIter != anAttrList.end(); anAttrIter++) { + AttributeRefAttrPtr aRefAttr = + std::dynamic_pointer_cast(*anAttrIter); + if (!aRefAttr || !aRefAttr->isObject()) + continue; + FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object()); + SolverConstraintPtr aConstraint = + SketchSolver_Builder::getInstance()->createRigidConstraint(aFeature); + if (!aConstraint) + continue; + aConstraint->setGroup(this); + aConstraint->setStorage(myStorage); + myTempConstraints.insert(aConstraint); + } + } + if (!myFeatureStorage) myFeatureStorage = FeatureStoragePtr(new SketchSolver_FeatureStorage); myFeatureStorage->changeConstraint(theConstraint); -//// if (theConstraint) { -//// if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID()) -//// return changeRigidConstraint(theConstraint); -//// if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) -//// return changeMirrorConstraint(theConstraint); -//// if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) -//// return changeFilletConstraint(theConstraint); -//// } -//// -//// // Search this constraint in the current group to update it -//// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint); -//// std::vector::iterator aConstrIter; -//// if (aConstrMapIter != myConstraintMap.end()) { -//// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints); -//// aConstrIter = myConstraints.begin() + aConstrPos; -//// } -//// -//// // Get constraint type and verify the constraint parameters are correct -//// SketchSolver_Constraint aConstraint(theConstraint); -//// int aConstrType = aConstraint.getType(); -//// if (aConstrType == SLVS_C_UNKNOWN -//// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType)) -//// return false; -//// const std::vector& aConstraintAttributes = aConstraint.getAttributes(); -//// -//// // Create constraint parameters -//// double aDistance = 0.0; // scalar value of the constraint -//// AttributeDoublePtr aDistAttr = std::dynamic_pointer_cast( -//// theConstraint->data()->attribute(SketchPlugin_Constraint::VALUE())); -//// if (aDistAttr) { -//// aDistance = aDistAttr->value(); -//// // Issue #196: checking the positivity of the distance constraint -//// if (aDistance < tolerance && -//// (aConstrType == SLVS_C_PT_PT_DISTANCE || aConstrType == SLVS_C_PT_LINE_DISTANCE)) -//// return false; -//// // SketchPlugin circle defined by its radius, but SolveSpace uses constraint for diameter -//// if (aConstrType == SLVS_C_DIAMETER) -//// aDistance *= 2.0; -//// if (aConstrMapIter != myConstraintMap.end() -//// && fabs(aConstrIter->valA - aDistance) > tolerance) { -//// myNeedToSolve = true; -//// aConstrIter->valA = aDistance; -//// } -//// } -//// -//// size_t aNbTmpConstraints = myTempConstraints.size(); -//// Slvs_hEntity aConstrEnt[CONSTRAINT_ATTR_SIZE]; // parameters of the constraint -//// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { -//// aConstrEnt[indAttr] = SLVS_E_UNKNOWN; -//// std::shared_ptr aConstrAttr = std::dynamic_pointer_cast< -//// ModelAPI_AttributeRefAttr>( -//// theConstraint->data()->attribute(aConstraintAttributes[indAttr])); -//// if (!aConstrAttr) -//// continue; -//// -//// // Convert the object of the attribute to the feature -//// FeaturePtr aFeature; -//// if (aConstrAttr->isObject() && aConstrAttr->object()) { -//// ResultConstructionPtr aRC = std::dynamic_pointer_cast( -//// aConstrAttr->object()); -//// if (!aRC) -//// continue; -//// std::shared_ptr aDoc = aRC->document(); -//// aFeature = aDoc->feature(aRC); -//// } -//// -//// // For the length constraint the start and end points of the line should be added to the entities list instead of line -//// if (aConstrType == SLVS_C_PT_PT_DISTANCE -//// && theConstraint->getKind().compare(SketchPlugin_ConstraintLength::ID()) == 0) { -//// Slvs_hEntity aLineEnt = changeEntityFeature(aFeature); -//// int aEntPos = Search(aLineEnt, myEntities); -//// aConstrEnt[indAttr++] = myEntities[aEntPos].point[0]; -//// aConstrEnt[indAttr++] = myEntities[aEntPos].point[1]; -//// while (indAttr < CONSTRAINT_ATTR_SIZE) -//// aConstrEnt[indAttr++] = 0; -//// break; // there should be no other entities -//// } else if (aConstrAttr->isObject()) -//// aConstrEnt[indAttr] = changeEntityFeature(aFeature); -//// else -//// aConstrEnt[indAttr] = changeEntity(aConstrAttr->attr()); -//// } -//// -//// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint -//// // Several points may be coincident, it is not necessary to store all constraints between them. -//// // Try to find sequence of coincident points which connects the points of new constraint -//// if (aConstrType == SLVS_C_POINTS_COINCIDENT) { -//// if (aConstrEnt[0] == aConstrEnt[1]) // no need to add self coincidence -//// return false; -//// if (!addCoincidentPoints(aConstrEnt[0], aConstrEnt[1])) { -//// myExtraCoincidence.insert(theConstraint); // the constraint is stored for further purposes -//// return false; -//// } -//// if (aNbTmpConstraints < myTempConstraints.size()) { -//// // There was added temporary constraint. Check that there is no coincident points which already rigid. -//// -//// // Get list of already fixed points -//// std::set anAlreadyFixed; -//// std::vector::const_iterator aCIter = myConstraints.begin(); -//// for (; aCIter != myConstraints.end(); aCIter++) -//// if (aCIter->type == SLVS_C_WHERE_DRAGGED) { -//// std::list::const_iterator aTmpIt = myTempConstraints.begin(); -//// for (; aTmpIt != myTempConstraints.end(); aTmpIt++) -//// if (*aTmpIt == aCIter->h) -//// break; -//// if (aTmpIt == myTempConstraints.end()) -//// anAlreadyFixed.insert(aCIter->ptA); -//// } -//// -//// std::set aTmpConstrToDelete; -//// std::list::reverse_iterator aTmpIter = myTempConstraints.rbegin(); -//// size_t aCurSize = myTempConstraints.size(); -//// for (; aCurSize > aNbTmpConstraints && aTmpIter != myTempConstraints.rend(); -//// aTmpIter++, aCurSize--) { -//// int aConstrPos = Search(*aTmpIter, myConstraints); -//// std::vector >::const_iterator -//// aCoincIter = myCoincidentPoints.begin(); -//// for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++) -//// if (aCoincIter->find(myConstraints[aConstrPos].ptA) != aCoincIter->end()) { -//// std::set::const_iterator anIt; -//// for (anIt = aCoincIter->begin(); anIt != aCoincIter->end(); anIt++) -//// if (anAlreadyFixed.find(*anIt) != anAlreadyFixed.end()) { -//// aTmpConstrToDelete.insert(*aTmpIter); -//// break; -//// } -//// break; -//// } -//// } -//// if (!aTmpConstrToDelete.empty()) -//// removeTemporaryConstraints(aTmpConstrToDelete); -//// } -//// } -//// // For the tangency constraints it is necessary to identify which points of entities are coincident -//// int aSlvsOtherFlag = 0; -//// int aSlvsOther2Flag = 0; -//// if (aConstrType == SLVS_C_ARC_LINE_TANGENT || aConstrType == SLVS_C_CURVE_CURVE_TANGENT) { -//// // Search entities used by constraint -//// int anEnt1Pos = Search(aConstrEnt[2], myEntities); -//// int anEnt2Pos = Search(aConstrEnt[3], myEntities); -//// // Obtain start and end points of entities -//// Slvs_hEntity aPointsToFind[4]; -//// aPointsToFind[0] = myEntities[anEnt1Pos].point[1]; -//// aPointsToFind[1]= myEntities[anEnt1Pos].point[2]; -//// bool hasLine = (myEntities[anEnt2Pos].type == SLVS_E_LINE_SEGMENT); -//// aPointsToFind[2]= myEntities[anEnt2Pos].point[hasLine ? 0 : 1]; -//// aPointsToFind[3]= myEntities[anEnt2Pos].point[hasLine ? 1 : 2]; -//// // Search coincident points -//// bool isPointFound[4]; -//// std::vector >::const_iterator aCPIter = myCoincidentPoints.begin(); -//// for ( ; aCPIter != myCoincidentPoints.end(); aCPIter++) { -//// for (int i = 0; i < 4; i++) -//// isPointFound[i] = (aCPIter->find(aPointsToFind[i]) != aCPIter->end()); -//// if ((isPointFound[0] || isPointFound[1]) && (isPointFound[2] || isPointFound[3])) { -//// // the arc is tangent by end point -//// if (isPointFound[1]) aSlvsOtherFlag = 1; -//// // the second item is an arc and it is tangent by end point too -//// if (!hasLine && isPointFound[3]) aSlvsOther2Flag = 1; -//// break; -//// } -//// } -//// if (aCPIter == myCoincidentPoints.end()) { -//// // There is no coincident points between tangential objects. Generate error message -//// Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this); -//// return false; -//// } -//// } -//// -//// // Create SolveSpace constraint structure -//// Slvs_Constraint aSlvsConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType, -//// myWorkplane.h, aDistance, aConstrEnt[0], -//// aConstrEnt[1], aConstrEnt[2], aConstrEnt[3]); -//// if (aSlvsOtherFlag != 0) aSlvsConstr.other = aSlvsOtherFlag; -//// if (aSlvsOther2Flag != 0) aSlvsConstr.other2 = aSlvsOther2Flag; -//// myConstraints.push_back(aSlvsConstr); -//// myConstraintMap[theConstraint] = std::vector(1, aSlvsConstr.h); -//// int aConstrPos = Search(aSlvsConstr.h, myConstraints); -//// aConstrIter = myConstraints.begin() + aConstrPos; -//// myNeedToSolve = true; -//// } else { // Attributes of constraint may be changed => update constraint -//// Slvs_hEntity* aCurrentAttr[] = {&aConstrIter->ptA, &aConstrIter->ptB, -//// &aConstrIter->entityA, &aConstrIter->entityB, -//// &aConstrIter->entityC, &aConstrIter->entityD}; -//// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) { -//// if (*(aCurrentAttr[indAttr]) != aConstrEnt[indAttr]) -//// { -//// *(aCurrentAttr[indAttr]) = aConstrEnt[indAttr]; -//// myNeedToSolve = true; -//// } -//// } -//// } -//// -//// // Update flags of entities to be used by constraints -//// for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) -//// if (aConstrEnt[indAttr] != 0) { -//// int aPos = Search(aConstrEnt[indAttr], myEntities); -//// myEntOfConstr[aPos] = true; -//// // Sub-entities should be used implcitly -//// Slvs_hEntity* aEntPtr = myEntities[aPos].point; -//// while (*aEntPtr != 0) { -//// aPos = Search(*aEntPtr, myEntities); -//// myEntOfConstr[aPos] = true; -//// aEntPtr++; -//// } -//// } -//// -//// checkConstraintConsistence(*aConstrIter); return true; } @@ -445,844 +268,6 @@ void SketchSolver_Group::moveFeature(std::shared_ptr theFe myTempConstraints.insert(aConstraint); } -////// ============================================================================ -////// Function: changeRigidConstraint -////// Class: SketchSolver_Group -////// Purpose: create/update the "Rigid" constraint in the group -////// ============================================================================ -////bool SketchSolver_Group::changeRigidConstraint( -//// std::shared_ptr theConstraint) -////{ -//// // Search this constraint in the current group to update it -//// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint); -//// std::vector::iterator aConstrIter; -//// if (aConstrMapIter != myConstraintMap.end()) { -//// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints); -//// aConstrIter = myConstraints.begin() + aConstrPos; -//// } -//// -//// // Get constraint type and verify the constraint parameters are correct -//// SketchSolver_Constraint aConstraint(theConstraint); -//// int aConstrType = aConstraint.getType(); -//// if (aConstrType == SLVS_C_UNKNOWN -//// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType)) -//// return false; -//// const std::vector& aConstraintAttributes = aConstraint.getAttributes(); -//// -//// Slvs_hEntity aConstrEnt = SLVS_E_UNKNOWN; -//// std::shared_ptr aConstrAttr = std::dynamic_pointer_cast< -//// ModelAPI_AttributeRefAttr>( -//// theConstraint->data()->attribute(aConstraintAttributes[0])); -//// if (!aConstrAttr) -//// return false; -//// -//// // Convert the object of the attribute to the feature -//// FeaturePtr aFeature; -//// if (aConstrAttr->isObject() && aConstrAttr->object()) { -//// ResultConstructionPtr aRC = std::dynamic_pointer_cast( -//// aConstrAttr->object()); -//// if (!aRC) -//// return false; -//// std::shared_ptr aDoc = aRC->document(); -//// aFeature = aDoc->feature(aRC); -//// } -//// -//// aConstrEnt = aConstrAttr->isObject() ? changeEntityFeature(aFeature) : changeEntity(aConstrAttr->attr()); -//// -//// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint -//// // Check the fixed entity is not a point. -//// std::shared_ptr aConstrAttr = std::dynamic_pointer_cast< -//// ModelAPI_AttributeRefAttr>(theConstraint->data()->attribute(aConstraintAttributes[0])); -//// std::shared_ptr aPoint = -//// std::dynamic_pointer_cast(aConstrAttr->attr()); -//// std::shared_ptr aPoint2D = -//// std::dynamic_pointer_cast(aConstrAttr->attr()); -//// if (aPoint || aPoint2D) { -//// // Create SolveSpace constraint structure -//// Slvs_Constraint aConstraint = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, -//// aConstrEnt, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aConstraint); -//// myConstraintMap[theConstraint] = std::vector(1, aConstraint.h); -//// int aConstrPos = Search(aConstraint.h, myConstraints); -//// aConstrIter = myConstraints.begin() + aConstrPos; -//// myNeedToSolve = true; -//// } else { -//// myConstraintMap[theConstraint] = std::vector(); -//// -//// // To avoid SolveSpace problems: -//// // * if the circle is rigid, we will fix its center and radius; -//// // * if the arc is rigid, we will fix its start and end points and radius. -//// double aRadius = 0.0; -//// bool isArc = false; -//// bool isCircle = false; -//// if (aFeature) { -//// if (aFeature->getKind() == SketchPlugin_Arc::ID()) { -//// std::shared_ptr aCenter = -//// std::dynamic_pointer_cast( -//// aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID())); -//// std::shared_ptr aStart = -//// std::dynamic_pointer_cast( -//// aFeature->data()->attribute(SketchPlugin_Arc::START_ID())); -//// aRadius = aStart->pnt()->distance(aCenter->pnt()); -//// isArc = true; -//// } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) { -//// aRadius = std::dynamic_pointer_cast( -//// aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()))->value(); -//// isCircle = true; -//// } -//// } -//// -//// // Get list of already fixed points -//// std::set anAlreadyFixed; -//// std::vector::const_iterator aCIter = myConstraints.begin(); -//// for (; aCIter != myConstraints.end(); aCIter++) -//// if (aCIter->type == SLVS_C_WHERE_DRAGGED) -//// anAlreadyFixed.insert(aCIter->ptA); -//// -//// // Create constraints to fix the parameters of the entity -//// int aEntPos = Search(aConstrEnt, myEntities); -//// Slvs_hEntity* aPointsPtr = myEntities[aEntPos].point; -//// if (isArc) aPointsPtr++; // avoid to fix center of arc -//// while (*aPointsPtr != 0) { -//// // Avoid to create additional "Rigid" constraints for coincident points -//// bool isCoincAlreadyFixed = false; -//// if (!anAlreadyFixed.empty()) { -//// if (anAlreadyFixed.find(*aPointsPtr) != anAlreadyFixed.end()) -//// isCoincAlreadyFixed = true; -//// -//// std::vector >::const_iterator aCoincIter = -//// myCoincidentPoints.begin(); -//// for (; !isCoincAlreadyFixed && aCoincIter != myCoincidentPoints.end(); aCoincIter++) { -//// if (aCoincIter->find(*aPointsPtr) == aCoincIter->end()) -//// continue; -//// std::set::const_iterator anIter = anAlreadyFixed.begin(); -//// for (; !isCoincAlreadyFixed && anIter != anAlreadyFixed.end(); anIter++) -//// if (aCoincIter->find(*anIter) != aCoincIter->end()) -//// isCoincAlreadyFixed = true; -//// } -//// } -//// -//// if (!isCoincAlreadyFixed) { -//// Slvs_Constraint aConstraint = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, -//// *aPointsPtr, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aConstraint); -//// myConstraintMap[theConstraint].push_back(aConstraint.h); -//// } -//// aPointsPtr++; -//// } -//// -//// if (isArc || isCircle) { // add radius constraint -//// Slvs_Constraint aConstraint = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, SLVS_C_DIAMETER, myWorkplane.h, 2.0 * aRadius, -//// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aConstrEnt, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aConstraint); -//// myConstraintMap[theConstraint].push_back(aConstraint.h); -//// } -//// -//// // The object is already rigid, so there is no constraints added -//// if (myConstraintMap[theConstraint].empty()) { -//// myConstraintMap.erase(theConstraint); -//// myNeedToSolve = false; -//// } -//// else -//// myNeedToSolve = true; -//// } -//// } -//// return true; -////} -//// -////// ============================================================================ -////// Function: changeMirrorConstraint -////// Class: SketchSolver_Group -////// Purpose: create/update the "Mirror" constraint in the group -////// ============================================================================ -////bool SketchSolver_Group::changeMirrorConstraint( -//// std::shared_ptr theConstraint) -////{ -//// DataPtr aConstrData = theConstraint->data(); -//// -//// // Search this constraint in the current group to update it -//// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint); -//// std::vector::iterator aConstrIter; -//// if (aConstrMapIter != myConstraintMap.end()) { -//// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints); -//// aConstrIter = myConstraints.begin() + aConstrPos; -//// } -//// -//// // Get constraint type and verify the constraint parameters are correct -//// SketchSolver_Constraint aConstraint(theConstraint); -//// int aConstrType = aConstraint.getType(); -//// if (aConstrType == SLVS_C_UNKNOWN -//// || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType)) -//// return false; -//// const std::vector& aConstraintAttributes = aConstraint.getAttributes(); -//// -//// Slvs_hEntity aMirrorLineEnt = SLVS_E_UNKNOWN; -//// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast( -//// aConstrData->attribute(aConstraintAttributes[0])); -//// if (!aConstrAttr) -//// return false; -//// -//// // Convert the object of the attribute to the feature -//// FeaturePtr aMirrorLineFeat; -//// if (aConstrAttr->isObject() && aConstrAttr->object()) { -//// ResultConstructionPtr aRC = std::dynamic_pointer_cast( -//// aConstrAttr->object()); -//// if (!aRC) -//// return false; -//// std::shared_ptr aDoc = aRC->document(); -//// aMirrorLineFeat = aDoc->feature(aRC); -//// } -//// aMirrorLineEnt = aConstrAttr->isObject() ? -//// changeEntityFeature(aMirrorLineFeat) : changeEntity(aConstrAttr->attr()); -//// -//// if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint -//// // Append symmetric constraint for each point of mirroring features -//// AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast( -//// aConstrData->attribute(aConstraintAttributes[1])); -//// AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast( -//// aConstrData->attribute(aConstraintAttributes[2])); -//// if (!aBaseRefList || !aMirroredRefList) -//// return false; -//// -//// std::list aBaseList = aBaseRefList->list(); -//// std::list aMirroredList = aMirroredRefList->list(); -//// if (aBaseList.size() != aMirroredList.size()) -//// return false; -//// -//// myConstraintMap[theConstraint] = std::vector(); -//// -//// FeaturePtr aBaseFeature, aMirrorFeature; -//// ResultConstructionPtr aRC; -//// std::list::iterator aBaseIter = aBaseList.begin(); -//// std::list::iterator aMirIter = aMirroredList.begin(); -//// for ( ; aBaseIter != aBaseList.end(); aBaseIter++, aMirIter++) { -//// aRC = std::dynamic_pointer_cast(*aBaseIter); -//// aBaseFeature = aRC ? aRC->document()->feature(aRC) : -//// std::dynamic_pointer_cast(*aBaseIter); -//// aRC = std::dynamic_pointer_cast(*aMirIter); -//// aMirrorFeature = aRC ? aRC->document()->feature(aRC) : -//// std::dynamic_pointer_cast(*aMirIter); -//// -//// if (!aBaseFeature || !aMirrorFeature || -//// aBaseFeature->getKind() != aMirrorFeature->getKind()) -//// return false; -//// Slvs_hEntity aBaseEnt = changeEntityFeature(aBaseFeature); -//// Slvs_hEntity aMirrorEnt = changeEntityFeature(aMirrorFeature); -//// // Make aMirrorEnt parameters to be symmetric with aBaseEnt -//// makeMirrorEntity(aBaseEnt, aMirrorEnt, aMirrorLineEnt); -//// -//// if (aBaseFeature->getKind() == SketchPlugin_Point::ID()) { -//// Slvs_Constraint aConstraint = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType, -//// myWorkplane.h, 0.0, aBaseEnt, aMirrorEnt, aMirrorLineEnt, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aConstraint); -//// myConstraintMap[theConstraint].push_back(aConstraint.h); -//// } else { -//// int aBasePos = Search(aBaseEnt, myEntities); -//// int aMirrorPos = Search(aMirrorEnt, myEntities); -//// if (aBaseFeature->getKind() == SketchPlugin_Line::ID()) { -//// for (int ind = 0; ind < 2; ind++) { -//// Slvs_Constraint aConstraint = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, -//// myEntities[aBasePos].point[ind], myEntities[aMirrorPos].point[ind], -//// aMirrorLineEnt, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aConstraint); -//// myConstraintMap[theConstraint].push_back(aConstraint.h); -//// } -//// } else if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) { -//// Slvs_Constraint aConstraint = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, -//// myEntities[aBasePos].point[0], myEntities[aMirrorPos].point[0], -//// aMirrorLineEnt, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aConstraint); -//// myConstraintMap[theConstraint].push_back(aConstraint.h); -//// // Additional constraint for equal radii -//// Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, SLVS_C_EQUAL_RADIUS, myWorkplane.h, 0.0, -//// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseEnt, aMirrorEnt); -//// myConstraints.push_back(anEqRadConstr); -//// myConstraintMap[theConstraint].push_back(anEqRadConstr.h); -//// } else if (aBaseFeature->getKind() == SketchPlugin_Arc::ID()) { -//// // Workaround to avoid problems in SolveSpace. -//// // The symmetry of two arcs will be done using symmetry of three points on these arcs: -//// // start point, end point, and any other point on the arc -//// Slvs_hEntity aBaseArcPoints[3] = { -//// myEntities[aBasePos].point[1], -//// myEntities[aBasePos].point[2], -//// SLVS_E_UNKNOWN}; -//// Slvs_hEntity aMirrorArcPoints[3] = { // indices of points of arc, center corresponds center, first point corresponds last point -//// myEntities[aMirrorPos].point[2], -//// myEntities[aMirrorPos].point[1], -//// SLVS_E_UNKNOWN}; -//// Slvs_hEntity aBothArcs[2] = {aBaseEnt, aMirrorEnt}; -//// Slvs_hEntity aBothMiddlePoints[2]; -//// for (int i = 0; i < 2; i++) { -//// double x, y; -//// calculateMiddlePoint(aBothArcs[i], x, y); -//// std::vector::iterator aParamIter = myParams.end(); -//// Slvs_hParam u = changeParameter(x, aParamIter); -//// Slvs_hParam v = changeParameter(y, aParamIter); -//// Slvs_Entity aPoint = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, u, v); -//// myEntities.push_back(aPoint); -//// aBothMiddlePoints[i] = aPoint.h; -//// // additional constraint point-on-curve -//// Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, SLVS_C_PT_ON_CIRCLE, myWorkplane.h, 0.0, -//// aPoint.h, SLVS_E_UNKNOWN, aBothArcs[i], SLVS_E_UNKNOWN); -//// myConstraints.push_back(aPonCircConstr); -//// myConstraintMap[theConstraint].push_back(aPonCircConstr.h); -//// } -//// -//// aBaseArcPoints[2] = aBothMiddlePoints[0]; -//// aMirrorArcPoints[2] = aBothMiddlePoints[1]; -//// for (int ind = 0; ind < 3; ind++) { -//// Slvs_Constraint aConstraint = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0, -//// aBaseArcPoints[ind], aMirrorArcPoints[ind], aMirrorLineEnt, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aConstraint); -//// myConstraintMap[theConstraint].push_back(aConstraint.h); -//// } -//// } -//// } -//// } -//// -//// // Set the mirror line unchanged during constraint recalculation -//// int aMirrorLinePos = Search(aMirrorLineEnt, myEntities); -//// Slvs_Constraint aRigidStart = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0, -//// myEntities[aMirrorLinePos].point[0], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aRigidStart); -//// myConstraintMap[theConstraint].push_back(aRigidStart.h); -//// Slvs_Constraint aRigidEnd = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, myWorkplane.h, 0, -//// myEntities[aMirrorLinePos].point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aRigidEnd); -//// myConstraintMap[theConstraint].push_back(aRigidEnd.h); -//// -//// // Add temporary constraints for initial objects to be unchanged -//// for (aBaseIter = aBaseList.begin(); aBaseIter != aBaseList.end(); aBaseIter++) { -//// aRC = std::dynamic_pointer_cast(*aBaseIter); -//// aBaseFeature = aRC ? aRC->document()->feature(aRC) : -//// std::dynamic_pointer_cast(*aBaseIter); -//// if (!aBaseFeature) continue; -//// std::list aPoints = aBaseFeature->data()->attributes(GeomDataAPI_Point2D::type()); -//// std::list::iterator anIt = aPoints.begin(); -//// for ( ; anIt != aPoints.end(); anIt++) { -//// // Arcs are fixed by center and start points only (to avoid solving errors in SolveSpace) -//// if (aBaseFeature->getKind() == SketchPlugin_Arc::ID() && -//// (*anIt)->id() == SketchPlugin_Arc::END_ID()) -//// continue; -//// addTemporaryConstraintWhereDragged(*anIt); -//// } -//// } -//// } -//// return true; -////} -//// -////// ============================================================================ -////// Function: changeFilletConstraint -////// Class: SketchSolver_Group -////// Purpose: create/update the "Fillet" constraint in the group -////// ============================================================================ -////bool SketchSolver_Group::changeFilletConstraint( -//// std::shared_ptr theConstraint) -////{ -//// DataPtr aConstrData = theConstraint->data(); -//// -//// // Search this constraint in the current group to update it -//// ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint); -//// std::vector::iterator aConstrIter; -//// if (aConstrMapIter != myConstraintMap.end()) { -//// int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints); -//// aConstrIter = myConstraints.begin() + aConstrPos; -//// } -//// -//// // Get constraint type and verify the constraint parameters are correct -//// SketchSolver_Constraint aConstraint(theConstraint); -//// int aConstrType = aConstraint.getType(); -//// if (aConstrType == SLVS_C_UNKNOWN) -//// return false; -//// const std::vector& aConstraintAttributes = aConstraint.getAttributes(); -//// -//// // Obtain hEntity for basic objects of fillet -//// Slvs_hEntity aBaseObject[2]; -//// FeaturePtr aBaseFeature[2]; -//// for (unsigned int indAttr = 0; indAttr < 2; indAttr++) { -//// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast( -//// aConstrData->attribute(aConstraintAttributes[indAttr])); -//// if (!aConstrAttr) -//// return false; -//// if (aConstrAttr->isObject() && aConstrAttr->object()) { -//// ResultConstructionPtr aRC = std::dynamic_pointer_cast( -//// aConstrAttr->object()); -//// if (!aRC) -//// return false; -//// std::shared_ptr aDoc = aRC->document(); -//// aBaseFeature[indAttr] = aDoc->feature(aRC); -//// } -//// aBaseObject[indAttr] = aConstrAttr->isObject() ? -//// changeEntityFeature(aBaseFeature[indAttr]) : changeEntity(aConstrAttr->attr()); -//// } -//// // Check the base entities have a coincident point -//// int aBaseObjInd[2] = { -//// Search(aBaseObject[0], myEntities), -//// Search(aBaseObject[1], myEntities) -//// }; -//// int aShift[2] = { // shift for calculating correct start and end points for different types of objects -//// myEntities[aBaseObjInd[0]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0, -//// myEntities[aBaseObjInd[1]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0, -//// }; -//// Slvs_hEntity aFirstObjPoints[2] = { // indices of start and end point of first object -//// myEntities[aBaseObjInd[0]].point[aShift[0]], -//// myEntities[aBaseObjInd[0]].point[1+aShift[0]] -//// }; -//// Slvs_hEntity aSecondObjPoints[2] = { // indices of start and end point of second object -//// myEntities[aBaseObjInd[1]].point[aShift[1]], -//// myEntities[aBaseObjInd[1]].point[1+aShift[1]] -//// }; -//// bool isCoincidentFound = false; -//// int aBaseCoincInd[2] = {0, 0}; // indices in aFirstObjPoint and aSecondObjPoint identifying coincident points -//// std::vector >::iterator aCPIter = myCoincidentPoints.begin(); -//// for ( ; aCPIter != myCoincidentPoints.end() && !isCoincidentFound; aCPIter++) -//// for (int ind1 = 0; ind1 < 2 && !isCoincidentFound; ind1++) -//// for (int ind2 = 0; ind2 < 2 && !isCoincidentFound; ind2++) -//// if (aCPIter->find(aFirstObjPoints[ind1]) != aCPIter->end() && -//// aCPIter->find(aSecondObjPoints[ind2]) != aCPIter->end()) { -//// aBaseCoincInd[0] = ind1; -//// aBaseCoincInd[1] = ind2; -//// isCoincidentFound = true; -//// } -//// if (!isCoincidentFound) { -//// // There is no coincident points between objects. Generate error message -//// Events_Error::send(SketchSolver_Error::NO_COINCIDENT_POINTS(), this); -//// return false; -//// } -//// -//// // Create fillet entities -//// // - first object is placed on the first base -//// // - second object is on the second base -//// // - third object is a filleting arc -//// static const int aNbFilletEnt = 3; -//// Slvs_hEntity aFilletEnt[aNbFilletEnt]; -//// int aFilletObjInd[aNbFilletEnt]; -//// AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast( -//// aConstrData->attribute(aConstraintAttributes[2])); -//// if (!aFilletRefList) -//// return false; -//// std::list aFilletList = aFilletRefList->list(); -//// if (aFilletList.size() < aNbFilletEnt) -//// return false; -//// FeaturePtr aFilletFeature; -//// ResultConstructionPtr aRC; -//// std::list::iterator aFilIter = aFilletList.begin(); -//// for (int indEnt = 0; aFilIter != aFilletList.end(); aFilIter++, indEnt++) { -//// aRC = std::dynamic_pointer_cast(*aFilIter); -//// aFilletFeature = aRC ? aRC->document()->feature(aRC) : -//// std::dynamic_pointer_cast(*aFilIter); -//// if (!aFilletFeature) -//// return false; -//// aFilletEnt[indEnt] = changeEntityFeature(aFilletFeature); -//// aFilletObjInd[indEnt] = Search(aFilletEnt[indEnt], myEntities); -//// } -//// // At first time, for correct result, move floating points of fillet on the middle points of base objects -//// if (myConstraintMap.find(theConstraint) == myConstraintMap.end()) { -//// double anArcPoints[6]; -//// for (int indEnt = 0; indEnt < aNbFilletEnt - 1; indEnt++) { -//// int anIndShift = myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE ? 1 : 0; -//// int aPointsPos[2] = { -//// Search(myEntities[aFilletObjInd[indEnt]].point[anIndShift], myEntities), -//// Search(myEntities[aFilletObjInd[indEnt]].point[1+anIndShift], myEntities) -//// }; -//// int aParamPos[2] = { -//// Search(myEntities[aPointsPos[0]].param[0], myParams), -//// Search(myEntities[aPointsPos[1]].param[0], myParams) -//// }; -//// int anIndex = aParamPos[aBaseCoincInd[indEnt]]; -//// if (anIndShift == 0) { -//// myParams[anIndex].val = -//// 0.5 * (myParams[aParamPos[0]].val + myParams[aParamPos[1]].val); -//// myParams[1 + anIndex].val = -//// 0.5 * (myParams[1 + aParamPos[0]].val + myParams[1 + aParamPos[1]].val); -//// } else { // place the changed point on the arc -//// double x = 0, y = 0; -//// calculateMiddlePoint(aFilletEnt[indEnt], x, y); -//// myParams[anIndex].val = x; -//// myParams[1 + anIndex].val = y; -//// } -//// anArcPoints[indEnt*2+2] = myParams[anIndex].val; -//// anArcPoints[indEnt*2+3] = myParams[1 + anIndex].val; -//// } -//// anArcPoints[0] = 0.5 * (anArcPoints[2] + anArcPoints[4]); -//// anArcPoints[1] = 0.5 * (anArcPoints[3] + anArcPoints[5]); -//// for (int indArcPt = 0; indArcPt < 3; indArcPt++) { -//// int aPtPos = Search(myEntities[aFilletObjInd[2]].point[indArcPt], myEntities); -//// int aParamPos = Search(myEntities[aPtPos].param[0], myParams); -//// myParams[aParamPos].val = anArcPoints[indArcPt * 2]; -//// myParams[aParamPos + 1].val = anArcPoints[indArcPt * 2 + 1]; -//// } -//// } -//// -//// // 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 -//// std::vector aConstrList; -//// bool isExists = myConstraintMap.find(theConstraint) != myConstraintMap.end(); // constraint already exists -//// std::vector::iterator aCMapIter = -//// isExists ? myConstraintMap[theConstraint].begin() : aConstrList.begin(); -//// 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 -//// aPtInd = 1-aBaseCoincInd[indEnt]+aShift[indEnt]; // (1-aBaseCoincInd[indEnt]) = index of non-coincident point, aShift is used to process all types of shapes -//// Slvs_hEntity aPtBase = myEntities[aBaseObjInd[indEnt]].point[aPtInd]; -//// Slvs_hEntity aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd]; -//// if (isExists) { -//// myConstraints[aCurConstrPos].ptA = aPtBase; -//// myConstraints[aCurConstrPos].ptB = aPtFillet; -//// aCMapIter++; -//// aCurConstrPos = Search(*aCMapIter, myConstraints); -//// } else { -//// Slvs_Constraint aCoincConstr = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h, -//// 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); -//// myConstraints.push_back(aCoincConstr); -//// aConstrList.push_back(aCoincConstr.h); -//// } -//// -//// // another point of fillet object should be placed on the base object -//// Slvs_Constraint aPonCurveConstr; -//// int aTangentType; -//// if (myEntities[aFilletObjInd[indEnt]].type == SLVS_E_ARC_OF_CIRCLE) { -//// // centers of arcs should be coincident -//// aPtBase = myEntities[aBaseObjInd[indEnt]].point[0]; -//// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[0]; -//// if (isExists) { -//// myConstraints[aCurConstrPos].ptA = aPtBase; -//// myConstraints[aCurConstrPos].ptB = aPtFillet; -//// aCMapIter++; -//// aCurConstrPos = Search(*aCMapIter, myConstraints); -//// } else { -//// aPonCurveConstr = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, SLVS_C_POINTS_COINCIDENT, myWorkplane.h, -//// 0, aPtBase, aPtFillet, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN); -//// } -//// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[1+aBaseCoincInd[indEnt]]; // !!! will be used below -//// aTangentType = SLVS_C_CURVE_CURVE_TANGENT; -//// } else { -//// aPtInd = aBaseCoincInd[indEnt]; -//// aPtFillet = myEntities[aFilletObjInd[indEnt]].point[aPtInd]; -//// if (isExists) { -//// myConstraints[aCurConstrPos].ptA = aPtFillet; -//// aCMapIter++; -//// aCurConstrPos = Search(*aCMapIter, myConstraints); -//// } else { -//// aPonCurveConstr = Slvs_MakeConstraint( -//// ++myConstrMaxID, myID, SLVS_C_PT_ON_LINE, myWorkplane.h, -//// 0, aPtFillet, SLVS_E_UNKNOWN, aBaseObject[indEnt], SLVS_E_UNKNOWN); -//// } -//// aTangentType = SLVS_C_ARC_LINE_TANGENT; -//// } -//// if (!isExists) { -//// 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); -//// -//// myConstraintMap[theConstraint] = aConstrList; -//// } -//// -//// // Additional temporary constraints for base objects to be fixed -//// for (unsigned int indAttr = 0; indAttr < 2; indAttr++) { -//// if (!aBaseFeature[indAttr]) { -//// AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast( -//// aConstrData->attribute(aConstraintAttributes[indAttr])); -//// addTemporaryConstraintWhereDragged(aConstrAttr->attr()); -//// continue; -//// } -//// std::list anAttributes = -//// aBaseFeature[indAttr]->data()->attributes(GeomDataAPI_Point2D::type()); -//// 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); -//// } -//// } -//// return true; -////} -//// -////// ============================================================================ -////// Function: changeEntity -////// Class: SketchSolver_Group -////// Purpose: create/update the element affected by any constraint -////// ============================================================================ -////Slvs_hEntity SketchSolver_Group::changeEntity( -//// std::shared_ptr theEntity) -////{ -//// // If the entity is already in the group, try to find it -//// std::map, Slvs_hEntity>::const_iterator aEntIter = -//// myEntityAttrMap.find(theEntity); -//// int aEntPos; -//// std::vector::const_iterator aParamIter; // looks at first parameter of already existent entity or at the end of vector otherwise -//// if (aEntIter == myEntityAttrMap.end()) // no such entity => should be created -//// aParamIter = myParams.end(); -//// else { // the entity already exists -//// aEntPos = Search(aEntIter->second, myEntities); -//// int aParamPos = Search(myEntities[aEntPos].param[0], myParams); -//// aParamIter = myParams.begin() + aParamPos; -//// } -//// const bool isEntExists = (aEntIter != myEntityAttrMap.end()); // defines that the entity already exists -//// const bool isNeedToSolve = myNeedToSolve; -//// myNeedToSolve = false; -//// -//// if (isEntExists) { -//// // Verify that the entity is not used by "Rigid" constraint. -//// // If it is used, the object should not move. -//// std::vector >::iterator aCoincIter = myCoincidentPoints.begin(); -//// for (; aCoincIter != myCoincidentPoints.end(); aCoincIter++) -//// if (aCoincIter->find(aEntIter->second) != aCoincIter->end()) -//// break; -//// std::set aCoincident; -//// if (aCoincIter != myCoincidentPoints.end()) { -//// aCoincident = *aCoincIter; -//// aCoincident.erase(aEntIter->second); -//// -//// std::vector::const_iterator aConstrIter = myConstraints.begin(); -//// for (; aConstrIter != myConstraints.end(); aConstrIter++) -//// if (aConstrIter->type == SLVS_C_WHERE_DRAGGED && -//// aCoincident.find(aConstrIter->ptA) != aCoincident.end()) { -//// myNeedToSolve = true; -//// return aEntIter->second; -//// } -//// } -//// } -//// -//// // Look over supported types of entities -//// Slvs_Entity aNewEntity; -//// aNewEntity.h = SLVS_E_UNKNOWN; -//// -//// // Point in 3D -//// std::shared_ptr aPoint = std::dynamic_pointer_cast( -//// theEntity); -//// if (aPoint) { -//// Slvs_hParam aX = changeParameter(aPoint->x(), aParamIter); -//// Slvs_hParam aY = changeParameter(aPoint->y(), aParamIter); -//// Slvs_hParam aZ = changeParameter(aPoint->z(), aParamIter); -//// if (!isEntExists) // New entity -//// aNewEntity = Slvs_MakePoint3d(++myEntityMaxID, myID, aX, aY, aZ); -//// } else { -//// // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error -//// if (myWorkplane.h == SLVS_E_UNKNOWN) -//// return SLVS_E_UNKNOWN; -//// -//// // Point in 2D -//// std::shared_ptr aPoint2D = -//// std::dynamic_pointer_cast(theEntity); -//// if (aPoint2D) { -//// Slvs_hParam aU = changeParameter(aPoint2D->x(), aParamIter); -//// Slvs_hParam aV = changeParameter(aPoint2D->y(), aParamIter); -//// if (!isEntExists) // New entity -//// aNewEntity = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, aU, aV); -//// } else { -//// // Scalar value (used for the distance entities) -//// AttributeDoublePtr aScalar = std::dynamic_pointer_cast(theEntity); -//// if (aScalar) { -//// Slvs_hParam aValue = changeParameter(aScalar->value(), aParamIter); -//// if (!isEntExists) // New entity -//// aNewEntity = Slvs_MakeDistance(++myEntityMaxID, myID, myWorkplane.h, aValue); -//// } -//// } -//// } -//// /// \todo Other types of entities -//// -//// Slvs_hEntity aResult = SLVS_E_UNKNOWN; // Unsupported or wrong entity type -//// -//// if (isEntExists) { -//// myNeedToSolve = myNeedToSolve || isNeedToSolve; -//// aResult = aEntIter->second; -//// } else if (aNewEntity.h != SLVS_E_UNKNOWN) { -//// myEntities.push_back(aNewEntity); -//// myEntOfConstr.push_back(false); -//// myEntityAttrMap[theEntity] = aNewEntity.h; -//// aResult = aNewEntity.h; -//// } -//// -//// // If the attribute was changed by the user, we need to fix it before solving -//// if (myNeedToSolve && theEntity->isImmutable()) -//// addTemporaryConstraintWhereDragged(theEntity, false); -//// -//// return aResult; -////} -//// -////// ============================================================================ -////// Function: changeEntity -////// Class: SketchSolver_Group -////// Purpose: create/update the element defined by the feature affected by any constraint -////// ============================================================================ -////Slvs_hEntity SketchSolver_Group::changeEntityFeature(FeaturePtr theEntity) -////{ -//// if (!theEntity->data()->isValid()) -//// return SLVS_E_UNKNOWN; -//// // If the entity is already in the group, try to find it -//// std::map::const_iterator aEntIter = myEntityFeatMap.find(theEntity); -//// // defines that the entity already exists -//// const bool isEntExists = (myEntityFeatMap.find(theEntity) != myEntityFeatMap.end()); -//// -//// Slvs_Entity aNewEntity; -//// aNewEntity.h = SLVS_E_UNKNOWN; -//// -//// // SketchPlugin features -//// std::shared_ptr aFeature = std::dynamic_pointer_cast< -//// SketchPlugin_Feature>(theEntity); -//// if (aFeature) { // Verify the feature by its kind -//// const std::string& aFeatureKind = aFeature->getKind(); -//// AttributePtr anAttribute; -//// -//// // Line -//// if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) { -//// anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID()); -//// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; -//// Slvs_hEntity aStart = changeEntity(anAttribute); -//// -//// anAttribute = aFeature->data()->attribute(SketchPlugin_Line::END_ID()); -//// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; -//// Slvs_hEntity aEnd = changeEntity(anAttribute); -//// -//// if (!isEntExists) // New entity -//// aNewEntity = Slvs_MakeLineSegment(++myEntityMaxID, myID, myWorkplane.h, aStart, aEnd); -//// } -//// // Circle -//// else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) { -//// anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID()); -//// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; -//// Slvs_hEntity aCenter = changeEntity(anAttribute); -//// -//// anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID()); -//// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; -//// Slvs_hEntity aRadius = changeEntity(anAttribute); -//// -//// if (!isEntExists) // New entity -//// aNewEntity = Slvs_MakeCircle(++myEntityMaxID, myID, myWorkplane.h, aCenter, -//// myWorkplane.normal, aRadius); -//// } -//// // Arc -//// else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) { -//// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID()); -//// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; -//// Slvs_hEntity aCenter = changeEntity(anAttribute); -//// -//// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::START_ID()); -//// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; -//// Slvs_hEntity aStart = changeEntity(anAttribute); -//// -//// anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::END_ID()); -//// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; -//// Slvs_hEntity aEnd = changeEntity(anAttribute); -//// -//// if (!isEntExists) -//// aNewEntity = Slvs_MakeArcOfCircle(++myEntityMaxID, myID, myWorkplane.h, -//// myWorkplane.normal, aCenter, aStart, aEnd); -//// } -//// // Point (it has low probability to be an attribute of constraint, so it is checked at the end) -//// else if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) { -//// anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()); -//// if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN; -//// Slvs_hEntity aPoint = changeEntity(anAttribute); -//// -//// if (isEntExists) -//// return aEntIter->second; -//// -//// // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier -//// myEntityFeatMap[theEntity] = aPoint; -//// myNeedToSolve = true; -//// return aPoint; -//// } -//// } -//// /// \todo Other types of features -//// -//// if (isEntExists) -//// return aEntIter->second; -//// -//// if (aNewEntity.h != SLVS_E_UNKNOWN) { -//// myEntities.push_back(aNewEntity); -//// myEntOfConstr.push_back(false); -//// myEntityFeatMap[theEntity] = aNewEntity.h; -//// myNeedToSolve = true; -//// return aNewEntity.h; -//// } -//// -//// // Unsupported or wrong entity type -//// return SLVS_E_UNKNOWN; -////} - // ============================================================================ // Function: addWorkplane // Class: SketchSolver_Group @@ -1356,33 +341,6 @@ bool SketchSolver_Group::updateWorkplane() return myWorkplaneID > 0; } -////// ============================================================================ -////// Function: changeParameter -////// Class: SketchSolver_Group -////// Purpose: create/update value of parameter -////// ============================================================================ -////Slvs_hParam SketchSolver_Group::changeParameter( -//// const double& theParam, std::vector::const_iterator& thePrmIter) -////{ -//// if (thePrmIter != myParams.end()) { // Parameter should be updated -//// int aParamPos = thePrmIter - myParams.begin(); -//// if (fabs(thePrmIter->val - theParam) > tolerance) { -//// myNeedToSolve = true; // parameter is changed, need to resolve constraints -//// myParams[aParamPos].val = theParam; -//// } -//// thePrmIter++; -//// return myParams[aParamPos].h; -//// } -//// -//// // Newly created parameter -//// Slvs_Param aParam = Slvs_MakeParam(++myParamMaxID, myID, theParam); -//// myParams.push_back(aParam); -//// myNeedToSolve = true; -//// // The list of parameters is changed, move iterator to the end of the list to avoid problems -//// thePrmIter = myParams.end(); -//// return aParam.h; -////} - // ============================================================================ // Function: resolveConstraints // Class: SketchSolver_Group @@ -1504,161 +462,6 @@ bool SketchSolver_Group::isConsistent() return aResult; } -////// ============================================================================ -////// Function: updateAttribute -////// Class: SketchSolver_Group -////// Purpose: update features of sketch after resolving constraints -////// ============================================================================ -////bool SketchSolver_Group::updateAttribute( -//// std::shared_ptr theAttribute, const Slvs_hEntity& theEntityID) -////{ -//// // Search the position of the first parameter of the entity -//// int anEntPos = Search(theEntityID, myEntities); -//// int aFirstParamPos = Search(myEntities[anEntPos].param[0], myParams); -//// -//// // Look over supported types of entities -//// -//// // Point in 3D -//// std::shared_ptr aPoint = std::dynamic_pointer_cast( -//// theAttribute); -//// if (aPoint) { -//// if (fabs(aPoint->x() - myParams[aFirstParamPos].val) > tolerance -//// || fabs(aPoint->y() - myParams[aFirstParamPos + 1].val) > tolerance -//// || fabs(aPoint->z() - myParams[aFirstParamPos + 2].val) > tolerance) { -//// aPoint->setValue(myParams[aFirstParamPos].val, myParams[aFirstParamPos + 1].val, -//// myParams[aFirstParamPos + 2].val); -//// return true; -//// } -//// return false; -//// } -//// -//// // Point in 2D -//// std::shared_ptr aPoint2D = -//// std::dynamic_pointer_cast(theAttribute); -//// if (aPoint2D) { -//// if (fabs(aPoint2D->x() - myParams[aFirstParamPos].val) > tolerance -//// || fabs(aPoint2D->y() - myParams[aFirstParamPos + 1].val) > tolerance) { -//// aPoint2D->setValue(myParams[aFirstParamPos].val, myParams[aFirstParamPos + 1].val); -//// return true; -//// } -//// return false; -//// } -//// -//// // Scalar value -//// AttributeDoublePtr aScalar = std::dynamic_pointer_cast(theAttribute); -//// if (aScalar) { -//// if (fabs(aScalar->value() - myParams[aFirstParamPos].val) > tolerance) { -//// aScalar->setValue(myParams[aFirstParamPos].val); -//// return true; -//// } -//// return false; -//// } -//// -//// /// \todo Support other types of entities -//// return false; -////} -//// -////// ============================================================================ -////// Function: updateEntityIfPossible -////// Class: SketchSolver_Group -////// Purpose: search the entity in this group and update it -////// ============================================================================ -////void SketchSolver_Group::updateEntityIfPossible( -//// std::shared_ptr theEntity) -////{ -//// if (myEntityAttrMap.find(theEntity) != myEntityAttrMap.end()) { -//// // If the attribute is a point and it is changed (the group needs to rebuild), -//// // probably user has dragged this point into this position, -//// // so it is necessary to add constraint which will guarantee the point will not change -//// -//// // Store myNeedToSolve flag to verify the entity is really changed -//// bool aNeedToSolveCopy = myNeedToSolve; -//// myNeedToSolve = false; -//// -//// changeEntity(theEntity); -//// -//// if (myNeedToSolve) // the entity is changed -//// { -//// // Verify the entity is a point and add temporary constraint of permanency -//// std::shared_ptr aPoint = std::dynamic_pointer_cast( -//// theEntity); -//// std::shared_ptr aPoint2D = std::dynamic_pointer_cast< -//// GeomDataAPI_Point2D>(theEntity); -//// if (aPoint || aPoint2D) -//// addTemporaryConstraintWhereDragged(theEntity); -//// } -//// -//// // Restore flag of changes -//// myNeedToSolve = myNeedToSolve || aNeedToSolveCopy; -//// -//// if (myNeedToSolve) -//// updateRelatedConstraints(theEntity); -//// } -////} -//// -////// ============================================================================ -////// Function: addTemporaryConstraintWhereDragged -////// Class: SketchSolver_Group -////// Purpose: add transient constraint SLVS_C_WHERE_DRAGGED for the entity, -////// which was moved by user -////// ============================================================================ -////void SketchSolver_Group::addTemporaryConstraintWhereDragged( -//// std::shared_ptr theEntity, -//// bool theAllowToFit) -////{ -//// // Find identifier of the entity -//// std::map, Slvs_hEntity>::const_iterator anEntIter = -//// myEntityAttrMap.find(theEntity); -//// if (anEntIter == myEntityAttrMap.end()) -//// return; -//// -//// // Get identifiers of all dragged points -//// std::set aDraggedPntID; -//// aDraggedPntID.insert(myTempPointWDrgdID); -//// std::list::const_iterator aTmpCoIter = myTempConstraints.begin(); -//// for (; aTmpCoIter != myTempConstraints.end(); aTmpCoIter++) { -//// unsigned int aConstrPos = Search(*aTmpCoIter, myConstraints); -//// if (aConstrPos < myConstraints.size()) -//// aDraggedPntID.insert(myConstraints[aConstrPos].ptA); -//// } -//// std::vector::const_iterator aConstrIter = myConstraints.begin(); -//// for (; aConstrIter != myConstraints.end(); aConstrIter++) -//// if (aConstrIter->type == SLVS_C_WHERE_DRAGGED) -//// aDraggedPntID.insert(aConstrIter->ptA); -//// // Find whether there is a point coincident with theEntity, which already has SLVS_C_WHERE_DRAGGED -//// std::vector >::iterator aCoPtIter = myCoincidentPoints.begin(); -//// for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) { -//// if (aCoPtIter->find(anEntIter->second) == aCoPtIter->end()) -//// continue; // the entity was not found in current set -//// -//// // Find one of already created SLVS_C_WHERE_DRAGGED constraints in current set of coincident points -//// std::set::const_iterator aDrgIter = aDraggedPntID.begin(); -//// for (; aDrgIter != aDraggedPntID.end(); aDrgIter++) -//// if (aCoPtIter->find(*aDrgIter) != aCoPtIter->end()) -//// return; // the SLVS_C_WHERE_DRAGGED constraint already exists -//// } -//// if (aDraggedPntID.find(anEntIter->second) != aDraggedPntID.end()) -//// return; -//// -//// // If this is a first dragged point, its parameters should be placed -//// // into Slvs_System::dragged field to avoid system inconsistense -//// if (myTempPointWhereDragged.empty() && theAllowToFit) { -//// int anEntPos = Search(anEntIter->second, myEntities); -//// Slvs_hParam* aDraggedParam = myEntities[anEntPos].param; -//// for (int i = 0; i < 4; i++, aDraggedParam++) -//// if (*aDraggedParam != 0) -//// myTempPointWhereDragged.push_back(*aDraggedParam); -//// myTempPointWDrgdID = myEntities[anEntPos].h; -//// return; -//// } -//// -//// // Create additional SLVS_C_WHERE_DRAGGED constraint if myTempPointWhereDragged field is not empty -//// Slvs_Constraint aWDConstr = Slvs_MakeConstraint(++myConstrMaxID, myID, SLVS_C_WHERE_DRAGGED, -//// myWorkplane.h, 0.0, anEntIter->second, 0, 0, 0); -//// myConstraints.push_back(aWDConstr); -//// myTempConstraints.push_back(aWDConstr.h); -////} - // ============================================================================ // Function: removeTemporaryConstraints // Class: SketchSolver_Group @@ -1673,6 +476,7 @@ void SketchSolver_Group::removeTemporaryConstraints() std::set aRemEnt; std::set aRemCon; myStorage->getRemoved(aRemPar, aRemEnt, aRemCon); + myStorage->setNeedToResolve(false); } // ============================================================================ @@ -1693,289 +497,3 @@ void SketchSolver_Group::removeConstraint(ConstraintPtr theConstraint) if (aCIter != myConstraints.end()) myConstraints.erase(aCIter); } - -////// ============================================================================ -////// Function: removeEntitiesById -////// Class: SketchSolver_Group -////// Purpose: Removes specified entities and their parameters -////// ============================================================================ -////void SketchSolver_Group::removeEntitiesById(const std::set& theEntities) -////{ -//// std::set::const_reverse_iterator aRemIter = theEntities.rbegin(); -//// for (; aRemIter != theEntities.rend(); aRemIter++) { -//// unsigned int anEntPos = Search(*aRemIter, myEntities); -//// if (anEntPos >= myEntities.size()) -//// continue; -//// if (myEntities[anEntPos].param[0] != 0) { -//// unsigned int aParamPos = Search(myEntities[anEntPos].param[0], myParams); -//// if (aParamPos >= myParams.size()) -//// continue; -//// int aNbParams = 0; -//// while (myEntities[anEntPos].param[aNbParams] != 0) -//// aNbParams++; -//// if (myEntities[anEntPos].param[aNbParams - 1] == myParamMaxID) -//// myParamMaxID -= aNbParams; -//// myParams.erase(myParams.begin() + aParamPos, myParams.begin() + aParamPos + aNbParams); -//// if (*aRemIter == myEntityMaxID) -//// myEntityMaxID--; -//// } -//// myEntities.erase(myEntities.begin() + anEntPos); -//// myEntOfConstr.erase(myEntOfConstr.begin() + anEntPos); -//// -//// // Remove entity's ID from the lists of conincident points -//// std::vector >::iterator aCoPtIter = myCoincidentPoints.begin(); -//// for (; aCoPtIter != myCoincidentPoints.end(); aCoPtIter++) -//// aCoPtIter->erase(*aRemIter); -//// } -////} -//// -////// ============================================================================ -////// Function: addCoincidentPoints -////// Class: SketchSolver_Group -////// Purpose: add coincident point the appropriate list of such points -////// ============================================================================ -////bool SketchSolver_Group::addCoincidentPoints(const Slvs_hEntity& thePoint1, -//// const Slvs_hEntity& thePoint2) -////{ -//// std::vector >::iterator aCoPtIter = myCoincidentPoints.begin(); -//// std::vector >::iterator aFirstFound = myCoincidentPoints.end(); -//// while (aCoPtIter != myCoincidentPoints.end()) { -//// bool isFound[2] = { // indicate which point ID was already in coincidence constraint -//// aCoPtIter->find(thePoint1) != aCoPtIter->end(), aCoPtIter->find(thePoint2) -//// != aCoPtIter->end(), }; -//// if (isFound[0] && isFound[1]) // points are already connected by coincidence constraints => no need additional one -//// return false; -//// if ((isFound[0] && !isFound[1]) || (!isFound[0] && isFound[1])) { -//// if (aFirstFound != myCoincidentPoints.end()) { // there are two groups of coincident points connected by created constraint => merge them -//// int aFirstFoundShift = aFirstFound - myCoincidentPoints.begin(); -//// int aCurrentShift = aCoPtIter - myCoincidentPoints.begin(); -//// aFirstFound->insert(aCoPtIter->begin(), aCoPtIter->end()); -//// myCoincidentPoints.erase(aCoPtIter); -//// aFirstFound = myCoincidentPoints.begin() + aFirstFoundShift; -//// aCoPtIter = myCoincidentPoints.begin() + aCurrentShift; -//// continue; -//// } else { -//// aCoPtIter->insert(isFound[0] ? thePoint2 : thePoint1); -//// aFirstFound = aCoPtIter; -//// } -//// } -//// aCoPtIter++; -//// } -//// // No points were found, need to create new set -//// if (aFirstFound == myCoincidentPoints.end()) { -//// std::set aNewSet; -//// aNewSet.insert(thePoint1); -//// aNewSet.insert(thePoint2); -//// myCoincidentPoints.push_back(aNewSet); -//// } -//// -//// return true; -////} -//// -////// ============================================================================ -////// Function: updateRelatedConstraints -////// Class: SketchSolver_Group -////// Purpose: emit the signal to update constraints -////// ============================================================================ -////void SketchSolver_Group::updateRelatedConstraints( -//// std::shared_ptr theEntity) const -////{ -//// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin(); -//// for (; aConstrIter != myConstraintMap.end(); aConstrIter++) { -//// std::list > anAttributes = aConstrIter->first->data() -//// ->attributes(std::string()); -//// -//// std::list >::iterator anAttrIter = anAttributes.begin(); -//// for (; anAttrIter != anAttributes.end(); anAttrIter++) { -//// bool isUpd = (*anAttrIter == theEntity); -//// std::shared_ptr aRefAttr = std::dynamic_pointer_cast< -//// ModelAPI_AttributeRefAttr>(*anAttrIter); -//// if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theEntity) -//// isUpd = true; -//// -//// if (isUpd) { -//// static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); -//// ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent); -//// break; -//// } -//// } -//// } -////} -//// -////void SketchSolver_Group::updateRelatedConstraintsFeature( -//// std::shared_ptr theFeature) const -////{ -//// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin(); -//// for (; aConstrIter != myConstraintMap.end(); aConstrIter++) { -//// std::list > anAttributes = aConstrIter->first->data() -//// ->attributes(std::string()); -//// -//// std::list >::iterator anAttrIter = anAttributes.begin(); -//// for (; anAttrIter != anAttributes.end(); anAttrIter++) { -//// std::shared_ptr aRefAttr = std::dynamic_pointer_cast< -//// ModelAPI_AttributeRefAttr>(*anAttrIter); -//// if (aRefAttr && aRefAttr->isObject() && aRefAttr->object() == theFeature) { -//// static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); -//// ModelAPI_EventCreator::get()->sendUpdated(aConstrIter->first, anEvent); -//// break; -//// } -//// } -//// } -////} -//// -////// ============================================================================ -////// Function: updateFilletConstraints -////// Class: SketchSolver_Group -////// Purpose: change fillet arc to be less than 180 degree -////// ============================================================================ -////void SketchSolver_Group::updateFilletConstraints() -////{ -//// ConstraintMap::const_iterator aConstrIter = myConstraintMap.begin(); -//// for (; aConstrIter != myConstraintMap.end(); aConstrIter++) -//// if (aConstrIter->first->getKind() == SketchPlugin_ConstraintFillet::ID()) { -//// AttributeRefListPtr aFilletRefList = std::dynamic_pointer_cast( -//// aConstrIter->first->data()->attribute(SketchPlugin_ConstraintFillet::ENTITY_C())); -//// if (!aFilletRefList) -//// return; -//// ObjectPtr anArcObj = aFilletRefList->object(2); -//// std::shared_ptr aCenter = std::dynamic_pointer_cast( -//// anArcObj->data()->attribute(SketchPlugin_Arc::CENTER_ID())); -//// std::shared_ptr aStart = std::dynamic_pointer_cast( -//// anArcObj->data()->attribute(SketchPlugin_Arc::START_ID())); -//// std::shared_ptr aEnd = std::dynamic_pointer_cast( -//// anArcObj->data()->attribute(SketchPlugin_Arc::END_ID())); -//// double aCosA = aStart->x() - aCenter->x(); -//// double aSinA = aStart->y() - aCenter->y(); -//// double aCosB = aEnd->x() - aCenter->x(); -//// double aSinB = aEnd->y() - aCenter->y(); -//// if (aCosA * aSinB - aSinA * aCosB <= 0.0) { -//// anArcObj->data()->blockSendAttributeUpdated(true); -//// double x = aStart->x(); -//// double y = aStart->y(); -//// aStart->setValue(aEnd->x(), aEnd->y()); -//// aEnd->setValue(x, y); -//// // Update constraint data -//// changeFilletConstraint(aConstrIter->first); -//// anArcObj->data()->blockSendAttributeUpdated(false); -//// } -//// } -////} -//// -////// ============================================================================ -////// Function: makeMirrorEntity -////// Class: SketchSolver_Group -////// Purpose: change entities parameters to make them symmetric relating to the mirror line -////// ============================================================================ -////void SketchSolver_Group::makeMirrorEntity(const Slvs_hEntity& theBase, -//// const Slvs_hEntity& theMirror, -//// const Slvs_hEntity& theMirrorLine) -////{ -//// Slvs_Entity aBase = myEntities[Search(theBase, myEntities)]; -//// Slvs_Entity aMirror = myEntities[Search(theMirror, myEntities)]; -//// int i = 0; -//// while (aBase.point[i] != 0 && aMirror.point[i] != 0) { -//// makeMirrorEntity(aBase.point[i], aMirror.point[i], theMirrorLine); -//// i++; -//// } -//// if (aBase.param[0] != 0 && aMirror.param[0] != 0) { // this is a point, copy it -//// Slvs_Entity aMirrorLine = myEntities[Search(theMirrorLine, myEntities)]; -//// std::shared_ptr aLinePoints[2]; -//// for (i = 0; i < 2; i++) { -//// Slvs_Entity aPoint = myEntities[Search(aMirrorLine.point[i], myEntities)]; -//// int aParamPos = Search(aPoint.param[0], myParams); -//// aLinePoints[i] = std::shared_ptr( -//// new GeomAPI_XY(myParams[aParamPos].val, myParams[1+aParamPos].val)); -//// } -//// int aBaseParamPos = Search(aBase.param[0], myParams); -//// int aMirrorParamPos = Search(aMirror.param[0], myParams); -//// std::shared_ptr aPoint = std::shared_ptr( -//// new GeomAPI_XY(myParams[aBaseParamPos].val, myParams[1+aBaseParamPos].val)); -//// -//// // direction of a mirror line -//// std::shared_ptr aDir = std::shared_ptr( -//// new GeomAPI_Dir2d(aLinePoints[1]->added(aLinePoints[0]->multiplied(-1.0)))); -//// // orthogonal direction -//// aDir = std::shared_ptr(new GeomAPI_Dir2d(aDir->y(), -aDir->x())); -//// -//// std::shared_ptr aVec = std::shared_ptr( -//// new GeomAPI_XY(aPoint->x() - aLinePoints[0]->x(), aPoint->y() - aLinePoints[0]->y())); -//// double aDist = aVec->dot(aDir->xy()); -//// std::shared_ptr aMirrorPoint = aPoint->added(aDir->xy()->multiplied(-2.0 * aDist)); -//// -//// myParams[aMirrorParamPos].val = aMirrorPoint->x(); -//// myParams[1+aMirrorParamPos].val = aMirrorPoint->y(); -//// } -////} -//// -////// ============================================================================ -////// Function: calculateMiddlePoint -////// Class: SketchSolver_Group -////// Purpose: calculates middle point on line or arc -////// ============================================================================ -////void SketchSolver_Group::calculateMiddlePoint( -//// const Slvs_hEntity& theEntity, -//// double& theX, -//// double& theY) const -////{ -//// int anInd = Search(theEntity, myEntities); -//// if (myEntities[anInd].type == SLVS_E_LINE_SEGMENT) { -//// int aLineParams[2]; -//// for (int i = 0; i < 2; i++) { -//// int aPtPos = Search(myEntities[anInd].point[i], myEntities); -//// aLineParams[i] = Search(myEntities[aPtPos].param[0], myParams); -//// } -//// theX = 0.5 * (myParams[aLineParams[0]].val + myParams[aLineParams[1]].val); -//// theY = 0.5 * (myParams[1 + aLineParams[0]].val + myParams[1 + aLineParams[1]].val); -//// } else if (myEntities[anInd].type == SLVS_E_ARC_OF_CIRCLE) { -//// double anArcPoint[3][2]; -//// for (int i = 0; i < 3; i++) { -//// int aPtPos = Search(myEntities[anInd].point[i], myEntities); -//// int anArcParam = Search(myEntities[aPtPos].param[0], myParams); -//// anArcPoint[i][0] = myParams[anArcParam].val; -//// anArcPoint[i][1] = myParams[1 + anArcParam].val; -//// } -//// // project last point of arc on the arc -//// double x = anArcPoint[1][0] - anArcPoint[0][0]; -//// double y = anArcPoint[1][1] - anArcPoint[0][1]; -//// double aRad = sqrt(x*x + y*y); -//// x = anArcPoint[2][0] - anArcPoint[0][0]; -//// y = anArcPoint[2][1] - anArcPoint[0][1]; -//// double aNorm = sqrt(x*x + y*y); -//// if (aNorm >= tolerance) { -//// anArcPoint[2][0] = anArcPoint[0][0] + x * aRad / aNorm; -//// anArcPoint[2][1] = anArcPoint[0][1] + y * aRad / aNorm; -//// } -//// -//// x = anArcPoint[1][0] + anArcPoint[2][0] - 2.0 * anArcPoint[0][0]; -//// y = anArcPoint[1][1] + anArcPoint[2][1] - 2.0 * anArcPoint[0][1]; -//// aNorm = sqrt(x*x + y*y); -//// if (aNorm >= tolerance) { -//// x *= aRad / aNorm; -//// y *= aRad / aNorm; -//// } else { // obtain orthogonal direction -//// x = 0.5 * (anArcPoint[2][1] - anArcPoint[1][1]); -//// y = -0.5 * (anArcPoint[2][0] - anArcPoint[1][0]); -//// } -//// theX = anArcPoint[0][0] + x; -//// theY = anArcPoint[0][1] + y; -//// } -////} - - -// ======================================================== -// ========= Auxiliary functions =============== -// ======================================================== - -template -int Search(const uint32_t& theEntityID, const std::vector& theEntities) -{ - int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0; - int aVecSize = theEntities.size(); - while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID) - aResIndex--; - while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID) - aResIndex++; - if (aResIndex == -1) - aResIndex = aVecSize; - return aResIndex; -} diff --git a/src/SketchSolver/SketchSolver_Group.h b/src/SketchSolver/SketchSolver_Group.h index 6e53af522..dceff0581 100644 --- a/src/SketchSolver/SketchSolver_Group.h +++ b/src/SketchSolver/SketchSolver_Group.h @@ -75,21 +75,6 @@ class SketchSolver_Group * \return \c true if the constraint added or updated successfully */ bool changeConstraint(std::shared_ptr theConstraint); -//// /** \brief Adds or updates a rigid constraint in the group -//// * \param[in] theConstraint constraint to be changed -//// * \return \c true if the constraint added or updated successfully -//// */ -//// bool changeRigidConstraint(std::shared_ptr theConstraint); -//// /** \brief Adds or updates a mirror constraint in the group -//// * \param[in] theConstraint constraint to be changed -//// * \return \c true if the constraint added or updated successfully -//// */ -//// bool changeMirrorConstraint(std::shared_ptr theConstraint); -//// /** \brief Adds or updates a fillet constraint in the group -//// * \param[in] theConstraint constraint to be changed -//// * \return \c true if the constraint added or updated successfully -//// */ -//// bool changeFilletConstraint(std::shared_ptr theConstraint); /** \brief Updates the data corresponding the specified feature * \param[in] theFeature the feature to be updated @@ -124,11 +109,6 @@ class SketchSolver_Group * \return \c true if workplane updated successfully, \c false if workplane parameters are not consistent */ bool updateWorkplane(); -//// -//// /** \brief If the entity is in this group it will updated -//// * \param[in] theEntity attribute, which values should update SolveSpace entity -//// */ -//// void updateEntityIfPossible(std::shared_ptr theEntity); /** \brief Searches invalid features and constraints in the group and removes them * \return \c false if the group several constraints were removed @@ -149,81 +129,12 @@ class SketchSolver_Group * \return \c false when no need to solve constraints */ bool resolveConstraints(); -//// -//// /** \brief Searches the constraints built on the entity and emit the signal to update them -//// * \param[in] theEntity attribute of the constraint -//// */ -//// void updateRelatedConstraints(std::shared_ptr theEntity) const; -//// /** \brief Searches the constraints built on the entity and emit the signal to update them -//// * \param[in] theFeature feature of the constraint -//// */ -//// void updateRelatedConstraintsFeature(std::shared_ptr theFeature) const; -//// -//// /** \brief Adds or updates an entity in the group -//// * -//// * The parameters of entity will be parsed and added to the list of SolveSpace parameters. -//// * Parameters of certain entity will be placed sequentially in the list. -//// * -//// * \param[in] theEntity the object of constraint -//// * \return identifier of changed entity or 0 if entity could not be changed -//// */ -//// Slvs_hEntity changeEntity(std::shared_ptr theEntity); -//// Slvs_hEntity changeEntityFeature(std::shared_ptr theEntity); protected: -//// /** \brief Adds or updates a normal in the group -//// * -//// * Normal is a special entity in SolveSpace, which defines a direction in 3D and -//// * a rotation about this direction. So, SolveSpace represents normals as unit quaternions. -//// * -//// * To define a normal there should be specified two coordinate axis -//// * on the plane transversed to created normal. -//// * -//// * \param[in] theDirX first coordinate axis of the plane -//// * \param[in] theNorm attribute for the normal (used to identify newly created entity) -//// * \return identifier of created or updated normal -//// */ -//// Slvs_hEntity changeNormal(std::shared_ptr theDirX, -//// std::shared_ptr theNorm); -//// -//// /** \brief Adds or updates a parameter in the group -//// * \param[in] theParam the value of parameter -//// * \param[in] thePrmIter the cell in the list of parameters which should be changed -//// * (the iterator will be increased if it does not reach the end of the list) -//// * \return identifier of changed parameter; when the parameter cannot be created, returned ID is 0 -//// */ -//// Slvs_hParam changeParameter(const double& theParam, -//// std::vector::const_iterator& thePrmIter); -//// -//// /** \brief Removes specified entities and their parameters -//// * \param[in] theEntities list of IDs of the entities to be removed -//// */ -//// void removeEntitiesById(const std::set& theEntities); - /** \brief Removes constraints from the group * \param[in] theConstraint constraint to be removed */ void removeConstraint(ConstraintPtr theConstraint); -//// -//// /** \brief Change values of attribute by parameters received from SolveSpace solver -//// * \param[in,out] theAttribute pointer to the attribute to be changed -//// * \param[in] theEntityID identifier of SolveSpace entity, which contains updated data -//// * \return \c true if the attribute's value has changed -//// */ -//// bool updateAttribute(std::shared_ptr theAttribute, -//// const Slvs_hEntity& theEntityID); -//// -//// /// \brief Update arc of fillet to be less than 180 degree -//// void updateFilletConstraints(); -//// -//// /** \brief Adds a constraint for a point which should not be changed during computations -//// * \param[in] theEntity the base for the constraint -//// * \param[in] theAllowToFit this flag shows that the entity may be placed into -//// * the 'dragged' field of SolveSpace solver, so this entity -//// * may be changed a little during solution -//// */ -//// void addTemporaryConstraintWhereDragged(std::shared_ptr theEntity, -//// bool theAllowToFit = true); /** \brief Remove all temporary constraint after computation finished * \param[in] theRemoved indexes of constraints to be removed. If empty, all temporary constraints should be deleted @@ -236,61 +147,6 @@ private: * \return \c true if success, \c false if workplane parameters are not consistent */ bool addWorkplane(CompositeFeaturePtr theSketch); -//// -//// /** \brief Add the entities of constraint for points coincidence into the appropriate list -//// * \param[in] thePoint1 identifier of the first point -//// * \param[in] thePoint2 identifier of the second point -//// * \return \c true if the points are added successfully, and -//// * \c false if the constraint is the extra one (should not be created in SolveSpace) -//// */ -//// bool addCoincidentPoints(const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2); -//// -//// /** \brief Change entities parameters to make them symmetric relating to the mirror line -//// * \param[in] theBase entity to be mirrored -//// * \param[in] theMirror a mirrored object -//// * \param[in] theMirrorLine a mirror line -//// */ -//// void makeMirrorEntity(const Slvs_hEntity& theBase, -//// const Slvs_hEntity& theMirror, -//// const Slvs_hEntity& theMirrorLine); -//// -//// /** \brief Calculates middle point on line or arc -//// * \param[in] theEntity identifier of line or arc -//// * \param[out] theX X value of middle point -//// * \param[out] theY Y value of middle point -//// */ -//// void calculateMiddlePoint(const Slvs_hEntity& theEntity, -//// double& theX, double& theY) const; -//// -//// private: -//// // SolveSpace entities -//// Slvs_hGroup myID; ///< the index of the group -//// Slvs_Entity myWorkplane; ///< Workplane for the current group -//// std::vector myParams; ///< List of parameters of the constraints -//// Slvs_hParam myParamMaxID; ///< Actual maximal ID of parameters (not equal to myParams size) -//// std::vector myEntities; ///< List of entities of the constaints -//// std::vector myEntOfConstr; ///< Flags show that certain entity used in constraints -//// Slvs_hEntity myEntityMaxID; ///< Actual maximal ID of entities (not equal to myEntities size) -//// std::vector myConstraints; ///< List of constraints in SolveSpace format -//// Slvs_hConstraint myConstrMaxID; ///< Actual maximal ID of constraints (not equal to myConstraints size) -//// bool myNeedToSolve; ///< Indicator that something changed in the group and constraint system need to be rebuilt -//// -//// SketchSolver_Solver myConstrSolver; ///< Solver for set of equations obtained by constraints -//// -//// std::vector myTempPointWhereDragged; ///< Parameters of one of the points which is moved by user -//// Slvs_hEntity myTempPointWDrgdID; ///< Identifier of such point -//// std::list myTempConstraints; ///< The list of identifiers of temporary constraints (SLVS_C_WHERE_DRAGGED) applied for all other points moved by user -//// -//// // SketchPlugin entities -//// std::shared_ptr mySketch; ///< Equivalent to workplane -//// ConstraintMap myConstraintMap; ///< The map between SketchPlugin and SolveSpace constraints -//// std::map, Slvs_hEntity> myEntityAttrMap; ///< The map between "attribute" parameters of constraints and their equivalent SolveSpace entities -//// std::map myEntityFeatMap; ///< The map between "feature" parameters of constraints and their equivalent SolveSpace entities -//// -//// // Conincident items -//// std::vector > myCoincidentPoints; ///< Stores the lists of identifiers of coincident points (to avoid unnecessary coincidence constraints) -//// std::set > myExtraCoincidence; ///< Additional coincidence constraints which are not necessary (coincidence between points already done -//// ///< by other constraints) but created by GUI tools. Useful when some coincidence constraints were removed private: Slvs_hGroup myID; ///< Index of the group diff --git a/src/SketchSolver/SketchSolver_Storage.cpp b/src/SketchSolver/SketchSolver_Storage.cpp index eabf3a5fa..244bc1c7d 100644 --- a/src/SketchSolver/SketchSolver_Storage.cpp +++ b/src/SketchSolver/SketchSolver_Storage.cpp @@ -403,6 +403,8 @@ int Search(const uint32_t& theEntityID, const std::vector& theEntities) { int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0; int aVecSize = theEntities.size(); + if (theEntities.empty()) + return 1; while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID) aResIndex--; while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID) -- 2.39.2