d3-geo-voronoi d3-tile多边形填充问题

问题描述 投票:0回答:1

我正在尝试使用d3-geo-voronoi使用d3-tile显示矢量图块数据。我最初的尝试是在显示数据时将填充设置为“ none”,但这种尝试非常有效!Voronoi tile map without color fill

但是,当我尝试填充多边形时,某些拼贴变形了。Voronoi tile map with color fill

我无法弄清楚为什么会这样。我检查了dom中的svg,一切看起来正确。没有多边形的svg是正确的,只是没有正确渲染它们,可能是被掩盖了。下面是我使用的代码:

const d3 = require('d3');
const d3tile = require('d3-tile');
const d3geovoronoi = require('d3-geo-voronoi');
const vt2geojson = require('@mapbox/vt2geojson');

const pi = Math.PI,
      tau = 2 * pi;

const width = Math.max(960, window.innerWidth),
      height = Math.max(500, window.innerHeight);

const map = d3.select("body").append("div")
  .attr("class", "map")
  .style("width", width + "px")
  .style("height", height + "px")
  .on("mousemove", mousemoved);

let projection = d3.geoMercator()
  .scale(1 / tau)
  .translate([0, 0]);

let center = projection([-76.3, 38.794745]);

const tile = d3tile.tile()
  .size([width, height]);

const zoom = d3.zoom()
  .scaleExtent([1 << 15, 1 << 24])
  .on("zoom", zoomed);

const svg = map.append("g")
  .attr("pointer-events", "none")
  .attr("class", "svg");

const info = map.append("g")
  .attr("class", "info");

const ramp = d3.scaleLinear().domain([0.05,0.07]).interpolate(d3.interpolateHcl).range(['#34d8eb','#3a34eb']).unknown("#5c5752")

map.call(zoom)
  .call(zoom.transform, d3.zoomIdentity
    .translate(width / 2, height / 2)
    .scale(1 << 21)
    .translate(-center[0], -center[1]));

function zoomed() {
  let transform = d3.event.transform;

  let tiles = tile(transform);

  let image = svg 
    .style("transform", stringify(tiles.scale, tiles.translate))
    .selectAll(".tile")
    .data(tiles, function(d) { return d; })
    .enter().append("svg")
    .attr("class", "tile")
    .attr("fill", "none")
    .attr("stroke", "#000")
    .attr("stroke-width", "0.5")
    .attr("stroke-linejoin", "round")
    .attr("stroke-linecap", "round")
    .style("left", function(d) { return d[0] * 256 + "px"; })
    .style("top", function(d) { return d[1] * 256 + "px"; })
    .each(function(d) { this._xhr = render(d, this); });

  projection
    .scale(transform.k / tau)
    .translate([transform.x, transform.y]);

}

function render(d, xnode) {
  let k = Math.pow(2, d[2]) * 256;
  vt2geojson({
    uri: 'http://localhost:7800/public.r3sim_fort_temp/'+d[2]+'/'+d[0]+'/'+d[1]+'.pbf?properties=node,zeta,mask,bathymetry'
  }, function (err, json) {
    if (err) throw err;
    d3.select(xnode)
      .selectAll("path")
      .data(d3geovoronoi.geoVoronoi().polygons(json).features)
      .enter().append("path")
    //.attr('fill', 'none')
        .attr("fill", function(d) {return ramp(d.properties.site.properties.zeta)})
        .attr("stroke", "#fff")
        .attr("stroke-width", "0.5")
        .attr("stroke-linejoin", "round")
        .attr("stroke-linecap", "round")
        .attr("d", d3.geoPath()
            .projection(d3.geoMercator()
                .scale(k / tau)
                .translate([k / 2 - d[0] * 256, k / 2 - d[1] * 256])
                .precision(0)));
  })
}

function stringify(scale, translate) {
  const k = scale / 256, r = scale % 1 ? Number : Math.round;
  return "matrix3d(" + [k, 0, 0, 0, 0, k, 0, 0, 0, 0, k, 0, r(translate[0] * scale), r(translate[1] * scale), 0, 1 ] + ")";
}

function mousemoved() {
  info.text(formatLocation(projection.invert(d3.mouse(this)), d3.zoomTransform(this).k));
}

function formatLocation(p, k) {
  const format = d3.format("." + Math.floor(Math.log(k) / 2 - 2) + "f");
  return (p[1] < 0 ? format(-p[1]) + "°S" : format(p[1]) + "°N") + " "
       + (p[0] < 0 ? format(-p[0]) + "°W" : format(p[0]) + "°E");
}

<!doctype html>
<head>
  <meta charset="utf-8">
  <title>D3 V5 Vector Tile Example</title>
  <style>
    body {
      margin: 0;
    }
    .map {
      background: #5c5752;
      position: relative;
      overflow: hidden;
    }
    .svg {
      position: absolute;
      will-change: transform;
    }
    .tile {
      position: absolute;
      width: 256px;
      height: 256px;
    }
    .info {
      position: absolute;
      bottom: 10px;
      left: 10px;
    }
  </style>
</head>
<body>
  <script src="bundle.js"></script>
</body>

在此示例中,我用不同的颜色值填充了多边形。但是,如果使用单一颜色值,则会发生完全相同的失真。如果我重新加载所有数据,这些失真也总是在同一位置。

dictionary d3.js svg voronoi vector-tiles
1个回答
0
投票

我深入研究了数据,找到了错误的svg路径,然后找到了与之相关的数据。看起来d3.geo.voronoi正在生成一些错误的坐标,但输入数据看起来还不错。以下是节点1192的两个打印输出。第一个是输入的geojson数据,显示了坐标,第二个是voronoi几何。 voronoi几何包含东半球(103.86 ...)中的经度值,该值超出了数据范围。我仍在尝试确定为什么会产生这些不良值。同样,输入坐标看起来正确,但是可能是其他数据进入了voronoi计算?

1192 
{…}
  geometry: {…}
    coordinates: (2) […]
      0: -76.12801194190979
      1: 38.78622954627738
      length: 2
      <prototype>: Array []
    type: "Point"
    <prototype>: Object { … }
  properties: Object { node: 180407, zeta: "NaN", mask: "True", … }
  type: "Feature"
  <prototype>: Object { … }

1192 (11) […]
  0: Array [ 103.86695733932268, -44.964779133003304 ]
  1: Array [ -76.13308210176842, 38.75793814039401 ]
  2: Array [ -76.13020999558496, 38.782688154120585 ]
  3: Array [ -76.12890669699081, 38.78647064351637 ]
  4: Array [ -76.12807302385534, 38.786723650244355 ]
  5: Array [ -76.12754554182737, 38.78651000385868 ]
  6: Array [ -76.12640847594942, 38.78408839960177 ]
  7: Array [ -76.11435851540921, 38.636536130021334 ]
  8: Array [ 103.858096036925, -39.00570100251519 ]
  9: Array [ 103.860092112702, -39.367933188411186 ]
  10: Array [ 103.86695733932268, -44.964779133003304 ]
  length: 11
  <prototype>: []
© www.soinside.com 2019 - 2024. All rights reserved.