Expose Geometry2D.bresenham_line() method

Co-authored-by: Hugo Locurcio <hugo.locurcio@hugo.pro>
This commit is contained in:
Danil Alexeev 2024-10-21 08:19:00 +03:00
parent 78a4e634f0
commit 9f0ae21095
No known key found for this signature in database
GPG Key ID: 124453E157DA8DC7
5 changed files with 38 additions and 7 deletions

View File

@ -920,6 +920,19 @@ Dictionary Geometry2D::make_atlas(const Vector<Size2> &p_rects) {
return ret; return ret;
} }
TypedArray<Point2i> Geometry2D::bresenham_line(const Point2i &p_from, const Point2i &p_to) {
Vector<Point2i> points = ::Geometry2D::bresenham_line(p_from, p_to);
TypedArray<Point2i> result;
result.resize(points.size());
for (int i = 0; i < points.size(); i++) {
result[i] = points[i];
}
return result;
}
void Geometry2D::_bind_methods() { void Geometry2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &Geometry2D::is_point_in_circle); ClassDB::bind_method(D_METHOD("is_point_in_circle", "point", "circle_position", "circle_radius"), &Geometry2D::is_point_in_circle);
ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &Geometry2D::segment_intersects_circle); ClassDB::bind_method(D_METHOD("segment_intersects_circle", "segment_from", "segment_to", "circle_position", "circle_radius"), &Geometry2D::segment_intersects_circle);
@ -954,6 +967,8 @@ void Geometry2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &Geometry2D::make_atlas); ClassDB::bind_method(D_METHOD("make_atlas", "sizes"), &Geometry2D::make_atlas);
ClassDB::bind_method(D_METHOD("bresenham_line", "from", "to"), &Geometry2D::bresenham_line);
BIND_ENUM_CONSTANT(OPERATION_UNION); BIND_ENUM_CONSTANT(OPERATION_UNION);
BIND_ENUM_CONSTANT(OPERATION_DIFFERENCE); BIND_ENUM_CONSTANT(OPERATION_DIFFERENCE);
BIND_ENUM_CONSTANT(OPERATION_INTERSECTION); BIND_ENUM_CONSTANT(OPERATION_INTERSECTION);

View File

@ -324,6 +324,8 @@ public:
Dictionary make_atlas(const Vector<Size2> &p_rects); Dictionary make_atlas(const Vector<Size2> &p_rects);
TypedArray<Point2i> bresenham_line(const Point2i &p_from, const Point2i &p_to);
Geometry2D() { singleton = this; } Geometry2D() { singleton = this; }
}; };

View File

@ -451,17 +451,17 @@ public:
return H; return H;
} }
static Vector<Point2i> bresenham_line(const Point2i &p_start, const Point2i &p_end) { static Vector<Point2i> bresenham_line(const Point2i &p_from, const Point2i &p_to) {
Vector<Point2i> points; Vector<Point2i> points;
Vector2i delta = (p_end - p_start).abs() * 2; Vector2i delta = (p_to - p_from).abs() * 2;
Vector2i step = (p_end - p_start).sign(); Vector2i step = (p_to - p_from).sign();
Vector2i current = p_start; Vector2i current = p_from;
if (delta.x > delta.y) { if (delta.x > delta.y) {
int err = delta.x / 2; int err = delta.x / 2;
for (; current.x != p_end.x; current.x += step.x) { for (; current.x != p_to.x; current.x += step.x) {
points.push_back(current); points.push_back(current);
err -= delta.y; err -= delta.y;
@ -473,7 +473,7 @@ public:
} else { } else {
int err = delta.y / 2; int err = delta.y / 2;
for (; current.y != p_end.y; current.y += step.y) { for (; current.y != p_to.y; current.y += step.y) {
points.push_back(current); points.push_back(current);
err -= delta.x; err -= delta.x;

View File

@ -9,6 +9,20 @@
<tutorials> <tutorials>
</tutorials> </tutorials>
<methods> <methods>
<method name="bresenham_line">
<return type="Vector2i[]" />
<param index="0" name="from" type="Vector2i" />
<param index="1" name="to" type="Vector2i" />
<description>
Returns the [url=https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm]Bresenham line[/url] between the [param from] and [param to] points. A Bresenham line is a series of pixels that draws a line and is always 1-pixel thick on every row and column of the drawing (never more, never less).
Example code to draw a line between two [Marker2D] nodes using a series of [method CanvasItem.draw_rect] calls:
[codeblock]
func _draw():
for pixel in Geometry2D.bresenham_line($MarkerA.position, $MarkerB.position):
draw_rect(Rect2(pixel, Vector2.ONE), Color.WHITE)
[/codeblock]
</description>
</method>
<method name="clip_polygons"> <method name="clip_polygons">
<return type="PackedVector2Array[]" /> <return type="PackedVector2Array[]" />
<param index="0" name="polygon_a" type="PackedVector2Array" /> <param index="0" name="polygon_a" type="PackedVector2Array" />

View File

@ -5,7 +5,7 @@
</brief_description> </brief_description>
<description> <description>
Stores information about a mouse or a pen motion. This includes relative position, absolute position, and velocity. See [method Node._input]. Stores information about a mouse or a pen motion. This includes relative position, absolute position, and velocity. See [method Node._input].
[b]Note:[/b] By default, this event is only emitted once per frame rendered at most. If you need more precise input reporting, set [member Input.use_accumulated_input] to [code]false[/code] to make events emitted as often as possible. If you use InputEventMouseMotion to draw lines, consider implementing [url=https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm]Bresenham's line algorithm[/url] as well to avoid visible gaps in lines if the user is moving the mouse quickly. [b]Note:[/b] By default, this event is only emitted once per frame rendered at most. If you need more precise input reporting, set [member Input.use_accumulated_input] to [code]false[/code] to make events emitted as often as possible. If you use InputEventMouseMotion to draw lines, consider using [method Geometry2D.bresenham_line] as well to avoid visible gaps in lines if the user is moving the mouse quickly.
[b]Note:[/b] This event may be emitted even when the mouse hasn't moved, either by the operating system or by Godot itself. If you really need to know if the mouse has moved (e.g. to suppress displaying a tooltip), you should check that [code]relative.is_zero_approx()[/code] is [code]false[/code]. [b]Note:[/b] This event may be emitted even when the mouse hasn't moved, either by the operating system or by Godot itself. If you really need to know if the mouse has moved (e.g. to suppress displaying a tooltip), you should check that [code]relative.is_zero_approx()[/code] is [code]false[/code].
</description> </description>
<tutorials> <tutorials>