Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wrong sum in Survey Area #764

Closed
wolkstein opened this issue May 12, 2014 · 6 comments
Closed

wrong sum in Survey Area #764

wolkstein opened this issue May 12, 2014 · 6 comments

Comments

@wolkstein
Copy link

hi,
i noticed a wrong result in calculated Area in m² if you create a Survey Polygon.
maybe this change in will fix getArea() in GeoTools. i am not sure if each polygon will calculated right. but some tests here produce good results. i use a known soccer field (FIFA-Norm105,00m x68,00m = 7.140,00 m²) to test the m² results.

new getArea() using simple Shoelace formula 2A = n SUM i=1(yi+ yi+1)(xi-xi+1). i use relative x and y values to reduce cpu load and prevent double overflow.

/**
     * Experimental Function, needs testing! Calculate the area of the polygon
     * 
     * @return area in m²
     */
    // TODO test and fix this function
    public static Area getArea(Polygon poly) {
        double sum = 0.0;
        int length = poly.getPoints().size();
        for (int i = 0; i < length - 1; i++) {
            // using relative x and y values reduce load
            // relative xi to x0, x0 = 0
            double x = latToMeters(poly.getPoints().get(i).getX()) - latToMeters(poly.getPoints().get(0).getX());
            // relative xi+1 to x0
            double xx = latToMeters(poly.getPoints().get(i + 1).getX()) - latToMeters(poly.getPoints().get(0).getX());
            // relative yi to y 0, y0 = 0
            double y = latToMeters(poly.getPoints().get(i).getY()) - latToMeters(poly.getPoints().get(0).getY());
            // relative yi+1 to y0
            double yy = latToMeters(poly.getPoints().get(i + 1).getY()) - latToMeters(poly.getPoints().get(0).getY());

            // Shoelace formula 2A = [n SUM i=1](yi+ yi+1)(xi-xi+1)
            // using variables here for better reading
            // no Math.abs here! trying "Math.abs((y + yy)*(x-xx)) / 2" produce random results in m² end sum.
            sum += (y + yy)*(x-xx) / 2;
        }
        // second A/2!? this is strange but works. we divide A / 2 in "sum += ..." two lines before
        return new Area(Math.abs(sum) / 2);
    }

/g
wolke

@arthurbenemann
Copy link
Member

@wolkstein That's great. Do you want to submit this as a pull request via git/github? That way your name will be logged into the history of the project.

Also if you could send me a set of coordinates, and the area contained in them I can write a unit test to make sure that this function will always return the correct value. Especialy if someone changes it in the future.

@wolkstein
Copy link
Author

hey,
i found a new problem with this code. if you draw the polygon counter-clockwise the result is wrong. :(. normally Shoelace formula produce positive values for each trapeze if the polygon points run cw and negative results if the points run in ccw direction. but after some more tests i noticed that points returned from poly produce sometimes positive and/or negative results in one for loop(one direction). maybe poly class returned points sorted. if i found more time, i will take a deeper look into this. at least calculating an polygon surface is a simple task with shoelace formula. so i do not understand why it makes so many problems here.

@arthurbenemann
Copy link
Member

@wolkstein Give me a set of coordinates, and the area contained in those and I can write a test to help in the development.

@wolkstein
Copy link
Author

ok, i will crate a test polygon with reference coordinates and area. i noticed that a soccer field is not so good because simple geometry. i think i will create something like a irregular pentagram.

@wolkstein
Copy link
Author

hi,
here are an polygon. t looks like an paper-sailboat sillouette.

Point, Lat, Long
1, 51,0282781100882, 2,16705322265625
2, 51,0317878663996, 2,16293267905712
3, 51,0313285768174, 2,16915607452393
4, 51,0349709823585, 2,17203207314014
5, 51,0318104275059, 2,17568457126617
6, 51,0326774403918, 2,18168333172798
7, 51,028521872254, 2,18014307320118

Hopefully i do a right calculation the surface area is 502915m²
defined as polygon point 8 = point 1

@arthurbenemann
Copy link
Member

@wolkstein I added the test case in #770. You can run if you checkout the https://github.com/arthurbenemann/droidplanner/tree/issue764 branch, and in eclipse select the CORE project and click "Run as Junit test". Here is the test file if you want to check:
https://github.com/arthurbenemann/droidplanner/blob/issue764/Core/test/org/droidplanner/core/helpers/geoTools/GeoToolsTest.java

With the code that you provided the result is:
junit.framework.AssertionFailedError: expected:<502915.0> but was:<389665.7608050064>

With the old code (current master):
junit.framework.AssertionFailedError: expected:<502915.0> but was:<799101.5992431641>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants