【问题标题】:Build a digital elevation model (DEM) while controlling number of mountains and their proximity建立数字高程模型 (DEM),同时控制山脉的数量及其邻近度
【发布时间】:2018-01-26 10:18:03
【问题描述】:

我的目标是获得一个二维数组(即矩阵)的浮点数,它可以被可视化为具有平滑轮廓的数字高程模型(即等高线图) > 如下图所示,前提是我能够控制每次运行脚本时生成多少个白山以及它们之间的距离

白色山脉表示 CSV 文件中包含大于 0.9 的值的单元格簇,如色标所示。在图中,我们看到两座山被低于 0.9 的区域划分。 这是我使用卷积过滤器创建这样一个图像的详细 cmets 的完整代码:

import numpy as np
import pandas as pd
from scipy import signal
import plotly
import plotly.graph_objs as go


def rndmtx():
    """Generate random 2d-array as a digital elevation model."""

    nx = 100
    ny = 100
    dem1 = np.random.rand(nx, ny)
    # Save array to csv file befor Gaussian filter.
    # Comment the next two lines if reading from the csv file.
    dafr = pd.DataFrame(dem1)
    dafr.to_csv('G_dem1.csv', header=False, index=False)

    # Uncomment the next two lines to read from csv file.
    # dafr = pd.read_csv('G_dem1.csv', header=None)
    # dem1 = dafr.values

    # Apply the first Gaussian filter.
    sizex = 5  # The less sizex and sizey the more highlands.
    sizey = 5  # The more sizex and sizey the more water.
    x, y = np.mgrid[-sizex:sizex+1, -sizey:sizey+1]
    scale = 0.33  # The more scale the bigger the difference in elevation.
    g = np.exp(-scale*(x**2/sizex+y**2/sizey))
    filter1 = g/g.sum()  # Normalise the Gaussian function.

    dem_smooth = signal.convolve(dem1, filter1, mode='valid')
    # Rescale so it lies between 0 and 1.
    dem_smooth = ((dem_smooth - dem_smooth.min())
                  / (dem_smooth.max() - dem_smooth.min()))

    # Apply the second Gaussian filter to make the boundaries smoother.
    sizex = 5
    sizey = 5
    x, y = np.mgrid[-sizex:sizex+1, -sizey:sizey+1]
    g = np.exp(-0.33*(x**2/sizex+y**2/sizey))
    filter2 = g/g.sum()

    dem_smooth1 = signal.convolve(dem_smooth, filter2, mode='valid')
    dem_smooth1 = ((dem_smooth1 - dem_smooth1.min())
                   / (dem_smooth1.max() - dem_smooth1.min()))

    return dem_smooth1

# Get the raw random array of the digital elevation model
#   and assign it to the variable.
contour_xy = rndmtx()

# Save the array into CSV file in the working directory.
df = pd.DataFrame(contour_xy)
df.to_csv('last_data.csv', header=False, index=False)

data = [
    go.Contour(
        z=contour_xy,
        colorscale=[
            [0, 'rgb(0, 161, 233)'], [0.28, 'rgb(0, 161, 233)'],
            [0.28, 'rgb(29, 210, 108)'], [0.50, 'rgb(29, 210, 108)'],
            [0.50, 'rgb(141, 232, 130)'], [0.65, 'rgb(141, 232, 130)'],
            [0.65, 'rgb(254, 254, 152)'], [0.75, 'rgb(254, 254, 152)'],
            [0.75, 'rgb(192, 182, 122)'], [0.82, 'rgb(192, 182, 122)'],
            [0.82, 'rgb(142, 110, 92)'], [0.88, 'rgb(142, 110, 92)'],
            [0.88, 'rgb(171, 147, 142)'], [0.93, 'rgb(171, 147, 142)'],
            [0.93, 'rgb(227, 219, 217)'], [0.97, 'rgb(227, 219, 217)'],
            [0.97, 'rgb(255, 255, 255)'], [1, 'rgb(255, 255, 255)']
        ],
    ),
]

layout = go.Layout(
    yaxis=dict(
        autorange='reversed'
    )
)

figure = go.Figure(data=data, layout=layout)
plotly.offline.plot(figure, filename='dem.html')

每次我运行脚本时,我都会得到一个唯一的随机数字数组。

如何控制要生成的白山的数量和距离?

例如,现在我想要在地块上放置 10 座白山,那么我只想要 2 座山,以此类推。

目前,我使用蛮力算法最终构建具有所需山脉数量的绘图,但我无法设置山脉的特定坐标来控制它们之间的距离。

高度赞赏慷慨的答案和指出正确的方向。喜欢玩代码!

【问题讨论】:

  • 有一种非常粗暴的方法,当您生成数字时,最多只能生成 0.9(不包括在内),然后再以 0.9-1.0 的值重新计算,并覆盖地图上的许多随机空间。这里有一些极端情况,你可能会得到不太理想的输出,但严格来说你会得到你想要的。

标签: python arrays pandas numpy scipy


【解决方案1】:

其中一个笨拙的解决方案是在高斯过滤器之前以高于 0.9 的值填充 CSV 文件中的一些单元格簇,例如,全部为 1,如下图所示。

这只是一个在 Excel 中打开的 CSV 文件,应用了色阶功能。左边是随机矩阵。在右侧,您可以看到我尝试设置四个大小相等的 6x4 单元格的山峰,所有单元格都包含一个值“1”。 应用卷积过滤器后,我得到以下结果: 这不好,因为我只有两座山和两个棕色高地。此外,还有很多水。我想要尽可能少的水。

如果您能指出其他技术,我不介意从头开始重写脚本。

更新

感谢社区,我终于找到了一个稳定的解决方案: 构建散点图,然后将其转换为等高线。

见问题Convert Scatter to Contour, every dot turns into a highland

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    相关资源
    最近更新 更多