Class com.vividsolutions.jts.algorithm.distance.PointPairDistance is
not thread safe as it uses tempSegment as a single temporary variable
for all threads.

In my case computeDistance() was called concurrently and in some rare
cases the PointPairDistance passed as a parameter had invalid
coordinates (ppd.getCoordinate(0) was (NaN, NaN, NaN)).

My suggestion is to make the field non-static and create a new
instance of the class for each call, e.g.:

--------------
public class DistanceToPointThreadSafe
{
    // used for point-line distance calculation
    private final LineSegment tempSegment = new LineSegment();

    private DistanceToPointThreadSafe()
    {
    }

    public static PointPairDistance computeDistance(Geometry geom,
Coordinate pt)
    {
        final PointPairDistance pointPairDistance = new PointPairDistance();
        new DistanceToPointThreadSafe().computeDistance(geom, pt,
pointPairDistance);
        return pointPairDistance;
    }

    private void computeDistance(Geometry geom, Coordinate pt,
PointPairDistance ptDist)
    {
        if (geom instanceof LineString)
        {
            computeDistance((LineString)geom, pt, ptDist);
        }
        else if (geom instanceof Polygon)
        {
            computeDistance((Polygon)geom, pt, ptDist);
        }
        else if (geom instanceof GeometryCollection)
        {
            final GeometryCollection gc = (GeometryCollection)geom;
            for (int i = 0; i < gc.getNumGeometries(); i++)
            {
                final Geometry g = gc.getGeometryN(i);
                computeDistance(g, pt, ptDist);
            }
        }
        else
        { // assume geom is Point
            ptDist.setMinimum(geom.getCoordinate(), pt);
        }
    }

    private void computeDistance(LineString line, Coordinate pt,
PointPairDistance ptDist)
    {
        final Coordinate[] coords = line.getCoordinates();
        for (int i = 0; i < coords.length - 1; i++)
        {
            tempSegment.setCoordinates(coords[i], coords[i + 1]);
            // this is somewhat inefficient - could do better
            final Coordinate closestPt = tempSegment.closestPoint(pt);
            ptDist.setMinimum(closestPt, pt);
        }
    }

    private void computeDistance(Polygon poly, Coordinate pt,
PointPairDistance ptDist)
    {
        computeDistance(poly.getExteriorRing(), pt, ptDist);
        for (int i = 0; i < poly.getNumInteriorRing(); i++)
        {
            computeDistance(poly.getInteriorRingN(i), pt, ptDist);
        }
    }
}
-------------

Kind regards,
Christoph.

------------------------------------------------------------------------------
_______________________________________________
Jts-topo-suite-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jts-topo-suite-user

Reply via email to