Skip to content

Commit a87c8bb

Browse files
committed
Expand convex hull bounds by half a pixel per side
1 parent 283ef3e commit a87c8bb

File tree

2 files changed

+35
-31
lines changed

2 files changed

+35
-31
lines changed

src/Drawable.js

+34-2
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,38 @@ class Drawable {
503503
return this.skin.isTouchingLinear(getLocalPosition(this, vec));
504504
}
505505

506+
/**
507+
* Initialize a bounding rectangle with a set of convex hull points, taking into account that the points refer to
508+
* pixel centers and not pixel edges.
509+
* @param {Rectangle} rect The bounding rectangle to initialize
510+
* @param {Array<Array.number>} points The convex hull points
511+
*/
512+
_initRectangleFromConvexHullPoints (rect, points) {
513+
rect.left = Infinity;
514+
rect.right = -Infinity;
515+
rect.top = -Infinity;
516+
rect.bottom = Infinity;
517+
518+
// Each convex hull point is the center of a pixel. However, said pixels each have area. We must take into
519+
// account the size of the pixels when calculating the bounds. The pixel dimensions depend on the scale and
520+
// rotation (as we're treating pixels as squares, which change dimensions when rotated).
521+
522+
// The "Scratch-space" size of one texture pixel at the drawable's current size.
523+
const pixelScale = (this.scale[0] / 100) * (this.skin.size[0] / this.skin._silhouette._width);
524+
// Half the size of a rotated pixel, if we assume pixels are shaped like squares.
525+
// At 0 degrees of rotation, this will be 0.5. At 45 degrees, it'll be 0.707 (half the square root of 2), etc.
526+
const halfPixel = (Math.abs(this._rotationMatrix[0]) + Math.abs(this._rotationMatrix[1])) * 0.5 * pixelScale;
527+
528+
for (let i = 0; i < points.length; i++) {
529+
const x = points[i][0];
530+
const y = points[i][1];
531+
if ((x - halfPixel) < rect.left) rect.left = x - halfPixel;
532+
if ((x + halfPixel) > rect.right) rect.right = x + halfPixel;
533+
if ((y + halfPixel) > rect.top) rect.top = y + halfPixel;
534+
if ((y - halfPixel) < rect.bottom) rect.bottom = y - halfPixel;
535+
}
536+
}
537+
506538
/**
507539
* Get the precise bounds for a Drawable.
508540
* This function applies the transform matrix to the known convex hull,
@@ -521,7 +553,7 @@ class Drawable {
521553
const transformedHullPoints = this._getTransformedHullPoints();
522554
// Search through transformed points to generate box on axes.
523555
result = result || new Rectangle();
524-
result.initFromPointsAABB(transformedHullPoints);
556+
this._initRectangleFromConvexHullPoints(result, transformedHullPoints);
525557
return result;
526558
}
527559

@@ -545,7 +577,7 @@ class Drawable {
545577
const filteredHullPoints = transformedHullPoints.filter(p => p[1] > maxY - slice);
546578
// Search through filtered points to generate box on axes.
547579
result = result || new Rectangle();
548-
result.initFromPointsAABB(filteredHullPoints);
580+
this._initRectangleFromConvexHullPoints(result, filteredHullPoints);
549581
return result;
550582
}
551583

src/Rectangle.js

+1-29
Original file line numberDiff line numberDiff line change
@@ -26,34 +26,6 @@ class Rectangle {
2626
this.top = top;
2727
}
2828

29-
/**
30-
* Initialize a Rectangle to the minimum AABB around a set of points.
31-
* @param {Array<Array<number>>} points Array of [x, y] points.
32-
*/
33-
initFromPointsAABB (points) {
34-
this.left = Infinity;
35-
this.right = -Infinity;
36-
this.top = -Infinity;
37-
this.bottom = Infinity;
38-
39-
for (let i = 0; i < points.length; i++) {
40-
const x = points[i][0];
41-
const y = points[i][1];
42-
if (x < this.left) {
43-
this.left = x;
44-
}
45-
if (x > this.right) {
46-
this.right = x;
47-
}
48-
if (y > this.top) {
49-
this.top = y;
50-
}
51-
if (y < this.bottom) {
52-
this.bottom = y;
53-
}
54-
}
55-
}
56-
5729
/**
5830
* Initialize a Rectangle to a 1 unit square centered at 0 x 0 transformed
5931
* by a model matrix.
@@ -123,7 +95,7 @@ class Rectangle {
12395
this.right = Math.min(this.right, right);
12496
this.bottom = Math.max(this.bottom, bottom);
12597
this.top = Math.min(this.top, top);
126-
98+
12799
this.left = Math.min(this.left, right);
128100
this.right = Math.max(this.right, left);
129101
this.bottom = Math.min(this.bottom, top);

0 commit comments

Comments
 (0)