다각형 기능이 있으며 그 안에 점을 생성 할 수 있기를 원합니다. 하나의 분류 작업에 필요합니다.
임의의 점이 다각형 내부에 올 때까지 임의의 점을 생성하면 시간이 실제로 예측할 수 없기 때문에 작동하지 않습니다.
다각형 기능이 있으며 그 안에 점을 생성 할 수 있기를 원합니다. 하나의 분류 작업에 필요합니다.
임의의 점이 다각형 내부에 올 때까지 임의의 점을 생성하면 시간이 실제로 예측할 수 없기 때문에 작동하지 않습니다.
답변:
다각형의 범위를 결정한 다음 해당 범위 내에서 X 및 Y 값의 난수 생성을 제한 할 수 있습니다.
기본 프로세스 : 1) 다각형 정점의 최대 값, 최대 값, 최소값, 최소값을 결정합니다. 2)이 값을 경계로 사용하여 임의의 점을 생성합니다. 3) 다각형과의 교점에 대해 각 점을 테스트합니다. 4) 교점을 만족하는 충분한 점이 있으면 생성을 중지합니다. 테스트
교차 테스트를위한 알고리즘 (C #)은 다음과 같습니다.
bool PointIsInGeometry(PointCollection points, MapPoint point)
{
int i;
int j = points.Count - 1;
bool output = false;
for (i = 0; i < points.Count; i++)
{
if (points[i].X < point.X && points[j].X >= point.X || points[j].X < point.X && points[i].X >= point.X)
{
if (points[i].Y + (point.X - points[i].X) / (points[j].X - points[i].X) * (points[j].Y - points[i].Y) < point.Y)
{
output = !output;
}
}
j = i;
}
return output;
}
당신을 위해 대부분의 무거운 작업을 수행하는 좋은 라이브러리가 있습니다.
파이썬에서 [shapely] [1]을 사용하는 예제.
import random
from shapely.geometry import Polygon, Point
def get_random_point_in_polygon(poly):
minx, miny, maxx, maxy = poly.bounds
while True:
p = Point(random.uniform(minx, maxx), random.uniform(miny, maxy))
if poly.contains(p):
return p
p = Polygon([(0, 0), (0, 2), (1, 1), (2, 2), (2, 0), (1, 1), (0, 0)])
point_in_poly = get_random_point_in_polygon(mypoly)
또는 .representative_point()
객체 내에서 포인트를 얻는 데 사용 하십시오 (dain이 언급 한 바와 같이).
지오메트리 객체 내에 있도록 저렴하게 계산 된 점을 반환합니다.
poly.representative_point().wkt
'POINT (-1.5000000000000000 0.0000000000000000)'
[1]: https://shapely.readthedocs.io
representative_point
: 방법 shapely.readthedocs.io/en/latest/...을
GIS 분석 측면에서 거의 요구되지 않는 솔루션을 제공하고 싶습니다. 특히 다각형을 삼각 측량 할 필요가 없습니다.
의사 코드로 제공되는 다음 알고리즘은 기본 목록 처리 기능 (생성, 길이 찾기, 추가, 정렬, 하위 목록 추출 및 연결) 외에 간격 [0, 1)에서 임의의 부동 소수점 생성과 더불어 몇 가지 간단한 작업을 나타냅니다.
Area: Return the area of a polygon (0 for an empty polygon).
BoundingBox: Return the bounding box (extent) of a polygon.
Width: Return the width of a rectangle.
Height: Return the height of a rectangle.
Left: Split a rectangle into two halves and return the left half.
Right: ... returning the right half.
Top: ... returning the top half.
Bottom: ... returning the bottom half.
Clip: Clip a polygon to a rectangle.
RandomPoint: Return a random point in a rectangle.
Search: Search a sorted list for a target value. Return the index
of the last element less than the target.
In: Test whether a point is inside a polygon.
이들은 거의 모든 GIS 또는 그래픽 프로그래밍 환경에서 사용할 수 있습니다 (그렇지 않으면 코딩하기 쉽습니다). Clip
축퇴 다각형 (즉, 면적이 0 인 다각형)을 반환해서는 안됩니다.
프로시 저는 SimpleRandomSample
다각형 내에 무작위로 분포 된 점 목록을 효율적으로 얻습니다. 에 대한 래퍼로 SRS
, 각 조각이 효율적으로 샘플링되기에 충분히 컴팩트해질 때까지 다각형을 작은 조각으로 나눕니다. 이를 위해 사전 계산 된 난수 목록을 사용하여 각 조각에 할당 할 포인트 수를 결정합니다.
매개 변수를 변경하여 SRS를 "조정"할 수 있습니다 t
. 이것은 허용 가능한 최대 경계 상자 : 폴리곤 면적 비율입니다. 크기를 작게 (그러나 1보다 크게) 만들면 대부분의 다각형이 여러 조각으로 분할됩니다. 크기를 크게하면 일부 다각형 (심각한, 은색 또는 구멍이 가득 찬)에 대해 많은 시험 점이 거부 될 수 있습니다. 이를 통해 원래 다각형을 샘플링하는 최대 시간을 예측할 수 있습니다.
Procedure SimpleRandomSample(P:Polygon, N:Integer) {
U = Sorted list of N independent uniform values between 0 and 1
Return SRS(P, BoundingBox(P), U)
}
다음 절차는 필요한 경우 재귀 적으로 호출합니다. 신비한 표현 t*N + 5*Sqrt(t*N)
은 기회 변동성을 고려하여 필요한 포인트 수의 상한을 보수적으로 추정합니다. 이것이 실패 할 가능성은 백만 건의 프로 시저 호출 당 0.3입니다. 원하는 경우이 가능성을 줄이려면 5에서 6 또는 7을 늘리십시오.
Procedure SRS(P:Polygon, B:Rectangle, U:List) {
N = Length(U)
If (N == 0) {Return empty list}
aP = Area(P)
If (aP <= 0) {
Error("Cannot sample degenerate polygons.")
Return empty list
}
t = 2
If (aP*t < Area(B)) {
# Cut P into pieces
If (Width(B) > Height(B)) {
B1 = Left(B); B2 = Right(B)
} Else {
B1 = Bottom(B); B2 = Top(B)
}
P1 = Clip(P, B1); P2 = Clip(P, B2)
K = Search(U, Area(P1) / aP)
V = Concatenate( SRS(P1, B1, U[1::K]), SRS(P2, B2, U[K+1::N]) )
} Else {
# Sample P
V = empty list
maxIter = t*N + 5*Sqrt(t*N)
While(Length(V) < N and maxIter > 0) {
Decrement maxIter
Q = RandomPoint(B)
If (Q In P) {Append Q to V}
}
If (Length(V) < N) {
Error("Too many iterations.")
}
}
Return V
}
다각형이 볼록하고 모든 꼭짓점을 알고 있다면 꼭짓점에 대한 "무작위"볼록한 가중치를 적용하여 볼록 껍질 (이 경우 다각형) 안에 놓일 수있는 새 점을 샘플링하는 것이 좋습니다.
예를 들어 정점이있는 N면 볼록 다각형이 있다고 가정합니다.
V_i, i={1,..,N}
그런 다음 무작위로 N 볼록한 가중치를 생성하십시오.
w_1,w_2,..,w_N such that ∑ w_i = 1; w_i>=0
그런 다음 무작위로 샘플링 된 점은
Y= ∑ w_i*V_i
N 볼록한 무게를 샘플링하는 다른 방법이있을 수 있습니다
다각형이 볼록하지 않은 심각하지 않은 경우 먼저 다각형을 볼록 껍질로 변환하는 것이 좋습니다. 이것은 최소한 다각형 바깥에있는 점의 수를 크게 제한해야합니다.
이 작업은 v.random을 사용하여 GRASS GIS (하나의 명령)에서 매우 쉽게 해결할 수 있습니다.
다음은 매뉴얼 페이지에서 선택한 다각형 (여기서는 노스 캐롤라이나 롤리시의 우편 번호 영역)에 3 개의 임의의 점을 추가하는 방법에 대한 예입니다. SQL "where"문을 수정하여 다각형을 선택할 수 있습니다.
답변 링크
https://gis.stackexchange.com/a/307204/103524
다른 접근법을 사용하는 세 가지 알고리즘.
기능 ==================================================== ==================
CREATE OR REPLACE FUNCTION public.I_Grid_Point_Distance(geom public.geometry, x_side decimal, y_side decimal)
RETURNS public.geometry AS $BODY$
DECLARE
x_min decimal;
x_max decimal;
y_max decimal;
x decimal;
y decimal;
returnGeom public.geometry[];
i integer := -1;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
----RAISE NOTICE 'No SRID Found.';
ELSE
----RAISE NOTICE 'SRID Found.';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_min := ST_XMin(geom);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
y := ST_YMin(geom);
x := x_min;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
<<yloop>>
LOOP
IF (y > y_max) THEN
EXIT;
END IF;
CASE i WHEN 0 THEN
y := ST_Y(returnGeom[0]);
ELSE
y := ST_Y(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), y_side, radians(0))::geometry);
END CASE;
x := x_min;
<<xloop>>
LOOP
IF (x > x_max) THEN
EXIT;
END IF;
i := i + 1;
returnGeom[i] := st_setsrid(ST_MakePoint(x, y), srid);
x := ST_X(ST_Project(st_setsrid(ST_MakePoint(x, y), srid), x_side, radians(90))::geometry);
END LOOP xloop;
END LOOP yloop;
RETURN
ST_CollectionExtract(st_transform(ST_Intersection(st_collect(returnGeom), geom), input_srid), 1);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE;
간단한 쿼리로 함수를 사용하십시오. 기하학은 유효하고 다각형, 다중 다각형 또는 엔벨로프 여야합니다.
SELECT I_Grid_Point_Distance(geom, 50, 61) from polygons limit 1;
결과 ================================================== =====================
Nicklas Avén 알고리즘 에 기반한 두 번째 기능 . SRID를 처리하려고했습니다.
알고리즘에 다음 변경 사항을 적용했습니다.
기능 ==================================================== ==================
CREATE OR REPLACE FUNCTION I_Grid_Point(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
srid := 4326;
x_side := x_side / 100000;
y_side := y_side / 100000;
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
RETURN QUERY
WITH res as (SELECT ST_SetSRID(ST_MakePoint(x, y), srid) point FROM
generate_series(x_min, x_max, x_side) as x,
generate_series(y_min, y_max, y_side) as y
WHERE st_intersects(geom, ST_SetSRID(ST_MakePoint(x, y), srid))
) select ST_TRANSFORM(ST_COLLECT(point), input_srid) from res;
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
간단한 쿼리로 사용하십시오.
SELECT I_Grid_Point(geom, 22, 15, false) from polygons;
결과 ================================================== ==================
기능 ==================================================== =================
CREATE OR REPLACE FUNCTION I_Grid_Point_Series(geom geometry, x_side decimal, y_side decimal, spheroid boolean default false)
RETURNS SETOF geometry AS $BODY$
DECLARE
x_max decimal;
y_max decimal;
x_min decimal;
y_min decimal;
srid integer := 4326;
input_srid integer;
x_series DECIMAL;
y_series DECIMAL;
BEGIN
CASE st_srid(geom) WHEN 0 THEN
geom := ST_SetSRID(geom, srid);
RAISE NOTICE 'SRID Not Found.';
ELSE
RAISE NOTICE 'SRID Found.';
END CASE;
CASE spheroid WHEN false THEN
RAISE NOTICE 'Spheroid False';
else
srid := 900913;
RAISE NOTICE 'Spheroid True';
END CASE;
input_srid:=st_srid(geom);
geom := st_transform(geom, srid);
x_max := ST_XMax(geom);
y_max := ST_YMax(geom);
x_min := ST_XMin(geom);
y_min := ST_YMin(geom);
x_series := CEIL ( @( x_max - x_min ) / x_side);
y_series := CEIL ( @( y_max - y_min ) / y_side );
RETURN QUERY
SELECT st_collect(st_setsrid(ST_MakePoint(x * x_side + x_min, y*y_side + y_min), srid)) FROM
generate_series(0, x_series) as x,
generate_series(0, y_series) as y
WHERE st_intersects(st_setsrid(ST_MakePoint(x*x_side + x_min, y*y_side + y_min), srid), geom);
END;
$BODY$ LANGUAGE plpgsql IMMUTABLE STRICT;
간단한 쿼리로 사용하십시오.
SELECT I_Grid_Point_Series(geom, 22, 15, false) from polygons;
결과 ================================================== ==========================