I'm trying to draw a smaller filled polygon (which are always convex not self-intersecting quadrangles in my case) over another filled polygon to get an impression of a border around that filled polygon. To do that I've found out how to calculate the centroid of quadrangle - it will be a point around which the smaller filled polygon will be scaled down. I've copied the algorithm from here: https://math.stackexchange.com/a/2878092
And here's a full code of the class:
public class BodyPartActor extends Actor {
private static TextureRegion textureRegion = Globals.getTextureRegion();
private static Color borderColor = Assets.getSkin().getColor("pink");
private static Color bodyPartColor = Assets.getSkin().getColor("green");
private static short[] triangles = new short[] {
0, 1, 2, // Two triangles using vertex indices.
0, 2, 3 // Take care of the counter-clockwise direction.
};
private PolygonRegion polygonRegion;
private BodyPart bodyPart;
private Vector2 centroid;
public BodyPartActor(BodyPart bodyPart) {
this.bodyPart = bodyPart;
polygonRegion = new PolygonRegion(textureRegion, this.bodyPart.getVertices(), triangles);
centroid = getCentroidOfQuadrangle();
}
private Vector2 getCentroidOfQuadrangle() {
float[] v = bodyPart.getVertices();
Vector2 centroidA = getCentroidOfTriangle(new float[]{v[0], v[1], v[2], v[3], v[4], v[5]});
Vector2 centroidB = getCentroidOfTriangle(new float[]{v[2], v[3], v[4], v[5], v[6], v[7]});
Vector2 centroidC = getCentroidOfTriangle(new float[]{v[4], v[5], v[6], v[7], v[0], v[1]});
Vector2 centroidD = getCentroidOfTriangle(new float[]{v[6], v[7], v[0], v[1], v[2], v[3]});
return getPointOfLinesIntersection(centroidA, centroidC, centroidB, centroidD);
}
private Vector2 getCentroidOfTriangle(float[] vertices) {
return new Vector2 (
(vertices[0] + vertices[2] + vertices[4]) / 3,
(vertices[1] + vertices[3] + vertices[5]) / 3
);
}
private Vector2 getPointOfLinesIntersection(Vector2 startLineA, Vector2 endLineA, Vector2 startLineB,
Vector2 endLineB) {
float detOfLineA = det2x2(startLineA.x, startLineA.y, endLineA.x, endLineA.y);
float detOfLineB = det2x2(startLineB.x, startLineB.y, endLineB.x, endLineB.y);
float xDeltaOfLineA = startLineA.x - endLineA.x;
float xDeltaOfLineB = startLineB.x - endLineB.x;
float yDeltaOfLineA = startLineA.y - endLineA.y;
float yDeltaOfLineB = startLineB.y - endLineB.y;
float xNom = det2x2(detOfLineA, xDeltaOfLineA, detOfLineB, xDeltaOfLineB);
float yNom = det2x2(detOfLineA, yDeltaOfLineA, detOfLineB, yDeltaOfLineB);
float deNom = det2x2(xDeltaOfLineA, yDeltaOfLineA, xDeltaOfLineB, yDeltaOfLineB);
return new Vector2(xNom / deNom, yNom / deNom);
}
/**
* Calculate determinant of a 2x2 matrix:
* |a b|
* |c d|
*/
private float det2x2(float a, float b, float c, float d) {
return (a * d) - (b * c);
}
@Override
public void draw(Batch batch, float parentAlpha) {
float x = bodyPart.getBody().getPosition().x;
float y = bodyPart.getBody().getPosition().y;
float width = polygonRegion.getRegion().getRegionWidth();
float height = polygonRegion.getRegion().getRegionHeight();
float originX = centroid.x;
float originY = centroid.y;
float rotation = calculateRotation(originX, originY);
PolygonSpriteBatch polygonSpriteBatch = (PolygonSpriteBatch) batch;
polygonSpriteBatch.setColor(borderColor.r, borderColor.g, borderColor.b, borderColor.a * parentAlpha);
polygonSpriteBatch.draw(polygonRegion, x, y, originX, originY, width, height, 1f, 1f, rotation);
polygonSpriteBatch.setColor(bodyPartColor.r, bodyPartColor.g, bodyPartColor.b, bodyPartColor.a * parentAlpha);
polygonSpriteBatch.draw(polygonRegion, x, y, originX, originY, width, height, 0.9f, 0.9f, rotation);
}
private float calculateRotation(float originX, float originY) {
// How to calculate when originX and originY are the center of quadrangle???
return bodyPart.getBody().getAngle() * MathUtils.radiansToDegrees; // Works only if originX and originY are 0.
}
}
It seems to the calculate centroid correctly, I checked it here: http://eguruchela.com/math/Calculator/polygon-centroid-point but the resulting borders doesn't look okay. I even thought there's some floating-point arithmetic issues in libGDX when calculating vertices positions but I couldn't found any, so I don't know where's the problem. There's also an issue with rotation, because now I'm drawing with origin point at the centroid of quadrangle, so it doesn't render properly (before trying to draw a border, originX and originY were 0, which made correct rendering rotated bodies correct, now it doesn't align how it should).
Do you know how to render properly this border and with proper rotation of the polygon? Or maybe the whole approach to this problem is wrong and there's a better way to do that?