Merge pull request #111581 from lawnjelly/span2

[3.x] `Span` - update more `Geometry` API to use span
This commit is contained in:
lawnjelly
2025-10-13 11:53:33 +01:00
committed by GitHub
8 changed files with 39 additions and 36 deletions

View File

@@ -1042,7 +1042,7 @@ struct _AtlasWorkRectResult {
int max_h; int max_h;
}; };
void Geometry::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size) { void Geometry::make_atlas(const Span<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size) {
// Super simple, almost brute force scanline stacking fitter. // Super simple, almost brute force scanline stacking fitter.
// It's pretty basic for now, but it tries to make sure that the aspect ratio of the // It's pretty basic for now, but it tries to make sure that the aspect ratio of the
// resulting atlas is somehow square. This is necessary because video cards have limits. // resulting atlas is somehow square. This is necessary because video cards have limits.
@@ -1052,14 +1052,14 @@ void Geometry::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_resu
// 256x8192 atlas (won't work anywhere). // 256x8192 atlas (won't work anywhere).
ERR_FAIL_COND(p_rects.size() == 0); ERR_FAIL_COND(p_rects.size() == 0);
for (int i = 0; i < p_rects.size(); i++) { for (uint32_t i = 0; i < p_rects.size(); i++) {
ERR_FAIL_COND(p_rects[i].width <= 0); ERR_FAIL_COND(p_rects[i].width <= 0);
ERR_FAIL_COND(p_rects[i].height <= 0); ERR_FAIL_COND(p_rects[i].height <= 0);
} }
Vector<_AtlasWorkRect> wrects; Vector<_AtlasWorkRect> wrects;
wrects.resize(p_rects.size()); wrects.resize(p_rects.size());
for (int i = 0; i < p_rects.size(); i++) { for (uint32_t i = 0; i < p_rects.size(); i++) {
wrects.write[i].s = p_rects[i]; wrects.write[i].s = p_rects[i];
wrects.write[i].idx = i; wrects.write[i].idx = i;
} }
@@ -1146,14 +1146,14 @@ void Geometry::make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_resu
r_result.resize(p_rects.size()); r_result.resize(p_rects.size());
for (int i = 0; i < p_rects.size(); i++) { for (uint32_t i = 0; i < p_rects.size(); i++) {
r_result.write[results[best].result[i].idx] = results[best].result[i].p; r_result.write[results[best].result[i].idx] = results[best].result[i].p;
} }
r_size = Size2(results[best].max_w, results[best].max_h); r_size = Size2(results[best].max_w, results[best].max_h);
} }
Vector<Vector<Point2>> Geometry::_polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open) { Vector<Vector<Point2>> Geometry::_polypaths_do_operation(PolyBooleanOperation p_op, const Span<Point2> &p_polypath_a, const Span<Point2> &p_polypath_b, bool is_a_open) {
using namespace ClipperLib; using namespace ClipperLib;
ClipType op = ctUnion; ClipType op = ctUnion;
@@ -1175,10 +1175,10 @@ Vector<Vector<Point2>> Geometry::_polypaths_do_operation(PolyBooleanOperation p_
Path path_a, path_b; Path path_a, path_b;
// Need to scale points (Clipper's requirement for robust computation). // Need to scale points (Clipper's requirement for robust computation).
for (int i = 0; i != p_polypath_a.size(); ++i) { for (uint32_t i = 0; i != p_polypath_a.size(); ++i) {
path_a << IntPoint(p_polypath_a[i].x * (real_t)SCALE_FACTOR, p_polypath_a[i].y * (real_t)SCALE_FACTOR); path_a << IntPoint(p_polypath_a[i].x * (real_t)SCALE_FACTOR, p_polypath_a[i].y * (real_t)SCALE_FACTOR);
} }
for (int i = 0; i != p_polypath_b.size(); ++i) { for (uint32_t i = 0; i != p_polypath_b.size(); ++i) {
path_b << IntPoint(p_polypath_b[i].x * (real_t)SCALE_FACTOR, p_polypath_b[i].y * (real_t)SCALE_FACTOR); path_b << IntPoint(p_polypath_b[i].x * (real_t)SCALE_FACTOR, p_polypath_b[i].y * (real_t)SCALE_FACTOR);
} }
Clipper clp; Clipper clp;
@@ -1212,7 +1212,7 @@ Vector<Vector<Point2>> Geometry::_polypaths_do_operation(PolyBooleanOperation p_
return polypaths; return polypaths;
} }
Vector<Vector<Point2>> Geometry::_polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { Vector<Vector<Point2>> Geometry::_polypath_offset(const Span<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
using namespace ClipperLib; using namespace ClipperLib;
JoinType jt = jtSquare; JoinType jt = jtSquare;
@@ -1252,7 +1252,7 @@ Vector<Vector<Point2>> Geometry::_polypath_offset(const Vector<Point2> &p_polypa
Path path; Path path;
// Need to scale points (Clipper's requirement for robust computation). // Need to scale points (Clipper's requirement for robust computation).
for (int i = 0; i != p_polypath.size(); ++i) { for (uint32_t i = 0; i != p_polypath.size(); ++i) {
path << IntPoint(p_polypath[i].x * (real_t)SCALE_FACTOR, p_polypath[i].y * (real_t)SCALE_FACTOR); path << IntPoint(p_polypath[i].x * (real_t)SCALE_FACTOR, p_polypath[i].y * (real_t)SCALE_FACTOR);
} }
co.AddPath(path, jt, et); co.AddPath(path, jt, et);
@@ -1436,7 +1436,7 @@ Vector<Vector3> Geometry::compute_convex_mesh_points(const Span<Plane> &p_planes
return points; return points;
} }
Vector<Geometry::PackRectsResult> Geometry::partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size) { Vector<Geometry::PackRectsResult> Geometry::partial_pack_rects(const Span<Vector2i> &p_sizes, const Size2i &p_atlas_size) {
Vector<stbrp_node> nodes; Vector<stbrp_node> nodes;
nodes.resize(p_atlas_size.width); nodes.resize(p_atlas_size.width);
memset(nodes.ptrw(), 0, sizeof(stbrp_node) * nodes.size()); memset(nodes.ptrw(), 0, sizeof(stbrp_node) * nodes.size());
@@ -1447,7 +1447,7 @@ Vector<Geometry::PackRectsResult> Geometry::partial_pack_rects(const Vector<Vect
Vector<stbrp_rect> rects; Vector<stbrp_rect> rects;
rects.resize(p_sizes.size()); rects.resize(p_sizes.size());
for (int i = 0; i < p_sizes.size(); i++) { for (uint32_t i = 0; i < p_sizes.size(); i++) {
rects.write[i].id = i; rects.write[i].id = i;
rects.write[i].w = p_sizes[i].width; rects.write[i].w = p_sizes[i].width;
rects.write[i].h = p_sizes[i].height; rects.write[i].h = p_sizes[i].height;
@@ -1461,7 +1461,7 @@ Vector<Geometry::PackRectsResult> Geometry::partial_pack_rects(const Vector<Vect
Vector<PackRectsResult> ret; Vector<PackRectsResult> ret;
ret.resize(p_sizes.size()); ret.resize(p_sizes.size());
for (int i = 0; i < p_sizes.size(); i++) { for (uint32_t i = 0; i < p_sizes.size(); i++) {
ret.write[rects[i].id] = { rects[i].x, rects[i].y, static_cast<bool>(rects[i].was_packed) }; ret.write[rects[i].id] = { rects[i].x, rects[i].y, static_cast<bool>(rects[i].was_packed) };
} }

View File

@@ -772,35 +772,35 @@ public:
END_ROUND END_ROUND
}; };
static Vector<Vector<Point2>> merge_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { static Vector<Vector<Point2>> merge_polygons_2d(const Span<Point2> &p_polygon_a, const Span<Point2> &p_polygon_b) {
return _polypaths_do_operation(OPERATION_UNION, p_polygon_a, p_polygon_b); return _polypaths_do_operation(OPERATION_UNION, p_polygon_a, p_polygon_b);
} }
static Vector<Vector<Point2>> clip_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { static Vector<Vector<Point2>> clip_polygons_2d(const Span<Point2> &p_polygon_a, const Span<Point2> &p_polygon_b) {
return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polygon_a, p_polygon_b); return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polygon_a, p_polygon_b);
} }
static Vector<Vector<Point2>> intersect_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { static Vector<Vector<Point2>> intersect_polygons_2d(const Span<Point2> &p_polygon_a, const Span<Point2> &p_polygon_b) {
return _polypaths_do_operation(OPERATION_INTERSECTION, p_polygon_a, p_polygon_b); return _polypaths_do_operation(OPERATION_INTERSECTION, p_polygon_a, p_polygon_b);
} }
static Vector<Vector<Point2>> exclude_polygons_2d(const Vector<Point2> &p_polygon_a, const Vector<Point2> &p_polygon_b) { static Vector<Vector<Point2>> exclude_polygons_2d(const Span<Point2> &p_polygon_a, const Span<Point2> &p_polygon_b) {
return _polypaths_do_operation(OPERATION_XOR, p_polygon_a, p_polygon_b); return _polypaths_do_operation(OPERATION_XOR, p_polygon_a, p_polygon_b);
} }
static Vector<Vector<Point2>> clip_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { static Vector<Vector<Point2>> clip_polyline_with_polygon_2d(const Span<Vector2> &p_polyline, const Span<Vector2> &p_polygon) {
return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polyline, p_polygon, true); return _polypaths_do_operation(OPERATION_DIFFERENCE, p_polyline, p_polygon, true);
} }
static Vector<Vector<Point2>> intersect_polyline_with_polygon_2d(const Vector<Vector2> &p_polyline, const Vector<Vector2> &p_polygon) { static Vector<Vector<Point2>> intersect_polyline_with_polygon_2d(const Span<Vector2> &p_polyline, const Span<Vector2> &p_polygon) {
return _polypaths_do_operation(OPERATION_INTERSECTION, p_polyline, p_polygon, true); return _polypaths_do_operation(OPERATION_INTERSECTION, p_polyline, p_polygon, true);
} }
static Vector<Vector<Point2>> offset_polygon_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) { static Vector<Vector<Point2>> offset_polygon_2d(const Span<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type) {
return _polypath_offset(p_polygon, p_delta, p_join_type, END_POLYGON); return _polypath_offset(p_polygon, p_delta, p_join_type, END_POLYGON);
} }
static Vector<Vector<Point2>> offset_polyline_2d(const Vector<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) { static Vector<Vector<Point2>> offset_polyline_2d(const Span<Vector2> &p_polygon, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type) {
ERR_FAIL_COND_V_MSG(p_end_type == END_POLYGON, Vector<Vector<Point2>>(), "Attempt to offset a polyline like a polygon (use offset_polygon_2d instead)."); ERR_FAIL_COND_V_MSG(p_end_type == END_POLYGON, Vector<Vector<Point2>>(), "Attempt to offset a polyline like a polygon (use offset_polygon_2d instead).");
return _polypath_offset(p_polygon, p_delta, p_join_type, p_end_type); return _polypath_offset(p_polygon, p_delta, p_join_type, p_end_type);
@@ -818,7 +818,7 @@ public:
return triangles; return triangles;
} }
static Vector<int> triangulate_polygon(const Vector<Vector2> &p_polygon) { static Vector<int> triangulate_polygon(const Span<Vector2> &p_polygon) {
Vector<int> triangles; Vector<int> triangles;
if (!Triangulate::triangulate(p_polygon, triangles)) { if (!Triangulate::triangulate(p_polygon, triangles)) {
return Vector<int>(); //fail return Vector<int>(); //fail
@@ -826,7 +826,7 @@ public:
return triangles; return triangles;
} }
static bool is_polygon_clockwise(const Vector<Vector2> &p_polygon) { static bool is_polygon_clockwise(const Span<Vector2> &p_polygon) {
int c = p_polygon.size(); int c = p_polygon.size();
if (c < 3) { if (c < 3) {
return false; return false;
@@ -843,7 +843,7 @@ public:
} }
// Alternate implementation that should be faster. // Alternate implementation that should be faster.
static bool is_point_in_polygon(const Vector2 &p_point, const Vector<Vector2> &p_polygon) { static bool is_point_in_polygon(const Vector2 &p_point, const Span<Vector2> &p_polygon) {
int c = p_polygon.size(); int c = p_polygon.size();
if (c < 3) { if (c < 3) {
return false; return false;
@@ -1008,14 +1008,14 @@ public:
static void sort_polygon_winding(Vector<Vector2> &r_verts, bool p_clockwise = true); static void sort_polygon_winding(Vector<Vector2> &r_verts, bool p_clockwise = true);
static real_t find_polygon_area(const Vector3 *p_verts, int p_num_verts); static real_t find_polygon_area(const Vector3 *p_verts, int p_num_verts);
static void make_atlas(const Vector<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size); static void make_atlas(const Span<Size2i> &p_rects, Vector<Point2i> &r_result, Size2i &r_size);
struct PackRectsResult { struct PackRectsResult {
int x; int x;
int y; int y;
bool packed; bool packed;
}; };
static Vector<PackRectsResult> partial_pack_rects(const Vector<Vector2i> &p_sizes, const Size2i &p_atlas_size); static Vector<PackRectsResult> partial_pack_rects(const Span<Vector2i> &p_sizes, const Size2i &p_atlas_size);
static Vector<Vector3> compute_convex_mesh_points(const Span<Plane> &p_planes, real_t p_epsilon = CMP_EPSILON); static Vector<Vector3> compute_convex_mesh_points(const Span<Plane> &p_planes, real_t p_epsilon = CMP_EPSILON);
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 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);
@@ -1023,8 +1023,8 @@ public:
static bool verify_indices(const int *p_indices, int p_num_indices, int p_num_vertices); static bool verify_indices(const int *p_indices, int p_num_indices, int p_num_vertices);
private: private:
static Vector<Vector<Point2>> _polypaths_do_operation(PolyBooleanOperation p_op, const Vector<Point2> &p_polypath_a, const Vector<Point2> &p_polypath_b, bool is_a_open = false); static Vector<Vector<Point2>> _polypaths_do_operation(PolyBooleanOperation p_op, const Span<Point2> &p_polypath_a, const Span<Point2> &p_polypath_b, bool is_a_open = false);
static Vector<Vector<Point2>> _polypath_offset(const Vector<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type); static Vector<Vector<Point2>> _polypath_offset(const Span<Point2> &p_polypath, real_t p_delta, PolyJoinType p_join_type, PolyEndType p_end_type);
}; };
#endif // GEOMETRY_H #endif // GEOMETRY_H

View File

@@ -30,7 +30,7 @@
#include "triangulate.h" #include "triangulate.h"
real_t Triangulate::get_area(const Vector<Vector2> &contour) { real_t Triangulate::get_area(const Span<Vector2> &contour) {
int n = contour.size(); int n = contour.size();
const Vector2 *c = &contour[0]; const Vector2 *c = &contour[0];
@@ -78,7 +78,7 @@ bool Triangulate::is_inside_triangle(real_t Ax, real_t Ay,
} }
} }
bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V, bool relaxed) { bool Triangulate::snip(const Span<Vector2> &p_contour, int u, int v, int w, int n, const Span<int> &V, bool relaxed) {
int p; int p;
real_t Ax, Ay, Bx, By, Cx, Cy, Px, Py; real_t Ax, Ay, Bx, By, Cx, Cy, Px, Py;
const Vector2 *contour = &p_contour[0]; const Vector2 *contour = &p_contour[0];
@@ -117,7 +117,7 @@ bool Triangulate::snip(const Vector<Vector2> &p_contour, int u, int v, int w, in
return true; return true;
} }
bool Triangulate::triangulate(const Vector<Vector2> &contour, Vector<int> &result) { bool Triangulate::triangulate(const Span<Vector2> &contour, Vector<int> &result) {
/* allocate and initialize list of Vertices in polygon */ /* allocate and initialize list of Vertices in polygon */
int n = contour.size(); int n = contour.size();

View File

@@ -41,10 +41,10 @@ class Triangulate {
public: public:
// triangulate a contour/polygon, places results in STL vector // triangulate a contour/polygon, places results in STL vector
// as series of triangles. // as series of triangles.
static bool triangulate(const Vector<Vector2> &contour, Vector<int> &result); static bool triangulate(const Span<Vector2> &contour, Vector<int> &result);
// compute area of a contour/polygon // compute area of a contour/polygon
static real_t get_area(const Vector<Vector2> &contour); static real_t get_area(const Span<Vector2> &contour);
// decide if point Px/Py is inside triangle defined by // decide if point Px/Py is inside triangle defined by
// (Ax,Ay) (Bx,By) (Cx,Cy) // (Ax,Ay) (Bx,By) (Cx,Cy)
@@ -55,7 +55,7 @@ public:
bool include_edges); bool include_edges);
private: private:
static bool snip(const Vector<Vector2> &p_contour, int u, int v, int w, int n, const Vector<int> &V, bool relaxed); static bool snip(const Span<Vector2> &p_contour, int u, int v, int w, int n, const Span<int> &V, bool relaxed);
}; };
#endif // TRIANGULATE_H #endif // TRIANGULATE_H

View File

@@ -424,6 +424,9 @@ public:
return find(p_val) != -1; return find(p_val) != -1;
} }
_FORCE_INLINE_ Span<T> span() const { return Span(read().ptr(), (uint32_t)size()); }
_FORCE_INLINE_ operator Span<T>() const { return span(); }
inline int size() const; inline int size() const;
inline bool empty() const; inline bool empty() const;
T get(int p_index) const; T get(int p_index) const;

View File

@@ -239,7 +239,7 @@ bool CollisionPolygon2D::_edit_use_rect() const {
} }
bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { bool CollisionPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
return Geometry::is_point_in_polygon(p_point, Variant(polygon)); return Geometry::is_point_in_polygon(p_point, polygon);
} }
#endif #endif

View File

@@ -68,7 +68,7 @@ Rect2 OccluderPolygon2D::_edit_get_rect() const {
bool OccluderPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { bool OccluderPolygon2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const {
if (closed) { if (closed) {
return Geometry::is_point_in_polygon(p_point, Variant(polygon)); return Geometry::is_point_in_polygon(p_point, polygon);
} else { } else {
const real_t d = LINE_GRAB_WIDTH / 2 + p_tolerance; const real_t d = LINE_GRAB_WIDTH / 2 + p_tolerance;
PoolVector<Vector2>::Read points = polygon.read(); PoolVector<Vector2>::Read points = polygon.read();

View File

@@ -73,7 +73,7 @@ bool NavigationPolygon::_edit_is_selected_on_click(const Point2 &p_point, double
if (outline_size < 3) { if (outline_size < 3) {
continue; continue;
} }
if (Geometry::is_point_in_polygon(p_point, Variant(outline))) { if (Geometry::is_point_in_polygon(p_point, outline)) {
return true; return true;
} }
} }