From 5aa98e895599827b1c0b7a1cc96d00fd78a9ff8b Mon Sep 17 00:00:00 2001 From: Relintai Date: Sun, 20 Nov 2022 02:33:40 +0100 Subject: [PATCH] Added Brenzenham's line algorithm found in the TileMapEditorPlugin to Geometry, and it's binder class. --- core/bind/core_bind.cpp | 6 +++ core/bind/core_bind.h | 2 + core/math/geometry.h | 92 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 890871151..dd311d8fc 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -1889,6 +1889,10 @@ int _Geometry::get_uv84_normal_bit(const Vector3 &p_vector) { return Geometry::get_uv84_normal_bit(p_vector); } +PoolVector2iArray _Geometry::brenzenham_line(int x0, int x1, int y0, int y1) { + return Geometry::brenzenham_line_pv(x0, x1, y0, y1); +} + void _Geometry::_bind_methods() { ClassDB::bind_method(D_METHOD("build_box_planes", "extents"), &_Geometry::build_box_planes); ClassDB::bind_method(D_METHOD("build_cylinder_planes", "radius", "height", "sides", "axis"), &_Geometry::build_cylinder_planes, DEFVAL(Vector3::AXIS_Z)); @@ -1936,6 +1940,8 @@ void _Geometry::_bind_methods() { ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &_Geometry::make_atlas); + ClassDB::bind_method(D_METHOD("brenzenham_line", "x0", "x1", "y0", "y1"), &_Geometry::brenzenham_line); + BIND_ENUM_CONSTANT(OPERATION_UNION); BIND_ENUM_CONSTANT(OPERATION_DIFFERENCE); BIND_ENUM_CONSTANT(OPERATION_INTERSECTION); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 5c56febaa..a78fe18e9 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -505,6 +505,8 @@ public: Dictionary make_atlas(const Vector &p_rects); + PoolVector2iArray brenzenham_line(int x0, int x1, int y0, int y1); + _Geometry(); }; diff --git a/core/math/geometry.h b/core/math/geometry.h index 78c923cc3..854ae2749 100644 --- a/core/math/geometry.h +++ b/core/math/geometry.h @@ -30,16 +30,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ +#include "core/containers/pool_vector.h" +#include "core/containers/vector.h" #include "core/math/delaunay.h" #include "core/math/face3.h" #include "core/math/rect2.h" #include "core/math/triangulate.h" -#include "core/math/vector3.h" #include "core/math/vector2i.h" +#include "core/math/vector3.h" #include "core/object/object.h" -#include "core/containers/pool_vector.h" #include "core/string/print_string.h" -#include "core/containers/vector.h" class Geometry { public: @@ -1021,6 +1021,92 @@ public: static bool convex_hull_intersects_convex_hull(const Plane *p_planes_a, int p_plane_count_a, const Plane *p_planes_b, int p_plane_count_b); static real_t calculate_convex_hull_volume(const Geometry::MeshData &p_md); + static _FORCE_INLINE_ Vector brenzenham_line(int x0, int x1, int y0, int y1) { + Vector points; + + float dx = ABS(x1 - x0); + float dy = ABS(y1 - y0); + + int x = x0; + int y = y0; + + int sx = x0 > x1 ? -1 : 1; + int sy = y0 > y1 ? -1 : 1; + + if (dx > dy) { + float err = dx / 2; + + for (; x != x1; x += sx) { + points.push_back(Vector2(x, y)); + + err -= dy; + if (err < 0) { + y += sy; + err += dx; + } + } + } else { + float err = dy / 2; + + for (; y != y1; y += sy) { + points.push_back(Vector2(x, y)); + + err -= dx; + if (err < 0) { + x += sx; + err += dy; + } + } + } + + points.push_back(Vector2(x, y)); + + return points; + } + + static _FORCE_INLINE_ PoolVector2iArray brenzenham_line_pv(int x0, int x1, int y0, int y1) { + PoolVector2iArray points; + + float dx = ABS(x1 - x0); + float dy = ABS(y1 - y0); + + int x = x0; + int y = y0; + + int sx = x0 > x1 ? -1 : 1; + int sy = y0 > y1 ? -1 : 1; + + if (dx > dy) { + float err = dx / 2; + + for (; x != x1; x += sx) { + points.push_back(Vector2(x, y)); + + err -= dy; + if (err < 0) { + y += sy; + err += dx; + } + } + } else { + float err = dy / 2; + + for (; y != y1; y += sy) { + points.push_back(Vector2(x, y)); + + err -= dx; + if (err < 0) { + x += sx; + err += dy; + } + } + } + + points.push_back(Vector2(x, y)); + + return points; + } + private: static Vector> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector &p_polypath_a, const Vector &p_polypath_b, bool is_a_open = false); static Vector> _polypath_offset(const Vector &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type);