Как визуализировать азимутальные данные с неопределенностью?

10

Я пытаюсь сделать рисунок, показывающий азимутальные данные с различным диапазоном неопределенностей в каждой точке. Эта фигура старой школы из газеты 1991 года отражает идею «сюжета Боути», к которой я стремлюсь:

От Hillhouse and Wells, 1991. «Магнитная ткань, направления потока и область истока туфа персикового источника в нижнем миоцене в Аризоне, Калифорнии и Неваде»

Любые предложения о том, как я мог бы сделать аналогичную фигуру? Я относительный новичок в GIS, но у меня есть доступ к ArcGIS через мой университет. Мой опыт в Arc был ограничен созданием геологических карт, поэтому мне не приходилось делать что-то слишком экзотическое.

Я разбирался в опциях символов в Arc и QGIS, но не видел никаких настроек, которые, как я думал, сработали бы. Обратите внимание, что это не просто поворот символов в форме бабочки по азимуту; Угловой диапазон каждой "бабочки" должен быть разным.

Я бы оценил мои навыки Python как «сильный промежуточный» и мои навыки R как «низкий промежуточный», так что я не прочь хакерство что - то вместе с matplotlibи mpl_toolkits.basemapили аналогичными библиотеками в случае необходимости. Но я подумал, что мне нужно будет посоветоваться здесь, прежде чем идти по этому пути, на случай, если есть более простое решение из ГИС, о котором я просто не слышал.

юра
источник
Каковы данные по каждому «бабочке»? Я предполагаю широту / долготу / высоту, но каковы дуги? Они отражены по существу?
Симбамангу
Да, каждая точка - широта / долгота, азимут («удар» в терминах геологии), плюс некоторая неопределенность в значении азимута. Например, если у меня есть точка с аз = 110 и неопределенностью 10 градусов, я хочу «галстук-бабочка», который раскрашивает углы между ними 100->120и эквивалентным диапазоном на 180 градусов в180->200
юрское время

Ответы:

10

Это требует своего рода «вычисления поля», в котором вычисленное значение (на основе широты, долготы, центрального азимута, неопределенности и расстояния) представляет собой форму бабочки, а не число. Поскольку при переходе от ArcView 3.x к ArcGIS 8.x такие возможности расчета полей были значительно более сложными и никогда не были полностью восстановлены, в настоящее время мы вместо этого используем сценарии на Python, R или чем-то еще: но процесс мышления все еще остается одни и те же.

Я проиллюстрирую с рабочим Rкодом. В его основе лежит расчет формы галстука-бабочки, который мы поэтому инкапсулируем как функция. Функция на самом деле очень проста: чтобы сгенерировать две дуги на концах лука, необходимо регулярно прослеживать последовательность (по азимуту). Для этого требуется возможность найти координаты (lon, lat) точки на основе начального (lon, lat) и пройденного расстояния. Это делается с помощью подпрограммы goto, где происходит весь тяжелый арифметический подъем. Остальное просто готовит все к применению, gotoа затем применяет его.

bowtie <- function(azimuth, delta, origin=c(0,0), radius=1, eps=1) {
  #
  # On entry:
  #   azimuth and delta are in degrees.
  #   azimuth is east of north; delta should be positive.
  #   origin is (lon, lat) in degrees.
  #   radius is in meters.
  #   eps is in degrees: it is the angular spacing between vertices.
  #
  # On exit:
  #   returns an n by 2 array of (lon, lat) coordinates describing a "bowtie" shape.
  #
  # NB: we work in radians throughout, making conversions from and to degrees at the
  #   entry and exit.
  #--------------------------------------------------------------------------------#
  if (eps <= 0) stop("eps must be positive")
  if (delta <= 0) stop ("delta must be positive")
  if (delta > 90) stop ("delta must be between 0 and 90")
  if (delta >= eps * 10^4) stop("eps is too small compared to delta")
  if (origin[2] > 90 || origin[2] < -90) stop("origin must be in lon-lat")
  a <- azimuth * pi/180; da <- delta * pi/180; de <- eps * pi/180 
  start <- origin * pi/180
  #
  # Precompute values for `goto`.
  #
  lon <- start[1]; lat <- start[2]
  lat.c <- cos(lat); lat.s <- sin(lat)
  radius.radians <- radius/6366710
  radius.c <- cos(radius.radians); radius.s <- sin(radius.radians) * lat.c
  #
  # Find the point at a distance of `radius` from the origin at a bearing of theta.
  # http://williams.best.vwh.net/avform.htm#Math
  #
  goto <- function(theta) {
    lat1 <- asin(lat1.s <- lat.s * radius.c + radius.s * cos(theta))
    dlon <- atan2(-sin(theta) * radius.s, radius.c - lat.s * lat1.s)
    lon1 <- lon - dlon + pi %% (2*pi) - pi
    c(lon1, lat1)
  }
  #
  # Compute the perimeter vertices.
  #
  n.vertices <- ceiling(2*da/de)
  bearings <- seq(from=a-da, to=a+da, length.out=n.vertices)
  t(cbind(start,
        sapply(bearings, goto),
          start,
        sapply(rev(bearings+pi), goto),
          start) * 180/pi)
}

Это предназначено для применения к таблице, записи которой у вас уже должны быть в той или иной форме: каждая из них дает местоположение, азимут, неопределенность (в виде угла на каждую сторону) и (необязательно) указание того, насколько велико сделать тетива. Давайте смоделируем такую ​​таблицу, разместив 1000 галстуков по всему северному полушарию:

n <- 1000
input <- data.frame(cbind(
  id = 1:n, 
  lon = runif(n, -180, 180),
  lat = asin(runif(n)) * 180/pi,
  azimuth = runif(n, 0, 360),
  delta = 90 * rbeta(n, 20, 70),
  radius = 10^7/90 * rgamma(n, 10, scale=2/10)
  ))

На данный момент все почти так же просто, как любой расчет поля. Вот:

  shapes <- as.data.frame(do.call(rbind, 
         by(input, input$id, 
            function(d) cbind(d$id, bowtie(d$azimuth, d$delta, c(d$lon, d$lat), d$radius, 1)))))

(Временные тесты показывают, что Rможет производить около 25 000 вершин в секунду. По умолчанию для каждой степени азимута существует одна вершина, которую можно задать с помощью epsаргумента to bowtie.)

Вы можете сделать простой график результатов Rсами по себе в качестве проверки:

colnames(shapes) <- c("id", "x", "y")
plot(shapes$x, shapes$y, type="n", xlab="Longitude", ylab="Latitude", main="Bowties")
temp <- by(shapes, shapes$id, function(d) lines(d$x, d$y, type="l", lwd=2, col=d$id))

Участок в R

Чтобы создать вывод шейп-файла для импорта в ГИС, используйте shapefilesпакет:

require(shapefiles)
write.shapefile(convert.to.shapefile(shapes, input, "id", 5), "f:/temp/bowties", arcgis=T)

Теперь вы можете проецировать результаты и т. Д. В этом примере используется стереографическая проекция северного полушария, а бабочки окрашены квантилями неопределенности. (Если вы посмотрите очень внимательно на 180 / -180 градусов долготы, вы увидите, где эта ГИС обрезала галстуки-бабочки, которые пересекают эту линию. Это общий недостаток ГИС; это не отражает ошибку в самом Rкоде.)

Сюжет в ArcView

Whuber
источник