사용 이 방법을 사용하면 포인트 X는 포인트 S와 포인트 E 사이에있는 것으로 잘못 판단하게됩니다. 이는 알고리즘의 테스트 1과 테스트 2를 모두 통과하기 때문입니다. 포인트 X는 선 스트링에 있고,
당신은 "폭발 할 수 있습니다 X에서 S와 X에서 E까지의 거리가 모두 E.
: LINESTRING(-122.360 47.656, -122.343 47.656, -122.310 47.690, -122.310 47.670)
는로 나누어받을 것
위의 각 선분을 반복하고 STIntersects
을 사용하여이 세그먼트 중 하나에 점이 있는지 테스트 할 수 있습니다. 이 테스트를 통과 한 지점이 시작 지점과 끝 지점에 있는지 확인할 수 있습니다.
가능한 경우 시작 지점/끝 지점을 원시 지리 지점이 아닌 선 스트링 경로의 지점에 대한 인덱스로 저장하는 것이 좋습니다. 우선이 방법으로이 문제를 쉽게 해결할 수 있지만 데이터 중복을 제거하고 선 스트링의 일부가 아닌 시작/끝점을 가질 수 없다는 보장이 제공됩니다. 단점은 선 세그먼트의 중간에 시작/끝점을 가질 수는 없지만 경로의 구석 중 하나에 있어야한다는 것입니다. 이제 응용 프로그램에서이 제한이 수용 가능한지 여부를 결정해야합니다.위의 표현을 선택하는 경우, 우리는 @path
도로를 나타내는 선 스트링입니다 다음 재귀 함수와이 문제를 해결할 수
, @start_point
및 @end_end
가 @path
에 두 지점의 인덱스를 나타냅니다 (첫 번째 인덱스는 1) , @test_point
은 테스트 할 지리 포인트입니다. 테스트 포인트는 거짓말을 할 수 있습니다.
CREATE FUNCTION [dbo].[func_PointBetween](@path geography,
@start_point int,
@end_point int,
@test_point geography)
RETURNS tinyint
AS
BEGIN
DECLARE @result tinyint = 0;
DECLARE @num_points int = @path.STNumPoints();
DECLARE @line_segment geography;
IF (@start_point < @end_point) AND (@end_point < @num_points)
BEGIN
/* Generate the line segment from the current start point
to the following point (@start_point + 1). */
SET @line_segment = geography::STLineFromText('LINESTRING(' +
CAST(@path.STPointN(@start_point).Long AS varchar(32))+ ' ' +
CAST(@path.STPointN(@start_point).Lat AS varchar(32)) + ',' +
CAST(@path.STPointN(@start_point + 1).Long AS varchar(32))+ ' ' +
CAST(@path.STPointN(@start_point + 1).Lat AS varchar(32)) + ')',
4326);
/* Add a buffer of 25m to @test_point. This is optional, but
recommended, otherwise it will be very difficult to get a
point exactly on the line. The buffer value may be tweaked
as necessary for your application. */
IF @test_point.STBuffer(25).STIntersects(@line_segment) = 1
BEGIN
/* The test point is on one of the line segments between
@start_point and @end_point. Return 1 and stop the
recursion. */
SET @result = 1;
END
ELSE
BEGIN
/* The test point is not between the @start_point and
@start_point + 1. Increment @start_point by 1 and
continue recursively. */
SET @result = [dbo].[func_PointBetween](@path,
@start_point + 1,
@end_point,
@test_point);
END
END
ELSE
BEGIN
/* There are no further points. The test point is not between the
@start_point and @end_point. Return 0 and stop the recursion. */
SET @result = 0;
END
RETURN @result;
END
위의 기능을 테스트하려면 위의 맵에 표시된 6 포인트 선 스트링을 정의합니다. 두 번째 테스트 포인트를 정의 할 것입니다 : @test_point_a
은 정확하게 세 번째와 네 번째 포인트 사이에 있고, @test_point_b
은 경로에서 벗어납니다.
DECLARE @road geography;
DECLARE @test_point_a geography;
DECLARE @test_point_b geography;
SET @road = geography::STGeomFromText('LINESTRING(-122.360 47.656,
-122.343 47.656,
-122.310 47.690,
-122.310 47.670,
-122.300 47.670,
-122.290 47.660)',
4326);
/* This point lies between point 3 and point 4 */
SET @test_point_a = geography::STGeomFromText('POINT(-122.310 47.680)', 4326);
/* This point lies outside the path */
SET @test_point_b = geography::STGeomFromText('POINT(-122.310 47.700)', 4326);
/* This returns 1, because the test point is between start and end */
SELECT dbo.func_PointBetween(@road, 2, 5, @test_point_a);
/* This returns 0 because the test point is not between start and end */
SELECT dbo.func_PointBetween(@road, 4, 5, @test_point_a);
/* This returns 0 because the test point lies outside the path */
SELECT dbo.func_PointBetween(@road, 1, 6, @test_point_b);
도로가 커브로 돌아가는 경우 현재 방법이 작동합니까? 예를 들어, U 턴의 각 끝에 두 개의 점이 있고 U 턴 뒤의 점을 확인하는 경우 해당 점과 시작점과 종점 사이의 거리가 시작점과 끝점 사이의 거리보다 작을 수 있습니다. 하지만 두 지점 사이의 도로에는 나타나지 않습니다. –
Eep, 네 말이 맞아! 좋아, 이제 정말로 대답이 필요해. :-) –