From adf32fdf4e10996653158853730a2e9d1bc255f3 Mon Sep 17 00:00:00 2001
From: namark <namark@disroot.org>
Date: Sun, 19 May 2019 23:52:37 +0400
Subject: [PATCH] Arc function and a simple test sketch for it.

---
 arc.cpp              | 98 ++++++++++++++++++++++++++++++++++++++++++++
 common/simple_vg.cpp |  6 +++
 common/simple_vg.h   |  2 +
 3 files changed, 106 insertions(+)
 create mode 100644 arc.cpp

diff --git a/arc.cpp b/arc.cpp
new file mode 100644
index 0000000..ff83a0e
--- /dev/null
+++ b/arc.cpp
@@ -0,0 +1,98 @@
+/* Nothing interesting here, just testing the arc function...
+ * There bunch of points in top left stacked on top of each other...
+ * You can drag them around and see what they do I guess...
+ */
+
+#include "common/sketchbook.hpp"
+
+constexpr float corner_radius = 14.f;
+constexpr float2 half = float2::one(.5f);
+const float tau = 2*std::acos(-1);
+
+
+struct point
+{
+	enum
+	{
+		radius,
+		angle_start,
+		angle_end,
+		center,
+
+		count
+	};
+};
+
+std::array<float2, point::count> points;
+
+float2* dragged_point = nullptr;
+
+bool is_near(float2 corner, float2 position);
+
+
+void start(Program& program)
+{
+
+	program.key_up = [&program](scancode code, keycode)
+	{
+		switch(code)
+		{
+			case scancode::leftbracket:
+			case scancode::c:
+				if(pressed(scancode::rctrl) || pressed(scancode::lctrl))
+			case scancode::escape:
+				program.end();
+			break;
+
+			default: break;
+		}
+	};
+
+	program.mouse_down = [](float2 position, auto)
+	{
+		for(int i = 0; i < point::count; ++i)
+			if(is_near(points[i], position))
+				dragged_point = &points[i];
+	};
+
+	program.mouse_up = [](auto, auto)
+	{
+		dragged_point = nullptr;
+	};
+
+	program.mouse_move = [](auto, float2 motion)
+	{
+		if(dragged_point)
+			(*dragged_point) += motion;
+	};
+
+	program.draw_loop = [](auto frame, auto)
+	{
+
+		frame.begin_sketch()
+			.rectangle(rect{ frame.size })
+			.fill(0xffffff_rgb)
+		;
+
+		const float2 angle_start = tau * points[point::angle_start]/frame.size;
+		const float2 angle_end = tau * points[point::angle_end]/frame.size;
+		frame.begin_sketch()
+			.arc(points[point::center], rangef{angle_start.x(), angle_end.x()},
+				points[point::radius].x())
+			.line_width(2).outline(0x0_rgb)
+			.fill(0xaaaaaa_rgb)
+		;
+
+		{ auto sketch = frame.begin_sketch();
+			for(int i = 0; i < point::count; ++i)
+				sketch.ellipse(rect{float2::one(corner_radius), points[i], half});
+			sketch.line_width(1).outline(0x555555_rgb);
+		}
+
+	};
+}
+
+bool is_near(float2 corner, float2 position)
+{
+	return (corner - position).magnitude() < corner_radius * corner_radius;
+}
diff --git a/common/simple_vg.cpp b/common/simple_vg.cpp
index 4f30932..5c4ecd8 100644
--- a/common/simple_vg.cpp
+++ b/common/simple_vg.cpp
@@ -125,6 +125,12 @@ sketch& sketch::line(float2 from, float2 to) noexcept
 	return *this;
 }
 
+sketch& sketch::arc(float2 center, rangef angle, float radius) noexcept
+{
+	nvgBarc(context, center.x(), center.y(), radius, angle.lower(), angle.upper(), NVG_CW, 0);
+	return *this;
+}
+
 sketch& sketch::fill(const rgba_vector& color) noexcept
 {
 	nvgFillColor(context, nvgRGBAf(color.r(), color.g(), color.b(), color.a()));
diff --git a/common/simple_vg.h b/common/simple_vg.h
index 3c41474..a44e2ed 100644
--- a/common/simple_vg.h
+++ b/common/simple_vg.h
@@ -16,6 +16,7 @@ namespace simple::vg
 	using graphical::rgb_pixel;
 	using graphical::rgba_pixel;
 	using range2f = support::range<float2>;
+	using rangef = support::range<float>;
 	using rect2f = geom::segment<float2>;
 	using anchored_rect2f = geom::anchored_segment<float2>;
 
@@ -90,6 +91,7 @@ namespace simple::vg
 			sketch& ellipse(const range2f&) noexcept;
 			sketch& rectangle(const range2f&) noexcept;
 			sketch& line(float2 from, float2 to) noexcept;
+			sketch& arc(float2 center, rangef angle, float radius) noexcept;
 
 			sketch& fill(const rgba_vector& color) noexcept;
 			sketch& fill(const rgba_pixel& color) noexcept;
-- 
GitLab