Hey, before i start I've seen this one already on forums, as i remember our BrainFree mentioned it.
Because my engrish is really bad, i will try to provide links instead writing how it works. So here it is one more time: Convex hull is generally tightest area of point set. So what we want to do is to calculate 2D points of our object, entity and make convex hull for it for perfect bounding polygon, it will be really helpfull on fighter scripts or any script that needs to interact alot, it will fail less time. Bounding box you were using:
What we want to accomplish:
As you see we have some blind spots on basic rect bounding box:
Red - hulling will reduce them. Yellow - hulling will not reduce them (actually the one i want to show)
It is not really necessary to remove yellow ones so w/e. The thing is we want to shink area a little bit to be more precise when interacting.
So the algorithm is like this:
/**
* Making convex hull around points.
*
* @param points - the points
* @return - the convex hull points points.
*/
public static short[][] hull(short[][] points) {
int upperSize = 2;
int lowerSize = 2;
int pointsSize = points.length;
short[][] lUpper = new short[pointsSize][2];
short[][] lLower = new short[pointsSize][2];
short[][] xSorted = points.clone();
Arrays.sort(xSorted, new Comparator<short[]>() {
@Override
public int compare(short[] o1, short[] o2) {
return Integer.compare(o1[0], o2[0]);
}
});
lUpper[0] = xSorted[0];
lUpper[1] = xSorted[1];
lLower[0] = xSorted[pointsSize - 1];
lLower[1] = xSorted[pointsSize - 2];
for (int i = 2; i < pointsSize; i++) {
lUpper[upperSize] = xSorted[i];
upperSize++;
while (upperSize > 2 && !rightTurn(lUpper[upperSize - 3], lUpper[upperSize - 2], lUpper[upperSize - 1])) {
lUpper[upperSize - 2] = lUpper[upperSize - 1];
upperSize--;
}
}
for (int i = pointsSize - 3; i >= 0; i--) {
lLower[lowerSize] = xSorted[i];
lowerSize++;
while (lowerSize > 2 && !rightTurn(lLower[lowerSize - 3], lLower[lowerSize - 2], lLower[lowerSize - 1])) {
lLower[lowerSize - 2] = lLower[lowerSize - 1];
lowerSize--;
}
}
short[][] result = new short[upperSize + lowerSize - 1][2];
System.arraycopy(lUpper, 0, result, 0, upperSize);
System.arraycopy(lLower, 0, result, upperSize, lowerSize - 1);
return result;
}
/**
* Checks if points turns right.
*
* @param a - the 'a' point.
* @param b - the 'b' point.
* @param c - the 'c' point.
* @return
*/
private static boolean rightTurn(short[] a, short[] b, short[] c) {
return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]) > 0;
}
(I ddnt made it as i remember but i cant find real author) What do you need to read to understand this algorithm:
http://en.wikipedia.org/wiki/Convex_hull
en.wikipedia.org/wiki/Graham_scan
/**
* Converting points to polygon.
*
* @param points - the - the points.
* @return the polygon based on points.
*/
public static Polygon toPolygon(short[][] points) {
Polygon result = new Polygon();
for (short[] point : points) {
result.addPoint(point[0], point[1]);
}
return result;
}
How to implement :
First we need to get screen coords:
http://osbot.org/osbot2_api/org/osbot/rs07/api/util/GraphicUtilities.html#getScreenCoordinates%28org.osbot.rs07.Bot,%20int,%20int,%20int,%20org.osbot.rs07.api.model.Model%29
Then we make hull based on points:
hull(screenCoordinates);
Example for dumbs:
Entity litara = npcs.closest("Litara");
short[][] screenCoordinates = Calculations.getScreenCoordinates(this, litara.getGridX(), litara.getGridY(), litara.getZ(), litara.getModel());
short[][] hull = Calculations.hull(screenCoordinates);
g.draw(Calculations.toPolygon(hull));