| Home | Rumble | Youtube | Twitter/X | Kofi | Contact / Crypto |
|---|
|
Polygons in c3dlas are 2-dimensional, "simple" polygons. They can be convex and concave, and can be sometimes be self-intersecting, but cannot
have holes. There is currently no support for 3D arbitrary polygons. The polygon consists of a loop of points held in
Centroid is the average of all the points, and maxRadiusSq is the squared distance of the farthest point from the centroid. The pair can be
used for cheap early rejection of intersections. Some functions that modify the polygon invalidate these stats and fill them with
Basic Operationsvoid polyFreeInternals(Polygon* poly) O(1) Free all internal memory.
void polyPushPoint(Polygon* poly, vec2 p) O(1) Adds a point to the end of the polygon point list. Stats need to be recalculated afterward.
void polyInsertPoint(Polygon* poly, int index, vec2 p) O(n) Insert a point at a specific index of the polygon point list. Index can be negative, but should be in the
range [-pointCount+1, pointCount] inclusive. Stats need to be recalculated afterward.
void polyCopy(Polygon* dst, Polygon* src) O(n) Makes a full deep copy of the source polygon.
void polyReverse(Polygon* poly) O(n) Reverses the point list, which flips the winding.
int polyGetWinding(Polygon* poly) O(1) Calculates the polygon winding and returns C3DLAS_CCW (counter-clockwise) or C3DLAS_CW (clockwise).
void polyEnsureCCW(Polygon* poly) O(n), if not already CCW Calculates the polygon winding and reverses the point list if not already CCW.
void polyEnsureCW(Polygon* poly) O(n), if not already CW Calculates the polygon winding and reverses the point list if not already CW.
Statsfloat polyCalcArea(Polygon* poly)
float polyCalcSignedArea(Polygon* poly) O(n) Calculates the signed or unsigned area of the polygon.
void polyCalcMinExtrema(Polygon* poly) O(n) Updates minExtrema index. This is usually tracked internally automatically, and you only need to call this function if
you have manually changed the points array.
AABB2 polyCalcBounds(Polygon* poly) O(n) Calculates the minimal axis-aligned bounding box that contains the polygon.
void polyCalcStats(Polygon* poly) O(n) Updates both the centroid and squared radius after operations that invalidate them.
void polyCalcCentroid(Polygon* poly) O(n) Updates the centroid after operations that invalidate it.
void polyCalcRadiusSq(Polygon* poly) O(n) Updates the squared radius from the centroid after operations that invalidate it. The centroid must already be valid.
int polyIsSelfIntersecting(Polygon* poly) O(n^2) Checks if the polygon is self-intersecting. Returns C3DLAS_TRUE or C3DLAS_FALSE.
Geometric Tests// returns 1 if the polygon needs a more precise check, and 0 if the polygon is definitely farther away than the radius int polyCheckMaybeWithinRadius(Polygon* poly, vec2 p, float radius);int polyCheckMaybeWithinRadius(Polygon* poly, vec2 p, float radius) O(1) Checks if the test point maybe is or definitely is not within a distance of radius outside of the polygon.
Internally it does a basic check against centroid and maxRadiusSq. Returns C3DLAS_TRUE or C3DLAS_FALSE. Centroid and maxRadiusSq
must be valid; GIGO.
int mm8_polyCheckMaybeWithinRadius_group(Polygon* poly, float px[8], float py[8], float radius)
int mm16_polyCheckMaybeWithinRadius_group(Polygon* poly, float px[16], float py[16], float radius)
int mm32_polyCheckMaybeWithinRadius_group(Polygon* poly, float px[32], float py[32], float radius) O(1) These functions use AVX SIMD code, if available, to run the polyCheckMaybeWithinRadius algorithm with the same polygon on 8, 16, or 32 test points
at the same time for approximately the same cost as a single call to polyCheckMaybeWithinRadius(), and performs a logical OR on the results.
If SIMD intrinsics are not supported, these functions automatically degrade to whatever is supported.
int polyContainsPoint(Polygon* poly, vec2 p) O(n) Returns C3DLAS_TRUE or C3DLAS_FALSE depending on if the point is inside the polygon. I don't know how it handles self-intersecting
polygons as I never use them.
float polyDistToPoint(Polygon* poly, vec2 p) O(n) Returns the distance from p to the closest point on the polygon. Interior distances are negative.
void mm8_polyDistToPoint(Polygon* poly, float px[8], float py[8], float out[8])
void mm16_polyDistToPoint(Polygon* poly, float px[16], float py[16], float out[16])
void mm32_polyDistToPoint(Polygon* poly, float px[32], float py[32], float out[32]) O(n) These functions use AVX SIMD code, if available, to run the polyDistToPoint algorithm with the same polygon on 8, 16, or 32 test points
at the same time for approximately the same cost as a single call to polyDistToPoint(). If SIMD intrinsics are not supported, these functions
automatically degrade to whatever is supported.
int polyCheckIntersect(Polygon* a, Polygon* b) O(a*b) Checks if the lines of the two polygons intersect, but does not detect if one polygon is entirely contained within the other.
Complete containment can be checked separately if desired by checking if the first point of a is inside b or vice versa; if the polygons
are not intersecting according to this function and one point of a is inside b, then all points of a are inside b.
Returns C3DLAS_INTERSECT or C3DLAS_DISJOINT. Uses centroid and maxRadiusSq if valid for early rejection.
int polyIntersect(Polygon* a, Polygon* b, int (*out_fn)(vec2 p, long seg_a, long seg_b, void* data), void* out_data) O(a*b) Calls
float polyMinDistToPoly(Polygon* a, Polygon* b, int* a_is_inside_b) O(a*b) There are three scenarios:
Geometric Operationsvoid polySubdivide(Polygon* poly, int degree) O(n) Subdivides each segment into
void polyCombineClosePoints(Polygon* poly, float dist) O(n) Walks along poly and deletes the next point if it's within dist of the current one.
void polyExteriorUnion(Polygon* a, Polygon* b, Polygon* poly) fucking complicated dynamic algorithm, at least O(a*b) Creates a polygon representing a shrink-wrapped hull around the union of the two inputs. All internal holes that would have been created in the
union are eliminated. Both polygons must be wound in the same direction. Returns C3DLAS_INTERSECT if the union was successful and C3DLAS_DISJOINT
if they don't intersect. If it returns disjoint then out will be a copy of either a or b.
void polyUnSelfIntersect(Polygon* poly) O(n^2) Works like polyExteriorUnion(), except only with itself. It produces a polygon that is not self-intersecting, but not necessarily the optimal
one from any given perspective.
void polyExtrude(Polygon* poly, float dist, Polygon* out) O(n) Creates a new larger polygon by moving each point along a line out from the center of each corner far enough to create dist perpendicular
separation between the original polygon edge and the new one. Only works on convex polygons.
void polyExtrude2(Polygon* poly, float dist, Polygon* out) O(n) Creates a new larger polygon by breaking the original one into individual segments, moving them outward by dist, then adding new lines connecting
those segments end to end. This can easily create self-intersecting polygons, so you should probably call polyUnSelfIntersect() on the result.
void polySortCCW(Polygon* poly) O(n log n) Calculates the centroid of all the points then does a radial sort around that point. Niche use; dosn't do what you might think it does. It was
originally built to create polygons representing the road-intersections of a road network based on the end points of the road segments.
|
|||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||