views:

462

answers:

3

I have a set of line and polygon object (SqlGeometry type) and a point object (SqlGeometry type). How can we find the the nearest point on each line from the given point object? Are there any API for doing this operation?

+3  A: 

I'm not sure if this is possible directly in SQL Server 2008:

http://social.msdn.microsoft.com/Forums/en/sqlspatial/thread/cb094fb8-07ba-4219-8d3d-572874c271b5

The workaround suggested in that thread is:

declare @g geometry = 'LINESTRING(0 0, 10 10)' 
declare @h geometry = 'POINT(0 10)' 

select @h.STBuffer(@h.STDistance(@g)).STIntersection(@g).ToString()

Otherwise you would have to write a script to read the geometry from your database and use separate spatial libraries.

geographika
for geography object, it was needed to add extra buffer of 0.1 meter and take the first point of the result. Other wise it was producing empty geometry [email protected](@h.STDistance(@g) + 0.1).STIntersection(@g).STFirstPoint().ToString()
malay
+2  A: 

If you are interested in actually finding the nearest point on the line (otherwise called a node) you can turn each line into a set of points with the same lineid. Then query for the closest and calc the distance.

If instead you are trying to calc the distance from a point to the nearest line - stdistance http://msdn.microsoft.com/en-us/library/bb933808.aspx I guess the problem that the other answer addresses is what to put in your where clause though you could use stdistance to specify a distance above which you don't care such as

Where pointGeom.stdistance(lineGeom) < "distance you care about"

TheSteve0
+2  A: 

Here a sample presenting possible solution using SqlGeometry and C#, no SQL Server is required:

using System;
using Microsoft.SqlServer.Types;
namespace MySqlGeometryTest
{
    class ReportNearestPointTest
    {
        static void ReportNearestPoint(string wktPoint, string wktGeom)
        {
            SqlGeometry point = SqlGeometry.Parse(wktPoint);
            SqlGeometry geom = SqlGeometry.Parse(wktGeom);
            double distance = point.STDistance(geom).Value;
            SqlGeometry pointBuffer = point.STBuffer(distance);
            SqlGeometry pointResult = pointBuffer.STIntersection(geom);
            string wktResult = new string(pointResult.STAsText().Value);
            Console.WriteLine(wktResult);
        }

        static void Main(string[] args)
        {
            ReportNearestPoint("POINT(10 10)", "MULTIPOINT (80 70, 20 20, 200 170, 140 120)");
            ReportNearestPoint("POINT(110 200)", "LINESTRING (90 80, 160 150, 300 150, 340 150, 340 240)");
            ReportNearestPoint("POINT(0 0)", "POLYGON((10 20, 10 10, 20 10, 20 20, 10 20))");
            ReportNearestPoint("POINT(70 170)", "POLYGON ((110 230, 80 160, 20 160, 20 20, 200 20, 200 160, 140 160, 110 230))");
        }
    }
}

The program output:

POINT (20 20)
POINT (160 150)
POINT (10 10)
POINT (70 160)
mloskot
this is same as geographika's answer but is C# code
malay
Yes, indeed, and I upvoted geographika's answer of course but also decided to provide this variation.
mloskot