我的应用程序中有地理围栏。使用这个我需要检查车辆是否接近地理围栏。所需距离距离标记的地理围栏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
答案 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