타원 엔벨로프 데이터의 D3 맵 작성


16

나는 타원, 더 구체적으로 타원 "봉투"가있는이 데이터 세트를 가지고 있습니다. 누군가 내가 D3 맵에서 어떻게 그릴 수 있는지에 대한 조언이 있는지 궁금합니다. 이미 메르카토르 투영을 사용한지도 설정이 있습니다. 이 stackoverflow 답변에는 createEllipse 함수가 있어서 닫았지만 데이터를 올바르게 해석하고 싶습니다.

데이터에서 타원의 장축 / 부축 값을 연결하고 회전에 방위각을 사용했는데 이것이 맞습니까? 나는 또한 "봉투"부분을 이해하지 못한다. 각 구역에서 여러 개의 타원이 어떻게 단일 연속 모양을 생성합니까?

모든 조언을 부탁드립니다.

여기에 이미지 설명을 입력하십시오

  const margin  = {top:0, right:0, bottom:0, left:0},
        width   = 1000 - margin.left - margin.right,
        height  = 800  - margin.top - margin.bottom;

  const svg = d3.select('body')
      .append('svg')
      .attr('width', '100%')
      .attr('height', '100%')
      .attr('viewBox', `0 0 ${width + margin.left + margin.right} ${height + margin.top + margin.bottom}`);

  const chart = svg.append('g')
      .attr('transform', `translate(${margin.left},${margin.top})`);

  //a/b are ellipse axes, x/y is center
  const createEllipse = function createEllipse(a, b, x = 0, y = 0, rotation = 0) {
    let k = Math.ceil(36 * (Math.max(a/b,b/a))); // sample angles
    let coords = [];
    for (let i = 0; i <= k; i++) {
      let angle = Math.PI*2 / k * i + rotation;
      let r = a * b / Math.sqrt(a*a*Math.sin(angle)*Math.sin(angle) + b*b*Math.cos(angle)*Math.cos(angle));
      coords.push(getLatLong([x,y],angle,r));
    }
    return { 'type':'Polygon', 'coordinates':[coords] };
  }

  const getLatLong = function getLatLong(center,angle,radius) {
    let rEarth = 6371; // kilometers
    x0 = center[0] * Math.PI / 180; // convert to radians.
    y0 = center[1] * Math.PI / 180;
    let y1 = Math.asin( Math.sin(y0)*Math.cos(radius/rEarth) + Math.cos(y0)*Math.sin(radius/rEarth)*Math.cos(angle) );
    let x1 = x0 + Math.atan2(Math.sin(angle)*Math.sin(radius/rEarth)*Math.cos(y0), Math.cos(radius/rEarth)-Math.sin(y0)*Math.sin(y1));
    y1 = y1 * 180 / Math.PI;
    x1 = x1 * 180 / Math.PI;
    return [x1,y1];
  } 


  d3.json('https://media.journalism.berkeley.edu/upload/2019/11/kazakhstan.json').then((data) => {

      const ellipses = [
        {lat: 48.6,    lng: 64.7,     axis_x: 30, axis_y: 16, azimuth: 26.5, area_hectar: 0.0713,  zone: 'U1'},
        {lat: 48.625,  lng: 64.625,   axis_x: 30, axis_y: 16, azimuth: 26.5, area_hectar: 0.0713,  zone: 'U1'},
        {lat: 48.366,  lng: 65.44166, axis_x: 50, axis_y: 30, azimuth: 40,   area_hectar: 0.11775, zone: 'U2'},
        {lat: 48.85,   lng: 65.61666, axis_x: 20, axis_y: 22, azimuth: 29,   area_hectar: 0.17584, zone: 'U3'},
        {lat: 48.9333, lng: 65.8,     axis_x: 22, axis_y: 22, azimuth: 28,   area_hectar: 0.17584, zone: 'U3'},
        {lat: 48.9166, lng: 66.05,    axis_x: 50, axis_y: 20, azimuth: 38,   area_hectar: 0.17584, zone: 'U3'},
        {lat: 48.9166, lng: 65.68333, axis_x: 20, axis_y: 22, azimuth: 29,   area_hectar: 0.17584, zone: 'U3'},
        {lat: 49,      lng: 65.86666, axis_x: 22, axis_y: 22, azimuth: 29,   area_hectar: 0.17584, zone: 'U3'}
      ]

      const projection = d3.geoMercator()
        .fitExtent([[0,0],[width,height]], data)

      const path = d3.geoPath()
        .projection(projection);


      chart.selectAll('path')
        .data(data.features)
        .enter()
        .append('path')
        .attr('d',  path)
        .attr('stroke', 'black')
        .attr('strok-width', '1px')
        .attr('fill', 'none');

      chart.selectAll(".ellipses")
        .data(ellipses.map((d) => createEllipse(d.axis_x, d.axis_y, d.lng, d.lat, d.azimuth)))
        .enter()
        .append('path')
        .attr('d', path)
        .attr('stroke', 'black')
        .attr('stroke-width', '1px')
        .attr('fill', 'orange');

  });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart"></div>

답변:


1

결과를 거의 올바르게 해석하는 것 같습니다.

내가 고친 한 가지 오류는 코드가 방위각을 고려하지 않는다는 것입니다.

다른 가능한 문제는 축과 관련이있을 수 있습니다. 제공된 표에서 이름은 타원 치수처럼 들리는 "축 치수"로 명명되며 createEllipse 함수는 반경을 매개 변수로 사용합니다. 위에서 언급 한 문제가 해결 된 상태 에서 확대 된 시각화 를 살펴보십시오 . 풍선 도움말이 참조 용으로 추가되었습니다.

세 번째 문제는 논쟁의 여지가 있으며 표에 설정된 데이터 형식에 따라 다릅니다. x가 항상 경도와 y-위도를 의미하는 것은 아닙니다. 그러나 논리적으로 타원의 긴 값 ( "x"값이 "y"값보다 크거나 같음)은 가로 방향에 해당해야합니다.

참고로 시각화의 정밀도는 대략적인 지구 반경 사용에 영향을 받지만 미미합니다.

여기서 "봉투 (envelope)"는 타원이 주어진 영역 값이 타원의 영역보다 훨씬 작다는 사실을 고려하여 타원이 내부에있는 특정 관심 영역을 둘러싸고 있음을 의미합니다.


이것은 엄청나게 도움이됩니다. 응답과 코드 샘플에 감사드립니다! 데이터 세트에 대한 자세한 정보를 얻고 있습니다. (이것은 떨어지는 로켓 파편에 대한 데이터입니다.) 따라서 봉투는 모든 타원이 포함 된 영역이라고 생각합니다.
jrue
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.