PostGIS에서 x 방향 (동서 방향)으로 다각형 내 최대 거리를 계산합니까?


13

동서 방향으로 호수와 같은 다각형의 최대 너비에 관심이 있습니다. 경계 상자는 단순한 다각형에만 도움이되고 복잡한 오목 다각형에는 도움이되지 않습니다.


3
postgis 기능에 익숙하지 않습니다. 그러나 경계 상자 도구가있을 수 있습니다. 바운딩 박스의 너비는 EW 방향의 최대 거리입니다.
Fezter

4
옳지 않은 @Fetzter : 간단한 복잡한 다각형의 경우에도 반례는 SW에서 NE로 확장되는 얇은 마름모입니다. 최대 동서 너비는 경계 상자 너비의 임의의 작은 부분 일 수 있습니다.
whuber

1
나는에 따라이 작업을위한 유틸리티 만든 제안을. 다각형의 최대 또는 최소 너비를 계산할 수 있습니다. 현재 shp 파일과 함께 작동하지만 PostGIS와 함께 작동하도록 PostGIS를 다시 작성하거나 PostGIS와 함께 작동하는 QGIS 플러그인으로 발전 할 때까지 잠시 기다리십시오. 자세한 설명 및 다운로드 링크는 여기를 클릭하십시오 .
SS_Rebelious

답변:


16

이를 위해서는 모든 GIS 플랫폼에서 일부 스크립팅이 필요합니다.

가장 효율적인 방법은 (직각적으로) 수직선 스윕입니다. 최소 y 좌표로 가장자리를 정렬 한 다음 O (e * log ()에 대해 가장자리 (최소 y)에서 위쪽 (최대 y)까지 가장자리를 처리해야합니다. e) e 모서리가 관련된 알고리즘 .

절차는 간단하지만 모든 경우에 올바르게 적용하기는 놀랍습니다. 다각형은 불쾌 할 수 있습니다. 매달린 것, 은색, 구멍, 연결 끊기, 정점 복제, 직선을 따라 정점 실행, 인접한 두 구성 요소 사이의 경계가 해소 될 수 있습니다. 다음은 이러한 많은 특성을 보여주는 예입니다.

다각형

우리는 구체적으로 폴리곤 의 폐쇄 내에있는 최대 길이의 수평 세그먼트를 추구 할 것이다 . 예를 들어, 이것은 x = 10과 x = 25 사이의 구멍에서 나오는 x = 20과 x = 40 사이의 댕글 링을 제거합니다. 그 후, 최대 길이의 수평 세그먼트 중 적어도 하나가 적어도 하나의 정점과 교차한다는 것을 나타내는 것이 간단하다. (어떤 정점을 교차하지 솔루션이있는 경우, 그들은 솔루션이 상단과 하단에 경계 일부 평행 사변형의 내부에 거짓말을한다 적어도 하나 개의 정점을 교차. 이것은 우리가 찾을 수있는 수단을 제공 하는 모든 솔루션을.)

따라서 라인 스윕은 가장 낮은 정점으로 시작한 다음 위쪽으로 (즉, 더 높은 y 값으로) 이동하여 각 정점에서 중지해야합니다. 매 정거장마다 해당 높이에서 위쪽으로 튀어 나오는 새로운 모서리가 발견됩니다. 해당 고도에서 아래에서 끝나는 모든 모서리를 제거합니다 (이는 핵심 아이디어 중 하나입니다. 알고리즘을 단순화하고 잠재적 인 처리의 절반을 제거합니다). 그리고 일정한 높이 (수평 가장자리)에 완전히 놓여있는 가장자리를주의해서 처리하십시오.

예를 들어, y = 10 레벨에 도달 한 상태를 고려하십시오. 왼쪽에서 오른쪽으로 다음과 같은 가장자리를 찾습니다.

      x.min x.max y.min y.max
 [1,]    10     0     0    30
 [2,]    10    24    10    20
 [3,]    20    24    10    20
 [4,]    20    40    10    10
 [5,]    40    20    10    10
 [6,]    60     0     5    30
 [7,]    60    60     5    30
 [8,]    60    70     5    20
 [9,]    60    70     5    15
[10,]    90   100    10    40

이 표에서 (x.min, y.min)은 가장자리의 아래쪽 끝점의 좌표이고 (x.max, y.max)는 위쪽 끝점의 좌표입니다. 이 수준 (y = 10)에서 첫 번째 가장자리는 내부에서 가로 채고 두 번째 가장자리는 아래쪽에서 가로 채됩니다. (10,0)에서 (10,10)과 같이이 수준에서 끝나는 일부 모서리 는 목록에 포함 되지 않습니다.

내부 점과 외부 점의 위치를 ​​결정하려면 다각형 바깥에있는 가장 왼쪽에서 시작하여 수평으로 오른쪽으로 이동하는 것을 상상해보십시오. 수평이 아닌 가장자리 교차 할 때마다 외부에서 내부 및 후면으로 교대로 전환됩니다. (이것은 또 다른 핵심 아이디어입니다.) 그러나 수평 가장자리 내의 모든 점은 다각형 내부에있는 것으로 결정됩니다. 다각형의 폐쇄에는 항상 모서리가 포함됩니다.

예제를 계속 진행하면 다음은 수평아닌 모서리가 y = 10 선에서 시작하거나 교차하는 x 좌표의 정렬 된 목록입니다 .

x.array    6.7 10 20 48 60 63.3 65 90
interior     1  0  1  0  1    0  1  0

x = 40은이 목록에 없습니다. interior배열 값 은 내부 세그먼트의 왼쪽 끝점을 표시합니다. 1은 내부 간격을, 0은 외부 간격을 나타냅니다. 따라서 처음 1은 x = 6.7에서 x = 10까지의 간격이 다각형 안에 있음을 나타냅니다. 다음 0은 x = 10에서 x = 20까지의 간격 이 다각형 외부에 있음을 나타냅니다 . 배열은 다각형 내부에서와 같이 4 개의 개별 간격을 식별합니다.

x = 60에서 x = 63.3의 간격과 같은 일부 간격은 정점과 교차하지 않습니다. y = 10 인 모든 정점의 x 좌표에 대한 빠른 검사는 이러한 간격을 제거합니다.

스캔하는 동안 지금까지 찾은 최대 길이 간격에 대한 데이터를 유지하면서 이러한 간격의 길이를 모니터링 할 수 있습니다.

이 접근 방식의 의미에 유의하십시오. "v"모양의 꼭짓점은 두 가장자리의 원점입니다. 따라서 두 개의 스위치가 교차 할 때 발생합니다. 그 스위치는 취소됩니다. 왼쪽에서 오른쪽으로 스캔하기 전에 양쪽 가장자리가 모두 제거되므로 거꾸로 된 "v"도 처리되지 않습니다. 두 경우 모두, 이러한 정점은 수평 세그먼트를 차단하지 않습니다.

두 개 이상의 모서리가 꼭지점을 공유 할 수 있습니다. 이는 (10,0), (60,5), (25, 20)에 설명되어 있지만 (20,10)과 (40)에서는 말하기 어렵지만 , 10). (매달려 있기 때문에 (20,10)-> (40,10)-> (40,0)-> (40, -50)-> (40, 10)-> (20, 10). (40,0)의 정점이 다른 가장자리의 내부에도 어떻게 나타나는지 주목하십시오.

까다로운 상황이 맨 아래에 설명되어 있습니다. 수평이 아닌 세그먼트의 x 좌표

30, 50

이것은 x = 30의 왼쪽에있는 모든 것을 외부로 간주하고, 30에서 50 사이의 모든 것을 내부로, 50 이후의 모든 것을 다시 외부로 만듭니다. x = 40의 정점은이 알고리즘에서도 고려되지 않습니다.

다음은 스캔이 끝날 때 다각형이 어떻게 보이는지입니다. 모든 정점 포함 내부 간격을 짙은 회색으로, 최대 길이 간격을 빨간색으로 표시하고, 정점의 y 좌표에 따라 색상을 지정합니다. 최대 간격은 64 단위입니다.

스캔 후

관련된 기하학적 계산 은 모서리가 수평선과 교차하는 위치를 계산하는 것입니다. 이는 단순한 선형 보간입니다. 어떤 정점을 포함하는 내부 세그먼트를 결정하려면 계산이 필요합니다. 이러한 정점 은 두 개의 불평등으로 쉽게 계산 되는 중간 성 결정입니다. 이 단순성은 알고리즘을 정수 및 부동 소수점 좌표 표현 모두에 강력하고 적합하게 만듭니다.

좌표가 지리적 인 경우 수평선은 실제로 위도의 원에 있습니다. 그들의 길이는 계산하기 어렵지 않습니다. 단지 유클리드 길이에 위도의 코사인 (구형 모델)을 곱하면됩니다. 따라서이 알고리즘은 지리적 좌표에 잘 맞습니다. (+ -180 자오선을 감싸는 것을 처리하려면 먼저 다각형을 통과하지 않는 남극에서 북극까지의 곡선을 찾아야합니다. 모든 x 좌표를 그에 대한 수평 변위로 다시 표현한 후 이 알고리즘은 최대 수평 세그먼트를 올바르게 찾습니다.)


다음은 R계산을 수행하고 그림을 생성하기 위해 구현 된 코드입니다.

#
# Plotting functions.
#
points.polygon <- function(p, ...) {
  points(p$v, ...)
}
plot.polygon <- function(p, ...) {
  apply(p$e, 1, function(e) lines(matrix(e[c("x.min", "x.max", "y.min", "y.max")], ncol=2), ...))
}
expand <- function(bb, e=1) {
  a <- matrix(c(e, 0, 0, e), ncol=2)
  origin <- apply(bb, 2, mean)
  delta <-  origin %*% a - origin
  t(apply(bb %*% a, 1, function(x) x - delta))
}
#
# Convert polygon to a better data structure.
#
# A polygon class has three attributes:
#   v is an array of vertex coordinates "x" and "y" sorted by increasing y;
#   e is an array of edges from (x.min, y.min) to (x.max, y.max) with y.max >= y.min, sorted by y.min;
#   bb is its rectangular extent (x0,y0), (x1,y1).
#
as.polygon <- function(p) {
  #
  # p is a list of linestrings, each represented as a sequence of 2-vectors 
  # with coordinates in columns "x" and "y". 
  #
  f <- function(p) {
    g <- function(i) {
      v <- p[(i-1):i, ]
      v[order(v[, "y"]), ]
    }
    sapply(2:nrow(p), g)
  }
  vertices <- do.call(rbind, p)
  edges <- t(do.call(cbind, lapply(p, f)))
  colnames(edges) <- c("x.min", "x.max", "y.min", "y.max")
  #
  # Sort by y.min.
  #
  vertices <- vertices[order(vertices[, "y"]), ]
  vertices <- vertices[!duplicated(vertices), ]
  edges <- edges[order(edges[, "y.min"]), ]

  # Maintaining an extent is useful.
  bb <- apply(vertices <- vertices[, c("x","y")], 2, function(z) c(min(z), max(z)))

  # Package the output.
  l <- list(v=vertices, e=edges, bb=bb); class(l) <- "polygon"
  l
}
#
# Compute the maximal horizontal interior segments of a polygon.
#
fetch.x <- function(p) {
  #
  # Update moves the line from the previous level to a new, higher level, changing the
  # state to represent all edges originating or strictly passing through level `y`.
  #
  update <- function(y) {
    if (y > state$level) {
      state$level <<- y
      #
      # Remove edges below the new level from state$current.
      #
      current <- state$current
      current <- current[current[, "y.max"] > y, ]
      #
      # Adjoin edges at this level.
      #
      i <- state$i
      while (i <= nrow(p$e) && p$e[i, "y.min"] <= y) {
        current <- rbind(current, p$e[i, ])
        i <- i+1
      }
      state$i <<- i
      #
      # Sort the current edges by x-coordinate.
      #
      x.coord <- function(e, y) {
        if (e["y.max"] > e["y.min"]) {
          ((y - e["y.min"]) * e["x.max"] + (e["y.max"] - y) * e["x.min"]) / (e["y.max"] - e["y.min"])
        } else {
          min(e["x.min"], e["x.max"])
        }
      }
      if (length(current) > 0) {
        x.array <- apply(current, 1, function(e) x.coord(e, y))
        i.x <- order(x.array)
        current <- current[i.x, ]
        x.array <- x.array[i.x]     
        #
        # Scan and mark each interval as interior or exterior.
        #
        status <- FALSE
        interior <- numeric(length(x.array))
        for (i in 1:length(x.array)) {
          if (current[i, "y.max"] == y) {
            interior[i] <- TRUE
          } else {
            status <- !status
            interior[i] <- status
          }
        }
        #
        # Simplify the data structure by retaining the last value of `interior`
        # within each group of common values of `x.array`.
        #
        interior <- sapply(split(interior, x.array), function(i) rev(i)[1])
        x.array <- sapply(split(x.array, x.array), function(i) i[1])

        print(y)
        print(current)
        print(rbind(x.array, interior))


        markers <- c(1, diff(interior))
        intervals <- x.array[markers != 0]
        #
        # Break into a list structure.
        #
        if (length(intervals) > 1) {
          if (length(intervals) %% 2 == 1) 
            intervals <- intervals[-length(intervals)]
          blocks <- 1:length(intervals) - 1
          blocks <- blocks - (blocks %% 2)
          intervals <- split(intervals, blocks)  
        } else {
          intervals <- list()
        }
      } else {
        intervals <- list()
      }
      #
      # Update the state.
      #
      state$current <<- current
    }
    list(y=y, x=intervals)
  } # Update()

  process <- function(intervals, x, y) {
    # intervals is a list of 2-vectors. Each represents the endpoints of
    # an interior interval of a polygon.
    # x is an array of x-coordinates of vertices.
    #
    # Retains only the intervals containing at least one vertex.
    between <- function(i) {
      1 == max(mapply(function(a,b) a && b, i[1] <= x, x <= i[2]))
    }
    is.good <- lapply(intervals$x, between)
    list(y=y, x=intervals$x[unlist(is.good)])
    #intervals
  }
  #
  # Group the vertices by common y-coordinate.
  #
  vertices.x <- split(p$v[, "x"], p$v[, "y"])
  vertices.y <- lapply(split(p$v[, "y"], p$v[, "y"]), max)
  #
  # The "state" is a collection of segments and an index into edges.
  # It will updated during the vertical line sweep.
  #
  state <- list(level=-Inf, current=c(), i=1, x=c(), interior=c())
  #
  # Sweep vertically from bottom to top, processing the intersection
  # as we go.
  #
  mapply(function(x,y) process(update(y), x, y), vertices.x, vertices.y)
}


scale <- 10
p.raw = list(scale * cbind(x=c(0:10,7,6,0), y=c(3,0,0,-1,-1,-1,0,-0.5,0.75,1,4,1.5,0.5,3)),
             scale *cbind(x=c(1,1,2.4,2,4,4,4,4,2,1), y=c(0,1,2,1,1,0,-0.5,1,1,0)),
             scale *cbind(x=c(6,7,6,6), y=c(.5,2,3,.5)))

#p.raw = list(cbind(x=c(0,2,1,1/2,0), y=c(0,0,2,1,0)))
#p.raw = list(cbind(x=c(0, 35, 100, 65, 0), y=c(0, 50, 100, 50, 0)))

p <- as.polygon(p.raw)

results <- fetch.x(p)
#
# Find the longest.
#
dx <- matrix(unlist(results["x", ]), nrow=2)
length.max <- max(dx[2,] - dx[1,])
#
# Draw pictures.
#
segment.plot <- function(s, length.max, colors,  ...) {
  lapply(s$x, function(x) {
      col <- ifelse (diff(x) >= length.max, colors[1], colors[2])
      lines(x, rep(s$y,2), col=col, ...)
    })
}
gray <- "#f0f0f0"
grayer <- "#d0d0d0"
plot(expand(p$bb, 1.1), type="n", xlab="x", ylab="y", main="After the Scan")
sapply(1:length(p.raw), function(i) polygon(p.raw[[i]], col=c(gray, "White", grayer)[i]))
apply(results, 2, function(s) segment.plot(s, length.max, colors=c("Red", "#b8b8a8"), lwd=4))
plot(p, col="Black", lty=3)
points(p, pch=19, col=round(2 + 2*p$v[, "y"]/scale, 0))
points(p, cex=1.25)

주어진 방향으로 볼록하지 않은 다각형 내부의 최대 길이 선이이 다각형의 하나 이상의 꼭짓점과 교차한다는 것을 증명하는 정리가 있습니까?
SS_Rebelious

@SS 예, 있습니다. 여기에 증거의 스케치가 있습니다. 교차점이 없으면 세그먼트의 끝 점이 모두 가장자리 내부에 있으며 세그먼트를 적어도 조금, 위아래로 움직일 수 있습니다. 길이는 변위량의 선형 함수입니다. 따라서 이동시 길이가 변하지 않는 경우에만 최대 길이를 가질 수 있습니다. 이것은 (a) 최대 길이의 세그먼트로 구성된 평행 사변형의 일부이고 (b) 평행 사변형의 상단과 하단 모서리가 꼭짓점 QED를 충족해야 함을 의미합니다.
whuber

그리고이 정리의 이름은 무엇입니까? 나는 그것을 찾기 위해 고심하고 있습니다. BTW, 꼭지점이없는 곡선 모서리는 어떻습니까 (이론적 접근 방식을 의미 함)? 내가 의미하는 그림의 예 (멍청한 종 모양의 다각형) : "C = D".
SS_Rebelious

@SS 모서리가 구부러지면 정리가 더 이상 유지되지 않습니다. 차등 기하학 기법을 적용하여 유용한 결과를 얻을 수 있습니다. 나는 Cheeger & Ebin의 저서 인 Riemannian Geometry 의 Compareson Theorems에서이 방법들을 배웠다 . 그러나 대부분의 GIS는 어쨌든 세부적인 폴리 라인으로 곡선을 근사화하므로 (실제로) 의문의 여지가 있습니다.
whuber

정리의 이름과 가능한 경우 페이지를 지정할 수 있습니까? 책을 받았는데 필요한 정리를 찾을 수 없었습니다.
SS_Rebelious

9

다음은 래스터 기반 솔루션입니다. 빠릅니다 (14 분 안에 모든 작업을 처음부터 끝까지 완료했습니다).

다각형의 래스터 표현으로 시작하십시오. 이것은 550 행과 1200 열의 그리드를 사용합니다.

다각형

이 표현에서 회색 (내부) 셀의 값은 1이고 다른 모든 셀은 NoData입니다.

웨이트 그리드의 단위 셀 값 ( "강우량")을 사용하여 서쪽에서 동쪽으로의 흐름 누적을 계산합니다 .

흐름 축적

낮은 축적은 어둡고 밝은 노랑에서 가장 높은 축적으로 증가합니다.

구역 최대 값 (그리드에 다각형을 사용하고 값에 흐름 누적을 사용)은 흐름이 가장 큰 셀을 식별합니다. 이를 보여주기 위해 오른쪽 하단으로 확대해야했습니다.

최고

적혈구는 흐름의 가장 높은 축적의 끝을 표시합니다. 이들은 다각형의 최대 길이 내부 세그먼트의 가장 오른쪽 끝점입니다.

이 세그먼트를 찾으려면 모든 무게를 적혈구에 놓고 흐름을 거꾸로 실행하십시오!

결과

바닥 근처의 빨간색 줄은 두 줄의 셀을 나타냅니다. 그 안에는 최대 길이의 가로 세그먼트가 있습니다. 추가 표현을 위해이 표현을있는 그대로 사용하거나 폴리 라인 (또는 다각형) 모양으로 변환하십시오.

래스터 표현으로 인한 이산화 오류가 있습니다. 계산 시간에 어느 정도의 비용으로 해상도를 높여서 줄일 수 있습니다.


이 접근법의 한 가지 좋은 점은 일반적으로 파이프 라인이나 축구장 배치, 생태 버퍼 생성 등과 같은 목표를 달성해야하는 더 큰 워크 플로의 일부로 극한의 가치를 발견한다는 것입니다. 이 과정에는 절충이 포함됩니다. 따라서 가장 긴 수평선은 최적 솔루션의 일부가 아닐 수 있습니다. 여기서 우리는 알고 대신에 관심이 있습니다 거의 긴 줄이 거짓말을 것입니다. 이는 구역 최대 흐름을 선택하는 것이 아니라 구역 최대에 가까운 모든 셀을 선택하십시오. 이 예에서 구역 최대 값은 744 (가장 긴 내부 세그먼트에 걸쳐있는 열 수)와 같습니다. 대신, 최대 값의 5 % 이내의 모든 셀을 선택하겠습니다 :

선택된 최적의 세포

동쪽에서 서쪽으로 흐름을 실행하면 다음과 같은 가로 세그먼트 모음이 생성됩니다.

거의 최적의 솔루션

이것은 중단되지 않은 동서 범위가 다각형 내 어디에서나 최대 동서 범위보다 95 % 이상 큰 위치의 맵입니다.


3

확인. 나는 또 다른 (더 나은) 아이디어를 가지고 있습니다 ( idea-№2 ). 그러나 SQL 쿼리가 아닌 파이썬 스크립트로 실현하는 것이 낫다고 생각합니다. 여기서도 EW뿐만 아니라 일반적인 경우가 있습니다.

다각형의 경계 상자와 측정 방향으로 방위각 (A)이 필요합니다. BBox 모서리의 길이가 LA 및 LB라고 가정하십시오. 다각형 내 최대 거리 (MD)는 다음 MB = (LA^2 * LB^2)^(1/2)과 같습니다 . 따라서 탐색 값 (V)은 MB :보다 크지 않습니다 V <= MB.

  1. BBox의 정점에서 시작하여 길이가 MB이고 방위가 A 인 선 (LL)을 만듭니다.
  2. 교차 선 (IL)을 얻기 위해 선 LL을 다각형과 교차
  3. IL의 지오메트리를 확인하십시오-IL 선에 두 개의 점만 있으면 길이를 계산하십시오. 4 이상인 경우-세그먼트를 계산하고 가장 긴 길이를 선택하십시오. Null (교차 없음)-무시
  4. 시작점에서 끝나지 않을 때까지 시작점에서 시계 반대 방향으로 또는 BBox의 가장자리쪽으로 시계 방향으로 이동하는 다른 LL 라인을 계속 만듭니다 (BBox에서 전체 루프를 수행함).
  5. 가장 큰 IL 길이 값을 선택하십시오 (실제로 모든 길이를 저장할 필요는 없으며 반복하는 동안 '지금까지'최대 값을 유지할 수 있습니다)-원하는 것이 될 것입니다.

이것은 꼭짓점에 대한 이중 루프처럼 들립니다. 이는 매우 단순화 된 다각형을 제외하고 피해야 할만큼 비효율적입니다.
whuber

@ whuber, 여기에 추가 루프가 표시되지 않습니다. 널만을 제공 할 BB의 2면에 대한 의미없는 처리가 있습니다. 그러나이 처리는 여기서 삭제 된 응답에서 제공 한 스크립트에서 제외되었습니다 (지금은 주석 인 것 같지만 주석으로 간주되지는 않으며 삭제 된 응답으로 만
보임

(1)이 질문에 대한 세 번째 의견입니다. (2) 당신 말이 옳습니다 : 당신의 설명을 매우주의 깊게 읽으면 경계 상자의 4 개의 정점과 다각형의 정점 사이에서 가장 긴 세그먼트를 찾는 것이 나에게 나타납니다. 그래도 이것이 어떻게 질문에 대답하는지 모르겠습니다. 결과는 OP가 추구 한 것이 아닙니다.
whuber

@whuber, 제안 된 알고리즘은 주어진 방향을 나타내는 선으로 다각형의 가장 긴 교차점을 찾습니다. 분명히 결과는 교차 선 사이의 거리가-> 0인지 또는 모든 꼭지점을 통과하는지 묻는 것입니다 (곡선이 아닌 숫자).
SS_Rebelious

3

Fetzer의 대답이 당신이하고 싶은 일인지 확실하지 않지만 st_box2d가 일을 할 수 있습니다.

SS_Rebelious의 아이디어 N ° 1은 많은 경우 작동하지만 일부 오목 다각형에는 적용되지 않습니다.

동서 선 가능성이있는 경우 정점으로 만든 선이 다각형의 경계를 통과 할 때 가장자리를 따르는 인공 lw 선을 만들어야한다고 생각합니다. 작동하지 않는 예

이를 위해 선 길이가 높은 4 개의 노드 다각형을 만들고 앞의 다각형과 겹치는 다각형 P *를 만들고 min (y1)과 max (y2)가 일부 x 선을 남기는 지 확인하십시오 가능성. (여기서 y1은 왼쪽 상단 코넷과 오른쪽 상단 모서리 사이의 포인트 세트이고, y2는 4 개의 노드 다각형의 왼쪽 하단과 오른쪽 하단 모서리 사이의 y 세트입니다). 이것은 당신이 당신을 도울 psql 도구를 찾을 수 있기를 쉽지 않습니다!


이것은 올바른 길에 있습니다. 가장 긴 EW 세그먼트는 다각형의 정점을 통과하는 수평선이있는 다각형의 내부와의 교차점에서 찾을 수 있습니다. 정점을 반복하는 코드가 필요합니다. 다각형 의 래스터 표현을 가로 지르는 인공 동 서류를 따라가는 대안 (그러나 동등한) 방법이 있습니다 . 다각형에서 발견되는 최대 흐름 길이 ( "영역 통계"중 하나)는 원하는 너비입니다. 래스터 솔루션은 3 ~ 4 단계만으로 얻을 수 있으며 루핑이나 스크립팅이 필요 없습니다.
whuber

@Aname, 오해를 피하기 위해 "SS_Rebelious의 아이디어"에 "№1"을 추가하십시오. 다른 제안을 추가했습니다. 이 편집은 6 자 미만이므로 답을 직접 편집 할 수 없습니다.
SS_Rebelious

1

나는 아이디어 -№1 ( 편집 : EW 방향뿐만 아니라 주석에 설명 된 몇 가지 제한 사항이있는 일반적인 경우). 코드를 제공하지 않고 개념 만 제공합니다. "x 방향"은 실제로 방위각이며 ST_Azimuth에 의해 계산됩니다. 제안 된 단계는 다음과 같습니다.

  1. 다각형에서 모든 정점을 점으로 추출합니다.
  2. 모든 점 쌍 사이에 선을 만듭니다.
  3. 원래 다각형 내에있는 선을 선택 (lw 선이라고 함)합니다 (다각형의 경계를 가로 지르는 선은 필요하지 않습니다).
  4. 모든 lw 라인에 대한 거리와 방위각을 찾으십시오.
  5. 방위각이 원하는 방위각과 같거나 일정한 간격에있는 lw- 라인에서 가장 긴 거리를 선택하십시오 (방위와 방위각이 정확히 동일하지 않을 수 있음).

이것은 정점 (0,0), (1000, 1000) 및 (501, 499)의 삼각형 과 같은 일부 삼각형 에서도 작동하지 않습니다 . 최대 동서 너비는 약 2입니다. 방위각은 모두 약 45 도입니다. 그리고 정점 사이의 최단 선분은 동서 너비보다 350 배 이상 길다.
whuber

@ whuber, 맞습니다. 삼각형에서는 실패하지만 일부 자연 지형지 물을 나타내는 다각형의 경우 유용 할 수 있습니다.
SS_Rebelious 2012 년

1
때로는 정확한 답변을 얻을 수 있기를 희망하는 단순한 경우에도 극적으로 실패하는 절차를 권장하기는 어렵습니다!
whuber

@ whuber이므로 권장하지 않습니다! ;-)이 질문에 대한 답변이 없기 때문에이 해결 방법을 제안했습니다. 더 나은 답변을 게시 할 수 있습니다. BTW, 삼각형 모서리에 몇 가지 점을
넣으면

나는 몇 가지 접근법을 제안했다. 래스터 하나는 gis.stackexchange.com/questions/32552/…에 있고 forums.esri.com/Thread.asp?c=93&f=982&t=107703&mc=3 에 자세히 설명되어 있습니다 . 적용 가능한 것은 아니지만 흥미로운 용도로 사용되는 또 하나는 gis.stackexchange.com/questions/23664/… (라돈 변환)에 있습니다. 이것은 stats.stackexchange.com/a/33102에 설명되어 있습니다 .
whuber

1

질문 과 Evil Genius 의 답변 을 살펴보십시오 .

호수 폴리곤에 많은 점이 있기를 바랍니다. 이러한 점에 방위각 (가로, 지리적 방향)으로 선을 만들 수 있습니다. 가장 먼 두 선 사이의 가장 짧은 선을 계산할 수 있도록 충분히 큰 선 길이 (ST_MakePoint 부분)를 선택하십시오.

예를 들면 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

이 예는 다각형의 최대 너비를 보여줍니다. 이 방법으로 ST_ShortestLine (빨간색 선)을 선택합니다. ST_MakeLine은 값 (파란색 선)을 증가시키고 선의 끝점 (왼쪽 아래)은 다각형의 파란색 선에 닿습니다. 작성된 (도움말) 선의 중심을 사용하여 거리를 계산해야합니다.

이 접근법에 대한 불규칙하거나 오목한 다각형에 대한 아이디어. 다각형을 래스터와 교차시켜야 할 수도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.