Skip to content

Commit

Permalink
tool draw arc: add set center, radius, angles mode
Browse files Browse the repository at this point in the history
  • Loading branch information
carrotIndustries committed Jun 26, 2021
1 parent edae90b commit 6fc2160
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 26 deletions.
158 changes: 136 additions & 22 deletions src/core/tools/tool_draw_arc.cpp
@@ -1,9 +1,8 @@
#include "tool_draw_arc.hpp"
#include "imp/imp_interface.hpp"
#include "document/idocument.hpp"
#include <iostream>
#include "common/arc.hpp"
#include <sstream>
#include "canvas/canvas_gl.hpp"

namespace horizon {

Expand All @@ -18,67 +17,141 @@ bool ToolDrawArc::can_begin()
return doc.r->has_object_type(ObjectType::ARC);
}

Junction *ToolDrawArc::make_junction(const Coordi &coords)
Junction *ToolDrawArc::make_junction(const Coordd &coords)
{
Junction *ju;
ju = doc.r->insert_junction(UUID::random());
imp->set_snap_filter({{ObjectType::JUNCTION, ju->uuid}});
ju->position = coords;
ju->position.x = coords.x;
ju->position.y = coords.y;
return ju;
}

ToolResponse ToolDrawArc::begin(const ToolArgs &args)
{
std::cout << "tool draw arc\n";

temp_junc = make_junction(args.coords);
temp_arc = nullptr;
from_junc = nullptr;
to_junc = nullptr;
state = DrawArcState::FROM;
state = State::CENTER_START;
annotation = imp->get_canvas()->create_annotation();
annotation->set_visible(true);
annotation->set_display(LayerDisplay(true, LayerDisplay::Mode::OUTLINE));
update_tip();
return ToolResponse();
}

ToolDrawArc::~ToolDrawArc()
{
if (annotation) {
imp->get_canvas()->remove_annotation(annotation);
annotation = nullptr;
}
}

void ToolDrawArc::update_tip()
{
std::vector<ActionLabelInfo> actions;
actions.reserve(8);
if (state == DrawArcState::FROM) {
switch (state) {
case State::FROM:
actions.emplace_back(InToolActionID::LMB, "place from junction");
}
else if (state == DrawArcState::TO) {
break;

case State::TO:
actions.emplace_back(InToolActionID::LMB, "place to junction");
}
else if (state == DrawArcState::CENTER) {
break;

case State::CENTER:
actions.emplace_back(InToolActionID::LMB, "place center junction");
break;

case State::CENTER_START:
actions.emplace_back(InToolActionID::LMB, "place center");
break;

case State::RADIUS:
actions.emplace_back(InToolActionID::LMB, "set radius");
break;

case State::START_ANGLE:
actions.emplace_back(InToolActionID::LMB, "set start angle");
break;

case State::END_ANGLE:
actions.emplace_back(InToolActionID::LMB, "set end angle");
break;
}

actions.emplace_back(InToolActionID::RMB, "cancel");
if (temp_arc)
if (state == State::CENTER || state == State::END_ANGLE)
actions.emplace_back(InToolActionID::FLIP_ARC);

if (state == State::FROM || state == State::CENTER_START)
actions.emplace_back(InToolActionID::ARC_MODE, "switch mode");
actions.emplace_back(InToolActionID::ENTER_WIDTH, "line width");
imp->tool_bar_set_actions(actions);
}

void ToolDrawArc::set_radius_angle(double r, double a, double b)
{
const auto c = Coordd(temp_arc->center->position);
temp_arc->from->position = (c + Coordd::euler(r, a)).to_coordi();
temp_arc->to->position = (c + Coordd::euler(r, b)).to_coordi();
}

void ToolDrawArc::update_end_angle(const Coordi &c)
{
const auto d = c - temp_arc->center->position;
const auto end_angle = atan2(d.y, d.x);
if (flipped)
set_radius_angle(radius, end_angle, start_angle);
else
set_radius_angle(radius, start_angle, end_angle);
}

ToolResponse ToolDrawArc::update(const ToolArgs &args)
{
if (args.type == ToolEventType::MOVE) {
temp_junc->position = args.coords;
if (state == State::RADIUS) {
radius = (args.coords - temp_arc->center->position).magd();
set_radius_angle(radius, 1e-3, 0);
annotation->clear();
annotation->draw_line(temp_arc->center->position, args.coords, ColorP::FROM_LAYER, 0);
}
else if (state == State::START_ANGLE) {
annotation->clear();
const Coordf c = temp_arc->center->position;
const auto d = Coordf(args.coords) - c;
const auto a = atan2(d.y, d.x);
annotation->draw_line(c, c + Coordf::euler(radius, a), ColorP::FROM_LAYER, 0);
}
else if (state == State::END_ANGLE) {
update_end_angle(args.coords);
annotation->clear();
annotation->draw_line(temp_arc->center->position, temp_arc->from->position, ColorP::FROM_LAYER, 0);
annotation->draw_line(temp_arc->center->position, temp_arc->to->position, ColorP::FROM_LAYER, 0);
}
else if (temp_junc) {
temp_junc->position = args.coords;
}
}
else if (args.type == ToolEventType::ACTION) {
switch (args.action) {
case InToolActionID::LMB:
if (state == DrawArcState::FROM) {
switch (state) {
case State::FROM:
if (args.target.type == ObjectType::JUNCTION) {
from_junc = doc.r->get_junction(args.target.path.at(0));
}
else {
from_junc = temp_junc;
temp_junc = make_junction(args.coords);
}
state = DrawArcState::TO;
}
else if (state == DrawArcState::TO) {
state = State::TO;
break;

case State::TO:
if (args.target.type == ObjectType::JUNCTION) {
to_junc = doc.r->get_junction(args.target.path.at(0));
}
Expand All @@ -92,9 +165,10 @@ ToolResponse ToolDrawArc::update(const ToolArgs &args)
temp_arc->to = to_junc;
temp_arc->center = temp_junc;
temp_arc->layer = args.work_layer;
state = DrawArcState::CENTER;
}
else if (state == DrawArcState::CENTER) {
state = State::CENTER;
break;

case State::CENTER:
if (args.target.type == ObjectType::JUNCTION) {
temp_arc->center = doc.r->get_junction(args.target.path.at(0));
doc.r->delete_junction(temp_junc->uuid);
Expand All @@ -104,6 +178,33 @@ ToolResponse ToolDrawArc::update(const ToolArgs &args)
temp_arc->center = temp_junc;
}
return ToolResponse::commit();
break;


case State::CENTER_START:
temp_arc = doc.r->insert_arc(UUID::random());
apply_settings();
temp_arc->from = make_junction(temp_junc->position);
temp_arc->to = make_junction(temp_junc->position);
temp_arc->center = temp_junc;
temp_arc->layer = args.work_layer;
state = State::RADIUS;
temp_junc = nullptr;
break;

case State::RADIUS:
state = State::START_ANGLE;
break;

case State::START_ANGLE: {
const auto d = args.coords - temp_arc->center->position;
start_angle = atan2(d.y, d.x);
state = State::END_ANGLE;
} break;

case State::END_ANGLE:
return ToolResponse::commit();
break;
}
break;

Expand All @@ -117,10 +218,23 @@ ToolResponse ToolDrawArc::update(const ToolArgs &args)

case InToolActionID::FLIP_ARC:
if (temp_arc) {
temp_arc->reverse();
if (state == State::END_ANGLE) {
flipped = !flipped;
update_end_angle(args.coords);
}
else {
temp_arc->reverse();
}
}
break;

case InToolActionID::ARC_MODE:
if (state == State::FROM)
state = State::CENTER_START;
else if (state == State::CENTER_START)
state = State::FROM;
break;

default:;
}
}
Expand Down
15 changes: 11 additions & 4 deletions src/core/tools/tool_draw_arc.hpp
Expand Up @@ -15,18 +15,25 @@ class ToolDrawArc : public ToolHelperLineWidthSetting {
{
using I = InToolActionID;
return {
I::LMB, I::CANCEL, I::RMB, I::ENTER_WIDTH, I::FLIP_ARC,
I::LMB, I::CANCEL, I::RMB, I::ENTER_WIDTH, I::FLIP_ARC, I::ARC_MODE,
};
}
~ToolDrawArc();

private:
enum class DrawArcState { FROM, TO, CENTER };
DrawArcState state = DrawArcState::FROM;
enum class State { FROM, TO, CENTER, CENTER_START, RADIUS, START_ANGLE, END_ANGLE };
State state;
class Junction *temp_junc = 0;
Junction *from_junc = 0;
Junction *to_junc = 0;
class Arc *temp_arc = 0;
Junction *make_junction(const Coordi &coords);
Junction *make_junction(const Coordd &coords);
void update_tip();
double radius = 0;
double start_angle = 0;
void set_radius_angle(double r, double a, double b);
void update_end_angle(const Coordi &c);
bool flipped = false;
class CanvasAnnotation *annotation = nullptr;
};
} // namespace horizon
3 changes: 3 additions & 0 deletions src/imp/in_tool_action.hpp
Expand Up @@ -75,6 +75,9 @@ enum class InToolActionID {

// add vertex
FLIP_DIRECTION,

// draw arc
ARC_MODE,
};

} // namespace horizon
3 changes: 3 additions & 0 deletions src/imp/in_tool_action_catalog.cpp
Expand Up @@ -80,6 +80,8 @@ const std::map<InToolActionID, InToolActionCatalogItem> in_tool_action_catalog =

{InToolActionID::FLIP_DIRECTION,
{"Flip direction", ToolID::ADD_VERTEX, InToolActionCatalogItem::FLAGS_DEFAULT}},

{InToolActionID::ARC_MODE, {"arc mode", ToolID::DRAW_ARC, InToolActionCatalogItem::FLAGS_DEFAULT}},
};


Expand Down Expand Up @@ -141,6 +143,7 @@ const LutEnumStr<InToolActionID> in_tool_action_lut = {
LUT_ITEM(ROUTER_MODE),
LUT_ITEM(NC_MODE),
LUT_ITEM(FLIP_DIRECTION),
LUT_ITEM(ARC_MODE),
};


Expand Down
8 changes: 8 additions & 0 deletions src/imp/in_tool_keys_default.json
Expand Up @@ -316,5 +316,13 @@
"mod": 0
}
]
],
"ARC_MODE": [
[
{
"key": "m",
"mod": 0
}
]
]
}

0 comments on commit 6fc2160

Please sign in to comment.