| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| |
|
| | #ifndef SKETCHERGUI_DrawSketchHandlerLine_H
|
| | #define SKETCHERGUI_DrawSketchHandlerLine_H
|
| |
|
| | #include <Gui/BitmapFactory.h>
|
| | #include <Gui/Notifications.h>
|
| | #include <Gui/Command.h>
|
| | #include <Gui/CommandT.h>
|
| | #include <Gui/InputHint.h>
|
| |
|
| | #include <Mod/Sketcher/App/SketchObject.h>
|
| |
|
| | #include "DrawSketchDefaultWidgetController.h"
|
| | #include "DrawSketchControllableHandler.h"
|
| |
|
| | #include "GeometryCreationMode.h"
|
| | #include "Utils.h"
|
| |
|
| | #include <vector>
|
| | #include <algorithm>
|
| |
|
| | namespace SketcherGui
|
| | {
|
| |
|
| | extern GeometryCreationMode geometryCreationMode;
|
| |
|
| | class DrawSketchHandlerLine;
|
| |
|
| | namespace ConstructionMethods
|
| | {
|
| |
|
| | enum class LineConstructionMethod
|
| | {
|
| | OnePointLengthAngle,
|
| | OnePointWidthHeight,
|
| | TwoPoints,
|
| | End
|
| | };
|
| |
|
| | }
|
| |
|
| | using DSHLineController = DrawSketchDefaultWidgetController<
|
| | DrawSketchHandlerLine,
|
| | StateMachines::TwoSeekEnd,
|
| | 2,
|
| | OnViewParameters<4, 4, 4>,
|
| | WidgetParameters<0, 0, 0>,
|
| | WidgetCheckboxes<0, 0, 0>,
|
| | WidgetComboboxes<1, 1, 1>,
|
| | ConstructionMethods::LineConstructionMethod,
|
| | true>;
|
| |
|
| | using DSHLineControllerBase = DSHLineController::ControllerBase;
|
| |
|
| | using DrawSketchHandlerLineBase = DrawSketchControllableHandler<DSHLineController>;
|
| |
|
| |
|
| | class DrawSketchHandlerLine: public DrawSketchHandlerLineBase
|
| | {
|
| | Q_DECLARE_TR_FUNCTIONS(SketcherGui::DrawSketchHandlerLine)
|
| |
|
| | friend DSHLineController;
|
| | friend DSHLineControllerBase;
|
| |
|
| | public:
|
| | explicit DrawSketchHandlerLine(
|
| | ConstructionMethod constrMethod = ConstructionMethod::OnePointLengthAngle
|
| | )
|
| | : DrawSketchHandlerLineBase(constrMethod)
|
| | , length(0.0)
|
| | , lengthSign(0)
|
| | , widthSign(0)
|
| | , capturedDirection(0.0, 0.0) {};
|
| | ~DrawSketchHandlerLine() override = default;
|
| |
|
| | private:
|
| | void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
|
| | {
|
| | switch (state()) {
|
| | case SelectMode::SeekFirst: {
|
| | toolWidgetManager.drawPositionAtCursor(onSketchPos);
|
| |
|
| | startPoint = onSketchPos;
|
| |
|
| | seekAndRenderAutoConstraint(sugConstraints[0], onSketchPos, Base::Vector2d(0.f, 0.f));
|
| | } break;
|
| | case SelectMode::SeekSecond: {
|
| | toolWidgetManager.drawDirectionAtCursor(onSketchPos, startPoint);
|
| |
|
| | endPoint = onSketchPos;
|
| |
|
| | try {
|
| | CreateAndDrawShapeGeometry();
|
| | }
|
| | catch (const Base::ValueError&) {
|
| | }
|
| |
|
| | seekAndRenderAutoConstraint(sugConstraints[1], onSketchPos, onSketchPos - startPoint);
|
| | } break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| | void executeCommands() override
|
| | {
|
| | try {
|
| | createShape(false);
|
| |
|
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add sketch line"));
|
| |
|
| | commandAddShapeGeometryAndConstraints();
|
| |
|
| | Gui::Command::commitCommand();
|
| | }
|
| | catch (const Base::Exception&) {
|
| | Gui::NotifyError(
|
| | sketchgui,
|
| | QT_TRANSLATE_NOOP("Notifications", "Error"),
|
| | QT_TRANSLATE_NOOP("Notifications", "Failed to add line")
|
| | );
|
| |
|
| | Gui::Command::abortCommand();
|
| | THROWM(
|
| | Base::RuntimeError,
|
| | QT_TRANSLATE_NOOP(
|
| | "Notifications",
|
| | "Tool execution aborted"
|
| | ) "\n"
|
| | )
|
| |
|
| | }
|
| | }
|
| |
|
| | void generateAutoConstraints() override
|
| | {
|
| | int LineGeoId = getHighestCurveIndex();
|
| |
|
| |
|
| | if (avoidRedundants) {
|
| | removeRedundantHorizontalVertical(getSketchObject(), sugConstraints[0], sugConstraints[1]);
|
| | }
|
| |
|
| | auto& ac1 = sugConstraints[0];
|
| | auto& ac2 = sugConstraints[1];
|
| |
|
| | generateAutoConstraintsOnElement(ac1, LineGeoId, Sketcher::PointPos::start);
|
| | generateAutoConstraintsOnElement(ac2, LineGeoId, Sketcher::PointPos::end);
|
| |
|
| |
|
| |
|
| |
|
| | removeRedundantAutoConstraints();
|
| | }
|
| |
|
| | void createAutoConstraints() override
|
| | {
|
| |
|
| | createGeneratedAutoConstraints(true);
|
| |
|
| | sugConstraints[0].clear();
|
| | sugConstraints[1].clear();
|
| | }
|
| |
|
| | std::string getToolName() const override
|
| | {
|
| | return "DSH_Line";
|
| | }
|
| |
|
| | QString getCrosshairCursorSVGName() const override
|
| | {
|
| | if (constructionMethod() == ConstructionMethod::OnePointLengthAngle) {
|
| | return QStringLiteral("Sketcher_Pointer_Create_Line_Polar");
|
| | }
|
| | else {
|
| | return QStringLiteral("Sketcher_Pointer_Create_Line.svg");
|
| | }
|
| | }
|
| |
|
| | std::unique_ptr<QWidget> createWidget() const override
|
| | {
|
| | return std::make_unique<SketcherToolDefaultWidget>();
|
| | }
|
| |
|
| | bool isWidgetVisible() const override
|
| | {
|
| | ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
|
| | "User parameter:BaseApp/Preferences/Mod/Sketcher/Tools"
|
| | );
|
| | auto index = hGrp->GetInt("OnViewParameterVisibility", 1);
|
| | return index != 0;
|
| | };
|
| |
|
| | QPixmap getToolIcon() const override
|
| | {
|
| | return Gui::BitmapFactory().pixmap("Sketcher_CreateLine");
|
| | }
|
| |
|
| | QString getToolWidgetText() const override
|
| | {
|
| | return QString(tr("Line Parameters"));
|
| | }
|
| |
|
| | bool canGoToNextMode() override
|
| | {
|
| | if (state() == SelectMode::SeekSecond && length < Precision::Confusion()) {
|
| |
|
| | return false;
|
| | }
|
| | return true;
|
| | }
|
| |
|
| | void angleSnappingControl() override
|
| | {
|
| | if (state() == SelectMode::SeekSecond) {
|
| | setAngleSnapping(true, startPoint);
|
| | }
|
| |
|
| | else {
|
| | setAngleSnapping(false);
|
| | }
|
| | }
|
| |
|
| | void onReset() override
|
| | {
|
| | lengthSign = 0;
|
| | widthSign = 0;
|
| | capturedDirection = Base::Vector2d(0.0, 0.0);
|
| | toolWidgetManager.resetControls();
|
| | }
|
| |
|
| | private:
|
| | Base::Vector2d startPoint, endPoint;
|
| | double length;
|
| |
|
| |
|
| | int lengthSign, widthSign;
|
| |
|
| | Base::Vector2d capturedDirection;
|
| |
|
| | void createShape(bool onlyeditoutline) override
|
| | {
|
| | Q_UNUSED(onlyeditoutline);
|
| | ShapeGeometry.clear();
|
| |
|
| | Base::Vector2d vecL = endPoint - startPoint;
|
| | length = vecL.Length();
|
| | if (length > Precision::Confusion()) {
|
| |
|
| | addLineToShapeGeometry(toVector3d(startPoint), toVector3d(endPoint), isConstructionMode());
|
| | }
|
| | }
|
| |
|
| | std::list<Gui::InputHint> getToolHints() const override
|
| | {
|
| | using State = std::pair<ConstructionMethod, SelectMode>;
|
| | using enum Gui::InputHint::UserInput;
|
| |
|
| | const Gui::InputHint switchModeHint {tr("%1 switch mode"), {KeyM}};
|
| |
|
| | return Gui::lookupHints<State>(
|
| | {constructionMethod(), state()},
|
| | {
|
| |
|
| | {.state = {ConstructionMethod::OnePointLengthAngle, SelectMode::SeekFirst},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick first point"), {MouseLeft}},
|
| | switchModeHint,
|
| | }},
|
| | {.state = {ConstructionMethod::OnePointLengthAngle, SelectMode::SeekSecond},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick second point"), {MouseLeft}},
|
| | switchModeHint,
|
| | }},
|
| |
|
| |
|
| | {.state = {ConstructionMethod::OnePointWidthHeight, SelectMode::SeekFirst},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick first point"), {MouseLeft}},
|
| | switchModeHint,
|
| | }},
|
| | {.state = {ConstructionMethod::OnePointWidthHeight, SelectMode::SeekSecond},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick second point"), {MouseLeft}},
|
| | switchModeHint,
|
| | }},
|
| |
|
| |
|
| | {.state = {ConstructionMethod::TwoPoints, SelectMode::SeekFirst},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick first point"), {MouseLeft}},
|
| | switchModeHint,
|
| | }},
|
| | {.state = {ConstructionMethod::TwoPoints, SelectMode::SeekSecond},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick second point"), {MouseLeft}},
|
| | switchModeHint,
|
| | }},
|
| | });
|
| | }
|
| | };
|
| |
|
| | template<>
|
| | auto DSHLineControllerBase::getState(int labelindex) const
|
| | {
|
| | switch (labelindex) {
|
| | case OnViewParameter::First:
|
| | case OnViewParameter::Second:
|
| | return SelectMode::SeekFirst;
|
| | break;
|
| | case OnViewParameter::Third:
|
| | case OnViewParameter::Fourth:
|
| | return SelectMode::SeekSecond;
|
| | break;
|
| | default:
|
| | THROWM(Base::ValueError, "Label index without an associated machine state")
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHLineController::configureToolWidget()
|
| | {
|
| | if (!init) {
|
| | QStringList names = {
|
| | QApplication::translate("Sketcher_CreateLine", "Point, length, angle"),
|
| | QApplication::translate("Sketcher_CreateLine", "Point, width, height"),
|
| | QApplication::translate("Sketcher_CreateLine", "2 points")
|
| | };
|
| | toolWidget->setComboboxElements(WCombobox::FirstCombo, names);
|
| |
|
| | if (isConstructionMode()) {
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 0,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateLineAngleLength_Constr")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 1,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateLineLengthWidth_Constr")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 2,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateLine_Constr")
|
| | );
|
| | }
|
| | else {
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 0,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateLineAngleLength")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 1,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateLineLengthWidth")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 2,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateLine")
|
| | );
|
| | }
|
| | }
|
| |
|
| | onViewParameters[OnViewParameter::First]->setLabelType(Gui::SoDatumLabel::DISTANCEX);
|
| | onViewParameters[OnViewParameter::Second]->setLabelType(Gui::SoDatumLabel::DISTANCEY);
|
| |
|
| | if (handler->constructionMethod() == ConstructionMethod::OnePointLengthAngle) {
|
| | onViewParameters[OnViewParameter::Third]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelType(
|
| | Gui::SoDatumLabel::ANGLE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::TwoPoints) {
|
| | onViewParameters[OnViewParameter::Third]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCEX,
|
| | Gui::EditableDatumLabel::Function::Positioning
|
| | );
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCEY,
|
| | Gui::EditableDatumLabel::Function::Positioning
|
| | );
|
| | }
|
| | else {
|
| | onViewParameters[OnViewParameter::Third]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCEX,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCEY,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | }
|
| | }
|
| |
|
| |
|
| | template<>
|
| | void DSHLineControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchPos)
|
| | {
|
| | switch (handler->state()) {
|
| | case SelectMode::SeekFirst: {
|
| | auto& firstParam = onViewParameters[OnViewParameter::First];
|
| | auto& secondParam = onViewParameters[OnViewParameter::Second];
|
| |
|
| | if (firstParam->isSet) {
|
| | onSketchPos.x = firstParam->getValue();
|
| | }
|
| |
|
| | if (secondParam->isSet) {
|
| | onSketchPos.y = secondParam->getValue();
|
| | }
|
| | } break;
|
| | case SelectMode::SeekSecond: {
|
| | auto& thirdParam = onViewParameters[OnViewParameter::Third];
|
| | auto& fourthParam = onViewParameters[OnViewParameter::Fourth];
|
| |
|
| | if (handler->constructionMethod() == ConstructionMethod::OnePointWidthHeight) {
|
| | if (thirdParam->isSet) {
|
| | double length = thirdParam->getValue();
|
| | if (fabs(length) < Precision::Confusion()) {
|
| |
|
| | if (fourthParam->isSet) {
|
| | double width = fourthParam->getValue();
|
| | if (fabs(width) < Precision::Confusion()
|
| | && fourthParam->hasFinishedEditing) {
|
| | unsetOnViewParameter(thirdParam.get());
|
| | handler->lengthSign = 0;
|
| | return;
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| | if (handler->lengthSign == 0) {
|
| | handler->lengthSign = (onSketchPos.x - handler->startPoint.x) >= 0 ? 1 : -1;
|
| | }
|
| | onSketchPos.x = handler->startPoint.x + handler->lengthSign * length;
|
| | }
|
| |
|
| | if (fourthParam->isSet) {
|
| | double width = fourthParam->getValue();
|
| | if (fabs(width) < Precision::Confusion()) {
|
| |
|
| | if (thirdParam->isSet) {
|
| | double length = thirdParam->getValue();
|
| | if (fabs(length) < Precision::Confusion()
|
| | && thirdParam->hasFinishedEditing) {
|
| | unsetOnViewParameter(fourthParam.get());
|
| | handler->widthSign = 0;
|
| | return;
|
| | }
|
| | }
|
| | }
|
| | if (handler->widthSign == 0) {
|
| | handler->widthSign = (onSketchPos.y - handler->startPoint.y) >= 0 ? 1 : -1;
|
| | }
|
| | onSketchPos.y = handler->startPoint.y + handler->widthSign * width;
|
| | }
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::OnePointLengthAngle) {
|
| |
|
| | Base::Vector2d dir = onSketchPos - handler->startPoint;
|
| | if (dir.Length() < Precision::Confusion()) {
|
| | dir.x = 1.0;
|
| | }
|
| | double length = dir.Length();
|
| |
|
| | if (fourthParam->isSet) {
|
| | const double angle = Base::toRadians(fourthParam->getValue());
|
| | const Base::Vector2d ovpDir(cos(angle), sin(angle));
|
| | handler->capturedDirection = ovpDir;
|
| | }
|
| | else {
|
| | handler->capturedDirection = dir.Normalize();
|
| | }
|
| |
|
| | if (thirdParam->isSet) {
|
| | length = thirdParam->getValue();
|
| | if (length < Precision::Confusion() && thirdParam->hasFinishedEditing) {
|
| | unsetOnViewParameter(thirdParam.get());
|
| | handler->capturedDirection = Base::Vector2d(0.0, 0.0);
|
| | return;
|
| | }
|
| |
|
| | onSketchPos = handler->startPoint + length * handler->capturedDirection;
|
| | }
|
| | else if (fourthParam->isSet) {
|
| |
|
| | onSketchPos.ProjectToLine(
|
| | onSketchPos - handler->startPoint,
|
| | handler->capturedDirection
|
| | );
|
| | onSketchPos += handler->startPoint;
|
| | }
|
| | }
|
| | else {
|
| | if (thirdParam->isSet) {
|
| | onSketchPos.x = thirdParam->getValue();
|
| | }
|
| | if (fourthParam->isSet) {
|
| | onSketchPos.y = fourthParam->getValue();
|
| | }
|
| | }
|
| |
|
| | if (thirdParam->hasFinishedEditing && fourthParam->hasFinishedEditing
|
| | && (onSketchPos - handler->startPoint).Length() < Precision::Confusion()) {
|
| | unsetOnViewParameter(thirdParam.get());
|
| | unsetOnViewParameter(fourthParam.get());
|
| | handler->lengthSign = 0;
|
| | handler->widthSign = 0;
|
| | }
|
| | } break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHLineController::adaptParameters(Base::Vector2d onSketchPos)
|
| | {
|
| | switch (handler->state()) {
|
| | case SelectMode::SeekFirst: {
|
| | auto& firstParam = onViewParameters[OnViewParameter::First];
|
| | auto& secondParam = onViewParameters[OnViewParameter::Second];
|
| |
|
| | if (!firstParam->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::First, onSketchPos.x);
|
| | }
|
| |
|
| | if (!secondParam->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Second, onSketchPos.y);
|
| | }
|
| |
|
| | bool sameSign = onSketchPos.x * onSketchPos.y > 0.;
|
| | firstParam->setLabelAutoDistanceReverse(!sameSign);
|
| | secondParam->setLabelAutoDistanceReverse(sameSign);
|
| | firstParam->setPoints(Base::Vector3d(), toVector3d(onSketchPos));
|
| | secondParam->setPoints(Base::Vector3d(), toVector3d(onSketchPos));
|
| | } break;
|
| | case SelectMode::SeekSecond: {
|
| | auto& thirdParam = onViewParameters[OnViewParameter::Third];
|
| | auto& fourthParam = onViewParameters[OnViewParameter::Fourth];
|
| |
|
| | if (handler->constructionMethod() == ConstructionMethod::OnePointWidthHeight) {
|
| | Base::Vector3d start = toVector3d(handler->startPoint);
|
| | Base::Vector3d end = toVector3d(handler->endPoint);
|
| | Base::Vector3d vec = end - start;
|
| |
|
| | if (!thirdParam->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Third, fabs(vec.x));
|
| | }
|
| |
|
| | if (!fourthParam->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Fourth, fabs(vec.y));
|
| | }
|
| |
|
| | bool sameSign = vec.x * vec.y > 0.;
|
| |
|
| | thirdParam->setLabelAutoDistanceReverse(!sameSign);
|
| | fourthParam->setLabelAutoDistanceReverse(sameSign);
|
| |
|
| | thirdParam->setPoints(start, end);
|
| | fourthParam->setPoints(start, end);
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::OnePointLengthAngle) {
|
| | Base::Vector3d start = toVector3d(handler->startPoint);
|
| | Base::Vector3d end = toVector3d(handler->endPoint);
|
| | Base::Vector3d vec = end - start;
|
| |
|
| | if (!thirdParam->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Third, vec.Length());
|
| | }
|
| |
|
| | double range = (handler->endPoint - handler->startPoint).Angle();
|
| | if (!fourthParam->isSet) {
|
| | setOnViewParameterValue(
|
| | OnViewParameter::Fourth,
|
| | Base::toDegrees(range),
|
| | Base::Unit::Angle
|
| | );
|
| | }
|
| | else if (vec.Length() > Precision::Confusion()) {
|
| | double ovpRange = Base::toRadians(fourthParam->getValue());
|
| | if (fabs(range - ovpRange) > Precision::Confusion()) {
|
| | setOnViewParameterValue(
|
| | OnViewParameter::Fourth,
|
| | Base::toDegrees(range),
|
| | Base::Unit::Angle
|
| | );
|
| | }
|
| | }
|
| |
|
| | thirdParam->setPoints(start, end);
|
| | fourthParam->setPoints(start, Base::Vector3d());
|
| | fourthParam->setLabelRange(range);
|
| | }
|
| | else {
|
| | if (!thirdParam->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Third, onSketchPos.x);
|
| | }
|
| |
|
| | if (!fourthParam->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Fourth, onSketchPos.y);
|
| | }
|
| |
|
| | bool sameSign = onSketchPos.x * onSketchPos.y > 0.;
|
| | thirdParam->setLabelAutoDistanceReverse(!sameSign);
|
| | fourthParam->setLabelAutoDistanceReverse(sameSign);
|
| | thirdParam->setPoints(Base::Vector3d(), toVector3d(onSketchPos));
|
| | fourthParam->setPoints(Base::Vector3d(), toVector3d(onSketchPos));
|
| | }
|
| | } break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHLineController::computeNextDrawSketchHandlerMode()
|
| | {
|
| | switch (handler->state()) {
|
| | case SelectMode::SeekFirst: {
|
| | auto& firstParam = onViewParameters[OnViewParameter::First];
|
| | auto& secondParam = onViewParameters[OnViewParameter::Second];
|
| |
|
| | if (firstParam->hasFinishedEditing && secondParam->hasFinishedEditing) {
|
| | handler->setNextState(SelectMode::SeekSecond);
|
| | }
|
| | } break;
|
| | case SelectMode::SeekSecond: {
|
| | auto& thirdParam = onViewParameters[OnViewParameter::Third];
|
| | auto& fourthParam = onViewParameters[OnViewParameter::Fourth];
|
| |
|
| | if (thirdParam->hasFinishedEditing && fourthParam->hasFinishedEditing) {
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | } break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| | template<>
|
| | void DSHLineController::addConstraints()
|
| | {
|
| | App::DocumentObject* obj = handler->sketchgui->getObject();
|
| |
|
| | int firstCurve = handler->getHighestCurveIndex();
|
| |
|
| | auto x0 = onViewParameters[OnViewParameter::First]->getValue();
|
| | auto y0 = onViewParameters[OnViewParameter::Second]->getValue();
|
| | auto p3 = onViewParameters[OnViewParameter::Third]->getValue();
|
| | auto p4 = onViewParameters[OnViewParameter::Fourth]->getValue();
|
| |
|
| | auto x0set = onViewParameters[OnViewParameter::First]->isSet;
|
| | auto y0set = onViewParameters[OnViewParameter::Second]->isSet;
|
| | auto p3set = onViewParameters[OnViewParameter::Third]->isSet;
|
| | auto p4set = onViewParameters[OnViewParameter::Fourth]->isSet;
|
| |
|
| | using namespace Sketcher;
|
| |
|
| | auto constraintToOrigin = [&]() {
|
| | ConstraintToAttachment(GeoElementId(firstCurve, PointPos::start), GeoElementId::RtPnt, x0, obj);
|
| | };
|
| |
|
| | auto constraintx0 = [&]() {
|
| | ConstraintToAttachment(GeoElementId(firstCurve, PointPos::start), GeoElementId::VAxis, x0, obj);
|
| | };
|
| |
|
| | auto constrainty0 = [&]() {
|
| | ConstraintToAttachment(GeoElementId(firstCurve, PointPos::start), GeoElementId::HAxis, y0, obj);
|
| | };
|
| |
|
| | auto constraintp3DistanceX = [&]() {
|
| | if (fabs(p3) < Precision::Confusion()) {
|
| | Gui::cmdAppObjectArgs(obj, "addConstraint(Sketcher.Constraint('Vertical',%d)) ", firstCurve);
|
| | }
|
| | else {
|
| | bool reverse = (handler->endPoint.x - handler->startPoint.x) < 0;
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('DistanceX',%d,%d,%d,%d,%f)) ",
|
| | firstCurve,
|
| | reverse ? 2 : 1,
|
| | firstCurve,
|
| | reverse ? 1 : 2,
|
| | fabs(p3)
|
| | );
|
| | }
|
| | };
|
| |
|
| | auto constraintp3length = [&]() {
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('Distance',%d,%f)) ",
|
| | firstCurve,
|
| | fabs(p3)
|
| | );
|
| | };
|
| |
|
| | auto constraintp3x = [&]() {
|
| | ConstraintToAttachment(GeoElementId(firstCurve, PointPos::end), GeoElementId::VAxis, p3, obj);
|
| | };
|
| |
|
| | auto constraintp4DistanceY = [&]() {
|
| | if (fabs(p4) < Precision::Confusion()) {
|
| | Gui::cmdAppObjectArgs(obj, "addConstraint(Sketcher.Constraint('Horizontal',%d)) ", firstCurve);
|
| | }
|
| | else {
|
| | bool reverse = (handler->endPoint.y - handler->startPoint.y) < 0;
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('DistanceY',%d,%d,%d,%d,%f)) ",
|
| | firstCurve,
|
| | reverse ? 2 : 1,
|
| | firstCurve,
|
| | reverse ? 1 : 2,
|
| | fabs(p4)
|
| | );
|
| | }
|
| | };
|
| |
|
| | auto constraintp4angle = [&]() {
|
| | ConstraintLineByAngle(firstCurve, Base::toRadians(p4), obj);
|
| | };
|
| |
|
| | auto constraintp4y = [&]() {
|
| | ConstraintToAttachment(GeoElementId(firstCurve, PointPos::end), GeoElementId::HAxis, p4, obj);
|
| | };
|
| |
|
| | if (handler->AutoConstraints.empty()) {
|
| |
|
| | if (x0set && y0set && x0 == 0. && y0 == 0.) {
|
| | constraintToOrigin();
|
| | }
|
| | else {
|
| | if (x0set) {
|
| | constraintx0();
|
| | }
|
| |
|
| | if (y0set) {
|
| | constrainty0();
|
| | }
|
| | }
|
| |
|
| | if (handler->constructionMethod()
|
| | == DrawSketchHandlerLine::ConstructionMethod::OnePointWidthHeight) {
|
| | if (p3set) {
|
| | constraintp3DistanceX();
|
| | }
|
| |
|
| | if (p4set) {
|
| | constraintp4DistanceY();
|
| | }
|
| | }
|
| | else if (handler->constructionMethod()
|
| | == DrawSketchHandlerLine::ConstructionMethod::OnePointLengthAngle) {
|
| | if (p3set) {
|
| | constraintp3length();
|
| | }
|
| |
|
| | if (p4set) {
|
| | constraintp4angle();
|
| | }
|
| | }
|
| | else {
|
| | if (p3set) {
|
| | constraintp3x();
|
| | }
|
| |
|
| | if (p4set) {
|
| | constraintp4y();
|
| | }
|
| | }
|
| | }
|
| | else {
|
| | auto startpointinfo = handler->getPointInfo(GeoElementId(firstCurve, PointPos::start));
|
| |
|
| | if (x0set && startpointinfo.isXDoF()) {
|
| | constraintx0();
|
| |
|
| | handler->diagnoseWithAutoConstraints();
|
| |
|
| |
|
| | startpointinfo = handler->getPointInfo(
|
| | GeoElementId(firstCurve, PointPos::start)
|
| | );
|
| | }
|
| |
|
| | if (y0set && startpointinfo.isYDoF()) {
|
| | constrainty0();
|
| |
|
| | handler->diagnoseWithAutoConstraints();
|
| |
|
| |
|
| | startpointinfo = handler->getPointInfo(
|
| | GeoElementId(firstCurve, PointPos::start)
|
| | );
|
| | }
|
| |
|
| | auto endpointinfo = handler->getPointInfo(GeoElementId(firstCurve, PointPos::end));
|
| |
|
| | if (handler->constructionMethod()
|
| | == DrawSketchHandlerLine::ConstructionMethod::OnePointWidthHeight) {
|
| |
|
| | int DoFs = startpointinfo.getDoFs();
|
| | DoFs += endpointinfo.getDoFs();
|
| |
|
| | if (p3set && DoFs > 0) {
|
| | constraintp3DistanceX();
|
| | DoFs--;
|
| | }
|
| |
|
| | if (p4set && DoFs > 0) {
|
| | constraintp4DistanceY();
|
| | }
|
| | }
|
| | else if (handler->constructionMethod()
|
| | == DrawSketchHandlerLine::ConstructionMethod::OnePointLengthAngle) {
|
| |
|
| | int DoFs = startpointinfo.getDoFs();
|
| | DoFs += endpointinfo.getDoFs();
|
| |
|
| | if (p3set && DoFs > 0) {
|
| | constraintp3length();
|
| | DoFs--;
|
| | }
|
| |
|
| | if (p4set && DoFs > 0) {
|
| | constraintp4angle();
|
| | }
|
| | }
|
| | else {
|
| | if (p3set && endpointinfo.isXDoF()) {
|
| | constraintp3x();
|
| |
|
| | handler->diagnoseWithAutoConstraints();
|
| |
|
| |
|
| | startpointinfo = handler->getPointInfo(
|
| | GeoElementId(firstCurve, PointPos::start)
|
| | );
|
| | endpointinfo = handler->getPointInfo(GeoElementId(firstCurve, PointPos::end));
|
| | }
|
| |
|
| | if (p4set && endpointinfo.isYDoF()) {
|
| | constraintp4y();
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | }
|
| |
|
| |
|
| | #endif
|
| |
|