| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| |
|
| | #ifndef SKETCHERGUI_DrawSketchHandlerRectangle_H
|
| | #define SKETCHERGUI_DrawSketchHandlerRectangle_H
|
| |
|
| | #include <QApplication>
|
| |
|
| | #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"
|
| |
|
| | namespace SketcherGui
|
| | {
|
| |
|
| | extern GeometryCreationMode geometryCreationMode;
|
| |
|
| | class DrawSketchHandlerRectangle;
|
| |
|
| | namespace ConstructionMethods
|
| | {
|
| |
|
| | enum class RectangleConstructionMethod
|
| | {
|
| | Diagonal,
|
| | CenterAndCorner,
|
| | ThreePoints,
|
| | CenterAnd3Points,
|
| | End
|
| | };
|
| |
|
| | }
|
| |
|
| | using DSHRectangleController = DrawSketchDefaultWidgetController<
|
| | DrawSketchHandlerRectangle,
|
| | StateMachines::FiveSeekEnd,
|
| | 3,
|
| | OnViewParameters<6, 6, 8, 8>,
|
| | WidgetParameters<0, 0, 0, 0>,
|
| | WidgetCheckboxes<2, 2, 2, 2>,
|
| | WidgetComboboxes<1, 1, 1, 1>,
|
| | ConstructionMethods::RectangleConstructionMethod,
|
| | true>;
|
| |
|
| | using DSHRectangleControllerBase = DSHRectangleController::ControllerBase;
|
| |
|
| | using DrawSketchHandlerRectangleBase = DrawSketchControllableHandler<DSHRectangleController>;
|
| |
|
| |
|
| | class DrawSketchHandlerRectangle: public DrawSketchHandlerRectangleBase
|
| | {
|
| | Q_DECLARE_TR_FUNCTIONS(SketcherGui::DrawSketchHandlerRectangle)
|
| |
|
| |
|
| | friend DSHRectangleController;
|
| | friend DSHRectangleControllerBase;
|
| |
|
| | public:
|
| | DrawSketchHandlerRectangle(
|
| | ConstructionMethod constrMethod = ConstructionMethod::Diagonal,
|
| | bool roundcorners = false,
|
| | bool frame = false
|
| | )
|
| | : DrawSketchHandlerRectangleBase(constrMethod)
|
| | , roundCorners(roundcorners)
|
| | , makeFrame(frame)
|
| | , cornersReversed(false)
|
| | , radius(0.0)
|
| | , length(0.0)
|
| | , width(0.0)
|
| | , thickness(0.)
|
| | , radiusFrame(0.0)
|
| | , angle(0.0)
|
| | , angle123(0.0)
|
| | , angle412(0.0)
|
| | , firstCurve(Sketcher::GeoEnum::GeoUndef)
|
| | , constructionPointOneId(Sketcher::GeoEnum::GeoUndef)
|
| | , constructionPointTwoId(Sketcher::GeoEnum::GeoUndef)
|
| | , constructionPointThreeId(Sketcher::GeoEnum::GeoUndef)
|
| | , centerPointId(Sketcher::GeoEnum::GeoUndef)
|
| | , side(0)
|
| | , lengthSign(0)
|
| | , widthSign(0)
|
| | {}
|
| |
|
| | ~DrawSketchHandlerRectangle() override = default;
|
| |
|
| | private:
|
| | std::list<Gui::InputHint> getToolHints() const override
|
| | {
|
| | using State = std::pair<ConstructionMethod, SelectMode>;
|
| | using enum Gui::InputHint::UserInput;
|
| |
|
| | const Gui::InputHint switchHint {.message = tr("%1 switch mode"), .sequences = {KeyM}};
|
| | const Gui::InputHint roundedCornersHint {
|
| | .message = tr("%1 toggle rounded corners"),
|
| | .sequences = {KeyU}
|
| | };
|
| | const Gui::InputHint frameHint {.message = tr("%1 toggle frame"), .sequences = {KeyJ}};
|
| |
|
| | return Gui::lookupHints<State>(
|
| | {constructionMethod(), state()},
|
| | {
|
| |
|
| | {.state = {ConstructionMethod::Diagonal, SelectMode::SeekFirst},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick first corner"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::Diagonal, SelectMode::SeekSecond},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick opposite corner"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::Diagonal, SelectMode::SeekThird},
|
| | .hints =
|
| | {
|
| | {tr("%1 set corner radius or frame thickness"), {MouseMove}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::Diagonal, SelectMode::SeekFourth},
|
| | .hints =
|
| | {
|
| | {tr("%1 set frame thickness"), {MouseMove}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| |
|
| |
|
| | {.state = {ConstructionMethod::CenterAndCorner, SelectMode::SeekFirst},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick center"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::CenterAndCorner, SelectMode::SeekSecond},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick corner"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::CenterAndCorner, SelectMode::SeekThird},
|
| | .hints =
|
| | {
|
| | {tr("%1 set corner radius or frame thickness"), {MouseMove}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::CenterAndCorner, SelectMode::SeekFourth},
|
| | .hints =
|
| | {
|
| | {tr("%1 set frame thickness"), {MouseMove}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| |
|
| |
|
| | {.state = {ConstructionMethod::ThreePoints, SelectMode::SeekFirst},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick first corner"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::ThreePoints, SelectMode::SeekSecond},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick second corner"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::ThreePoints, SelectMode::SeekThird},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick third corner"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::ThreePoints, SelectMode::SeekFourth},
|
| | .hints =
|
| | {
|
| | {tr("%1 set corner radius or frame thickness"), {MouseMove}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| |
|
| |
|
| | {.state = {ConstructionMethod::CenterAnd3Points, SelectMode::SeekFirst},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick center"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::CenterAnd3Points, SelectMode::SeekSecond},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick first corner"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::CenterAnd3Points, SelectMode::SeekThird},
|
| | .hints =
|
| | {
|
| | {tr("%1 pick second corner"), {MouseLeft}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | {.state = {ConstructionMethod::CenterAnd3Points, SelectMode::SeekFourth},
|
| | .hints =
|
| | {
|
| | {tr("%1 set corner radius or frame thickness"), {MouseMove}},
|
| | switchHint,
|
| | roundedCornersHint,
|
| | frameHint,
|
| | }},
|
| | });
|
| | }
|
| |
|
| | private:
|
| | void updateDataAndDrawToPosition(Base::Vector2d onSketchPos) override
|
| | {
|
| | using std::numbers::pi;
|
| |
|
| | switch (state()) {
|
| | case SelectMode::SeekFirst: {
|
| | toolWidgetManager.drawPositionAtCursor(onSketchPos);
|
| |
|
| | if (constructionMethod() == ConstructionMethod::Diagonal
|
| | || constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | corner1 = onSketchPos;
|
| | }
|
| | else {
|
| | center = onSketchPos;
|
| | }
|
| |
|
| | seekAndRenderAutoConstraint(sugConstraints[0], onSketchPos, Base::Vector2d(0.f, 0.f));
|
| | } break;
|
| | case SelectMode::SeekSecond: {
|
| | if (constructionMethod() == ConstructionMethod::Diagonal) {
|
| | toolWidgetManager.drawDirectionAtCursor(onSketchPos, corner1);
|
| |
|
| |
|
| |
|
| | corner3 = onSketchPos;
|
| | if ((corner3.x - corner1.x) * (corner3.y - corner1.y) > 0) {
|
| | corner2 = Base::Vector2d(onSketchPos.x, corner1.y);
|
| | corner4 = Base::Vector2d(corner1.x, onSketchPos.y);
|
| | cornersReversed = false;
|
| | }
|
| | else {
|
| | corner4 = Base::Vector2d(onSketchPos.x, corner1.y);
|
| | corner2 = Base::Vector2d(corner1.x, onSketchPos.y);
|
| | cornersReversed = true;
|
| | }
|
| | angle123 = pi / 2;
|
| | angle412 = pi / 2;
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | toolWidgetManager.drawDirectionAtCursor(onSketchPos, center);
|
| |
|
| | corner1 = center - (onSketchPos - center);
|
| | corner3 = onSketchPos;
|
| | if (Base::sgn(corner3.x - corner1.x) * Base::sgn(corner3.y - corner1.y) > 0) {
|
| | corner2 = Base::Vector2d(onSketchPos.x, corner1.y);
|
| | corner4 = Base::Vector2d(corner1.x, onSketchPos.y);
|
| | cornersReversed = false;
|
| | }
|
| | else {
|
| | corner4 = Base::Vector2d(onSketchPos.x, corner1.y);
|
| | corner2 = Base::Vector2d(corner1.x, onSketchPos.y);
|
| | cornersReversed = true;
|
| | }
|
| | angle123 = pi / 2;
|
| | angle412 = pi / 2;
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | toolWidgetManager.drawDirectionAtCursor(onSketchPos, corner1);
|
| |
|
| | corner2 = onSketchPos;
|
| | Base::Vector2d perpendicular;
|
| | perpendicular.x = -(corner2 - corner1).y;
|
| | perpendicular.y = (corner2 - corner1).x;
|
| | corner3 = corner2 + perpendicular;
|
| | corner4 = corner1 + perpendicular;
|
| | angle123 = pi / 2;
|
| | angle412 = pi / 2;
|
| | corner2Initial = corner2;
|
| | side = getPointSideOfVector(corner3, corner2 - corner1, corner1);
|
| | }
|
| | else {
|
| | toolWidgetManager.drawDirectionAtCursor(onSketchPos, center);
|
| |
|
| | corner1 = onSketchPos;
|
| | corner3 = center - (onSketchPos - center);
|
| | Base::Vector2d perpendicular;
|
| | perpendicular.x = -(onSketchPos - center).y;
|
| | perpendicular.y = (onSketchPos - center).x;
|
| | corner2 = center + perpendicular;
|
| | corner4 = center - perpendicular;
|
| | angle123 = pi / 2;
|
| | angle412 = pi / 2;
|
| | side = getPointSideOfVector(corner2, corner3 - corner1, corner1);
|
| | }
|
| |
|
| | if (roundCorners) {
|
| | length = (corner2 - corner1).Length();
|
| | width = (corner4 - corner1).Length();
|
| | radius = std::min(length, width) / 6;
|
| | }
|
| | else {
|
| | radius = 0.;
|
| | }
|
| |
|
| | try {
|
| | CreateAndDrawShapeGeometry();
|
| |
|
| | toolWidgetManager.drawWidthHeightAtCursor(onSketchPos, length, width);
|
| | }
|
| | catch (const Base::ValueError&) {
|
| | }
|
| |
|
| | seekAndRenderAutoConstraint(sugConstraints[1], onSketchPos, Base::Vector2d(0.0, 0.0));
|
| | } break;
|
| | case SelectMode::SeekThird: {
|
| | if (constructionMethod() == ConstructionMethod::Diagonal
|
| | || constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (roundCorners) {
|
| | calculateRadius(onSketchPos);
|
| | toolWidgetManager.drawDoubleAtCursor(onSketchPos, radius);
|
| | }
|
| | else {
|
| | calculateThickness(onSketchPos);
|
| | toolWidgetManager.drawDoubleAtCursor(onSketchPos, thickness);
|
| | }
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | corner2 = corner2Initial;
|
| | corner3 = onSketchPos;
|
| | if (side == getPointSideOfVector(corner3, corner2 - corner1, corner1)) {
|
| | corner4 = corner1 + (corner3 - corner2);
|
| | cornersReversed = false;
|
| | }
|
| | else {
|
| | corner4 = corner2;
|
| | corner2 = corner1 + (corner3 - corner4);
|
| | cornersReversed = true;
|
| | }
|
| | Base::Vector2d a = corner1 - corner2;
|
| | Base::Vector2d b = corner3 - corner2;
|
| | if (fabs((sqrt(a.x * a.x + a.y * a.y) * sqrt(b.x * b.x + b.y * b.y)))
|
| | > Precision::Confusion()) {
|
| | angle123 = acos(
|
| | (a.x * b.x + a.y * b.y)
|
| | / (sqrt(a.x * a.x + a.y * a.y) * sqrt(b.x * b.x + b.y * b.y))
|
| | );
|
| | }
|
| | angle412 = pi - angle123;
|
| | if (roundCorners) {
|
| | radius = std::min(length, width) / 6
|
| | * std::min(
|
| | sqrt(1 - cos(angle412) * cos(angle412)),
|
| | sqrt(1 - cos(angle123) * cos(angle123))
|
| | );
|
| | }
|
| | else {
|
| | radius = 0.;
|
| | }
|
| |
|
| | toolWidgetManager.drawWidthHeightAtCursor(onSketchPos, length, width);
|
| | }
|
| | else {
|
| | corner2 = onSketchPos;
|
| | corner4 = center - (onSketchPos - center);
|
| | cornersReversed = false;
|
| | if (side != getPointSideOfVector(corner2, corner3 - corner1, corner1)) {
|
| | corner4 = onSketchPos;
|
| | corner2 = center - (onSketchPos - center);
|
| | cornersReversed = true;
|
| | }
|
| | Base::Vector2d a = corner4 - corner1;
|
| | Base::Vector2d b = corner2 - corner1;
|
| | if (fabs((sqrt(a.x * a.x + a.y * a.y) * sqrt(b.x * b.x + b.y * b.y)))
|
| | > Precision::Confusion()) {
|
| | angle412 = acos(
|
| | (a.x * b.x + a.y * b.y)
|
| | / (sqrt(a.x * a.x + a.y * a.y) * sqrt(b.x * b.x + b.y * b.y))
|
| | );
|
| | }
|
| | angle123 = pi - angle412;
|
| | if (roundCorners) {
|
| | radius = std::min(length, width) / 6
|
| | * std::min(
|
| | sqrt(1 - cos(angle412) * cos(angle412)),
|
| | sqrt(1 - cos(angle123) * cos(angle123))
|
| | );
|
| | }
|
| | else {
|
| | radius = 0.;
|
| | }
|
| |
|
| | toolWidgetManager.drawWidthHeightAtCursor(onSketchPos, length, width);
|
| | }
|
| |
|
| | try {
|
| | CreateAndDrawShapeGeometry();
|
| | }
|
| | catch (const Base::ValueError&) {
|
| | }
|
| |
|
| | if ((constructionMethod() == ConstructionMethod::ThreePoints
|
| | || constructionMethod() == ConstructionMethod::CenterAnd3Points)) {
|
| | seekAndRenderAutoConstraint(sugConstraints[2], onSketchPos, Base::Vector2d(0.0, 0.0));
|
| | }
|
| | } break;
|
| | case SelectMode::SeekFourth: {
|
| | if (constructionMethod() == ConstructionMethod::Diagonal
|
| | || constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | calculateThickness(onSketchPos);
|
| | toolWidgetManager.drawDoubleAtCursor(onSketchPos, thickness);
|
| | }
|
| | else {
|
| | if (roundCorners) {
|
| | calculateRadius(onSketchPos);
|
| | toolWidgetManager.drawDoubleAtCursor(onSketchPos, radius);
|
| | }
|
| | else {
|
| | calculateThickness(onSketchPos);
|
| | toolWidgetManager.drawDoubleAtCursor(onSketchPos, thickness);
|
| | }
|
| | }
|
| |
|
| | CreateAndDrawShapeGeometry();
|
| | } break;
|
| | case SelectMode::SeekFifth: {
|
| | calculateThickness(onSketchPos);
|
| | toolWidgetManager.drawDoubleAtCursor(onSketchPos, thickness);
|
| |
|
| | CreateAndDrawShapeGeometry();
|
| | } break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| | void executeCommands() override
|
| | {
|
| | try {
|
| | firstCurve = getHighestCurveIndex() + 1;
|
| |
|
| | createShape(false);
|
| |
|
| | Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add sketch box"));
|
| |
|
| | commandAddShapeGeometryAndConstraints();
|
| |
|
| | Gui::Command::commitCommand();
|
| | }
|
| | catch (const Base::Exception&) {
|
| | Gui::NotifyError(
|
| | sketchgui,
|
| | QT_TRANSLATE_NOOP("Notifications", "Error"),
|
| | QT_TRANSLATE_NOOP("Notifications", "Failed to add box")
|
| | );
|
| |
|
| | Gui::Command::abortCommand();
|
| | THROWM(
|
| | Base::RuntimeError,
|
| | QT_TRANSLATE_NOOP(
|
| | "Notifications",
|
| | "Tool execution aborted"
|
| | ) "\n"
|
| | )
|
| |
|
| | }
|
| |
|
| | thickness = 0.;
|
| | }
|
| |
|
| | void generateAutoConstraints() override
|
| | {
|
| |
|
| | if (constructionMethod() == ConstructionMethod::Diagonal) {
|
| |
|
| | if (radius > Precision::Confusion()) {
|
| | if (!sugConstraints[0].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[0],
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | if (!sugConstraints[1].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | }
|
| | else {
|
| | if (!sugConstraints[0].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[0],
|
| | firstCurve,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | if (!sugConstraints[1].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | firstCurve + 1,
|
| | Sketcher::PointPos::end
|
| | );
|
| | }
|
| | }
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| |
|
| | if (!sugConstraints[0].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[0],
|
| | centerPointId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| |
|
| | if (!sugConstraints[1].empty()) {
|
| | if (radius > Precision::Confusion()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | else {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | firstCurve + 1,
|
| | Sketcher::PointPos::end
|
| | );
|
| | }
|
| | }
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | if (radius > Precision::Confusion()) {
|
| | if (!sugConstraints[0].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[0],
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | if (!sugConstraints[1].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | if (!sugConstraints[2].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[2],
|
| | constructionPointThreeId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | }
|
| | else {
|
| | if (!sugConstraints[0].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[0],
|
| | firstCurve,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | if (!sugConstraints[1].empty()) {
|
| | if (!cornersReversed) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | firstCurve + 1,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | else {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | firstCurve + 3,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | }
|
| |
|
| | if (!sugConstraints[2].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[2],
|
| | firstCurve + 2,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | }
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| |
|
| | if (!sugConstraints[0].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[0],
|
| | centerPointId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| |
|
| | if (radius > Precision::Confusion()) {
|
| | if (!sugConstraints[1].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | if (!sugConstraints[2].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[2],
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | }
|
| | else {
|
| | if (!sugConstraints[1].empty()) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[1],
|
| | firstCurve,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | if (!sugConstraints[2].empty()) {
|
| | if (!cornersReversed) {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[2],
|
| | firstCurve + 1,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | else {
|
| | generateAutoConstraintsOnElement(
|
| | sugConstraints[2],
|
| | firstCurve + 3,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| | removeRedundantAutoConstraints();
|
| | }
|
| |
|
| | void createAutoConstraints() override
|
| | {
|
| | createGeneratedAutoConstraints(true);
|
| |
|
| | sugConstraints[0].clear();
|
| | sugConstraints[1].clear();
|
| | }
|
| |
|
| | std::string getToolName() const override
|
| | {
|
| | return "DSH_Rectangle";
|
| | }
|
| |
|
| | QString getCrosshairCursorSVGName() const override
|
| | {
|
| | if (!roundCorners && !makeFrame) {
|
| | if (constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | return QStringLiteral("Sketcher_Pointer_Create_Box_Center");
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | return QStringLiteral("Sketcher_Pointer_Create_Box_3Points");
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | return QStringLiteral("Sketcher_Pointer_Create_Box_3Points_Center");
|
| | }
|
| | else {
|
| | return QStringLiteral("Sketcher_Pointer_Create_Box");
|
| | }
|
| | }
|
| | else if (roundCorners && !makeFrame) {
|
| | if (constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | return QStringLiteral("Sketcher_Pointer_Oblong_Center");
|
| | }
|
| | else {
|
| | return QStringLiteral("Sketcher_Pointer_Oblong");
|
| | }
|
| | }
|
| | else if (!roundCorners && makeFrame) {
|
| | if (constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | return QStringLiteral("Sketcher_Pointer_Create_Frame_Center");
|
| | }
|
| | else {
|
| | return QStringLiteral("Sketcher_Pointer_Create_Frame");
|
| | }
|
| | }
|
| | else {
|
| | if (constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | return QStringLiteral("Sketcher_Pointer_Oblong_Frame_Center");
|
| | }
|
| | else {
|
| | return QStringLiteral("Sketcher_Pointer_Oblong_Frame");
|
| | }
|
| | }
|
| | }
|
| |
|
| | std::unique_ptr<QWidget> createWidget() const override
|
| | {
|
| | return std::make_unique<SketcherToolDefaultWidget>();
|
| | }
|
| |
|
| | bool isWidgetVisible() const override
|
| | {
|
| | return true;
|
| | };
|
| |
|
| | QPixmap getToolIcon() const override
|
| | {
|
| | return Gui::BitmapFactory().pixmap("Sketcher_CreateRectangle");
|
| | }
|
| |
|
| | QString getToolWidgetText() const override
|
| | {
|
| | return QString(tr("Rectangle Parameters"));
|
| | }
|
| |
|
| | void angleSnappingControl() override
|
| | {
|
| | if ((constructionMethod() == ConstructionMethod::ThreePoints)
|
| | && state() == SelectMode::SeekSecond) {
|
| | setAngleSnapping(true, corner1);
|
| | }
|
| | else if ((constructionMethod() == ConstructionMethod::CenterAnd3Points)
|
| | && state() == SelectMode::SeekSecond) {
|
| | setAngleSnapping(true, center);
|
| | }
|
| | else if ((constructionMethod() == ConstructionMethod::ThreePoints)
|
| | && state() == SelectMode::SeekThird) {
|
| | setAngleSnapping(true, cornersReversed ? corner4 : corner2);
|
| | }
|
| | else if ((constructionMethod() == ConstructionMethod::CenterAnd3Points)
|
| | && state() == SelectMode::SeekThird) {
|
| | setAngleSnapping(true, corner1);
|
| | }
|
| |
|
| | else {
|
| | setAngleSnapping(false);
|
| | }
|
| | }
|
| |
|
| | bool canGoToNextMode() override
|
| | {
|
| | if (state() == SelectMode::SeekSecond
|
| | && (length < Precision::Confusion() || width < Precision::Confusion())) {
|
| | return false;
|
| | }
|
| |
|
| | return true;
|
| | }
|
| |
|
| |
|
| | void onButtonPressed(Base::Vector2d onSketchPos) override
|
| | {
|
| | this->updateDataAndDrawToPosition(onSketchPos);
|
| |
|
| | if (canGoToNextMode()) {
|
| | if (constructionMethod() == ConstructionMethod::Diagonal
|
| | || constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (state() == SelectMode::SeekSecond && !roundCorners && !makeFrame) {
|
| | setState(SelectMode::End);
|
| | }
|
| | else if ((state() == SelectMode::SeekThird && roundCorners && !makeFrame)
|
| | || (state() == SelectMode::SeekThird && !roundCorners && makeFrame)) {
|
| | setState(SelectMode::End);
|
| | }
|
| | else if (state() == SelectMode::SeekFourth) {
|
| | setState(SelectMode::End);
|
| | }
|
| | else {
|
| | this->moveToNextMode();
|
| | }
|
| | }
|
| | else {
|
| | if (state() == SelectMode::SeekThird && !roundCorners && !makeFrame) {
|
| | setState(SelectMode::End);
|
| | }
|
| | else if ((state() == SelectMode::SeekFourth && roundCorners && !makeFrame)
|
| | || (state() == SelectMode::SeekFourth && !roundCorners && makeFrame)) {
|
| | setState(SelectMode::End);
|
| | }
|
| | else {
|
| | this->moveToNextMode();
|
| | }
|
| | }
|
| | }
|
| | }
|
| |
|
| | void onReset() override
|
| | {
|
| | thickness = 0.;
|
| | lengthSign = 0;
|
| | widthSign = 0;
|
| | toolWidgetManager.resetControls();
|
| | }
|
| |
|
| | private:
|
| | Base::Vector2d center, corner1, corner2, corner3, corner4, frameCorner1, frameCorner2,
|
| | frameCorner3, frameCorner4, corner2Initial;
|
| | Base::Vector3d center1, center2, center3, center4;
|
| | bool roundCorners, makeFrame, cornersReversed;
|
| | double radius, length, width, thickness, radiusFrame, angle, angle123, angle412;
|
| | int firstCurve, constructionPointOneId, constructionPointTwoId, constructionPointThreeId,
|
| | centerPointId, side;
|
| |
|
| |
|
| |
|
| | int lengthSign, widthSign;
|
| |
|
| | void createShape(bool onlyeditoutline) override
|
| | {
|
| | ShapeGeometry.clear();
|
| |
|
| | Base::Vector2d vecL = corner2 - corner1;
|
| | Base::Vector2d vecW = corner4 - corner1;
|
| | length = vecL.Length();
|
| | width = vecW.Length();
|
| | angle = vecL.Angle();
|
| | if (length < Precision::Confusion() || width < Precision::Confusion()
|
| | || fmod(fabs(angle123), std::numbers::pi) < Precision::Confusion()) {
|
| | return;
|
| | }
|
| |
|
| | vecL = vecL / length;
|
| | vecW = vecW / width;
|
| | double L1 = radius;
|
| | double L2 = radius;
|
| | if (cos(angle123 / 2) != 1 && cos(angle412 / 2) != 1) {
|
| | L1 = radius / sqrt(1 - cos(angle123 / 2) * cos(angle123 / 2));
|
| | L2 = radius / sqrt(1 - cos(angle412 / 2) * cos(angle412 / 2));
|
| | }
|
| |
|
| | createFirstRectangleGeometries(vecL, vecW, L1, L2);
|
| |
|
| | bool thicknessNotZero = fabs(thickness) > Precision::Confusion();
|
| | bool negThicknessEqualRadius = fabs(radius + thickness) < Precision::Confusion();
|
| | if (makeFrame && state() != SelectMode::SeekSecond && thicknessNotZero) {
|
| | createSecondRectangleGeometries(vecL, vecW, L1, L2);
|
| | }
|
| |
|
| | if (!onlyeditoutline) {
|
| | ShapeConstraints.clear();
|
| |
|
| | if (radius > Precision::Confusion()) {
|
| | finishOblongCreation(thicknessNotZero, negThicknessEqualRadius);
|
| | }
|
| | else {
|
| | finishRectangleCreation(thicknessNotZero);
|
| | }
|
| | }
|
| | }
|
| |
|
| | void createFirstRectangleGeometries(Base::Vector2d vecL, Base::Vector2d vecW, double L1, double L2)
|
| | {
|
| | createFirstRectangleLines(vecL, vecW, L1, L2);
|
| |
|
| | if (roundCorners && radius > Precision::Confusion()) {
|
| | createFirstRectangleFillets(vecL, vecW, L1, L2);
|
| | }
|
| | }
|
| |
|
| | void createFirstRectangleLines(Base::Vector2d vecL, Base::Vector2d vecW, double L1, double L2)
|
| | {
|
| | addLineToShapeGeometry(
|
| | toVector3d(corner1 + vecL * L2 * cos(angle412 / 2)),
|
| | toVector3d(corner2 - vecL * L1 * cos(angle123 / 2)),
|
| | isConstructionMode()
|
| | );
|
| | addLineToShapeGeometry(
|
| | toVector3d(corner2 + vecW * L1 * cos(angle123 / 2)),
|
| | toVector3d(corner3 - vecW * L2 * cos(angle412 / 2)),
|
| | isConstructionMode()
|
| | );
|
| | addLineToShapeGeometry(
|
| | toVector3d(corner3 - vecL * L2 * cos(angle412 / 2)),
|
| | toVector3d(corner4 + vecL * L1 * cos(angle123 / 2)),
|
| | isConstructionMode()
|
| | );
|
| | addLineToShapeGeometry(
|
| | toVector3d(corner4 - vecW * L1 * cos(angle123 / 2)),
|
| | toVector3d(corner1 + vecW * L2 * cos(angle412 / 2)),
|
| | isConstructionMode()
|
| | );
|
| | }
|
| |
|
| | void createFirstRectangleFillets(Base::Vector2d vecL, Base::Vector2d vecW, double L1, double L2)
|
| | {
|
| | using std::numbers::pi;
|
| |
|
| |
|
| |
|
| | double end = angle - pi / 2;
|
| |
|
| | Base::Vector2d b1 = (vecL + vecW) / (vecL + vecW).Length();
|
| | Base::Vector2d b2 = (vecL - vecW) / (vecL - vecW).Length();
|
| | center1 = toVector3d(corner1 + b1 * L2);
|
| | center2 = toVector3d(corner2 - b2 * L1);
|
| | center3 = toVector3d(corner3 - b1 * L2);
|
| | center4 = toVector3d(corner4 + b2 * L1);
|
| |
|
| | addArcToShapeGeometry(center1, end - pi + angle412, end, radius, isConstructionMode());
|
| | addArcToShapeGeometry(center2, end, end - pi - angle123, radius, isConstructionMode());
|
| | addArcToShapeGeometry(center3, end + angle412, end - pi, radius, isConstructionMode());
|
| | addArcToShapeGeometry(center4, end - pi, end - angle123, radius, isConstructionMode());
|
| | }
|
| |
|
| | void createSecondRectangleGeometries(Base::Vector2d vecL, Base::Vector2d vecW, double L1, double L2)
|
| | {
|
| | using std::numbers::pi;
|
| |
|
| | double end = angle - pi / 2;
|
| |
|
| | if (radius < Precision::Confusion()) {
|
| | radiusFrame = 0.;
|
| | }
|
| | else {
|
| | radiusFrame = radius + thickness;
|
| | if (radiusFrame < 0.) {
|
| | radiusFrame = 0.;
|
| | }
|
| | }
|
| |
|
| | Base::Vector2d vecLF = frameCorner2 - frameCorner1;
|
| | Base::Vector2d vecWF = frameCorner4 - frameCorner1;
|
| | double lengthF = vecLF.Length();
|
| | double widthF = vecWF.Length();
|
| |
|
| | double L1F = 0.;
|
| | double L2F = 0.;
|
| | if (radius > Precision::Confusion()) {
|
| | L1F = L1 * radiusFrame / radius;
|
| | L2F = L2 * radiusFrame / radius;
|
| | }
|
| |
|
| | addLineToShapeGeometry(
|
| | toVector3d(frameCorner1 + vecLF / lengthF * L2F * cos(angle412 / 2)),
|
| | toVector3d(frameCorner2 - vecLF / lengthF * L1F * cos(angle123 / 2)),
|
| | isConstructionMode()
|
| | );
|
| | addLineToShapeGeometry(
|
| | toVector3d(frameCorner2 + vecWF / widthF * L1F * cos(angle123 / 2)),
|
| | toVector3d(frameCorner3 - vecWF / widthF * L2F * cos(angle412 / 2)),
|
| | isConstructionMode()
|
| | );
|
| | addLineToShapeGeometry(
|
| | toVector3d(frameCorner3 - vecLF / lengthF * L2F * cos(angle412 / 2)),
|
| | toVector3d(frameCorner4 + vecLF / lengthF * L1F * cos(angle123 / 2)),
|
| | isConstructionMode()
|
| | );
|
| | addLineToShapeGeometry(
|
| | toVector3d(frameCorner4 - vecWF / widthF * L1F * cos(angle123 / 2)),
|
| | toVector3d(frameCorner1 + vecWF / widthF * L2F * cos(angle412 / 2)),
|
| | isConstructionMode()
|
| | );
|
| |
|
| | if (roundCorners && radiusFrame > Precision::Confusion()) {
|
| | Base::Vector2d b1 = (vecL + vecW) / (vecL + vecW).Length();
|
| | Base::Vector2d b2 = (vecL - vecW) / (vecL - vecW).Length();
|
| |
|
| | addArcToShapeGeometry(
|
| | toVector3d(frameCorner1 + b1 * L2F),
|
| | end - pi + angle412,
|
| | end,
|
| | radiusFrame,
|
| | isConstructionMode()
|
| | );
|
| | addArcToShapeGeometry(
|
| | toVector3d(frameCorner2 - b2 * L1F),
|
| | end,
|
| | end - pi - angle123,
|
| | radiusFrame,
|
| | isConstructionMode()
|
| | );
|
| | addArcToShapeGeometry(
|
| | toVector3d(frameCorner3 - b1 * L2F),
|
| | end + angle412,
|
| | end - pi,
|
| | radiusFrame,
|
| | isConstructionMode()
|
| | );
|
| | addArcToShapeGeometry(
|
| | toVector3d(frameCorner4 + b2 * L1F),
|
| | end - pi,
|
| | end - angle123,
|
| | radiusFrame,
|
| | isConstructionMode()
|
| | );
|
| | }
|
| | }
|
| |
|
| |
|
| | void finishOblongCreation(bool thicknessNotZero, bool negThicknessEqualRadius)
|
| | {
|
| | addTangentCoincidences(firstCurve);
|
| |
|
| | addAlignmentConstraints();
|
| |
|
| | addArcEqualities();
|
| |
|
| | if (thicknessNotZero) {
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | if (radiusFrame < Precision::Confusion()) {
|
| | addRectangleCoincidences(firstCurve + 8);
|
| |
|
| |
|
| | if (negThicknessEqualRadius) {
|
| | finishOblongFrameCase1();
|
| | }
|
| | else {
|
| | finishOblongFrameCase2();
|
| | }
|
| | }
|
| | else {
|
| | finishOblongFrameCase3();
|
| | }
|
| | }
|
| |
|
| | if (constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | finishOblongThreePoints(thicknessNotZero, negThicknessEqualRadius);
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | finishOblongCenterAnd3Points(thicknessNotZero, negThicknessEqualRadius);
|
| | }
|
| | else if (constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | finishOblongCenterAndCorner(thicknessNotZero, negThicknessEqualRadius);
|
| | }
|
| | else {
|
| | finishOblongDiagonal(thicknessNotZero, negThicknessEqualRadius);
|
| | }
|
| | }
|
| |
|
| | void finishOblongFrameCase1()
|
| | {
|
| |
|
| |
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 8,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 4,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 9,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 5,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 10,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 6,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 11,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 7,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | }
|
| |
|
| | void finishOblongFrameCase2()
|
| | {
|
| |
|
| |
|
| | addFrameAlignmentConstraints(firstCurve + 8);
|
| |
|
| | addLineToShapeGeometry(center1, Base::Vector3d(frameCorner1.x, frameCorner1.y, 0.), true);
|
| | addLineToShapeGeometry(center2, Base::Vector3d(frameCorner2.x, frameCorner2.y, 0.), true);
|
| | addLineToShapeGeometry(center3, Base::Vector3d(frameCorner3.x, frameCorner3.y, 0.), true);
|
| | addLineToShapeGeometry(center4, Base::Vector3d(frameCorner4.x, frameCorner4.y, 0.), true);
|
| |
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 12,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 4,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 12,
|
| | Sketcher::PointPos::end,
|
| | firstCurve + 8,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 13,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 5,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 13,
|
| | Sketcher::PointPos::end,
|
| | firstCurve + 9,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 14,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 6,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 14,
|
| | Sketcher::PointPos::end,
|
| | firstCurve + 10,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 15,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 7,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 15,
|
| | Sketcher::PointPos::end,
|
| | firstCurve + 11,
|
| | Sketcher::PointPos::start
|
| | );
|
| |
|
| | addToShapeConstraints(
|
| | Sketcher::Perpendicular,
|
| | firstCurve + 12,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 13
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Perpendicular,
|
| | firstCurve + 13,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 14
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Perpendicular,
|
| | firstCurve + 14,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 15
|
| | );
|
| | }
|
| |
|
| | void finishOblongFrameCase3()
|
| | {
|
| | addTangentCoincidences(firstCurve + 8);
|
| |
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 4,
|
| | Sketcher::PointPos::mid,
|
| | firstCurve + 12,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 5,
|
| | Sketcher::PointPos::mid,
|
| | firstCurve + 13,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 6,
|
| | Sketcher::PointPos::mid,
|
| | firstCurve + 14,
|
| | Sketcher::PointPos::mid
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 7,
|
| | Sketcher::PointPos::mid,
|
| | firstCurve + 15,
|
| | Sketcher::PointPos::mid
|
| | );
|
| |
|
| | addFrameAlignmentConstraints(firstCurve + 8, false);
|
| | }
|
| |
|
| | void finishOblongThreePoints(bool thicknessNotZero, bool negThicknessEqualRadius)
|
| | {
|
| | if (thicknessNotZero) {
|
| | if (negThicknessEqualRadius) {
|
| | constructionPointOneId = firstCurve + 12;
|
| | constructionPointTwoId = firstCurve + 13;
|
| | constructionPointThreeId = firstCurve + 14;
|
| | }
|
| | else {
|
| | constructionPointOneId = firstCurve + 16;
|
| | constructionPointTwoId = firstCurve + 17;
|
| | constructionPointThreeId = firstCurve + 18;
|
| | }
|
| | }
|
| | else {
|
| | constructionPointOneId = firstCurve + 8;
|
| | constructionPointTwoId = firstCurve + 9;
|
| | constructionPointThreeId = firstCurve + 10;
|
| | }
|
| |
|
| | addPointToShapeGeometry(Base::Vector3d(corner1.x, corner1.y, 0.), true);
|
| | if (!cornersReversed) {
|
| | addPointToShapeGeometry(Base::Vector3d(corner2.x, corner2.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 1
|
| | );
|
| | }
|
| | else {
|
| | addPointToShapeGeometry(Base::Vector3d(corner4.x, corner4.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 2
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 3
|
| | );
|
| | }
|
| | addPointToShapeGeometry(Base::Vector3d(corner3.x, corner3.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 3
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointThreeId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 1
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointThreeId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 2
|
| | );
|
| | }
|
| |
|
| | void finishOblongCenterAnd3Points(bool thicknessNotZero, bool negThicknessEqualRadius)
|
| | {
|
| | if (thicknessNotZero) {
|
| | if (negThicknessEqualRadius) {
|
| | constructionPointOneId = firstCurve + 12;
|
| | constructionPointTwoId = firstCurve + 13;
|
| | centerPointId = firstCurve + 14;
|
| | }
|
| | else {
|
| | constructionPointOneId = firstCurve + 16;
|
| | constructionPointTwoId = firstCurve + 17;
|
| | centerPointId = firstCurve + 18;
|
| | }
|
| | }
|
| | else {
|
| | constructionPointOneId = firstCurve + 8;
|
| | constructionPointTwoId = firstCurve + 9;
|
| | centerPointId = firstCurve + 10;
|
| | }
|
| |
|
| | addPointToShapeGeometry(Base::Vector3d(corner1.x, corner1.y, 0.), true);
|
| | if (!cornersReversed) {
|
| | addPointToShapeGeometry(Base::Vector3d(corner2.x, corner2.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 1
|
| | );
|
| | }
|
| | else {
|
| | addPointToShapeGeometry(Base::Vector3d(corner4.x, corner4.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 2
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 3
|
| | );
|
| | }
|
| | addPointToShapeGeometry(Base::Vector3d(center.x, center.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::Symmetric,
|
| | firstCurve + 2,
|
| | Sketcher::PointPos::start,
|
| | firstCurve,
|
| | Sketcher::PointPos::start,
|
| | centerPointId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 3
|
| | );
|
| | }
|
| |
|
| | void finishOblongCenterAndCorner(bool thicknessNotZero, bool negThicknessEqualRadius)
|
| | {
|
| | if (thicknessNotZero) {
|
| | if (negThicknessEqualRadius) {
|
| | constructionPointOneId = firstCurve + 12;
|
| | centerPointId = firstCurve + 13;
|
| | }
|
| | else {
|
| | constructionPointOneId = firstCurve + 16;
|
| | centerPointId = firstCurve + 17;
|
| | }
|
| | }
|
| | else {
|
| | constructionPointOneId = firstCurve + 8;
|
| | centerPointId = firstCurve + 9;
|
| | }
|
| |
|
| | addPointToShapeGeometry(Base::Vector3d(corner3.x, corner3.y, 0.), true);
|
| | addPointToShapeGeometry(Base::Vector3d(center.x, center.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::Symmetric,
|
| | firstCurve + 2,
|
| | Sketcher::PointPos::start,
|
| | firstCurve,
|
| | Sketcher::PointPos::start,
|
| | centerPointId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 1
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 2
|
| | );
|
| | }
|
| |
|
| | void finishOblongDiagonal(bool thicknessNotZero, bool negThicknessEqualRadius)
|
| | {
|
| | if (thicknessNotZero) {
|
| | if (negThicknessEqualRadius) {
|
| | constructionPointOneId = firstCurve + 12;
|
| | constructionPointTwoId = firstCurve + 13;
|
| | }
|
| | else {
|
| | constructionPointOneId = firstCurve + 16;
|
| | constructionPointTwoId = firstCurve + 17;
|
| | }
|
| | }
|
| | else {
|
| | constructionPointOneId = firstCurve + 8;
|
| | constructionPointTwoId = firstCurve + 9;
|
| | }
|
| |
|
| | addPointToShapeGeometry(Base::Vector3d(corner1.x, corner1.y, 0.), true);
|
| | addPointToShapeGeometry(Base::Vector3d(corner3.x, corner3.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointOneId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 3
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 1
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::PointOnObject,
|
| | constructionPointTwoId,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 2
|
| | );
|
| | }
|
| |
|
| | void addTangentCoincidences(int geoId)
|
| | {
|
| | addToShapeConstraints(
|
| | Sketcher::Tangent,
|
| | geoId,
|
| | Sketcher::PointPos::start,
|
| | geoId + 4,
|
| | Sketcher::PointPos::end
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Tangent,
|
| | geoId,
|
| | Sketcher::PointPos::end,
|
| | geoId + 5,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Tangent,
|
| | geoId + 1,
|
| | Sketcher::PointPos::start,
|
| | geoId + 5,
|
| | Sketcher::PointPos::end
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Tangent,
|
| | geoId + 1,
|
| | Sketcher::PointPos::end,
|
| | geoId + 6,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Tangent,
|
| | geoId + 2,
|
| | Sketcher::PointPos::start,
|
| | geoId + 6,
|
| | Sketcher::PointPos::end
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Tangent,
|
| | geoId + 2,
|
| | Sketcher::PointPos::end,
|
| | geoId + 7,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Tangent,
|
| | geoId + 3,
|
| | Sketcher::PointPos::start,
|
| | geoId + 7,
|
| | Sketcher::PointPos::end
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Tangent,
|
| | geoId + 3,
|
| | Sketcher::PointPos::end,
|
| | geoId + 4,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | void addArcEqualities()
|
| | {
|
| | addToShapeConstraints(
|
| | Sketcher::Equal,
|
| | firstCurve + 4,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 5
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Equal,
|
| | firstCurve + 5,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 6
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Equal,
|
| | firstCurve + 6,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 7
|
| | );
|
| | }
|
| |
|
| | void finishRectangleCreation(bool thicknessNotZero)
|
| | {
|
| | addRectangleCoincidences(firstCurve);
|
| |
|
| | addAlignmentConstraints();
|
| |
|
| | if (thicknessNotZero) {
|
| | finishRectangleFrameCreation();
|
| | }
|
| |
|
| | if (constructionMethod() == ConstructionMethod::CenterAndCorner
|
| | || constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | finishCenteredRectangleCreation(thicknessNotZero);
|
| | }
|
| | }
|
| |
|
| | void addRectangleCoincidences(int geoId)
|
| | {
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | geoId,
|
| | Sketcher::PointPos::end,
|
| | geoId + 1,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | geoId + 1,
|
| | Sketcher::PointPos::end,
|
| | geoId + 2,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | geoId + 2,
|
| | Sketcher::PointPos::end,
|
| | geoId + 3,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | geoId + 3,
|
| | Sketcher::PointPos::end,
|
| | geoId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| | void addAlignmentConstraints()
|
| | {
|
| | Sketcher::ConstraintType typeA = Sketcher::Horizontal;
|
| | Sketcher::ConstraintType typeB = Sketcher::Vertical;
|
| | if (Base::sgn(corner3.x - corner1.x) * Base::sgn(corner3.y - corner1.y) < 0) {
|
| | typeA = Sketcher::Vertical;
|
| | typeB = Sketcher::Horizontal;
|
| | }
|
| |
|
| | if (fabs(angle) < Precision::Confusion() || constructionMethod() == ConstructionMethod::Diagonal
|
| | || constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | addToShapeConstraints(typeA, firstCurve);
|
| | addToShapeConstraints(typeA, firstCurve + 2);
|
| | addToShapeConstraints(typeB, firstCurve + 1);
|
| | addToShapeConstraints(typeB, firstCurve + 3);
|
| | }
|
| | else {
|
| | addToShapeConstraints(
|
| | Sketcher::Parallel,
|
| | firstCurve,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 2
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Parallel,
|
| | firstCurve + 1,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 3
|
| | );
|
| | if (fabs(angle123 - std::numbers::pi / 2) < Precision::Confusion()) {
|
| | addToShapeConstraints(
|
| | Sketcher::Perpendicular,
|
| | firstCurve,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 1
|
| | );
|
| | }
|
| | }
|
| | }
|
| |
|
| | void finishRectangleFrameCreation()
|
| | {
|
| | addRectangleCoincidences(firstCurve + 4);
|
| |
|
| | addFrameAlignmentConstraints(firstCurve + 4);
|
| |
|
| | addRectangleFrameConstructionLines();
|
| | }
|
| |
|
| | void addFrameAlignmentConstraints(int geoId, bool addLast = true)
|
| | {
|
| | Sketcher::ConstraintType typeA = Sketcher::Horizontal;
|
| | Sketcher::ConstraintType typeB = Sketcher::Vertical;
|
| | if (Base::sgn(corner3.x - corner1.x) * Base::sgn(corner3.y - corner1.y) < 0) {
|
| | typeA = Sketcher::Vertical;
|
| | typeB = Sketcher::Horizontal;
|
| | }
|
| |
|
| | if (fabs(angle) < Precision::Confusion() || constructionMethod() == ConstructionMethod::Diagonal
|
| | || constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | addToShapeConstraints(typeA, geoId);
|
| | addToShapeConstraints(typeA, geoId + 2);
|
| | addToShapeConstraints(typeB, geoId + 1);
|
| | if (addLast) {
|
| | addToShapeConstraints(typeB, geoId + 3);
|
| | }
|
| | }
|
| | else {
|
| | addToShapeConstraints(
|
| | Sketcher::Parallel,
|
| | geoId,
|
| | Sketcher::PointPos::none,
|
| | geoId + 2
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Parallel,
|
| | geoId + 1,
|
| | Sketcher::PointPos::none,
|
| | geoId + 3
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Parallel,
|
| | firstCurve,
|
| | Sketcher::PointPos::none,
|
| | geoId
|
| | );
|
| | if (addLast) {
|
| | addToShapeConstraints(
|
| | Sketcher::Parallel,
|
| | firstCurve + 1,
|
| | Sketcher::PointPos::none,
|
| | geoId + 1
|
| | );
|
| | }
|
| | }
|
| | }
|
| |
|
| | void addRectangleFrameConstructionLines()
|
| | {
|
| | addLineToShapeGeometry(
|
| | Base::Vector3d(corner1.x, corner1.y, 0.),
|
| | Base::Vector3d(frameCorner1.x, frameCorner1.y, 0.),
|
| | true
|
| | );
|
| | addLineToShapeGeometry(
|
| | Base::Vector3d(corner2.x, corner2.y, 0.),
|
| | Base::Vector3d(frameCorner2.x, frameCorner2.y, 0.),
|
| | true
|
| | );
|
| | addLineToShapeGeometry(
|
| | Base::Vector3d(corner3.x, corner3.y, 0.),
|
| | Base::Vector3d(frameCorner3.x, frameCorner3.y, 0.),
|
| | true
|
| | );
|
| | addLineToShapeGeometry(
|
| | Base::Vector3d(corner4.x, corner4.y, 0.),
|
| | Base::Vector3d(frameCorner4.x, frameCorner4.y, 0.),
|
| | true
|
| | );
|
| |
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 8,
|
| | Sketcher::PointPos::start,
|
| | firstCurve,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 8,
|
| | Sketcher::PointPos::end,
|
| | firstCurve + 4,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 9,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 1,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 9,
|
| | Sketcher::PointPos::end,
|
| | firstCurve + 5,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 10,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 2,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 10,
|
| | Sketcher::PointPos::end,
|
| | firstCurve + 6,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 11,
|
| | Sketcher::PointPos::start,
|
| | firstCurve + 3,
|
| | Sketcher::PointPos::start
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Coincident,
|
| | firstCurve + 11,
|
| | Sketcher::PointPos::end,
|
| | firstCurve + 7,
|
| | Sketcher::PointPos::start
|
| | );
|
| |
|
| | addToShapeConstraints(
|
| | Sketcher::Perpendicular,
|
| | firstCurve + 8,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 9
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Perpendicular,
|
| | firstCurve + 9,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 10
|
| | );
|
| | addToShapeConstraints(
|
| | Sketcher::Perpendicular,
|
| | firstCurve + 10,
|
| | Sketcher::PointPos::none,
|
| | firstCurve + 11
|
| | );
|
| | }
|
| |
|
| | void finishCenteredRectangleCreation(bool thicknessNotZero)
|
| | {
|
| | if (thicknessNotZero) {
|
| | centerPointId = firstCurve + 12;
|
| | }
|
| | else {
|
| | centerPointId = firstCurve + 4;
|
| | }
|
| |
|
| | addPointToShapeGeometry(Base::Vector3d(center.x, center.y, 0.), true);
|
| | addToShapeConstraints(
|
| | Sketcher::Symmetric,
|
| | firstCurve + 2,
|
| | Sketcher::PointPos::start,
|
| | firstCurve,
|
| | Sketcher::PointPos::start,
|
| | centerPointId,
|
| | Sketcher::PointPos::start
|
| | );
|
| | }
|
| |
|
| |
|
| | int getPointSideOfVector(
|
| | Base::Vector2d pointToCheck,
|
| | Base::Vector2d separatingVector,
|
| | Base::Vector2d pointOnVector
|
| | )
|
| | {
|
| | Base::Vector2d secondPointOnVec = pointOnVector + separatingVector;
|
| | double d = (pointToCheck.x - pointOnVector.x) * (secondPointOnVec.y - pointOnVector.y)
|
| | - (pointToCheck.y - pointOnVector.y) * (secondPointOnVec.x - pointOnVector.x);
|
| | if (abs(d) < Precision::Confusion()) {
|
| | return 0;
|
| | }
|
| | else if (d < 0) {
|
| | return -1;
|
| | }
|
| | else {
|
| | return 1;
|
| | }
|
| | }
|
| |
|
| | void calculateRadius(Base::Vector2d onSketchPos)
|
| | {
|
| | Base::Vector2d u = (corner2 - corner1) / (corner2 - corner1).Length();
|
| | Base::Vector2d v = (corner4 - corner1) / (corner4 - corner1).Length();
|
| | Base::Vector2d e = onSketchPos - corner1;
|
| | double du = (v.y * e.x - v.x * e.y) / (u.x * v.y - u.y * v.x);
|
| | double dv = (-u.y * e.x + u.x * e.y) / (u.x * v.y - u.y * v.x);
|
| |
|
| | if (-Precision::Confusion() < du && du < 0) {
|
| | du = 0.0;
|
| | }
|
| | if (-Precision::Confusion() < dv && dv < 0) {
|
| | dv = 0.0;
|
| | }
|
| |
|
| | if (du < 0.0 || du > length || dv < 0.0 || dv > width) {
|
| | radius = 0.;
|
| | }
|
| | else {
|
| | if (du < length - du && dv < width - dv) {
|
| | radius = (du + dv
|
| | + std::max(
|
| | 2 * sqrt(du * dv) * sin(angle412 / 2),
|
| | -2 * sqrt(du * dv) * sin(angle412 / 2)
|
| | ))
|
| | * tan(angle412 / 2);
|
| | }
|
| | else if (du > length - du && dv < width - dv) {
|
| | du = length - du;
|
| | radius = (du + dv
|
| | + std::max(
|
| | 2 * sqrt(du * dv) * sin(angle123 / 2),
|
| | -2 * sqrt(du * dv) * sin(angle123 / 2)
|
| | ))
|
| | * tan(angle123 / 2);
|
| | }
|
| | else if (du < length - du && dv > width - dv) {
|
| | dv = width - dv;
|
| | radius = (du + dv
|
| | + std::max(
|
| | 2 * sqrt(du * dv) * sin(angle123 / 2),
|
| | -2 * sqrt(du * dv) * sin(angle123 / 2)
|
| | ))
|
| | * tan(angle123 / 2);
|
| | }
|
| | else {
|
| | du = length - du;
|
| | dv = width - dv;
|
| | radius = (du + dv
|
| | + std::max(
|
| | 2 * sqrt(du * dv) * sin(angle412 / 2),
|
| | -2 * sqrt(du * dv) * sin(angle412 / 2)
|
| | ))
|
| | * tan(angle412 / 2);
|
| | }
|
| | radius = std::min(
|
| | radius,
|
| | std::min(length * 0.999, width * 0.999)
|
| | / (cos(angle412 / 2) / sqrt(1 - cos(angle412 / 2) * cos(angle412 / 2))
|
| | + cos(angle123 / 2) / sqrt(1 - cos(angle123 / 2) * cos(angle123 / 2)))
|
| | );
|
| | }
|
| | }
|
| |
|
| | void calculateThickness(Base::Vector2d onSketchPos)
|
| | {
|
| |
|
| | Base::Vector2d u = (corner2 - corner1) / (corner2 - corner1).Length();
|
| | Base::Vector2d v = (corner4 - corner1) / (corner4 - corner1).Length();
|
| | Base::Vector2d e = onSketchPos - corner1;
|
| | double obliqueThickness = 0.;
|
| | double du = (v.y * e.x - v.x * e.y) / (u.x * v.y - u.y * v.x);
|
| | double dv = (-u.y * e.x + u.x * e.y) / (u.x * v.y - u.y * v.x);
|
| | if (du > 0 && du < length && !(dv > 0 && dv < width)) {
|
| | obliqueThickness = std::min(fabs(dv), fabs(width - dv));
|
| | }
|
| | else if (dv > 0 && dv < width && !(du > 0 && du < length)) {
|
| | obliqueThickness = std::min(fabs(du), fabs(length - du));
|
| | }
|
| | else if (du > 0 && du < length && dv > 0 && dv < width) {
|
| | obliqueThickness = -std::min(
|
| | std::min(fabs(du), fabs(length - du)),
|
| | std::min(fabs(dv), fabs(width - dv))
|
| | );
|
| | }
|
| | else {
|
| | obliqueThickness = std::max(
|
| | std::min(fabs(du), fabs(length - du)),
|
| | std::min(fabs(dv), fabs(width - dv))
|
| | );
|
| | }
|
| |
|
| |
|
| | frameCorner1 = corner1 - u * obliqueThickness - v * obliqueThickness;
|
| | frameCorner2 = corner2 + u * obliqueThickness - v * obliqueThickness;
|
| | frameCorner3 = corner3 + u * obliqueThickness + v * obliqueThickness;
|
| | frameCorner4 = corner4 - u * obliqueThickness + v * obliqueThickness;
|
| |
|
| | thickness = obliqueThickness * sin(angle412);
|
| | }
|
| | };
|
| |
|
| | template<>
|
| | auto DSHRectangleControllerBase::getState(int labelindex) const
|
| | {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | switch (labelindex) {
|
| | case OnViewParameter::First:
|
| | case OnViewParameter::Second:
|
| | return SelectMode::SeekFirst;
|
| | break;
|
| | case OnViewParameter::Third:
|
| | case OnViewParameter::Fourth:
|
| | return SelectMode::SeekSecond;
|
| | break;
|
| | case OnViewParameter::Fifth:
|
| | if (handler->roundCorners) {
|
| | return SelectMode::SeekThird;
|
| | }
|
| | else {
|
| | return SelectMode::End;
|
| | }
|
| | break;
|
| | case OnViewParameter::Sixth:
|
| | if (handler->makeFrame) {
|
| | if (!handler->roundCorners) {
|
| | return SelectMode::SeekThird;
|
| | }
|
| | else {
|
| | return SelectMode::SeekFourth;
|
| | }
|
| | }
|
| | else {
|
| | return SelectMode::End;
|
| | }
|
| | break;
|
| | default:
|
| | THROWM(Base::ValueError, "Parameter index without an associated machine state")
|
| | }
|
| | }
|
| | else {
|
| | switch (labelindex) {
|
| | case OnViewParameter::First:
|
| | case OnViewParameter::Second:
|
| | return SelectMode::SeekFirst;
|
| | break;
|
| | case OnViewParameter::Third:
|
| | case OnViewParameter::Fourth:
|
| | return SelectMode::SeekSecond;
|
| | break;
|
| | case OnViewParameter::Fifth:
|
| | case OnViewParameter::Sixth:
|
| | return SelectMode::SeekThird;
|
| | break;
|
| | case OnViewParameter::Seventh:
|
| | if (handler->roundCorners) {
|
| | return SelectMode::SeekFourth;
|
| | }
|
| | else {
|
| | return SelectMode::End;
|
| | }
|
| | break;
|
| | case OnViewParameter::Eighth:
|
| | if (handler->makeFrame) {
|
| | if (!handler->roundCorners) {
|
| | return SelectMode::SeekFourth;
|
| | }
|
| | else {
|
| | return SelectMode::SeekFifth;
|
| | }
|
| | }
|
| | else {
|
| | return SelectMode::End;
|
| | }
|
| | break;
|
| | default:
|
| | THROWM(Base::ValueError, "Parameter index without an associated machine state")
|
| | }
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHRectangleController::configureToolWidget()
|
| | {
|
| | if (!init) {
|
| | QStringList names = {
|
| | QApplication::translate("TaskSketcherTool_c1_rectangle", "Corner, width, height"),
|
| | QApplication::translate("TaskSketcherTool_c1_rectangle", "Center, width, height"),
|
| | QApplication::translate("TaskSketcherTool_c1_rectangle", "3 corners"),
|
| | QApplication::translate("TaskSketcherTool_c1_rectangle", "Center, 2 corners")
|
| | };
|
| | toolWidget->setComboboxElements(WCombobox::FirstCombo, names);
|
| |
|
| | toolWidget->setCheckboxLabel(
|
| | WCheckbox::FirstBox,
|
| | QApplication::translate("TaskSketcherTool_c1_rectangle", "Rounded corners (U)")
|
| | );
|
| | toolWidget->setCheckboxToolTip(
|
| | WCheckbox::FirstBox,
|
| | QApplication::translate(
|
| | "TaskSketcherTool_c1_rectangle",
|
| | "Create a rectangle with rounded corners."
|
| | )
|
| | );
|
| | syncCheckboxToHandler(WCheckbox::FirstBox, handler->roundCorners);
|
| |
|
| | toolWidget->setCheckboxLabel(
|
| | WCheckbox::SecondBox,
|
| | QApplication::translate("TaskSketcherTool_c2_rectangle", "Frame (J)")
|
| | );
|
| | toolWidget->setCheckboxToolTip(
|
| | WCheckbox::SecondBox,
|
| | QApplication::translate(
|
| | "TaskSketcherTool_c2_rectangle",
|
| | "Create two rectangles with a constant offset."
|
| | )
|
| | );
|
| | syncCheckboxToHandler(WCheckbox::SecondBox, handler->makeFrame);
|
| |
|
| | if (isConstructionMode()) {
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 0,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle_Constr")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 1,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle_Center_Constr")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 2,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle3Points_Constr")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 3,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle3Points_Center_Constr")
|
| | );
|
| |
|
| | toolWidget->setCheckboxIcon(
|
| | WCheckbox::FirstBox,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong_Constr")
|
| | );
|
| | toolWidget->setCheckboxIcon(
|
| | WCheckbox::SecondBox,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateFrame_Constr")
|
| | );
|
| | }
|
| | else {
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 0,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 1,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle_Center")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 2,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle3Points")
|
| | );
|
| | toolWidget->setComboboxItemIcon(
|
| | WCombobox::FirstCombo,
|
| | 3,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateRectangle3Points_Center")
|
| | );
|
| |
|
| | toolWidget->setCheckboxIcon(
|
| | WCheckbox::FirstBox,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateOblong")
|
| | );
|
| | toolWidget->setCheckboxIcon(
|
| | WCheckbox::SecondBox,
|
| | Gui::BitmapFactory().iconFromTheme("Sketcher_CreateFrame")
|
| | );
|
| | }
|
| | }
|
| |
|
| | onViewParameters[OnViewParameter::First]->setLabelType(Gui::SoDatumLabel::DISTANCEX);
|
| | onViewParameters[OnViewParameter::Second]->setLabelType(Gui::SoDatumLabel::DISTANCEY);
|
| |
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | onViewParameters[OnViewParameter::Third]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCEX,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCEY,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Fifth]->setLabelType(
|
| | Gui::SoDatumLabel::RADIUS,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Sixth]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | onViewParameters[OnViewParameter::Third]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelType(
|
| | Gui::SoDatumLabel::ANGLE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Fifth]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Sixth]->setLabelType(
|
| | Gui::SoDatumLabel::ANGLE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Seventh]->setLabelType(
|
| | Gui::SoDatumLabel::RADIUS,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Eighth]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | onViewParameters[OnViewParameter::Third]->setLabelType(Gui::SoDatumLabel::DISTANCEX);
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelType(Gui::SoDatumLabel::DISTANCEY);
|
| | onViewParameters[OnViewParameter::Fifth]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Sixth]->setLabelType(
|
| | Gui::SoDatumLabel::ANGLE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Seventh]->setLabelType(
|
| | Gui::SoDatumLabel::RADIUS,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | onViewParameters[OnViewParameter::Eighth]->setLabelType(
|
| | Gui::SoDatumLabel::DISTANCE,
|
| | Gui::EditableDatumLabel::Function::Dimensioning
|
| | );
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHRectangleController::adaptDrawingToCheckboxChange(int checkboxindex, bool value)
|
| | {
|
| | Q_UNUSED(checkboxindex);
|
| |
|
| | switch (checkboxindex) {
|
| | case WCheckbox::FirstBox:
|
| | handler->roundCorners = value;
|
| | break;
|
| | case WCheckbox::SecondBox:
|
| | handler->makeFrame = value;
|
| | break;
|
| | }
|
| |
|
| | handler->updateCursor();
|
| | }
|
| |
|
| | template<>
|
| | void DSHRectangleControllerBase::doEnforceControlParameters(Base::Vector2d& onSketchPos)
|
| | {
|
| | switch (handler->state()) {
|
| | case SelectMode::SeekFirst: {
|
| | if (onViewParameters[OnViewParameter::First]->isSet) {
|
| | onSketchPos.x = onViewParameters[OnViewParameter::First]->getValue();
|
| | }
|
| |
|
| | if (onViewParameters[OnViewParameter::Second]->isSet) {
|
| | onSketchPos.y = onViewParameters[OnViewParameter::Second]->getValue();
|
| | }
|
| | } break;
|
| | case SelectMode::SeekSecond: {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (onViewParameters[OnViewParameter::Third]->isSet) {
|
| | double length = onViewParameters[OnViewParameter::Third]->getValue();
|
| | if (fabs(length) < Precision::Confusion()
|
| | && onViewParameters[OnViewParameter::Third]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Third].get());
|
| | handler->lengthSign = 0;
|
| | return;
|
| | }
|
| |
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal) {
|
| | if (handler->lengthSign == 0) {
|
| | handler->lengthSign = (onSketchPos.x - handler->corner1.x) >= 0 ? 1 : -1;
|
| | }
|
| | onSketchPos.x = handler->corner1.x + handler->lengthSign * length;
|
| | }
|
| | else {
|
| | onSketchPos.x = handler->center.x + length / 2;
|
| | }
|
| | }
|
| | if (onViewParameters[OnViewParameter::Fourth]->isSet) {
|
| | double width = onViewParameters[OnViewParameter::Fourth]->getValue();
|
| | if (fabs(width) < Precision::Confusion()
|
| | && onViewParameters[OnViewParameter::Fourth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Fourth].get());
|
| | handler->widthSign = 0;
|
| | return;
|
| | }
|
| |
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal) {
|
| | if (handler->widthSign == 0) {
|
| | handler->widthSign = (onSketchPos.y - handler->corner1.y) >= 0 ? 1 : -1;
|
| | }
|
| | onSketchPos.y = handler->corner1.y + handler->widthSign * width;
|
| | }
|
| | else {
|
| | onSketchPos.y = handler->center.y + width / 2;
|
| | }
|
| | }
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | Base::Vector2d dir = onSketchPos - handler->corner1;
|
| | if (dir.Length() < Precision::Confusion()) {
|
| | dir.x = 1.0;
|
| | }
|
| | double length = dir.Length();
|
| |
|
| | if (onViewParameters[OnViewParameter::Third]->isSet) {
|
| | length = onViewParameters[OnViewParameter::Third]->getValue();
|
| | if (length < Precision::Confusion()
|
| | && onViewParameters[OnViewParameter::Third]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Third].get());
|
| | return;
|
| | }
|
| |
|
| | onSketchPos = handler->corner1 + length * dir.Normalize();
|
| | }
|
| |
|
| | if (onViewParameters[OnViewParameter::Fourth]->isSet) {
|
| | double angle = Base::toRadians(
|
| | onViewParameters[OnViewParameter::Fourth]->getValue()
|
| | );
|
| | onSketchPos.x = handler->corner1.x + cos(angle) * length;
|
| | onSketchPos.y = handler->corner1.y + sin(angle) * length;
|
| | }
|
| | }
|
| | else {
|
| | if (onViewParameters[OnViewParameter::Third]->isSet) {
|
| | onSketchPos.x = onViewParameters[OnViewParameter::Third]->getValue();
|
| | }
|
| |
|
| | if (onViewParameters[OnViewParameter::Fourth]->isSet) {
|
| | onSketchPos.y = onViewParameters[OnViewParameter::Fourth]->getValue();
|
| | }
|
| | if (onViewParameters[OnViewParameter::Third]->hasFinishedEditing
|
| | && onViewParameters[OnViewParameter::Fourth]->hasFinishedEditing
|
| | && (onSketchPos - handler->center).Length() < Precision::Confusion()) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Third].get());
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Fourth].get());
|
| | }
|
| | }
|
| | } break;
|
| | case SelectMode::SeekThird: {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (handler->roundCorners) {
|
| | if (onViewParameters[OnViewParameter::Fifth]->isSet) {
|
| | Base::Vector2d vecL = (handler->corner2 - handler->corner1).Normalize();
|
| | onSketchPos = handler->corner1
|
| | + vecL * onViewParameters[OnViewParameter::Fifth]->getValue();
|
| | }
|
| | }
|
| | else {
|
| | if (onViewParameters[OnViewParameter::Sixth]->isSet) {
|
| | double thickness = onViewParameters[OnViewParameter::Sixth]->getValue();
|
| | if (thickness <= -std::min(handler->width, handler->length) / 2
|
| | && onViewParameters[OnViewParameter::Sixth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Sixth].get());
|
| | return;
|
| | }
|
| |
|
| | Base::Vector2d u = (handler->corner2 - handler->corner1).Normalize();
|
| | Base::Vector2d v = (handler->corner4 - handler->corner1).Normalize();
|
| | onSketchPos = handler->corner1 - u * thickness - v * thickness;
|
| | }
|
| | }
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | Base::Vector2d dir = onSketchPos - handler->corner2Initial;
|
| | if (dir.Length() < Precision::Confusion()) {
|
| | dir.x = 1.0;
|
| | }
|
| | double width = dir.Length();
|
| |
|
| | if (onViewParameters[OnViewParameter::Fifth]->isSet) {
|
| | width = onViewParameters[OnViewParameter::Fifth]->getValue();
|
| | if (width < Precision::Confusion()
|
| | && onViewParameters[OnViewParameter::Fifth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Fifth].get());
|
| | return;
|
| | }
|
| |
|
| | onSketchPos = handler->corner2Initial + width * dir.Normalize();
|
| | }
|
| | if (onViewParameters[OnViewParameter::Sixth]->isSet) {
|
| | double angle = Base::toRadians(
|
| | onViewParameters[OnViewParameter::Sixth]->getValue()
|
| | );
|
| | if (fmod(angle, std::numbers::pi) < Precision::Confusion()
|
| | && onViewParameters[OnViewParameter::Sixth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Sixth].get());
|
| | return;
|
| | }
|
| |
|
| | int sign1 = handler->getPointSideOfVector(
|
| | onSketchPos,
|
| | handler->corner2Initial - handler->corner1,
|
| | handler->corner1
|
| | );
|
| |
|
| | int sign = handler->side != sign1 ? 1 : -1;
|
| |
|
| | double angle123 = (handler->corner2Initial - handler->corner1).Angle()
|
| | + std::numbers::pi + sign * angle;
|
| |
|
| | onSketchPos.x = handler->corner2Initial.x + cos(angle123) * width;
|
| | onSketchPos.y = handler->corner2Initial.y + sin(angle123) * width;
|
| | }
|
| | }
|
| | else {
|
| | Base::Vector2d dir = onSketchPos - handler->corner1;
|
| | if (dir.Length() < Precision::Confusion()) {
|
| | dir.x = 1.0;
|
| | }
|
| | double width = dir.Length();
|
| | if (onViewParameters[OnViewParameter::Fifth]->isSet) {
|
| | width = onViewParameters[OnViewParameter::Fifth]->getValue();
|
| | if (width < Precision::Confusion()
|
| | && onViewParameters[OnViewParameter::Fifth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Fifth].get());
|
| | return;
|
| | }
|
| |
|
| | onSketchPos = handler->corner1 + width * dir.Normalize();
|
| | }
|
| | if (onViewParameters[OnViewParameter::Sixth]->isSet) {
|
| | double c = Base::toRadians(onViewParameters[OnViewParameter::Sixth]->getValue());
|
| | if (fmod(c, std::numbers::pi) < Precision::Confusion()
|
| | && onViewParameters[OnViewParameter::Sixth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Sixth].get());
|
| | return;
|
| | }
|
| |
|
| | double a = asin(
|
| | width * sin(std::numbers::pi - c)
|
| | / (handler->corner3 - handler->corner1).Length()
|
| | );
|
| |
|
| | int sign1 = handler->getPointSideOfVector(
|
| | onSketchPos,
|
| | handler->corner3 - handler->corner1,
|
| | handler->corner1
|
| | );
|
| |
|
| | int sign = handler->side != sign1 ? 1 : -1;
|
| |
|
| | double angle = (handler->center - handler->corner1).Angle() + sign * (c - a);
|
| |
|
| | onSketchPos.x = handler->corner1.x + cos(angle) * width;
|
| | onSketchPos.y = handler->corner1.y + sin(angle) * width;
|
| | }
|
| | }
|
| | } break;
|
| | case SelectMode::SeekFourth: {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| |
|
| | if (onViewParameters[OnViewParameter::Sixth]->isSet) {
|
| | double thickness = onViewParameters[OnViewParameter::Sixth]->getValue();
|
| | if (thickness <= -std::min(handler->width, handler->length) / 2
|
| | && onViewParameters[OnViewParameter::Sixth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Sixth].get());
|
| | return;
|
| | }
|
| |
|
| | Base::Vector2d u = (handler->corner2 - handler->corner1).Normalize();
|
| | Base::Vector2d v = (handler->corner4 - handler->corner1).Normalize();
|
| | onSketchPos = handler->corner1 - u * thickness - v * thickness;
|
| | }
|
| | }
|
| | else {
|
| | if (handler->roundCorners) {
|
| | if (onViewParameters[OnViewParameter::Seventh]->isSet) {
|
| | double angleToUse = handler->angle412 / 2;
|
| | if (handler->constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | angleToUse = handler->angle123 / 2;
|
| | }
|
| | Base::Vector2d vecL = (handler->corner2Initial - handler->corner1).Normalize();
|
| | double L2 = onViewParameters[OnViewParameter::Seventh]->getValue()
|
| | / sqrt(1 - cos(angleToUse) * cos(angleToUse));
|
| | onSketchPos = handler->corner1 + vecL * L2 * cos(angleToUse);
|
| | }
|
| | }
|
| | else {
|
| | if (onViewParameters[OnViewParameter::Eighth]->isSet) {
|
| | double thickness = onViewParameters[OnViewParameter::Eighth]->getValue();
|
| | if (thickness <= -std::min(handler->width, handler->length) / 2
|
| | && onViewParameters[OnViewParameter::Eighth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Eighth].get());
|
| | return;
|
| | }
|
| |
|
| | Base::Vector2d u = (handler->corner2 - handler->corner1).Normalize();
|
| | Base::Vector2d v = (handler->corner4 - handler->corner1).Normalize();
|
| | Base::Vector2d dir = (u + v).Normalize();
|
| | double angle = u.GetAngle(v) / 2;
|
| | double sinAngle = fabs(sin(angle));
|
| | if (sinAngle < Precision::Confusion()) {
|
| | sinAngle = 1;
|
| | }
|
| | double tr = thickness / sinAngle;
|
| |
|
| | onSketchPos = handler->corner1 - dir * tr;
|
| | }
|
| | }
|
| | }
|
| | } break;
|
| | case SelectMode::SeekFifth: {
|
| | if (onViewParameters[OnViewParameter::Eighth]->isSet) {
|
| | double thickness = onViewParameters[OnViewParameter::Eighth]->getValue();
|
| | if (thickness <= -std::min(handler->width, handler->length) / 2
|
| | && onViewParameters[OnViewParameter::Eighth]->hasFinishedEditing) {
|
| | unsetOnViewParameter(onViewParameters[OnViewParameter::Eighth].get());
|
| | return;
|
| | }
|
| |
|
| | Base::Vector2d u = (handler->corner2 - handler->corner1).Normalize();
|
| | Base::Vector2d v = (handler->corner4 - handler->corner1).Normalize();
|
| | Base::Vector2d dir = (u + v).Normalize();
|
| | double angle = u.GetAngle(v) / 2;
|
| | double sinAngle = fabs(sin(angle));
|
| | if (sinAngle < Precision::Confusion()) {
|
| | sinAngle = 1;
|
| | }
|
| | double tr = thickness / sinAngle;
|
| |
|
| | onSketchPos = handler->corner1 - dir * tr;
|
| | }
|
| | } break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHRectangleController::adaptParameters(Base::Vector2d onSketchPos)
|
| | {
|
| |
|
| |
|
| |
|
| | if (syncCheckboxToHandler(WCheckbox::FirstBox, handler->roundCorners)) {
|
| | return;
|
| | }
|
| |
|
| | if (syncCheckboxToHandler(WCheckbox::SecondBox, handler->makeFrame)) {
|
| | return;
|
| | }
|
| |
|
| | switch (handler->state()) {
|
| | case SelectMode::SeekFirst: {
|
| | if (!onViewParameters[OnViewParameter::First]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::First, onSketchPos.x);
|
| | }
|
| |
|
| | if (!onViewParameters[OnViewParameter::Second]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Second, onSketchPos.y);
|
| | }
|
| |
|
| | bool sameSign = onSketchPos.x * onSketchPos.y > 0.;
|
| | onViewParameters[OnViewParameter::First]->setLabelAutoDistanceReverse(!sameSign);
|
| | onViewParameters[OnViewParameter::Second]->setLabelAutoDistanceReverse(sameSign);
|
| | onViewParameters[OnViewParameter::First]->setPoints(
|
| | Base::Vector3d(),
|
| | toVector3d(onSketchPos)
|
| | );
|
| | onViewParameters[OnViewParameter::Second]->setPoints(
|
| | Base::Vector3d(),
|
| | toVector3d(onSketchPos)
|
| | );
|
| | } break;
|
| | case SelectMode::SeekSecond: {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (!onViewParameters[OnViewParameter::Third]->isSet) {
|
| | double length = handler->cornersReversed ? handler->width : handler->length;
|
| | setOnViewParameterValue(OnViewParameter::Third, length);
|
| | }
|
| |
|
| | if (!onViewParameters[OnViewParameter::Fourth]->isSet) {
|
| | double width = handler->cornersReversed ? handler->length : handler->width;
|
| | setOnViewParameterValue(OnViewParameter::Fourth, width);
|
| | }
|
| |
|
| | Base::Vector3d start = toVector3d(handler->corner1);
|
| | Base::Vector3d vec = toVector3d(onSketchPos) - start;
|
| | bool sameSign = vec.x * vec.y > 0.;
|
| |
|
| | onViewParameters[OnViewParameter::Third]->setLabelAutoDistanceReverse(sameSign);
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelAutoDistanceReverse(!sameSign);
|
| |
|
| | onViewParameters[OnViewParameter::Third]->setPoints(
|
| | start,
|
| | toVector3d(handler->cornersReversed ? handler->corner4 : handler->corner2)
|
| | );
|
| | onViewParameters[OnViewParameter::Fourth]->setPoints(
|
| | start,
|
| | toVector3d(handler->cornersReversed ? handler->corner2 : handler->corner4)
|
| | );
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | if (!onViewParameters[OnViewParameter::Third]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Third, handler->length);
|
| | }
|
| |
|
| | onViewParameters[OnViewParameter::Third]->setPoints(
|
| | toVector3d(handler->corner4),
|
| | toVector3d(handler->corner3)
|
| | );
|
| |
|
| | if (!onViewParameters[OnViewParameter::Fourth]->isSet) {
|
| | setOnViewParameterValue(
|
| | OnViewParameter::Fourth,
|
| | Base::toDegrees(handler->angle),
|
| | Base::Unit::Angle
|
| | );
|
| | }
|
| |
|
| | onViewParameters[OnViewParameter::Fourth]->setPoints(
|
| | toVector3d(handler->corner1),
|
| | Base::Vector3d()
|
| | );
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelRange(
|
| | (handler->corner2 - handler->corner1).Angle()
|
| | );
|
| | }
|
| | else {
|
| | if (!onViewParameters[OnViewParameter::Third]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Third, onSketchPos.x);
|
| | }
|
| |
|
| | if (!onViewParameters[OnViewParameter::Fourth]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Fourth, onSketchPos.y);
|
| | }
|
| |
|
| | bool sameSign = onSketchPos.x * onSketchPos.y > 0.;
|
| | onViewParameters[OnViewParameter::Third]->setLabelAutoDistanceReverse(!sameSign);
|
| | onViewParameters[OnViewParameter::Fourth]->setLabelAutoDistanceReverse(sameSign);
|
| | onViewParameters[OnViewParameter::Third]->setPoints(
|
| | Base::Vector3d(),
|
| | toVector3d(onSketchPos)
|
| | );
|
| | onViewParameters[OnViewParameter::Fourth]->setPoints(
|
| | Base::Vector3d(),
|
| | toVector3d(onSketchPos)
|
| | );
|
| | }
|
| | } break;
|
| | case SelectMode::SeekThird: {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (handler->roundCorners) {
|
| | if (!onViewParameters[OnViewParameter::Fifth]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Fifth, handler->radius);
|
| | }
|
| |
|
| | Base::Vector3d center = handler->center3;
|
| | Base::Vector3d end = toVector3d(handler->corner3);
|
| |
|
| | if (handler->radius != 0.0) {
|
| | Base::Vector3d vec = (end - center).Normalize();
|
| | end = center + vec * handler->radius;
|
| | }
|
| |
|
| | onViewParameters[OnViewParameter::Fifth]->setPoints(center, end);
|
| | }
|
| | else {
|
| | if (!onViewParameters[OnViewParameter::Sixth]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Sixth, handler->thickness);
|
| | }
|
| |
|
| | Base::Vector3d start = toVector3d(handler->corner3);
|
| | Base::Vector3d end
|
| | = Base::Vector3d(handler->corner3.x, handler->frameCorner3.y, 0.0);
|
| | onViewParameters[OnViewParameter::Sixth]->setPoints(start, end);
|
| | }
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | onViewParameters[OnViewParameter::Third]->setPoints(
|
| | toVector3d(handler->corner4),
|
| | toVector3d(handler->corner3)
|
| | );
|
| |
|
| | bool reversed = handler->cornersReversed;
|
| |
|
| | if (!onViewParameters[OnViewParameter::Fifth]->isSet) {
|
| | setOnViewParameterValue(
|
| | OnViewParameter::Fifth,
|
| | reversed ? handler->length : handler->width
|
| | );
|
| | }
|
| |
|
| | Base::Vector3d start = toVector3d(handler->corner1);
|
| | onViewParameters[OnViewParameter::Fifth]->setLabelAutoDistanceReverse(reversed);
|
| | onViewParameters[OnViewParameter::Fifth]->setPoints(
|
| | start,
|
| | toVector3d(reversed ? handler->corner2 : handler->corner4)
|
| | );
|
| |
|
| |
|
| | if (!onViewParameters[OnViewParameter::Sixth]->isSet) {
|
| | double val = Base::toDegrees(handler->angle123);
|
| | setOnViewParameterValue(OnViewParameter::Sixth, val, Base::Unit::Angle);
|
| | }
|
| |
|
| | onViewParameters[OnViewParameter::Sixth]->setPoints(
|
| | toVector3d(reversed ? handler->corner4 : handler->corner2),
|
| | Base::Vector3d()
|
| | );
|
| | double startAngle = reversed ? (handler->corner1 - handler->corner4).Angle()
|
| | : (handler->corner3 - handler->corner2).Angle();
|
| | onViewParameters[OnViewParameter::Sixth]->setLabelStartAngle(startAngle);
|
| | onViewParameters[OnViewParameter::Sixth]->setLabelRange(handler->angle123);
|
| | }
|
| | else {
|
| | bool reversed = handler->cornersReversed;
|
| |
|
| | if (!onViewParameters[OnViewParameter::Fifth]->isSet) {
|
| | setOnViewParameterValue(
|
| | OnViewParameter::Fifth,
|
| | reversed ? handler->width : handler->length
|
| | );
|
| | }
|
| |
|
| | Base::Vector3d start = toVector3d(handler->corner1);
|
| | onViewParameters[OnViewParameter::Fifth]->setLabelAutoDistanceReverse(true);
|
| | onViewParameters[OnViewParameter::Fifth]->setPoints(
|
| | start,
|
| | toVector3d(reversed ? handler->corner4 : handler->corner2)
|
| | );
|
| |
|
| |
|
| | if (!onViewParameters[OnViewParameter::Sixth]->isSet) {
|
| | double val = Base::toDegrees(handler->angle412);
|
| | setOnViewParameterValue(OnViewParameter::Sixth, val, Base::Unit::Angle);
|
| | }
|
| |
|
| | onViewParameters[OnViewParameter::Sixth]->setPoints(
|
| | toVector3d(handler->corner1),
|
| | Base::Vector3d()
|
| | );
|
| | double startAngle = (handler->corner2 - handler->corner1).Angle();
|
| | onViewParameters[OnViewParameter::Sixth]->setLabelStartAngle(startAngle);
|
| | onViewParameters[OnViewParameter::Sixth]->setLabelRange(handler->angle412);
|
| | }
|
| |
|
| | } break;
|
| | case SelectMode::SeekFourth: {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (!onViewParameters[OnViewParameter::Sixth]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Sixth, handler->thickness);
|
| | }
|
| |
|
| | Base::Vector3d start = toVector3d(handler->corner3);
|
| | Base::Vector3d end = Base::Vector3d(handler->corner3.x, handler->frameCorner3.y, 0.0);
|
| | onViewParameters[OnViewParameter::Sixth]->setPoints(start, end);
|
| | }
|
| | else {
|
| | if (handler->roundCorners) {
|
| | if (!onViewParameters[OnViewParameter::Seventh]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Seventh, handler->radius);
|
| | }
|
| |
|
| | Base::Vector3d center = handler->center3;
|
| | Base::Vector3d end = toVector3d(handler->corner3);
|
| |
|
| | if (handler->radius != 0.0) {
|
| | Base::Vector3d vec = (end - center).Normalize();
|
| | end = center + vec * handler->radius;
|
| | }
|
| |
|
| | onViewParameters[OnViewParameter::Seventh]->setPoints(center, end);
|
| | }
|
| | else {
|
| | if (!onViewParameters[OnViewParameter::Eighth]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Eighth, handler->thickness);
|
| | }
|
| |
|
| | Base::Vector3d start = toVector3d(handler->corner3);
|
| | Base::Vector3d vec = toVector3d((handler->corner3 - handler->corner2).Normalize());
|
| | Base::Vector3d end = start + handler->thickness * vec;
|
| | onViewParameters[OnViewParameter::Eighth]->setPoints(start, end);
|
| | }
|
| | }
|
| | } break;
|
| | case SelectMode::SeekFifth: {
|
| | if (!onViewParameters[OnViewParameter::Eighth]->isSet) {
|
| | setOnViewParameterValue(OnViewParameter::Eighth, handler->thickness);
|
| | }
|
| |
|
| | Base::Vector3d start = toVector3d(handler->corner3);
|
| | Base::Vector3d vec = toVector3d((handler->corner3 - handler->corner2).Normalize());
|
| | Base::Vector3d end = start + handler->thickness * vec;
|
| | onViewParameters[OnViewParameter::Eighth]->setPoints(start, end);
|
| | } break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHRectangleController::computeNextDrawSketchHandlerMode()
|
| | {
|
| | switch (handler->state()) {
|
| | case SelectMode::SeekFirst: {
|
| | if (onViewParameters[OnViewParameter::First]->hasFinishedEditing
|
| | && onViewParameters[OnViewParameter::Second]->hasFinishedEditing) {
|
| |
|
| | handler->setNextState(SelectMode::SeekSecond);
|
| | }
|
| | } break;
|
| | case SelectMode::SeekSecond: {
|
| | if (onViewParameters[OnViewParameter::Third]->hasFinishedEditing
|
| | && onViewParameters[OnViewParameter::Fourth]->hasFinishedEditing) {
|
| |
|
| | if (handler->roundCorners || handler->makeFrame
|
| | || handler->constructionMethod() == ConstructionMethod::ThreePoints
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| |
|
| | handler->setNextState(SelectMode::SeekThird);
|
| | }
|
| | else {
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | }
|
| | } break;
|
| | case SelectMode::SeekThird: {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (handler->roundCorners
|
| | && onViewParameters[OnViewParameter::Fifth]->hasFinishedEditing) {
|
| |
|
| | if (handler->makeFrame) {
|
| | handler->setNextState(SelectMode::SeekFourth);
|
| | }
|
| | else {
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | }
|
| | else if (handler->makeFrame
|
| | && onViewParameters[OnViewParameter::Sixth]->hasFinishedEditing) {
|
| |
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | }
|
| | else {
|
| | if (onViewParameters[OnViewParameter::Fifth]->hasFinishedEditing
|
| | && onViewParameters[OnViewParameter::Sixth]->hasFinishedEditing) {
|
| | if (handler->roundCorners || handler->makeFrame) {
|
| | handler->setNextState(SelectMode::SeekFourth);
|
| | }
|
| | else {
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | }
|
| | }
|
| | } break;
|
| | case SelectMode::SeekFourth: {
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAndCorner) {
|
| | if (onViewParameters[OnViewParameter::Sixth]->hasFinishedEditing) {
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | }
|
| | else {
|
| | if (handler->roundCorners
|
| | && onViewParameters[OnViewParameter::Seventh]->hasFinishedEditing) {
|
| |
|
| | if (handler->makeFrame) {
|
| | handler->setNextState(SelectMode::SeekFifth);
|
| | }
|
| | else {
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | }
|
| | else if (handler->makeFrame
|
| | && onViewParameters[OnViewParameter::Eighth]->hasFinishedEditing) {
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | }
|
| | } break;
|
| | case SelectMode::SeekFifth: {
|
| | if (handler->makeFrame && onViewParameters[OnViewParameter::Eighth]->hasFinishedEditing) {
|
| | handler->setNextState(SelectMode::End);
|
| | }
|
| | } break;
|
| | default:
|
| | break;
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHRectangleController::addConstraints()
|
| | {
|
| | using std::numbers::pi;
|
| |
|
| | App::DocumentObject* obj = handler->sketchgui->getObject();
|
| |
|
| | int firstCurve = handler->firstCurve;
|
| | bool reverse = handler->cornersReversed;
|
| | if (handler->constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | reverse = !reverse;
|
| | }
|
| |
|
| | auto x0 = onViewParameters[OnViewParameter::First]->getValue();
|
| | auto y0 = onViewParameters[OnViewParameter::Second]->getValue();
|
| | auto length = onViewParameters[OnViewParameter::Third]->getValue();
|
| | auto width = onViewParameters[OnViewParameter::Fourth]->getValue();
|
| | auto radius = onViewParameters[OnViewParameter::Fifth]->getValue();
|
| | auto thickness = onViewParameters[OnViewParameter::Sixth]->getValue();
|
| |
|
| | auto x0set = onViewParameters[OnViewParameter::First]->isSet;
|
| | auto y0set = onViewParameters[OnViewParameter::Second]->isSet;
|
| | auto lengthSet = onViewParameters[OnViewParameter::Third]->isSet;
|
| | auto widthSet = onViewParameters[OnViewParameter::Fourth]->isSet;
|
| | auto radiusSet = onViewParameters[OnViewParameter::Fifth]->isSet;
|
| | auto thicknessSet = onViewParameters[OnViewParameter::Sixth]->isSet;
|
| |
|
| | auto corner1x = onViewParameters[OnViewParameter::Third]->getValue();
|
| | auto corner1y = onViewParameters[OnViewParameter::Fourth]->getValue();
|
| | auto angle = Base::toRadians(onViewParameters[OnViewParameter::Fourth]->getValue());
|
| | auto innerAngle = Base::toRadians(onViewParameters[OnViewParameter::Sixth]->getValue());
|
| |
|
| | auto corner1xSet = onViewParameters[OnViewParameter::Third]->isSet;
|
| | auto corner1ySet = onViewParameters[OnViewParameter::Fourth]->isSet;
|
| | auto angleSet = onViewParameters[OnViewParameter::Fourth]->isSet;
|
| | auto innerAngleSet = onViewParameters[OnViewParameter::Sixth]->isSet;
|
| |
|
| | if (handler->constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | lengthSet = false;
|
| | }
|
| | if (handler->constructionMethod() == ConstructionMethod::ThreePoints
|
| | || handler->constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | width = onViewParameters[OnViewParameter::Fifth]->getValue();
|
| | radius = onViewParameters[OnViewParameter::Seventh]->getValue();
|
| | thickness = onViewParameters[OnViewParameter::Eighth]->getValue();
|
| |
|
| | widthSet = onViewParameters[OnViewParameter::Fifth]->isSet;
|
| | radiusSet = onViewParameters[OnViewParameter::Seventh]->isSet;
|
| | thicknessSet = onViewParameters[OnViewParameter::Eighth]->isSet;
|
| | }
|
| |
|
| | using namespace Sketcher;
|
| |
|
| | int firstPointId = firstCurve;
|
| | if (handler->constructionMethod() == ConstructionMethod::Diagonal
|
| | || handler->constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | if (handler->radius > Precision::Confusion()) {
|
| | firstPointId = handler->constructionPointOneId;
|
| | }
|
| | }
|
| | else {
|
| | firstPointId = handler->centerPointId;
|
| | }
|
| |
|
| | auto constraintx0 = [&]() {
|
| | ConstraintToAttachment(GeoElementId(firstPointId, PointPos::start), GeoElementId::VAxis, x0, obj);
|
| | };
|
| |
|
| | auto constrainty0 = [&]() {
|
| | ConstraintToAttachment(GeoElementId(firstPointId, PointPos::start), GeoElementId::HAxis, y0, obj);
|
| | };
|
| |
|
| | auto constraintlength = [&]() {
|
| | int curveId = reverse ? firstCurve : firstCurve + 1;
|
| |
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('Distance',%d,%d,%d,%d,%f)) ",
|
| | curveId,
|
| | 1,
|
| | curveId + 2,
|
| | 2,
|
| | fabs(length)
|
| | );
|
| | };
|
| |
|
| | auto constraintwidth = [&]() {
|
| | int curveId = reverse ? firstCurve + 1 : firstCurve;
|
| |
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('Distance',%d,%d,%d,%d,%f)) ",
|
| | curveId,
|
| | 1,
|
| | curveId + 2,
|
| | 2,
|
| | fabs(width)
|
| | );
|
| | };
|
| |
|
| |
|
| |
|
| | if (handler->AutoConstraints.empty()) {
|
| | if (x0set) {
|
| | constraintx0();
|
| | }
|
| |
|
| | if (y0set) {
|
| | constrainty0();
|
| | }
|
| |
|
| | if (lengthSet) {
|
| | constraintlength();
|
| | }
|
| |
|
| | if (widthSet) {
|
| | constraintwidth();
|
| | }
|
| | }
|
| | else {
|
| | auto firstpointinfo = handler->getPointInfo(GeoElementId(firstPointId, PointPos::start));
|
| |
|
| | if (x0set && firstpointinfo.isXDoF()) {
|
| | constraintx0();
|
| |
|
| | handler->diagnoseWithAutoConstraints();
|
| |
|
| |
|
| | firstpointinfo = handler->getPointInfo(
|
| | GeoElementId(firstPointId, PointPos::start)
|
| | );
|
| | }
|
| |
|
| | if (y0set && firstpointinfo.isYDoF()) {
|
| | constrainty0();
|
| |
|
| | handler->diagnoseWithAutoConstraints();
|
| |
|
| | }
|
| |
|
| | if (lengthSet) {
|
| | int curveId = reverse ? firstCurve : firstCurve + 1;
|
| | auto startpointinfo = handler->getPointInfo(GeoElementId(curveId, PointPos::start));
|
| | auto endpointinfo = handler->getPointInfo(GeoElementId(curveId + 2, PointPos::end));
|
| |
|
| | int DoFs = startpointinfo.getDoFs();
|
| | DoFs += endpointinfo.getDoFs();
|
| |
|
| | if (DoFs > 0) {
|
| | constraintlength();
|
| | }
|
| |
|
| | handler->diagnoseWithAutoConstraints();
|
| | }
|
| |
|
| | if (widthSet) {
|
| | int curveId = reverse ? firstCurve + 1 : firstCurve;
|
| | auto startpointinfo = handler->getPointInfo(GeoElementId(curveId, PointPos::start));
|
| | auto endpointinfo = handler->getPointInfo(GeoElementId(curveId + 2, PointPos::end));
|
| |
|
| | int DoFs = startpointinfo.getDoFs();
|
| | DoFs += endpointinfo.getDoFs();
|
| |
|
| | if (DoFs > 0) {
|
| | constraintwidth();
|
| | }
|
| | }
|
| | }
|
| |
|
| |
|
| |
|
| |
|
| | if (handler->constructionMethod() == ConstructionMethod::ThreePoints) {
|
| | if (angleSet) {
|
| | ConstraintLineByAngle(firstCurve, angle, obj);
|
| | }
|
| | if (innerAngleSet) {
|
| | if (fabs(innerAngle - pi / 2) > Precision::Confusion()) {
|
| |
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('Angle',%d,%d,%d,%d,%f)) ",
|
| | firstCurve + 1,
|
| | 1,
|
| | firstCurve,
|
| | 2,
|
| | innerAngle
|
| | );
|
| | }
|
| | }
|
| | }
|
| | else if (handler->constructionMethod() == ConstructionMethod::CenterAnd3Points) {
|
| | if (corner1xSet) {
|
| | ConstraintToAttachment(
|
| | GeoElementId(firstCurve, PointPos::start),
|
| | GeoElementId::VAxis,
|
| | corner1x,
|
| | obj
|
| | );
|
| | }
|
| | if (corner1ySet) {
|
| | ConstraintToAttachment(
|
| | GeoElementId(firstCurve, PointPos::start),
|
| | GeoElementId::HAxis,
|
| | corner1y,
|
| | obj
|
| | );
|
| | }
|
| | if (innerAngleSet) {
|
| | if (fabs(innerAngle - pi / 2) > Precision::Confusion()) {
|
| |
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('Angle',%d,%d,%d,%d,%f)) ",
|
| | firstCurve,
|
| | 1,
|
| | firstCurve + 3,
|
| | 2,
|
| | innerAngle
|
| | );
|
| | }
|
| | }
|
| | }
|
| |
|
| | if (radiusSet && radius > Precision::Confusion()) {
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ",
|
| | firstCurve + 5,
|
| | radius
|
| | );
|
| | }
|
| |
|
| | bool negThicknessEqualRadius = fabs(radius + thickness) < Precision::Confusion();
|
| |
|
| |
|
| | if (thicknessSet && !negThicknessEqualRadius) {
|
| | Gui::cmdAppObjectArgs(
|
| | obj,
|
| | "addConstraint(Sketcher.Constraint('Distance',%d,%d,%d,%f)) ",
|
| | firstCurve + (handler->roundCorners == true ? 8 : 4),
|
| | 1,
|
| | firstCurve,
|
| | fabs(thickness)
|
| | );
|
| | }
|
| | }
|
| |
|
| | template<>
|
| | void DSHRectangleController::doConstructionMethodChanged()
|
| | {
|
| | handler->updateHint();
|
| | }
|
| |
|
| | }
|
| |
|
| |
|
| | #endif
|
| |
|