Skip to content

Commit

Permalink
Implemented polygon plotting. Partially addresses #25
Browse files Browse the repository at this point in the history
  • Loading branch information
cannontwo committed Feb 5, 2021
1 parent d7b9026 commit c89aa09
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 3 deletions.
1 change: 1 addition & 0 deletions cannon/graphics/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ list(APPEND GRAPHICS_SOURCES
opengl_state.cpp
render_pass.cpp
opengl_writer.cpp
random_color.cpp
)

add_library(graphics OBJECT ${GRAPHICS_SOURCES})
56 changes: 56 additions & 0 deletions cannon/graphics/random_color.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <cannon/graphics/random_color.hpp>

using namespace cannon::graphics;

Vector4f cannon::graphics::generate_random_color(float saturation, float value) {
Vector4f ret_vec = Vector4f::Ones();

static std::random_device rd;
static std::default_random_engine gen(rd());
static std::uniform_real_distribution<float> d(0.0, 360.0);
float hue = d(gen);

auto rgb_part = hsv_to_rgb(hue, saturation, value);
ret_vec.head(3) = rgb_part;

return ret_vec;
}

Vector3f cannon::graphics::hsv_to_rgb(float hue, float saturation, float value) {
assert(0.0 <= hue);
assert(hue <= 360.0);
assert(0 <= saturation);
assert(saturation <= 1);
assert(0 <= value);
assert(value <= 1);

// Adapted from https://www.rapidtables.com/convert/color/hsv-to-rgb.html
float c = value * saturation;
float x = c * (1.0 - std::fabs(std::fmod((hue / 60), 2) - 1));
float m = value - c;

Vector3f ret_vec = Vector3f::Zero();

if (hue <= 60) {
ret_vec[0] = c;
ret_vec[1] = x;
} else if (hue <= 120) {
ret_vec[0] = x;
ret_vec[1] = c;
} else if (hue <= 180) {
ret_vec[1] = c;
ret_vec[2] = x;
} else if (hue <= 240) {
ret_vec[1] = x;
ret_vec[2] = c;
} else if (hue <= 300) {
ret_vec[0] = x;
ret_vec[2] = c;
} else {
ret_vec[0] = c;
ret_vec[2] = x;
}

ret_vec += Vector3f::Ones() * m;
return ret_vec;
}
21 changes: 21 additions & 0 deletions cannon/graphics/random_color.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef CANNON_GRAPHICS_RANDOM_COLOR_H
#define CANNON_GRAPHICS_RANDOM_COLOR_H

#include <cmath>
#include <random>

#include <Eigen/Dense>

using namespace Eigen;

namespace cannon {
namespace graphics {

Vector4f generate_random_color(float saturation=0.75f, float value=.90f);

Vector3f hsv_to_rgb(float hue, float saturation, float value);

} // namespace graphics
} // namespace cannon

#endif /* ifndef CANNON_GRAPHICS_RANDOM_COLOR_H */
1 change: 1 addition & 0 deletions cannon/plot/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ list(APPEND PLOT_SOURCES
plotter.cpp
scatter.cpp
axes.cpp
polygon.cpp
)

add_library(plot OBJECT ${PLOT_SOURCES})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion cannon/plot/line.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ namespace cannon {

Line(Plotter& plotter, std::shared_ptr<ShaderProgram> program, MatrixX2f points, Vector4f color) : plotter_(plotter), points_(points), color_(color), vao_(new VertexArrayObject), buf_(vao_), program_(program) {
buf_.buffer(points_);
log_info(buf_);
}

Line(Line& s) = delete;
Expand Down
16 changes: 16 additions & 0 deletions cannon/plot/plotter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ std::shared_ptr<Line> Plotter::plot_line(MatrixX2f points, Vector4f color) {
return l;
}

std::shared_ptr<Polygon> Plotter::plot_polygon(const Polygon_2& poly, Vector4f color) {
auto p = std::make_shared<Polygon>(*this, poly_program_, poly, color);
polygon_plots_.push_back(p);

RowVector2f maxes = p->points_.colwise().maxCoeff();
RowVector2f mins = p->points_.colwise().minCoeff();
axes_.update_limits(mins[0], maxes[0], mins[1], maxes[1], w_.width, w_.height);

return p;
}

void Plotter::set_xlim(float low, float high) {
axes_.update_limits(low, high, 0.0, 0.0, w_.width, w_.height);
}
Expand All @@ -63,6 +74,11 @@ void Plotter::draw_pass() {
line->draw();
}

poly_program_->set_uniform("matrix", axes_.make_scaling_matrix());
for (auto& poly : polygon_plots_) {
poly->draw();
}

// TODO
}

Expand Down
12 changes: 11 additions & 1 deletion cannon/plot/plotter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <cannon/plot/axes.hpp>
#include <cannon/log/registry.hpp>
#include <cannon/plot/line.hpp>
#include <cannon/plot/polygon.hpp>

using namespace cannon::graphics;
using namespace cannon::log;
Expand All @@ -21,11 +22,12 @@ namespace cannon {

class Scatter;
class Line;
class Polygon;

class Plotter {
public:
Plotter() : w_(), point_program_(new ShaderProgram), line_program_(new
ShaderProgram), axes_(2.0f / (float)w_.height) {
ShaderProgram), poly_program_(new ShaderProgram), axes_(2.0f / (float)w_.height) {

//glEnable(GL_BLEND);
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Expand All @@ -52,6 +54,10 @@ namespace cannon {
line_program_->attach_shader(vl);
line_program_->attach_shader(fl);
line_program_->link();

poly_program_->attach_shader(vl);
poly_program_->attach_shader(fl);
poly_program_->link();
}

void render();
Expand All @@ -71,6 +77,7 @@ namespace cannon {
std::shared_ptr<Scatter> plot_points(MatrixX2f points, Vector4f
color={0.0, 0.0, 0.0, 1.0}, float size=15.0);
std::shared_ptr<Line> plot_line(MatrixX2f points, Vector4f color={0.0, 0.0, 0.0, 1.0});
std::shared_ptr<Polygon> plot_polygon(const Polygon_2& poly, Vector4f color={0.0, 0.0, 0.0, 1.0});

void display_fps();

Expand All @@ -80,9 +87,12 @@ namespace cannon {
Window w_;
std::shared_ptr<ShaderProgram> point_program_;
std::shared_ptr<ShaderProgram> line_program_;
std::shared_ptr<ShaderProgram> poly_program_;

Axes axes_;
std::vector<std::shared_ptr<Scatter>> scatter_plots_;
std::vector<std::shared_ptr<Line>> line_plots_;
std::vector<std::shared_ptr<Polygon>> polygon_plots_;
};

} // namespace plot
Expand Down
30 changes: 30 additions & 0 deletions cannon/plot/polygon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <cannon/plot/polygon.hpp>

using namespace cannon::plot;

void Polygon::draw() {
program_->set_uniform("uColor", color_);
program_->activate();

buf_.bind();
glDrawArrays(GL_TRIANGLES, 0, points_.rows());
}

std::vector<Polygon_2> Polygon::extract_triangles_(const Polygon_2& cgal_poly) {
std::vector<Polygon_2> ret_vec;

CDT cdt;
cdt.insert_constraint(cgal_poly.vertices_begin(), cgal_poly.vertices_end(), true);

for (auto& fh : cdt.finite_face_handles()) {
Polygon_2 p;
p.push_back(fh->vertex(0)->point());
p.push_back(fh->vertex(1)->point());
p.push_back(fh->vertex(2)->point());

assert(p.orientation() == CGAL::COUNTERCLOCKWISE);
ret_vec.push_back(p);
}

return ret_vec;
}
75 changes: 75 additions & 0 deletions cannon/plot/polygon.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#ifndef CANNON_PLOT_POLYGON_H
#define CANNON_PLOT_POLYGON_H

#include <Eigen/Dense>

#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Polygon_2.h>

using K = CGAL::Exact_predicates_exact_constructions_kernel;
using Polygon_2 = CGAL::Polygon_2<K>;

using Itag = CGAL::Exact_predicates_tag;
using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, CGAL::Default, Itag>;

#include <cannon/plot/plotter.hpp>
#include <cannon/graphics/shader_program.hpp>

using namespace Eigen;


namespace cannon {
namespace plot {

class Plotter;


class Polygon {
public:
Polygon() = delete;

Polygon(Plotter& plotter, std::shared_ptr<ShaderProgram> program, const
Polygon_2& cgal_poly, Vector4f color) : plotter_(plotter),
color_(color), vao_(new VertexArrayObject), buf_(vao_),
program_(program) {

auto triangles = extract_triangles_(cgal_poly);
points_ = MatrixX2f::Zero(3 * triangles.size(), 2);

for (unsigned int i = 0; i < triangles.size(); i++) {
assert(triangles[i].size() == 3);
for (unsigned int j = 0; j < 3; j++) {
points_(3*i + j, 0) = CGAL::to_double(triangles[i].vertex(j).x());
points_(3*i + j, 1) = CGAL::to_double(triangles[i].vertex(j).y());
}
}

buf_.buffer(points_);
}

Polygon(Polygon& o) = delete;

Polygon(Polygon&& o) : plotter_(o.plotter_), points_(o.points_), color_(o.color_),
vao_(o.vao_), buf_(std::move(o.buf_)), program_(std::move(o.program_)) {}

friend class Plotter;

private:
void draw();

std::vector<Polygon_2> extract_triangles_(const Polygon_2& cgal_poly);

Plotter& plotter_;
MatrixX2f points_;
Vector4f color_;
std::shared_ptr<VertexArrayObject> vao_;
VertexBuffer buf_;
std::shared_ptr<ShaderProgram> program_;

};

} // namespace plot
} // namespace cannon

#endif /* ifndef CANNON_PLOT_POLYGON_H */
34 changes: 34 additions & 0 deletions cannon/plot/polygon.test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <catch2/catch.hpp>
#include <thirdparty/approval_tests/ApprovalTests.hpp>

#include <cannon/plot/polygon.hpp>
#include <cannon/plot/plotter.hpp>
#include <cannon/graphics/opengl_writer.hpp>

using namespace cannon::plot;
using namespace cannon::graphics;

TEST_CASE("Polygon", "[plot]") {
Plotter p;

Polygon_2 poly;
poly.push_back(CDT::Point(0, 0));
poly.push_back(CDT::Point(2, 0));
poly.push_back(CDT::Point(2, 2));
poly.push_back(CDT::Point(0, 2));

p.plot_polygon(poly);

p.set_xlim(-5.0, 5.0);
p.set_ylim(-5.0, 5.0);

p.render([&]() {
static int i = 0;
i++;

if (i == 20) {
OpenGLWriter writer(p);
Approvals::verify(writer);
}
});
}

0 comments on commit c89aa09

Please sign in to comment.