src/circularprimitive.h

changeset 232
8efa3a33172e
child 247
07ad61423c3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/circularprimitive.h	Mon Jun 20 02:04:51 2022 +0300
@@ -0,0 +1,88 @@
+#pragma once
+#include <glm/gtc/matrix_transform.hpp>
+#include "basics.h"
+#include "model.h"
+#include "ldrawalgorithm.h"
+
+template<typename Fn>
+void rasterize(const CircularPrimitive& circ, Fn&& fn)
+{
+	std::vector<ModelElement> result;
+	const auto xform = [&circ](const glm::vec2& p, float y){
+		return glm::vec3{circ.transformation * glm::vec4{p.x, y, p.y, 1}};
+	};
+	const glm::vec3 origin = xform({0, 0}, 0);
+	switch(circ.type) {
+	case CircularPrimitive::Circle:
+		ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
+		(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
+			fn(edge(xform(p1, 0), xform(p2, 0)));
+		});
+		break;
+	case CircularPrimitive::Disc:
+		ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
+		(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
+			fn(triangle(origin, xform(p1, 0), xform(p2, 0)));
+		});
+		break;
+	case CircularPrimitive::Cylinder:
+		ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
+		(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
+			fn(quadrilateral(xform(p1, 1), xform(p2, 1), xform(p2, 0), xform(p1, 0)));
+		});
+		break;
+	case CircularPrimitive::CylinderOpen:
+		rasterize(CircularPrimitive{
+			.type = CircularPrimitive::Cylinder,
+			.fraction = circ.fraction,
+			.transformation = circ.transformation,
+		}, fn);
+		rasterize(CircularPrimitive{
+			.type = CircularPrimitive::Circle,
+			.fraction = circ.fraction,
+			.transformation = circ.transformation,
+		}, fn);
+		rasterize(CircularPrimitive{
+			.type = CircularPrimitive::Circle,
+			.fraction = circ.fraction,
+			.transformation = glm::translate(circ.transformation, {0, 1, 0}),
+		}, fn);
+		break;
+	case CircularPrimitive::CylinderClosed:
+		rasterize(CircularPrimitive{
+			.type = CircularPrimitive::CylinderOpen,
+			.fraction = circ.fraction,
+			.transformation = circ.transformation,
+		}, fn);
+		rasterize(CircularPrimitive{
+			.type = CircularPrimitive::Disc,
+			.fraction = circ.fraction,
+			.transformation = circ.transformation,
+		}, fn);
+		break;
+	case CircularPrimitive::DiscNegative:
+		{
+			unsigned int i = 0;
+			ldraw::circle(circ.fraction.segments, circ.fraction.divisions, [&]
+			(const glm::vec2&, const glm::vec2& p1, const glm::vec2& p2){
+				constexpr glm::vec2 corners[4] = {
+					{+1, +1},
+					{-1, +1},
+					{-1, -1},
+					{+1, -1},
+				};
+				const glm::vec2& corner = corners[i * 4 / circ.fraction.divisions];
+				fn(triangle(xform(p2, 0), xform(p1, 0), xform(corner, 0)));
+				++i;
+			});
+		}
+		break;
+	case CircularPrimitive::Chord:
+		for (unsigned int i = 1; i < circ.fraction.segments; ++i) {
+			const glm::vec2& p1 = ldraw::rimpoint(circ.fraction.divisions, i);
+			const glm::vec2& p2 = ldraw::rimpoint(circ.fraction.divisions, i + 1);
+			fn(triangle(xform(p2, 0), xform(p1, 0), xform({1, 0}, 0)));
+		}
+		break;
+	}
+}

mercurial