aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--geom.hpp6
-rw-r--r--main.cpp6
-rw-r--r--problem.cpp19
-rw-r--r--problem.hpp8
-rw-r--r--ui.cpp205
-rw-r--r--ui.hpp16
7 files changed, 240 insertions, 22 deletions
diff --git a/Makefile b/Makefile
index 4a1dfb4..b0c9fe9 100644
--- a/Makefile
+++ b/Makefile
@@ -6,4 +6,4 @@ $(BIN): *.hpp $(OBJ)
g++ -o $@ $(OBJ) -lm -lsfml-system -lsfml-window -lsfml-graphics -O2 -std=c++11
%.o: %.cpp *.hpp
- g++ -c -o $@ $< -std=c++11 -O2
+ g++ -c -o $@ $< -std=c++11 -O2 -Wall -Wextra
diff --git a/geom.hpp b/geom.hpp
index e6dee0c..06b9e65 100644
--- a/geom.hpp
+++ b/geom.hpp
@@ -27,7 +27,7 @@ struct vec {
double angle() const {
if (is_nil()) return 0;
double xx = x / norm();
- double a = acos(x);
+ double a = acos(xx);
return (y >= 0 ? a : -a + 2*M_PI);
}
@@ -144,6 +144,10 @@ struct circle {
vec at_angle(double theta) const {
return c + vec(r * cos(theta), r * sin(theta));
}
+
+ bool intersects(vec p) const {
+ return (c - p).norm() <= r;
+ }
};
struct circarc {
diff --git a/main.cpp b/main.cpp
index d1fa143..440a12f 100644
--- a/main.cpp
+++ b/main.cpp
@@ -4,9 +4,9 @@
int main() {
hilare_a_param p;
- p.l = 30;
- p.r_c_car = 15;
- p.r_c_trolley = 12;
+ p.l = 50;
+ p.r_c_car = 25;
+ p.r_c_trolley = 20;
UI the_ui(&p);
diff --git a/problem.cpp b/problem.cpp
index fb7670b..28ef8fa 100644
--- a/problem.cpp
+++ b/problem.cpp
@@ -56,14 +56,29 @@ bool hilare_a_mvt::intersects(const problem &p) const {
// ================================= //
solution solution::direct_sol(const hilare_a &pos_a, const hilare_a &pos_b) {
+ vector<hilare_a_mvt> sol;
+
// TODO: try different possibilities and chose the shortest one
- return solution(vector<hilare_a_mvt>());
+ hilare_a_mvt mvt;
+ mvt.from = pos_a;
+ mvt.to = pos_b;
+ mvt.is_arc = false;
+ // la suite à compléter
+ sol.push_back(mvt);
+
+ return solution(sol);
}
// =============================== //
// IMPLEMENTATION FOR CLASS SOLVER //
// =============================== //
-// TODO
+solver::solver() {
+ // nothing ?
+}
+
+solver_internal solver::peek_internal() {
+ return _d;
+}
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/problem.hpp b/problem.hpp
index 3fc3054..f268d55 100644
--- a/problem.hpp
+++ b/problem.hpp
@@ -7,6 +7,7 @@
struct obstacle {
circle c;
+ obstacle(circle cc) : c(cc) {}
};
struct hilare_a_param {
@@ -51,6 +52,7 @@ struct hilare_a_mvt {
// deux étapes dans le mouvement :
// - bien orienter la voiture (c'est l'angle dtheta_before)
// - avancer/reculer sur le cercle (c'est l'angle domega)
+ hilare_a_mvt() : center(0, 0) {}
hilare_a from, to;
@@ -88,14 +90,14 @@ struct solver_internal {
// intermediate data for the solver
// represents a graph of randomly chosen positions and simple solutions between them
std::vector<hilare_a> pts;
- std::map<int, std::map<int, hilare_a_mvt> > paths;
+ std::map<int, std::map<int, solution> > paths;
};
class solver {
// mutex-protected asynchronous structure
private:
- //todo
+ solver_internal _d;
public:
solver();
@@ -103,6 +105,8 @@ class solver {
void start(const problem &p);
bool finished();
solution get_solution();
+
+ solver_internal peek_internal();
};
diff --git a/ui.cpp b/ui.cpp
index 23a2b48..1f61f03 100644
--- a/ui.cpp
+++ b/ui.cpp
@@ -1,19 +1,30 @@
+#include <iostream>
+
#include "ui.hpp"
/*
All modes :
- h, j, k, l : move around
- i, o : zoom in/out
-
+ Main mode (command mode) :
+ - s : select start pos
+ - e : select end pos
+ - a : add obstacle
+ - d : delete obstacle under mouse pointer
+ Select modes : no other keys
*/
-UI::UI(hilare_a_param *p) {
+using namespace std;
+
+UI::UI(hilare_a_param *p) : _sel_obs(vec(0,0), 0) {
_param = p;
_p.begin_pos.param = _p.end_pos.param = p;
_view.x0 = _view.y0 = 0;
_view.zoom = 1;
+
+ _mode = M_NORMAL;
}
void UI::run() {
@@ -32,8 +43,24 @@ void UI::run() {
if (ev.type == sf::Event::TextEntered) {
int k = ev.text.unicode;
- // TODO
+ if (k == 'h') {
+ _view.x0 -= 20 / _view.zoom;
+ } else if (k == 'j') {
+ _view.y0 += 20 / _view.zoom;
+ } else if (k == 'k') {
+ _view.y0 -= 20 / _view.zoom;
+ } else if (k == 'l') {
+ _view.x0 += 20 / _view.zoom;
+ } else if (k == 'i') {
+ _view.zoom *= 1.1;
+ } else if (k == 'o') {
+ _view.zoom /= 1.1;
+ }
}
+
+ if (_mode == M_NORMAL) handle_normal(ev);
+ if (_mode == M_INS_OBSTACLE) handle_ins_obs(ev);
+ if (_mode == M_SEL_BEGIN || _mode == M_SEL_END) handle_sel_pos(ev);
}
_win.clear(sf::Color::Black);
@@ -42,10 +69,113 @@ void UI::run() {
render_solution();
render_problem();
+ if (_mode == M_INS_OBSTACLE)
+ render_circle(_sel_obs, sf::Color::Transparent, sf::Color::White, 0);
+ if (_mode == M_SEL_BEGIN || _mode == M_SEL_END)
+ render_pos(_sel_pos, sf::Color::White);
+
_win.display();
}
}
+void UI::handle_normal(const sf::Event &ev) {
+ if (ev.type == sf::Event::TextEntered) {
+ int k = ev.text.unicode;
+
+ if (k == 's') {
+ _mode = M_SEL_BEGIN;
+ _sel_step = S_XY;
+ _sel_pos = _p.begin_pos;
+ vec p = mouse_coord();
+ _sel_pos.x = p.x;
+ _sel_pos.y = p.y;
+ }
+ if (k == 'e') {
+ _mode = M_SEL_END;
+ _sel_step = S_XY;
+ _sel_pos = _p.end_pos;
+ vec p = mouse_coord();
+ _sel_pos.x = p.x;
+ _sel_pos.y = p.y;
+ }
+ if (k == 'a') {
+ _mode = M_INS_OBSTACLE;
+ _sel_step = S_XY;
+ _sel_obs.c = mouse_coord();
+ _sel_obs.r = 20 / _view.zoom;
+ }
+ if (k == 'd') {
+ vec p = mouse_coord();
+ vector<obstacle> o2;
+ for(auto& i: _p.obstacles) {
+ if (!i.c.intersects(p)) o2.push_back(i);
+ }
+ _p.obstacles = o2;
+ }
+ }
+}
+
+void UI::handle_ins_obs(const sf::Event &ev) {
+ if (_sel_step == S_XY) {
+ if (ev.type == sf::Event::MouseMoved) {
+ _sel_obs.c = mouse_coord();
+ } else if (ev.type == sf::Event::MouseButtonReleased
+ && ev.mouseButton.button == sf::Mouse::Button::Left) {
+ _sel_step = S_RADIUS;
+ }
+ } else {
+ if (ev.type == sf::Event::MouseMoved) {
+ _sel_obs.r = (mouse_coord() - _sel_obs.c).norm();
+ } else if (ev.type == sf::Event::MouseButtonReleased
+ && ev.mouseButton.button == sf::Mouse::Button::Left) {
+ _p.obstacles.push_back(obstacle(_sel_obs));
+ _mode = M_NORMAL;
+ }
+ }
+
+ if (ev.type == sf::Event::MouseButtonReleased
+ && ev.mouseButton.button == sf::Mouse::Button::Right) {
+ _mode = M_NORMAL; // cancel out
+ }
+}
+
+void UI::handle_sel_pos(const sf::Event &ev) {
+ if (_sel_step == S_XY) {
+ if (ev.type == sf::Event::MouseMoved) {
+ vec p = mouse_coord();
+ _sel_pos.x = p.x;
+ _sel_pos.y = p.y;
+ } else if (ev.type == sf::Event::MouseButtonReleased
+ && ev.mouseButton.button == sf::Mouse::Button::Left) {
+ _sel_step = S_THETA;
+ }
+ } else if (_sel_step == S_THETA) {
+ if (ev.type == sf::Event::MouseMoved) {
+ _sel_pos.theta = (mouse_coord() - _sel_pos.pos()).angle();
+ } else if (ev.type == sf::Event::MouseButtonReleased
+ && ev.mouseButton.button == sf::Mouse::Button::Left) {
+ _sel_step = S_PHI;
+ }
+ } else {
+ if (ev.type == sf::Event::MouseMoved) {
+ _sel_pos.phi = (mouse_coord() - _sel_pos.pos()).angle() - _sel_pos.theta;
+ } else if (ev.type == sf::Event::MouseButtonReleased
+ && ev.mouseButton.button == sf::Mouse::Button::Left) {
+ if (_mode == M_SEL_BEGIN) {
+ _p.begin_pos = _sel_pos;
+ } else {
+ _p.end_pos = _sel_pos;
+ }
+ _mode = M_NORMAL; // cancel out
+ }
+ }
+
+ if (ev.type == sf::Event::MouseButtonReleased
+ && ev.mouseButton.button == sf::Mouse::Button::Right) {
+ _mode = M_NORMAL; // cancel out
+ }
+}
+
void UI::render_circle(const circle &c, sf::Color border, sf::Color inside, int w) {
double r = c.r * _view.zoom;
sf::CircleShape a(r);
@@ -60,6 +190,17 @@ void UI::render_circle(const circle &c, sf::Color border, sf::Color inside, int
void UI::render_pos(const hilare_a &pos, sf::Color c) {
render_circle(circle(pos.pos(), pos.param->r_c_car), c, sf::Color::Transparent, 2);
+ sf::ConvexShape l;
+
+ l.setPointCount(3);
+ l.setPoint(0, to_view(pos.pos() - vec::from_polar(pos.param->r_c_car * 0.8, pos.theta + M_PI / 2)));
+ l.setPoint(1, to_view(pos.pos() + vec::from_polar(pos.param->r_c_car * 0.8, pos.theta + M_PI / 2)));
+ l.setPoint(2, to_view(pos.pos() + vec::from_polar(pos.param->r_c_car * 0.8, pos.theta)));
+
+ l.setFillColor(c);
+
+ _win.draw(l);
+
render_circle(circle(pos.pos_trolley(), pos.param->r_c_trolley), c, sf::Color::Transparent, 2);
}
@@ -67,8 +208,34 @@ void UI::render_obstacle(const obstacle &o) {
render_circle(o.c, sf::Color::Transparent, sf::Color(100, 100, 100), 0);
}
-void UI::render_mvt(const hilare_a_mvt &m) {
- // TODO
+void UI::render_mvt(const hilare_a_mvt &m, sf::Color c) {
+ if (m.is_arc) {
+ sf::Vertex l[20];
+
+ l[0] = sf::Vertex(to_view(m.from.pos()), c);
+
+ double th = (m.from.pos() - m.center).angle();
+ double r = (m.from.pos() - m.center).norm();
+ for (int i = 1; i < 19; i++) {
+ l[i] = sf::Vertex(to_view(m.center + vec::from_polar(r, th + m.domega * i / 20)), c);
+ }
+
+ l[19] = sf::Vertex(to_view(m.to.pos()), c);
+
+ _win.draw(l, 20, sf::Lines);
+ } else {
+ sf::Vertex l[] = {
+ sf::Vertex(to_view(m.from.pos()), c),
+ sf::Vertex(to_view(m.to.pos()), c),
+ };
+ _win.draw(l, 2, sf::Lines);
+ }
+}
+
+void UI::render_sol(const solution &s, sf::Color c) {
+ for (auto i: s.movement) {
+ render_mvt(i, c);
+ }
}
void UI::render_problem() {
@@ -84,20 +251,40 @@ void UI::render_solution() {
for (auto i = _s.movement.begin(); i != _s.movement.end(); i++) {
if (i != _s.movement.begin())
render_pos(i->from, sf::Color::Green);
- render_mvt(*i);
}
+ render_sol(_s.movement, sf::Color::Green);
}
void UI::render_internal() {
- // TODO
+ solver_internal x = _solver.peek_internal();
+
+ for (auto& p: x.pts) {
+ render_pos(p, sf::Color(42, 42, 42));
+ }
+
+ for (auto& kv: x.paths) {
+ for (auto kv2: kv.second) {
+ render_sol(kv2.second, sf::Color(42, 42, 42));
+ }
+ }
}
sf::Vector2f UI::to_view(const vec &p) {
- return sf::Vector2f((p.x - _view.x0) * _view.zoom, (p.y - _view.y0) * _view.zoom);
+ sf::Vector2u s = _win.getSize();
+ return sf::Vector2f((p.x - _view.x0) * _view.zoom + (s.x/2), (p.y - _view.y0) * _view.zoom + (s.y/2));
}
vec UI::from_view(const sf::Vector2f &p) {
- return vec(p.x / _view.zoom + _view.x0, p.y / _view.zoom + _view.y0);
+ sf::Vector2u s = _win.getSize();
+ return vec((p.x - s.x/2) / _view.zoom + _view.x0, (p.y - s.y/2) / _view.zoom + _view.y0);
+}
+
+vec UI::from_view(const sf::Vector2i &p) {
+ return from_view(sf::Vector2f(p.x, p.y));
+}
+
+vec UI::mouse_coord() {
+ return from_view(sf::Mouse::getPosition() - _win.getPosition());
}
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/ui.hpp b/ui.hpp
index 552dfa2..8496b58 100644
--- a/ui.hpp
+++ b/ui.hpp
@@ -10,7 +10,6 @@
enum {
M_NORMAL,
M_INS_OBSTACLE,
- M_DEL_OBSTACLE,
M_SEL_BEGIN,
M_SEL_END
};
@@ -19,7 +18,6 @@ enum {
S_XY,
S_THETA,
S_PHI,
- S_CENTER,
S_RADIUS
};
@@ -28,8 +26,8 @@ class UI {
hilare_a_param *_param;
problem _p;
-
solution _s;
+ solver _solver;
struct {
double x0, y0, zoom;
@@ -40,14 +38,22 @@ class UI {
// interaction mode
int _mode, _sel_step;
+ hilare_a _sel_pos;
+ circle _sel_obs;
public:
UI(hilare_a_param *p);
+ void handle_normal(const sf::Event &ev);
+ void handle_ins_obs(const sf::Event &ev);
+ void handle_sel_pos(const sf::Event &ev);
+
void render_circle(const circle& c, sf::Color border, sf::Color inside, int linewidth);
+
void render_pos(const hilare_a &pos, sf::Color c);
void render_obstacle(const obstacle &o);
- void render_mvt(const hilare_a_mvt &m);
+ void render_mvt(const hilare_a_mvt &m, sf::Color c);
+ void render_sol(const solution &s, sf::Color c);
void render_problem();
void render_solution();
@@ -55,6 +61,8 @@ class UI {
sf::Vector2f to_view(const vec &p);
vec from_view(const sf::Vector2f &p);
+ vec from_view(const sf::Vector2i &p);
+ vec mouse_coord();
void run();
};