PostGIS'de x-yönünde (doğu-batı yönünde) çokgen içindeki maksimum mesafeyi mi hesaplıyorsunuz?


13

Doğu-batı yönünde bir gölün maksimum genişliğiyle ilgileniyorum. Sınırlayıcı kutular sadece basit çokgenlerde yardımcı olur, ancak karmaşık içbükey çokgenlerde yardımcı olmaz.


3
Postgis işlevselliğine aşina değilim. Ancak, sınırlayıcı bir kutu aracı olabilir. Sınırlama kutusunun genişliği EW yönündeki maksimum mesafe olacaktır.
Fezter

4
@Fetzter doğru değil: basit bir karmaşık çokgen için bile bir karşı örnek, SW'den NE'ye uzanan ince bir eşkenar dörtgen. Maksimum doğu-batı genişliği sınırlayıcı kutusunun genişliğinin keyfi olarak küçük bir kısmı olabilir.
whuber

1
Bu ve bu tekliflere dayanarak bu görev için bir yardımcı program oluşturdum . Çokgenin maksimum veya minimum genişliğini hesaplayabilir. Şu anda bir shp dosyalarıyla çalışır, ancak bir PostGIS ile çalışmak için yeniden yazabilir veya PostGIS ile de çalışacak bir QGIS eklentisine dönüşene kadar bir süre bekleyebilirsiniz. Ayrıntılı açıklama ve indirme linki burada .
SS_Rebelious

Yanıtlar:


16

Bu muhtemelen herhangi bir CBS platformunda bazı komut dosyaları gerektirir.

En verimli yöntem (asimptotik olarak) dikey bir çizgi taramasıdır: kenarları minimum y koordinatlarına göre sıralamayı ve ardından kenarları alttan (minimum y) yukarı (maksimum y), bir O (e * günlüğü ( e)) e kenarlar söz konusu olduğunda algoritma .

Prosedür, her ne kadar basit olsa da, her durumda doğru bir şekilde elde etmek şaşırtıcı derecede zordur. Çokgenler kötü olabilir: sarkmalara, şeritlere, deliklere sahip olabilirler, bağlantı kesilebilirler, çoğaltılmış köşeleri, düz çizgiler boyunca köşeler ve iki bitişik bileşen arasında çözülmemiş sınırları olabilir. İşte bu özelliklerin çoğunu (ve daha fazlasını) gösteren bir örnek:

Çokgen

Özellikle tamamen çokgenin kapatılması içinde bulunan maksimum uzunluktaki yatay segment (ler) i arayacağız . Örneğin bu, x = 10 ve x = 25 arasındaki delikten çıkan x = 20 ve x = 40 arasındaki salgıyı ortadan kaldırır. Daha sonra, maksimum uzunluktaki yatay segmentlerden en az birinin en az bir tepe ile kesiştiğini göstermek kolaydır. (Hayır köşe kesişen çözümler varsa, bunlar çözümlerle altta ve üstte sınırlanmış bazı paralelkenar iç yatacak yapmak en az bir tepeye kesiştiği. Bu bize bulmak için bir araç verir bütün çözümleri.)

Buna göre, çizgi taraması en düşük köşelerle başlamalı ve sonra her bir tepe noktasında durmak için yukarı doğru (yani daha yüksek y değerlerine doğru) hareket etmelidir. Her durakta, o yükseklikten yukarı doğru çıkan yeni kenarlar buluyoruz; bu yükseklikte aşağıdan sonlanan kenarları ortadan kaldırın (bu, anahtar fikirlerden biridir: algoritmayı basitleştirir ve potansiyel işlemenin yarısını ortadan kaldırır); ve tamamen sabit bir yükseklikte (yatay kenarlar) yatan kenarları dikkatlice işleyin.

Örneğin, y = 10 seviyesine ulaşıldığında durumu düşünün. Soldan sağa aşağıdaki kenarları buluruz:

      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

Bu tabloda, (x.min, y.min) kenarın alt uç noktasının koordinatlarıdır ve (x.max, y.max) üst uç noktasının koordinatlarıdır. Bu seviyede (y = 10), ilk kenar iç kısmında durdurulur, ikincisi alt kısmında durdurulur, vb. İçin, örneğin (10,0) itibaren bu düzeyde son bulan bazı kenarları (10,10), olan olmayan listeye dahil.

İç noktaların ve dış noktaların nerede olduğunu belirlemek için, elbette çokgenin dışında olan aşırı soldan başlayıp yatay olarak sağa doğru hareket ettiğinizi hayal edin. Yatay olmayan bir kenarı her geçtiğimizde , sırayla dıştan iç mekana ve arkaya geçeriz. (Bu başka bir önemli fikirdir.) Bununla birlikte, herhangi bir yatay kenardaki tüm noktaların, ne olursa olsun, çokgenin içinde olduğu belirlenir. (Çokgenin kapatılması her zaman kenarlarını içerir.)

Örneğe devam edersek, yatay olmayan kenarların y = 10 satırında başladığı veya geçtiği x koordinatlarının sıralı listesi aşağıdadır :

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

(X = 40'ın bu listede olmadığına dikkat edin.) Dizinin değerleri interior, iç segmentlerin sol uç noktalarını işaretler: 1, bir iç aralık, 0 bir dış aralık belirtir. Böylece, ilk 1 x = 6.7 ila x = 10 arasındaki aralığın çokgenin içinde olduğunu gösterir. Sonraki 0, x = 10 ile x = 20 arasındaki aralığın çokgenin dışında olduğunu gösterir . Ve böylece devam eder: dizi, çokgenin içindeki gibi dört ayrı aralık tanımlar.

Bu aralıkların bazıları, örneğin x = 60 ila x = 63.3 gibi, herhangi bir köşeyi kesmez: y = 10 ile tüm köşelerin x koordinatlarına karşı hızlı bir kontrol, bu aralıkları ortadan kaldırır.

Tarama sırasında, şimdiye kadar bulunan maksimum uzunluk aralıkları ile ilgili verileri koruyarak bu aralıkların uzunluklarını izleyebiliriz.

Bu yaklaşımın bazı etkilerine dikkat edin. Bir "v" şekilli tepe noktası, karşılaşıldığında, iki kenarın kökenidir. Bu nedenle , geçerken iki anahtar oluşur. Bu anahtarlar iptal edilir. Herhangi bir baş aşağı "v" bile işlenmez, çünkü soldan sağa taramaya başlamadan önce her iki kenarı da ortadan kaldırılır. Her iki durumda da, böyle bir tepe yatay bir parçayı engellemez.

İkiden fazla kenar bir tepe noktasını paylaşabilir: bu (10,0), (60,5), (25, 20) 'de gösterilmiştir ve - söylemek zor olsa da (20,10) ve (40) , 10). (Çünkü sarkan gider (20,10) -> (40,10) -> (40,0) -> (40, -50) -> (40, 10) -> (20, (40,0) 'daki tepe noktasının da başka bir kenarın iç kısmında nasıl olduğuna dikkat edin ... bu çok kötü.) Bu algoritma bu durumları gayet iyi idare ediyor.

Zor bir durum en altta gösterilmiştir: yatay olmayan segmentlerin x koordinatları vardır

30, 50

Bu, x = 30'un solundaki her şeyin dış olarak kabul edilmesine, 30 ile 50 arasındaki her şeyin iç olmasına ve 50'den sonraki her şeyin tekrar dış olmasına neden olur. X = 40'taki tepe noktası bu algoritmada asla dikkate alınmaz.

Taramanın sonunda çokgenin görüntüsü. Köşe içeren tüm iç aralıkları koyu gri, maksimum uzunluk aralığını kırmızı olarak gösterir ve köşeleri y koordinatlarına göre renklendiririm. Maksimum aralık 64 birim uzunluğundadır.

Taramadan sonra

İlgili tek geometrik hesaplamalar kenarların yatay çizgilerle kesiştiği yeri hesaplamaktır: bu basit bir doğrusal enterpolasyondur. Hesaplamalar ayrıca iç kesimleri köşe içeren belirlemek için gereklidir: bunlar betweenness kolayca eşitsizliklerin bir çift hesaplanan tespitler. Bu basitlik algoritmayı hem tamsayı hem de kayan nokta koordinat gösterimleri için sağlam ve uygun hale getirir.

Koordinatlar coğrafi ise , yatay çizgiler gerçekten enlem dairelerinde bulunur. Uzunluklarını hesaplamak zor değildir: Öklid uzunluklarını enlemlerinin kosinüsü ile çarpın (küresel bir modelde). Bu nedenle bu algoritma coğrafi koordinatlara iyi uyum sağlar. (+ -180 meridyen kuyusunun etrafına sarmak için, önce güney kutbundan kuzey kutbuna çokgenden geçmeyen bir eğri bulunması gerekebilir. Tüm x-koordinatlarını buna göre yatay yer değiştirmeler olarak tekrar ifade ettikten sonra eğri, bu algoritma maksimum yatay segmenti doğru bir şekilde bulur.)


RHesaplamaları yapmak ve resimleri oluşturmak için uygulanan kod aşağıdadı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)

Herhangi bir yönde dışbükey olmayan çokgen içindeki maksimum uzunluk çizgisinin bu çokgenin en az bir tepe noktasıyla kesiştiğini kanıtlayan bir teorem var mı?
SS_Rebelious

@SS Evet, var. İşte bir kanıt taslağı: Kavşak yoksa, segmentin uç noktaları hem kenarların iç kısımlarında hem de segment en azından biraz yukarı ve aşağı hareket ettirilebilir. Uzunluğu, yer değiştirme miktarının doğrusal bir fonksiyonudur. Böylece, sadece uzunluk taşınırken değişmezse maksimum bir uzunluğa sahip olabilir. Bu, hem (a) maksimum uzunluktaki segmentlerden oluşan bir paralelkenarın parçası olduğu ve (b) bu ​​paralelkenarın hem üst hem de alt kenarlarının QED tepe noktasına uyması gerektiği anlamına gelir.
whuber

Ve bu teoremin adı nedir? Onu bulmak için uğraşıyorum. BTW, tepe noktası olmayan kavisli kenarlar hakkında (teorik bir yaklaşım demek istiyorum)? Demek istediğim şekil örneği (aptal-çan biçimli çokgen): "C = D".
SS_Rebelious

@SS Kenarlar kavisli olduğunda, teorem artık kalmaz. Yararlı sonuçlar elde etmek için diferansiyel geometri teknikleri uygulanabilir. Bu yöntemleri Cheeger & Ebin'in Riemann Geometrisinde Karşılaştırma Teoremleri kitabından öğrendim . Bununla birlikte, çoğu CBS, eğrileri detaylı polinilerle yaklaşık olarak tahmin edecektir, bu nedenle soru (pratik bir konu olarak) tartışmalıdır.
whuber

teorem adını (ve mümkünse sayfayı) belirtir misiniz? Kitabı aldım ve gerekli teoremi bulamadım.
SS_Rebelious

9

İşte raster tabanlı bir çözüm. Hızlıdır (14 dakika içinde baştan sona tüm işleri yaptım), komut dosyası gerektirmez, sadece birkaç işlem yapar ve makul doğrudur.

Çokgenin raster gösterimi ile başlayın. Bu, 550 satır ve 1200 sütunluk bir ızgara kullanır:

Çokgen

Bu gösterimde, gri (iç) hücreler 1 değerine sahiptir ve diğer tüm hücreler NoData'dır.

Ağırlık ızgarası için birim hücre değerlerini ("yağış" miktarı) kullanarak batı-doğu yönünde akış birikimini hesaplayın :

Akış birikimi

Düşük birikim karanlıktır ve parlak sarıdaki en yüksek birikimlere yükselir.

Bir maksimum bölge (ızgara için çokgen ve değerler için akış birikimi kullanılarak), akışın en büyük olduğu hücreleri belirler. Bunları göstermek için sağ alta doğru yakınlaştırmak zorunda kaldım:

Maksimum

Kırmızı hücreler, en yüksek akış birikimlerinin uçlarını işaretler: bunlar, çokgenin maksimum uzunluktaki iç segmentlerinin en sağ uç noktalarıdır.

Bu segmentleri bulmak için, tüm ağırlıkları kırmızı hücrelere yerleştirin ve akışı geriye doğru çalıştırın!

Sonuç

Alt taraftaki kırmızı şerit iki sıra hücre işaretler: bunların içinde maksimum uzunluktaki yatay segment bulunur. Bu temsili daha fazla analiz için olduğu gibi kullanın veya çokgen (veya çokgen) şekle dönüştürün.

Raster temsili ile yapılan bazı takdir yetkisi hatası var. Hesaplama süresinde bir miktar maliyetle çözünürlüğü artırarak azaltılabilir.


Bu yaklaşımın gerçekten güzel bir yönü, tipik olarak, bazı hedeflere ulaşılması gereken daha büyük bir iş akışının parçası olarak şeylerin aşırı değerlerini bulmamızdır: bir boru hattı veya futbol sahası oturmak, ekolojik tamponlar oluşturmak vb. Süreç ödünleşmeleri içerir. Bu nedenle, en uzun yatay çizgi optimal bir çözümün parçası olmayabilir. Bunun yerine neredeyse en uzun çizgilerin nerede olacağını bilmek isteriz. Bu basit: bölgesel maksimum akışı seçmek yerine, bölgesel maksimuma yakın tüm hücreleri seçin. Bu örnekte, bölgesel maks 744'e (en uzun iç segment tarafından yayılan sütun sayısı) eşittir. Bunun yerine, bu maksimum değerin% 5'indeki tüm hücreleri seçelim:

Seçilen optimal hücrelere yakın

Doğudan batıya doğru akışı yürütmek, bu yatay segment koleksiyonunu üretir:

Neredeyse en uygun çözümler

Bu, çokgen içinde herhangi bir yerde kesintisiz doğu-batı boyutunun maksimum doğu-batı boyutundan% 95 veya daha fazla olduğu konumların haritasıdır.


3

Tamam. Başka (daha iyi) bir fikrim var ( fikir-№2 ). Ama bir SQL-querry olarak değil, bir python betiği olarak gerçekleştirilmesinin daha iyi olduğunu düşünüyorum. Yine burada ortak durum, sadece EW değil.

Çokgen için sınırlayıcı bir kutu ve ölçüm yönünüz olarak bir azimut (A) gerekir. BBox kenarlarının uzunluğunun LA ve LB olduğunu varsayın. Poligon içinde maksimum olası mesafe (MD) 'dir: MB = (LA^2 * LB^2)^(1/2), değer (V) arayan MB'den değil büyüktür böylece: V <= MB.

  1. BBox'un herhangi bir köşesinden başlayarak, MB ve azimut A uzunluğunda bir çizgi (LL) oluşturun.
  2. Kavşak çizgisi (IL) elde etmek için LL çizgisini poligonla kesiştir
  3. IL geometrisini kontrol edin - IL hattında sadece iki nokta varsa, uzunluğunu hesaplayın. 4 veya daha fazla ise - segmentleri hesaplayın ve en uzun olanın uzunluğunu alın. Boş (hiç kavşak yok) - yoksay.
  4. Başlangıç ​​noktasında bitmeyene kadar (tüm döngüyü BBox üzerinden yapacaksınız) başlayana kadar başlangıç ​​noktasından saat yönünde veya saat yönünde BBox'un kenarlarına doğru hareket eden başka bir LL çizgisi oluşturmaya devam edin.
  5. En büyük IL uzunluğu değerini alın (aslında tüm uzunlukları saklamak zorunda değilsiniz, döngü sırasında 'şimdiye kadar' maksimum değeri koruyabilirsiniz) - aradığınız şey olacaktır.

Bu, köşelerde çift döngü gibi görünür: kaçınılması gereken kadar verimsizdir (çok basitleştirilmiş çokgenler hariç).
whuber

@whuber, burada fazladan döngü görmüyorum. BB'nin 2 tarafının null'lardan başka bir şey vermeyecek bazı anlamsız işlemleri vardır. Ancak bu işlem, burada silinen cevapta sağladığım komut dosyasında hariç tutuldu (şimdi bir yorum gibi görünüyor, ancak bir yorum olarak görmüyorum - sadece silinmiş bir cevap olarak)
SS_Rebelious

(1) Bu sorunun üçüncü yorumu. (2) Haklısın: açıklamanızı çok dikkatli okuduktan sonra, sınırlayıcı kutunun (dört) köşeleri ile çokgenin köşeleri arasındaki en uzun parçayı bulduğunuz anlaşılıyor. Ancak bunun soruyu nasıl cevapladığını görmüyorum: sonuç kesinlikle OP'nin aradığı şey değil.
whuber

@whuber, önerilen algoritma çokgenin verilen yönü temsil eden en uzun kesişim noktasını bulur. Görünüşe göre sonuç, kesişme çizgileri arasındaki mesafe -> 0 ise veya tüm tepe noktalarını geçerse (eğri olmayan şekiller için) sorulan şeydir.
SS_Rebelious

3

Fetzer'in cevabının yapmak istediğiniz şey olduğundan emin değilim, ancak st_box2d işi yapabilir.

SS_Rebelious'un N ° 1 fikri birçok durumda işe yarar ancak bazı içbükey çokgenler için işe yaramaz.

Doğu-batı çizgi olasılığı varsa, köşe yapımı çizgiler çokgenin sınırlarını aştığında noktaları takip eden yapay lw-çizgileri oluşturmanız gerektiğini düşünüyorum. işe yaramayacağı bir örnek

Bunun için, satır uzunluğunun yüksek olduğu bir 4 düğümlü çokgen yapmaya çalışabilir, önceki poligonla üst üste binen poligon P * 'yı yapabilir ve min (y1) ve max (y2)' nin biraz x-çizgisi bırakıp bırakmadığını görebilirsiniz. olasılık. (burada y1, sol üst kornet ile sağ üst köşe arasındaki nokta kümesidir ve y2, 4 düğümlü çokgeninizin sol alt ve sağ alt köşeleri arasındaki y kümesidir). Bu o kadar kolay değil umarım size yardımcı olacak psql araçları bulacaksınız!


Bu doğru yolda. En uzun EW segmenti, çokgenin iç kısmı ile yatay çizgiler ve çokgenin köşelerinden geçen kavşaklar arasında bulunacaktır. Bu, köşelerin üzerinde döngü oluşturmak için kod gerektirir. Poligonun raster temsili boyunca yapay bir doğu-batı akışı izlenerek alternatif (fakat eşdeğer) bir yöntem vardır : çokgendeki ("bölgesel istatistiklerinden" biridir) bulunan maksimum akış uzunluğu istenen genişliktir. Raster çözeltisi sadece 3 veya 4 adımda elde edilir ve hiçbir döngü veya komut dosyası gerektirmez.
whuber

@Aname, yanlış anlaşılmayı önlemek için lütfen "SS_Rebelious'un fikrine" "№1" ekleyin: Başka bir teklif ekledim. Cevabınızı kendim düzenleyemiyorum çünkü bu düzenleme 6 karakterden az.
SS_Rebelious

1

Bir fikrim №1 ( Düzenleme: ortak durum için, sadece EW yönü ve yorumlarda açıklanan bazı sınırlamalarla) var. Kodu vermeyeceğim, sadece bir kavram. "X-yönü" aslında ST_Azimuth tarafından hesaplanan bir azimuttur. Önerilen adımlar:

  1. Poligondaki tüm köşeleri nokta olarak çıkarın.
  2. Her nokta çifti arasında çizgiler oluşturun.
  3. Orijinal çokgen dahilindeki satırları seçin (onlara lw-çizgileri diyelim) (çokgenin sınırlarını aşacak çizgilere ihtiyacımız yok).
  4. Her lw hattı için mesafeleri ve azimutları bulun.
  5. Azimutun azimut için aranan veya eşit bir aralıkta olduğu lw-çizgilerinden en uzun mesafeyi seçin (hiçbir azimutun azimut için tam olarak eşit olmayacağı olabilir).

Bu, (0,0), (1000, 1000) ve (501, 499) köşelerindeki üçgenler için bile işe yaramaz . Maksimum doğu-batı genişliği yaklaşık 2'dir; azimutların hepsi yaklaşık 45 derecedir; ve ne olursa olsun, köşeler arasındaki en kısa çizgi dilimi doğu-batı genişliğinden 350 kat daha uzundur.
whuber

@whuber, haklısın, üçgenler için başarısız olacak, ancak çokgenler için, bazı doğa özelliklerini temsil eden yararlı olabilir.
SS_Rebelious

1
Bazen doğru cevap alabileceği umuduyla basit vakalarda bile önemli ölçüde başarısız olan bir prosedür önermek zordur!
whuber

@whuber, bu yüzden tavsiye etmeyin! ;-) Bu geçici çözümü önerdim çünkü bu sorunun cevabı yoktu. Kendi daha iyi yanıtınızı gönderebileceğinizi unutmayın. BTW, üçgen kenarlarına bazı noktalar yerleştirirseniz, teklifim işe yarayacaktır ;-)
SS_Rebelious

Birkaç yaklaşım önerdim. Bir tarama gis.stackexchange.com/questions/32552/… adresindedir ve forums.esri.com/Thread.asp?c=93&f=982&t=107703&mc=3 adresinde detaylandırılmıştır . Bir diğeri - tam olarak uygulanabilir değil, ancak ilginç kullanımlarla - gis.stackexchange.com/questions/23664/… (radon dönüşümü) adresindedir . Bu, stats.stackexchange.com/a/33102 adresinde gösterilmiştir .
whuber

1

Benim göz at sorusuna ve cevap Evil Genius dan.

Umarım göl poligonunuzun birkaç noktası vardır, bu noktalarda azimut (en boy, coğrafi yön) ile çizgiler oluşturabilirsiniz. En uzak iki çizgi arasındaki en kısa çizgiyi hesaplayabilmeniz için çizgilerin uzunluğunu (ST_MakePoint bölümü) seçin.

İşte bir örnek:

resim açıklamasını buraya girin

Örnek, çokgenin maksimum genişliğini göstermektedir. Bu yaklaşım için ST_ShortestLine (kırmızı çizgi) seçiyorum. ST_MakeLine değeri (mavi çizgi) artıracak ve çizginin bitiş noktası (sol alt) çokgenin mavi çizgisine çarpacaktır. Mesafeyi, oluşturulan (yardım) çizgilerin centroidleri ile hesaplamanız gerekir.

Bu yaklaşım için düzensiz veya içbükey çokgenler için bir fikir. Belki poligonu bir rasterle kesmeniz gerekebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.