Skip to content

Commit

Permalink
Add handedness enum for is_polygon_clockwise
Browse files Browse the repository at this point in the history
When this was originally implemented in
16022da, the implementation treated the
vertices as being in a space where the y-axis is positive in the up
direction. This causes it to return the incorrect value for 2D games,
since Godot treats the y-axis as being positive in the down direction.

This change maintains compatibility with existing uses of
`is_polygon_clockwise` by adding an optional parameter which allows the
user to select which handedness their coordinate system uses. The
documentation for `is_polygon_clockwise` has also been updated to
describe the difference.

Fixes godotengine#49716.
  • Loading branch information
exodrifter committed Mar 20, 2024
1 parent fe01776 commit 8e679d7
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 7 deletions.
47 changes: 47 additions & 0 deletions core/core_bind.compat.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/**************************************************************************/
/* core_bind.compat.inc */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/

#ifndef DISABLE_DEPRECATED

namespace core_bind {

////// Geometry2D //////

bool Geometry2D::_is_polygon_clockwise_bind_compat_89635(const Vector<Vector2> &p_polygon) {
return is_polygon_clockwise(p_polygon, RIGHT_HANDED);
}

void Geometry2D::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("is_polygon_clockwise", "polygon"), &Geometry2D::_is_polygon_clockwise_bind_compat_89635);
}

} // namespace core_bind

#endif // DISABLE_DEPRECATED
10 changes: 7 additions & 3 deletions core/core_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
/**************************************************************************/

#include "core_bind.h"
#include "core_bind.compat.inc"

#include "core/config/project_settings.h"
#include "core/crypto/crypto_core.h"
Expand Down Expand Up @@ -731,8 +732,8 @@ bool Geometry2D::point_is_inside_triangle(const Vector2 &s, const Vector2 &a, co
return ::Geometry2D::is_point_in_triangle(s, a, b, c);
}

bool Geometry2D::is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
return ::Geometry2D::is_polygon_clockwise(p_polygon);
bool Geometry2D::is_polygon_clockwise(const Vector<Vector2> &p_polygon, PolyHandedness p_handedness) {
return ::Geometry2D::is_polygon_clockwise(p_polygon, ::Geometry2D::PolyHandedness(p_handedness));
}

bool Geometry2D::is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon) {
Expand Down Expand Up @@ -888,7 +889,7 @@ void Geometry2D::_bind_methods() {

ClassDB::bind_method(D_METHOD("point_is_inside_triangle", "point", "a", "b", "c"), &Geometry2D::point_is_inside_triangle);

ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon"), &Geometry2D::is_polygon_clockwise);
ClassDB::bind_method(D_METHOD("is_polygon_clockwise", "polygon", "handedness"), &Geometry2D::is_polygon_clockwise, DEFVAL(RIGHT_HANDED));
ClassDB::bind_method(D_METHOD("is_point_in_polygon", "point", "polygon"), &Geometry2D::is_point_in_polygon);
ClassDB::bind_method(D_METHOD("triangulate_polygon", "polygon"), &Geometry2D::triangulate_polygon);
ClassDB::bind_method(D_METHOD("triangulate_delaunay", "points"), &Geometry2D::triangulate_delaunay);
Expand Down Expand Up @@ -922,6 +923,9 @@ void Geometry2D::_bind_methods() {
BIND_ENUM_CONSTANT(END_BUTT);
BIND_ENUM_CONSTANT(END_SQUARE);
BIND_ENUM_CONSTANT(END_ROUND);

BIND_ENUM_CONSTANT(RIGHT_HANDED);
BIND_ENUM_CONSTANT(LEFT_HANDED);
}

////// Geometry3D //////
Expand Down
12 changes: 11 additions & 1 deletion core/core_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ class Geometry2D : public Object {
protected:
static void _bind_methods();

#ifndef DISABLE_DEPRECATED
bool _is_polygon_clockwise_bind_compat_89635(const Vector<Vector2> &p_polygon);
static void _bind_compatibility_methods();
#endif // DISABLE_DEPRECATED

public:
static Geometry2D *get_singleton();
Variant segment_intersects_segment(const Vector2 &p_from_a, const Vector2 &p_to_a, const Vector2 &p_from_b, const Vector2 &p_to_b);
Expand All @@ -269,7 +274,11 @@ class Geometry2D : public Object {
bool is_point_in_circle(const Vector2 &p_point, const Vector2 &p_circle_pos, real_t p_circle_radius);
real_t segment_intersects_circle(const Vector2 &p_from, const Vector2 &p_to, const Vector2 &p_circle_pos, real_t p_circle_radius);

bool is_polygon_clockwise(const Vector<Vector2> &p_polygon);
enum PolyHandedness {
RIGHT_HANDED,
LEFT_HANDED,
};
bool is_polygon_clockwise(const Vector<Vector2> &p_polygon, PolyHandedness p_handedness = RIGHT_HANDED);
bool is_point_in_polygon(const Point2 &p_point, const Vector<Vector2> &p_polygon);
Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon);
Vector<int> triangulate_delaunay(const Vector<Vector2> &p_points);
Expand Down Expand Up @@ -590,6 +599,7 @@ VARIANT_ENUM_CAST(core_bind::OS::SystemDir);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyBooleanOperation);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyJoinType);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyEndType);
VARIANT_ENUM_CAST(core_bind::Geometry2D::PolyHandedness);

VARIANT_ENUM_CAST(core_bind::Thread::Priority);

Expand Down
12 changes: 10 additions & 2 deletions core/math/geometry_2d.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,10 @@ class Geometry2D {
END_SQUARE,
END_ROUND
};
enum PolyHandedness {
RIGHT_HANDED,
LEFT_HANDED,
};

static Vector<Vector<Point2>> merge_polygons(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) {
return _polypaths_do_operation(OPERATION_UNION, p_polygon_a, p_polygon_b);
Expand Down Expand Up @@ -350,7 +354,7 @@ class Geometry2D {
return triangles;
}

static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon) {
static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon, PolyHandedness p_handedness = RIGHT_HANDED) {
int c = p_polygon.size();
if (c < 3) {
return false;
Expand All @@ -363,7 +367,11 @@ class Geometry2D {
sum += (v2.x - v1.x) * (v2.y + v1.y);
}

return sum > 0.0f;
if (p_handedness == RIGHT_HANDED) {
return sum > 0.0f;
} else {
return sum < 0.0f;
}
}

// Alternate implementation that should be faster.
Expand Down
9 changes: 8 additions & 1 deletion doc/classes/Geometry2D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@
<method name="is_polygon_clockwise">
<return type="bool" />
<param index="0" name="polygon" type="PackedVector2Array" />
<param index="1" name="handedness" type="int" enum="Geometry2D.PolyHandedness" default="0" />
<description>
Returns [code]true[/code] if [param polygon]'s vertices are ordered in clockwise order, otherwise returns [code]false[/code].
Returns [code]true[/code] if [param polygon]'s vertices are ordered in clockwise order, otherwise returns [code]false[/code]. The result depends on [param handedness], which is used to determine if the coordinate space of the vertices is [constant RIGHT_HANDED] or [constant LEFT_HANDED].
</description>
</method>
<method name="line_intersects_line">
Expand Down Expand Up @@ -266,5 +267,11 @@
<constant name="END_ROUND" value="4" enum="PolyEndType">
Endpoints are rounded off and extended by [code]delta[/code] units.
</constant>
<constant name="RIGHT_HANDED" value="0" enum="PolyHandedness">
Vertices are in a right-handed coordinate system (the x-axis is positive rightwards and the y-axis is positive upwards or the x-axis is positive leftwards and the y-axis is positive downwards).
</constant>
<constant name="LEFT_HANDED" value="1" enum="PolyHandedness">
Vertices are in a left-handed coordinate system (the x-axis is positive rightwards and the y-axis is positive downwards or the x-axis is positive leftwards and the y-axis is positive upwards).
</constant>
</constants>
</class>
7 changes: 7 additions & 0 deletions misc/extension_api_validation/4.2-stable.expected
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,10 @@ Validate extension JSON: Error: Field 'classes/AcceptDialog/methods/register_tex
Validate extension JSON: Error: Field 'classes/AcceptDialog/methods/remove_button/arguments/0': type changed value in new API, from "Control" to "Button".

Changed argument type to the more specific one actually expected by the method. Compatibility method registered.


GH-89635
--------
Validate extension JSON: Error: Field 'classes/Geometry2D/methods/is_polygon_clockwise/arguments': size changed value in new API, from 1 to 2.

Added handedness argument. Compatibility method registered.

0 comments on commit 8e679d7

Please sign in to comment.