Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/base/StarBlocksAlongLine.hpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/base/StarBlocksAlongLine.hpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/base/StarBlocksAlongLine.hpp')
-rw-r--r--source/base/StarBlocksAlongLine.hpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/source/base/StarBlocksAlongLine.hpp b/source/base/StarBlocksAlongLine.hpp
new file mode 100644
index 0000000..bdd3c9a
--- /dev/null
+++ b/source/base/StarBlocksAlongLine.hpp
@@ -0,0 +1,108 @@
+#ifndef STAR_BLOCKS_ALONG_LINE_HPP
+#define STAR_BLOCKS_ALONG_LINE_HPP
+
+#include "StarVector.hpp"
+
+namespace Star {
+
+// Iterate over integral cells based on Bresenham's line drawing algorithm.
+// Returns false immediately when the callback returns false for any cell,
+// returns true after iterating through every cell otherwise.
+template <typename Scalar>
+bool forBlocksAlongLine(Vector<Scalar, 2> origin, Vector<Scalar, 2> const& dxdy, function<bool(int, int)> callback) {
+ Vector<Scalar, 2> remote = origin + dxdy;
+
+ double dx = dxdy[0];
+ if (dx < 0)
+ dx *= -1;
+
+ double dy = dxdy[1];
+ if (dy < 0)
+ dy *= -1;
+
+ double oxfloor = floor(origin[0]);
+ double oyfloor = floor(origin[1]);
+ double rxfloor = floor(remote[0]);
+ double ryfloor = floor(remote[1]);
+
+ if (dx == 0) {
+ if (oyfloor < ryfloor) {
+ for (int i = oyfloor; i <= ryfloor; ++i) {
+ if (!callback(oxfloor, i))
+ return false;
+ }
+ } else {
+ for (int i = oyfloor; i >= ryfloor; --i) {
+ if (!callback(oxfloor, i))
+ return false;
+ }
+ }
+ return true;
+
+ } else if (dy == 0) {
+ if (oxfloor < rxfloor) {
+ for (int i = oxfloor; i <= rxfloor; ++i) {
+ if (!callback(i, oyfloor))
+ return false;
+ }
+ } else {
+ for (int i = oxfloor; i >= rxfloor; --i) {
+ if (!callback(i, oyfloor))
+ return false;
+ }
+ }
+ return true;
+
+ } else {
+ int x = oxfloor;
+ int y = oyfloor;
+
+ int n = 1;
+ int x_inc, y_inc;
+ double error;
+
+ if (dxdy[0] > 0) {
+ x_inc = 1;
+ n += int(rxfloor) - x;
+ error = (oxfloor + 1 - origin[0]) * dy;
+ } else {
+ x_inc = -1;
+ n += x - int(rxfloor);
+ error = (origin[0] - oxfloor) * dy;
+ }
+
+ if (dxdy[1] > 0) {
+ y_inc = 1;
+ n += int(ryfloor) - y;
+ error -= (oyfloor + 1 - origin[1]) * dx;
+ } else {
+ y_inc = -1;
+ n += y - int(ryfloor);
+ error -= (origin[1] - oyfloor) * dx;
+ }
+
+ for (; n > 0; --n) {
+ if (!callback(x, y))
+ return false;
+
+ if (error > 0) {
+ y += y_inc;
+ error -= dx;
+ } else if (error < 0) {
+ x += x_inc;
+ error += dy;
+ } else {
+ --n;
+ y += y_inc;
+ x += x_inc;
+ error += dy;
+ error -= dx;
+ }
+ }
+ return true;
+ }
+}
+
+}
+
+#endif