d3 v4 geo draws boundary inverted

后端 未结 2 1187
生来不讨喜
生来不讨喜 2021-01-14 12:57

When I draw the Bermuda Triangle in an SVG element the scale is not what I expect (triangle should extend to edges of box) and the fill is backward (instead of drawing a tri

相关标签:
2条回答
  • 2021-01-14 13:12

    Let's change this:

    [
        [-64.73, 32.31],
        [-80.19, 25.76],
        [-66.09, 18.43],
        [-64.73, 32.31]
    ]
    

    To this:

    [
        [-64.73, 32.31],
        [-66.09, 18.43],
        [-80.19, 25.76],
        [-64.73, 32.31]
    ]
    

    It seems like a small change, but it is an important one: D3 expects the polygon vertices in a clockwise order.

    According to the API:

    Spherical polygons also require a winding order convention to determine which side of the polygon is the inside: the exterior ring for polygons smaller than a hemisphere must be clockwise, while the exterior ring for polygons larger than a hemisphere must be anticlockwise. (emphasis mine)

    Also, this is an interesting bl.ocks made by Bostock (D3 creator), didactically explaining your issue: https://bl.ocks.org/mbostock/a7bdfeb041e850799a8d3dce4d8c50c8

    Here is your code with that change (and removing the fitSize):

    var geojson = {
      "features": [{
        "type": "Feature",
        "properties": {
          "name": "Bermuda Triangle",
          "area": 1150180
        },
        "geometry": {
          "type": "Polygon",
          "coordinates": [
            [
              [-64.73, 32.31],
              [-66.09, 18.43],
              [-80.19, 25.76],
              [-64.73, 32.31]
            ]
          ]
        }
      }],
      "type": "FeatureCollection"
    };
    
    var width = 480;
    var height = 480;
    
    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height)
      .attr("style", "border: 2px solid black");
    
    var projection = d3.geoMercator();
    var path = d3.geoPath().projection(projection);
    
    svg.selectAll('path')
      .data(geojson.features)
      .enter()
      .append('path')
      .attr('d', path)
      .style("fill", "red")
      .style("stroke-width", "1")
      .style("stroke", "black");
    <script src="//d3js.org/d3.v4.js"></script>

    0 讨论(0)
  • 2021-01-14 13:24

    If someone will see a similar problem, I created a tool which will help you to rewind or reverse geojson

    It helped me to make changes in some geoJson files, without much hassle

    https://observablehq.com/@bumbeishvili/rewind-geojson

    You can run it as a snippet just bellow

    <div class="notebook-content">
      
    </div>
    
    <script type="module"> 
    
    import notebook from "https://api.observablehq.com/@bumbeishvili/rewind-geojson.js";  //  "download code" url
    
    document.querySelector('.notebook-content').innerHTML =notebook.modules[0].variables
    .filter(d=>d)
    .map((d,i)=>` <div class=" observable-wrapper div-number-${i}"></div>`)
    .join('')
    .concat('<div style="display:none" class="hidden"></div>')
    
    
    import {Inspector, Runtime} from "https://unpkg.com/@observablehq/runtime@3/dist/runtime.js"; 
    let i=1;
    Runtime.load(notebook, (variable) => { 
    if(i==4 ){i++;  return new Inspector(document.querySelector(`.hidden`));}
    if(i==13)return;
    return new Inspector(document.querySelector(`.observable-wrapper:nth-child(${i++})`));
     }); 
    
    
    </script>

    0 讨论(0)
提交回复
热议问题