如何检查当前位置是否距离GeoFence 2公里

时间:2014-12-29 04:43:15

标签: sql sql-server geofencing

我的应用程序中有地理围栏。使用这个我需要检查车辆是否接近地理围栏。所需距离距离标记的地理围栏2公里。

我该怎么做?

我已经有一个函数可以检查当前点是否在GeoFence中。

这里我附加了函数

ALTER FUNCTION [dbo].[Fn_checkwithingeofence] (
-- Add the parameters for the function here
@latitude   VARCHAR(100),
@longitude  VARCHAR(100),
@geoFenceId BIGINT)
RETURNS BIT
WITH EXECUTE AS CALLER
AS
  BEGIN
      -- Declare the return variable here
      DECLARE @inGeoFence BIT
      DECLARE @Point GEOGRAPHY
      DECLARE @CoordinateStream VARBINARY(MAX)
      DECLARE @polygon   GEOMETRY,
              @origPoint GEOMETRY
      DECLARE @polygonGeography GEOGRAPHY
      DECLARE @pointToCheck GEOGRAPHY
      DECLARE @i INT
      DECLARE @pointWKT VARCHAR(MAX)

      SET @i = 0
      -- Create the WKT string.
      SET @pointWKT = 'POINT(' + @longitude + ' ' + @latitude + ')'

      -- Check if the value can be used to create valid geography
      IF( dbo.Isvalidgeographyfromtext(@pointWKT, 4326) ) = '1'
        BEGIN
            -- Set in geo fence as true
            SET @inGeoFence = '1'
            -- Create valid geography from text.
            SET @pointToCheck = dbo.Makevalidgeographyfromtext(@pointWKT, 4326)

            -- Define curson to fetch the geo points and get the coordinate stream
            DECLARE GeomCursor CURSOR FOR
              SELECT gp.SpatialPoint
              FROM   tblGeoFencePoints gp WITH (NOLOCK)
              WHERE  gp.GeoFenceId = @geoFenceId
              ORDER  BY gp.GeoFencePointId;

            OPEN GeomCursor;

            FETCH NEXT FROM GeomCursor INTO @Point;

            WHILE @@FETCH_STATUS = 0
              BEGIN
                  IF ( @i = 0 )
                    BEGIN
                        SET @CoordinateStream = Substring(@Point.STAsBinary(), 6, 16)
                    END
                  ELSE
                    BEGIN
                        SET @CoordinateStream = @CoordinateStream
                                                + Substring(@Point.STAsBinary(), 6, 16)
                    END;

                  SET @i = @i + 1

                  FETCH NEXT FROM GeomCursor INTO @Point;
              END;

            CLOSE GeomCursor;

            DEALLOCATE GeomCursor;

            -- Build the polygon using the coordinated stream
            SELECT @polygon = geometry::STGeomFromWKB(0x01 -- Again, sepcify big-endian byte order
                                                      + 0x03000000 -- This is a 4-byte value showing that we are building a polygon
                                                      + 0x01000000 -- The number of rings in the polygon. Let's keep it simple and assume we only have an exterior ring
                                                      + CONVERT(VARBINARY, Reverse(CONVERT(VARBINARY, @i+1))) -- There is one more point in the polygon definition than in the original set of points, since we repeat the start/end point
                                                      + @CoordinateStream
                                                      + Substring(@CoordinateStream, 1, 16)-- We take the co-ordinate stream, and repeat the first point co-ordinates to close the ring
                              , 4326)

            --SET @polygon = @polygon.MakeValid()
            SET @polygonGeography = dbo.Makevalidgeographyfromgeometry(@polygon)
            ---- CHECK if the point is within the polygon
            SET @inGeoFence = @polygonGeography.STIntersection(@pointToCheck).STEquals(@pointToCheck);
        END
      ELSE
        BEGIN
            SET @inGeoFence = '1'
        END

      RETURN @inGeoFence
  END 

1 个答案:

答案 0 :(得分:0)

我遵循了这些步骤......希望它能正常工作

ALTER FUNCTION [dbo].[fn_CheckApproachingGeoFence]
(
    -- Add the parameters for the function here
    @latitude VARCHAR(100),
    @longitude VARCHAR(100),
    @geoFenceId BIGINT
)
RETURNS BIT
WITH EXECUTE AS CALLER
AS
BEGIN
    -- Declare the return variable here
    DECLARE @inGeoFence BIT
    DECLARE @approachGeoFence BIT
    DECLARE @Point GEOGRAPHY
    DECLARE @CoordinateStream VARBINARY(MAX)
    DECLARE @polygon GEOMETRY, @origPoint GEOMETRY
    DECLARE @radialGeoFenceApproch GEOGRAPHY, @radialGeoGeometryApproch GEOMETRY
    DECLARE @polygonGeography GEOGRAPHY
    DECLARE @pointToCheck GEOGRAPHY
    DECLARE @i INT
    DECLARE @pointWKT VARCHAR(MAX)
    DECLARE @location GEOGRAPHY
    SET @i = 0


        -- CREATE LOCATION AS GEOGRAPHY
        SET @location = dbo.fn_GetGeography(@latitude, @longitude)
        --Sarat Change for Geofence IN 2km
        SET @radialGeoFenceApproch = @location.STBuffer(2000);
        --Sarat Change for Geofence IN 2km Ends here

    -- CONVERT TO A GEOMETRY INSTANCE
    SET @radialGeoGeometryApproch = CAST(@radialGeoFenceApproch AS varbinary(max))
    -- CONVERT TO AN MBR
    SET @radialGeoGeometryApproch = @radialGeoGeometryApproch.STEnvelope();
    -- CONVERT BACK TO A GEOGRAPHY
    SET @radialGeoFenceApproch = CAST(@radialGeoGeometryApproch as varbinary(max));





    -- Create the WKT string.
    SET @pointWKT = 'POINT(' + @longitude + ' ' + @latitude + ')'

    -- Check if the value can be used to create valid geography
    IF(dbo.IsValidGeographyFromText(@pointWKT, 4326)) = '1'
    BEGIN

    -- Set in geo fence as true
    SET @inGeoFence = '1' 

    -- Create valid geography from text.
    SET @pointToCheck = dbo.MakeValidGeographyFromText(@pointWKT, 4326)

    -- Define curson to fetch the geo points and get the coordinate stream
    DECLARE GeomCursor CURSOR FOR SELECT gp.SpatialPoint FROM tblGeoFencePoints gp WITH (NOLOCK)
    WHERE gp.GeoFenceId = @geoFenceId ORDER BY gp.GeoFencePointId;
    OPEN GeomCursor;
        FETCH NEXT FROM GeomCursor INTO @Point;
        WHILE @@FETCH_STATUS = 0
        BEGIN
            IF (@i=0) BEGIN
                SET @CoordinateStream = SUBSTRING(@Point.STAsBinary(),6,16)
            END
            ELSE BEGIN
                SET @CoordinateStream = @CoordinateStream + SUBSTRING(@Point.STAsBinary(),6,16)
            END;
            SET @i = @i+1
            FETCH NEXT FROM GeomCursor INTO @Point;
        END;
    CLOSE GeomCursor;
    DEALLOCATE GeomCursor;

    -- Build the polygon using the coordinated stream
    SELECT @polygon = geometry::STGeomFromWKB(
         0x01 -- Again, sepcify big-endian byte order
         + 0x03000000 -- This is a 4-byte value showing that we are building a polygon
         + 0x01000000 -- The number of rings in the polygon. Let's keep it simple and assume we only have an exterior ring
         + CONVERT(varbinary,REVERSE(CONVERT(varbinary,@i+1))) -- There is one more point in the polygon definition than in the original set of points, since we repeat the start/end point
         + @CoordinateStream + SUBSTRING(@CoordinateStream,1,16)-- We take the co-ordinate stream, and repeat the first point co-ordinates to close the ring
        ,4326)
    --SET @polygon = @polygon.MakeValid()
    SET @polygonGeography = dbo.MakeValidGeographyFromGeometry(@polygon)

    ---- CHECK if the point is within the polygon
    --SET @inGeoFence = @polygonGeography.STIntersection(@pointToCheck).STEquals(@pointToCheck);

    --Checks current location is 2km inside the polygon

    SET @inGeoFence=@polygonGeography.STIntersects(@radialGeoFenceApproch);


    END
    ELSE
    BEGIN
        SET @inGeoFence = '0'
    END
    RETURN @inGeoFence

END