Calculating every cartesian point in a circle

2019-07-19 05:07发布

I have an array: int[][] lawn = new int[980][1280];

wich stores the values of the height of the blades in the lawn.

In my simulation i have a robot that goes around the lawn and cuts the blades.

my robot has the form of a circle with a diameter (rDiameter). The coordinate system is done with Double and my lawn is in Integer.

I have developped two "algorithms" that allows the robot to cut the lawn but i'm not satisfied because the precisions of my algorithms is not high enough and the performance also.

My question is, is there a way to do this other than the ideas that I have already thought of?

Or do I need to change the implementation of my lawn to get better results?

Feel free to ask anything if i was not clear enough.

Here is the code for my two algorithms (k stands for the robot), centerPosition returns the center of my robot(so the center of the circle)

approach with square
    int bottomLeftCornerX = (int) (k.getCenterPosition().getX() - simulParams.getKDiameter() / 2);
    int bottomLeftCornerY = (int) (k.getCenterPosition().getY() - simulParams.getKDiameter() / 2);

    for (int i = bottomLeftCornerX; i < bottomLeftCornerX + simulParams.getKDiameter(); i++) {
        for (int j = bottomLeftCornerY; j < bottomLeftCornerY + simulParams.getKDiameter(); j++) {
            ((LawnArea) lawn.getBladeHeight()).cutBladeInArea(j, i);
        }
    }

And here the one with the circle approach (basically it's the circonference formule present in wikipedia...):

for (int r = 0; r < simulParams.getKDiameter() / 2; r++) {

        for (double t = 0; t < 2 * Math.PI; t = t + 0.1) {
            Point2D p = circumference(k.getCenterPosition().getX(), k.getCenterPosition().getY(), t, r);
            int intX = (int) Math.ceil(p.getX());
            int intY = (int) Math.ceil(p.getY());
                ((LawnArea) lawn.getBladeHeight()).cutBladeInArea(intY, intX);
            }
        }
    }

2条回答
可以哭但决不认输i
2楼-- · 2019-07-19 05:48

For readability: k.x is the x coordinate, k.y is the y coordinate, k.r is the radius.

for(int y = (int)Math.max(0, Math.ceil(k.y - k.r)); y <= (int)Math.min(980, Math.floor(k.y + k.r)); y++) {
    doulbe dx = Math.sqrt(k.r * k.r - Math.abs(y-k.y) * Math.abs(y-k.y));
    for(int x = Math.max(0, (int)Math.ceil(k.x - dx)); x <= (int)Math.min(1280, Math.floor(k.x + dx)); x++) {
        cut(x,y);
    }
}

There are two loops:
The first one is for the y-coordinate and starts at k.y - k.r and goes until k.y + k.r if the circle is completly on the field (I didn't know if it always was, if yes then you can't reach the corners), so from the top to the bottom of your screen.
The second one is for the x coordinate. The smalles and biggest x are calculated with the help of the formular (k.x - x)² + (k.y - y)² = k.r².
With that you only get points in your circle. It's a little smaller because of double to int conversion.

查看更多
▲ chillily
3楼-- · 2019-07-19 05:48

The first approach (based on a bounding box) is a good start. But you now just need to add a conditional that checks whether each point inside the bounding box is also in the circle.

Something like:

for each (point p inside bounding-box) {
    if (p inside circle centred at k) {
        cutBlade(p);
    }
}

You can improve this by noticing that in each row (or column) of the bounding box, the set of blades that need to be cut are all neighbours. If you calculate the end-points of this range, then you don't need any conditionals.

Something like:

for each (x inside bounding-box) {
    calculate y_first;
    calculate y_last;
    for (y = y_first; y < y_last; y++) {
        cutBlade(x,y);
    }
}
查看更多
登录 后发表回答