StackOverflowError during Circle.linearizeArc

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

StackOverflowError during Circle.linearizeArc

Daniel Beer
Hi,

yesterday I ran into a StackOverflowError while reading geometries (lines) out of an Oracle DB.
The stack trace revealed an infinite recursion at org.hibernatespatial.Circle.linearizeInternal().

I was able to reproduce the error using the following code:

double x1 = 454033778;
double y1 = 601560635;
double x2 = 454033765;
double y2 = 601560632;
double x3 = 454033761;
double y3 = 601560638;
org.hibernatespatial.Circle.linearizeArc(x1, y1, x2, y2, x3, y3);

The values are from real data using centimeter as unit.
Those points are located quite close to each other, as you can see. The radius of the described circle is only approx. 10 cm.
Presumably the linearization algorithm is numerically unstable when using this kind of data (close to each other but high absolute value).
Especially the method org.hibernatespatial.Circle.initThreePointCircle uses subtraction of squared ordinates which will lead to a loss of precision.

A workaround which I tested already successfully is the following:
1. Shift the source coordinates towards the point of origin, hence obtaining coordinates with lower absolute value but the same relation to each other.
2. Then perform the linearization which will terminate as expected.
3. Finally shift the resulting coordinates back to its original location.

Considering how org.hibernatespatial.Circle.initThreePointCircle works it would be beneficial to shift the third coordinate (namely "p3") into the point of origin, hence getting lots of zeros.

Please find a code example below (modified method "linearizeArc"):

public static Coordinate[] linearizeArc(double x1, double y1, double x2,
                double y2, double x3, double y3) {
        Coordinate p1 = new Coordinate(x1 - x3, y1 - y3);
        Coordinate p2 = new Coordinate(x2 - x3, y2 - y3);
        Coordinate p3 = new Coordinate(0, 0);
        Circle c = new Circle(p1, p2, p3);
        double tolerence = 0.01 * c.getRadius();
        return shiftAll(c.linearizeArc(p1, p2, p3, tolerence), x3, y3);
}

private static Coordinate[] shiftAll(Coordinate[] coords, double x, double y) {
        for (Coordinate coord : coords) {
                coord.x += x;
                coord.y += y;
        }
        return coords;
}

Similar things should be done for the other static linearizeArc() method as well as for linearizeCircle().

Could you please fix this issue in the next release?
Thanks!
_______________________________________________
hibernatespatial-users mailing list
[hidden email]
http://www.hibernatespatial.org/cgi-bin/mailman/listinfo/hibernatespatial-users
Reply | Threaded
Open this post in threaded view
|

Re: StackOverflowError during Circle.linearizeArc

Karel Maesen
Administrator
Hello Daniel,

Thanks for the report. I created an bug report for this issue: http://www.hibernatespatial.org/jira/browse/HIBSPA-84

I'll fix it in the next release.

Regards,

Karel

On 30 May 2011, at 18:09, Daniel Beer wrote:

> Hi,
>
> yesterday I ran into a StackOverflowError while reading geometries (lines) out of an Oracle DB.
> The stack trace revealed an infinite recursion at org.hibernatespatial.Circle.linearizeInternal().
>
> I was able to reproduce the error using the following code:
>
> double x1 = 454033778;
> double y1 = 601560635;
> double x2 = 454033765;
> double y2 = 601560632;
> double x3 = 454033761;
> double y3 = 601560638;
> org.hibernatespatial.Circle.linearizeArc(x1, y1, x2, y2, x3, y3);
>
> The values are from real data using centimeter as unit.
> Those points are located quite close to each other, as you can see. The radius of the described circle is only approx. 10 cm.
> Presumably the linearization algorithm is numerically unstable when using this kind of data (close to each other but high absolute value).
> Especially the method org.hibernatespatial.Circle.initThreePointCircle uses subtraction of squared ordinates which will lead to a loss of precision.
>
> A workaround which I tested already successfully is the following:
> 1. Shift the source coordinates towards the point of origin, hence obtaining coordinates with lower absolute value but the same relation to each other.
> 2. Then perform the linearization which will terminate as expected.
> 3. Finally shift the resulting coordinates back to its original location.
>
> Considering how org.hibernatespatial.Circle.initThreePointCircle works it would be beneficial to shift the third coordinate (namely "p3") into the point of origin, hence getting lots of zeros.
>
> Please find a code example below (modified method "linearizeArc"):
>
> public static Coordinate[] linearizeArc(double x1, double y1, double x2,
> double y2, double x3, double y3) {
> Coordinate p1 = new Coordinate(x1 - x3, y1 - y3);
> Coordinate p2 = new Coordinate(x2 - x3, y2 - y3);
> Coordinate p3 = new Coordinate(0, 0);
> Circle c = new Circle(p1, p2, p3);
> double tolerence = 0.01 * c.getRadius();
> return shiftAll(c.linearizeArc(p1, p2, p3, tolerence), x3, y3);
> }
>
> private static Coordinate[] shiftAll(Coordinate[] coords, double x, double y) {
> for (Coordinate coord : coords) {
> coord.x += x;
> coord.y += y;
> }
> return coords;
> }
>
> Similar things should be done for the other static linearizeArc() method as well as for linearizeCircle().
>
> Could you please fix this issue in the next release?
> Thanks!
> _______________________________________________
> hibernatespatial-users mailing list
> [hidden email]
> http://www.hibernatespatial.org/cgi-bin/mailman/listinfo/hibernatespatial-users

_______________________________________________
hibernatespatial-users mailing list
[hidden email]
http://www.hibernatespatial.org/cgi-bin/mailman/listinfo/hibernatespatial-users