【问题标题】:Draw svg points from geoJSON query and image using d3 library使用 d3 库从 geoJSON 查询和图像中绘制 svg 点
【发布时间】:2021-08-31 19:02:06
【问题描述】:

我可以绘制图像地图并且可以检索几何路径,但是尽管 geoData 链接正确,但它并未在地图中绘制任何几何图形。 从堆栈和其他地方看到一些示例,示例与此类似。

知道为什么没有读取数据(我假设问题在于正在检索的数据)?

提前致谢

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<body>
    <div id="map" style="position:absolute; width:400px; height:600px; overflow:hidden; border: 1px solid red;">
        <img
            src="https://sig.cm-figfoz.pt/arcgis/rest/services/Internet/MunisigWeb_DadosContexto/MapServer/export?dpi=96&transparent=true&format=png8&layers=show:1,2,4,7,8,12,13&bbox=-58842.91417500004,43056.64792531277,-58667.48812500015,43317.59417468761&bboxSR=3763&imageSR=3763&size=400,595&f=image">
    </div>
    <svg overflow="hidden" width="400" height="600" id="map_gc"
        style="touch-action: none; will-change: transform; overflow: visible; position: absolute; transform: translate3d(0x, 0px, 0px);">
    </svg>
    <script>
        var width = 400;
        var height = 600;

        var chosenProjection = d3.geoMercator()
            .scale(0)
            .translate([0, 0])

        var path = d3.geoPath()
            .projection(chosenProjection);

        var OutputJSON = "https://sig.cm-figfoz.pt/arcgis/rest/services/Internet/MunisigWeb_DadosContexto/MapServer/12/query?where=NOMERUA+LIKE+%27%25Beco+da+F%C3%A9%25%27+AND+LUG11DESIG+LIKE+%27%25Franco%25%27&text=&objectIds=&time=&geometry=&geometryType=esriGeometryPolygon&inSR=&spatialRel=esriSpatialRelIntersects&relationParam=&outFields=&returnGeometry=true&returnTrueCurves=false&maxAllowableOffset=&geometryPrecision=&outSR=&returnIdsOnly=false&returnCountOnly=false&orderByFields=&groupByFieldsForStatistics=&outStatistics=&returnZ=false&returnM=false&gdbVersion=&returnDistinctValues=false&resultOffset=&resultRecordCount=&queryByDistance=&returnExtentsOnly=false&datumTransformation=&parameterValues=&rangeValues=&f=pjson"

        d3.json(OutputJSON, function (error, data) {

            d3.select("svg").append("path")
                .attr("d", path(data));
        });
    </script>
</body>

【问题讨论】:

    标签: javascript d3.js map-projections


    【解决方案1】:

    从 d3v5 开始,d3.json 返回一个承诺。您需要使用格式 d3.json("url").then(function(data) {... 而不是 d3.json("url", function(data) { ...)

    另外,您的数据实际上并不是 geojson。 ESRI 有自己的 json 格式,它非常 not geojson。似乎 ESRI 最近在其产品中内置了更多 geojson 支持,但也有很多选项可以将 shapefile 转换为 geojson(与其他格式相比,ESRI 的 json 格式相对较少)。在线 shapefile → geojson 转换工具见mapshaper。无效的 geojson 不会对 D3 产生错误,它只是不会导致 d3.geoPath 返回任何路径数据。所以。要解决这个问题,您需要使用有效的 geojson 数据源。

    修复上述两点后,您将成功加载数据并将路径附加到您的 SVG。

    不过,这会引出您的下一个问题:我的功能在哪里?以上两点可能会解决您最紧迫的问题,但可能会导致一个新问题,我将简要介绍一下:

    我的功能在哪里?

    您没有在图像和“geojson”之间对齐坐标。图像有一个以像素为单位测量的坐标系:左上角的像素位于 [0,0] 处,右下角的像素位于 [400,595] 处。您的 json 坐标绝对超出此范围,例如 [-58696.7258,43252.2659]

    您可能已经通过使用 D3 投影预料到了这一点。 虽然这是一个单独的问题,但您已将比例值设置为 0。比例值决定了地图的宽度:默认值约为 152,这意味着(经度的)单个弧度应该横跨152 像素。值为零表示单个弧度应该完全不跨越任何像素,这意味着该特征无论如何都不可见。

    您的“geojson”数据是投影的,因为它不包含三维地球上的经纬度对。相反,它包含二维曲面上的笛卡尔点。 D3 地理预测采用前者。因此,如果我们想使用这种类型的投影,我们可以“取消投影”数据,以便它使用 WGS84 坐标。 在此之后,我们需要创建一个与图像匹配的投影。

    或者,我们可以对数据应用变换,使变换后的数据与图像占据相同的坐标空间。

    选项 1:取消投影数据:

    如果

    • 我们知道 geojson 使用什么坐标系
    • 我们知道图片的地理范围
    • 我们知道用于创建图像的投影类型/坐标系

    我们可以取消投影数据并将其投影以匹配图像。

    对于未投影的数据,我们可以将带有 WGS84 坐标的 geojson 传递给 d3.geoPath - 但是,这不是图像的坐标系(因为 [400,595] 不是有效的长/纬度对)。我们需要匹配两个坐标系。

    然后,我们通过遵循this 之类的过程来模拟用于创建图像的投影,以将 d3-geoProjection 匹配到某个任意投影。 (见also)。

    由于图像源的投影很可能不在以像素为基本单位的坐标系中,因此我们需要以度为单位获取其边界框,以正确缩放投影的 geojson。没有这个,我们就无法知道[0,0]对应的地理点像素。

    选项 2:转换数据

    如果

    • image 和 geojson 使用相同的投影
    • 具有相同的程度

    然后我们可以使用变换来对齐两者。我们可以使用d3.geoIdentity() 来做到这一点,其中包括一个名为fitExtent([[left,top],[right,bottom]],geojsonObject) 的方法。

    由于图像的坐标以像素为单位,我们需要将 geojson 的坐标压缩/拉伸到与图像相同的像素范围,fitExtent 就是这样做的(上/左/下/右值以像素为单位)。如果图像锚定在 [0,0],那么我们将使用:d3.geoIdentity().fitExtent([[0,0],[400,595]],geojsonObject)

    我们可能需要在 y 轴上镜像 geojson,因为地理惯例通常会在向北移动时增加 y 值,而 SVG 在向下移动屏幕时会增加 y 值,我们可以使用 identity.reflectY() 来实现这一目标。

    如果范围不同 - 我们仍然可以使用 d3.geoTransform 创建一个变换函数,只是会变得更复杂一些。


    无论哪种方式,只有借助附加信息,我们才能尝试对齐两个不同的坐标系:像素与任意投影坐标系。如果您需要,一个新问题应该包含此信息以便给出明确的答案。

    【讨论】:

    • 嗨,读了几次之后,我想我明白该怎么做了……目前我已经设法完成了第一部分(就像你说的那样,这很容易)。我将不得不再次阅读第二部分及其选项)。一旦我对它做了什么,我一定会写一些东西。提前致谢
    • 哦还有一件事...我可以访问原始查询,我可以在其中以我想要的方式输出我想要的内容。问题是,在尝试使用 geoJSON 输出之后,由于它没有显示任何内容,我测试了其他的(没有结果)。看来问题出在你所说的那个承诺上。现在我在geoJSON中有这个,它的坐标是很小的数字,比如[-8.8210301082068749,40.055763774201118],而不是[-58696.725800000131,43252.26590000093]。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    • 2021-06-21
    • 1970-01-01
    • 2014-01-26
    相关资源
    最近更新 更多