LoginSignup
4
1

More than 1 year has passed since last update.

大円軌跡およびそれを囲む矩形(円筒投影法)

Last updated at Posted at 2017-05-22

こんにちは。
大円の軌跡(部分)およびそれを囲む円筒投影法矩形1 2を d3.js を使って描きました。geojson3の LineString を与えると大円軌跡を描きます。

braun.jpg
boundingBox.html
<!DOCTYPE html>
<meta charset="utf-8">
<title>Braun projection</title>
<style>
.frame {
  fill: none;
  stroke: #000;
  stroke-width: 3px;
}
.fill {
  fill: #fff;
}
.arc {
  fill: none;
  stroke: #0fc;
  stroke-width: 1.5px;
}
.graticule {
  fill: none;
  stroke: #777;
  stroke-width: 0.5px;
  stroke-opacity: 0.5;
}
.land {
  fill: #888;
}
.boundary {
  fill: none;
  stroke: #fff;
  stroke-width: 0.5px;
}
.bounds {
  fill: #f00;
  fill-opacity: .1;
  stroke: #f00;
  stroke-width: 0.2px;
  pointer-events: none;
}
</style>
<svg width="600" height="400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://unpkg.com/topojson-client@3"></script>
<script>
var geojson_geometry = {type: "LineString", coordinates: [[110, 60], [-110, 60]]};

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");

var projection = d3.geoProjection(braunRaw)
     .scale((width - 3) / (2 * Math.PI))
    .translate([width/2, height/2])
    .precision(0.1);

function braunRaw(lambda, phi) {
  return [lambda, Math.tan(phi/2)*2];
}

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

var graticule = d3.geoGraticule();

svg.append("defs").append("path")
    .datum(graticule.outline())
    .attr("id", "sphere")
    .attr("d", path);

svg.append("use")
    .attr("class", "frame")
    .attr("xlink:href", "#sphere");

svg.append("use")
    .attr("class", "fill")
    .attr("xlink:href", "#sphere");

svg.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);

svg.append("path")
	.datum(geojson_geometry)
    .attr("class", "arc")
	.attr("d", path);

svg.append("path")
	.datum(boundRect(geojson_geometry))
	.attr("class", "bounds")
	.attr("d", path);


d3.json("https://unpkg.com/world-atlas@1/world/50m.json", function(error, world) {
  svg.insert("path", ".graticule")
      .datum(topojson.feature(world, world.objects.land))
      .attr("class", "land")
      .attr("d", path);

  svg.insert("path", ".graticule")
      .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
      .attr("class", "boundary")
      .attr("d", path);
});

function boundRect(pnts) {
  var coords = [[pnts[0][0],pnts[0][1]]]
      .concat(parallel(pnts[0][0], pnts[1][0], pnts[0][1]))
      .concat(parallel(pnts[0][0], pnts[1][0], pnts[1][1]).reverse());
  return rfc7946tod3({type: "Polygon", coordinates: [coords]})
}

function parallel(λ0, λ1, φ)  {
  if (λ0 > λ1) λ1 += 360;
  var  = λ1 - λ0,
      step =  / Math.ceil();
  return d3.range(λ0, λ1 + 0.5 * step, step).map(function(λ) { return [normalize(λ), φ]; });
}

function normalize(x) {
  return (x + 180) % 360 - 180;
}

// https://github.com/tyrasd/rfc7946-to-d3
function rfc7946tod3(geojson) {
    switch ((geojson && geojson.type) || null) {
        case 'FeatureCollection':
            geojson.features.forEach(rfc7946tod3)
            break
        case 'GeometryCollection':
            geojson.geometries.forEach(rfc7946tod3)
            break
        case 'Feature':
            rfc7946tod3(geojson.geometry)
            break
        case 'MultiPolygon':
            geojson.coordinates.forEach(function(polygon) {
                polygon.forEach(function(ring) {
                    ring.reverse()
                })
            })
            break
        case 'Polygon':
            geojson.coordinates.forEach(function(ring) {
                ring.reverse()
            })
            break
    }
    return geojson
}
</script>

  1. 矩形に必要な緯線を作る処理は、参考:「Geographic Bounding Boxes

  2. 今回の投影法はBraun投影です。

  3. 内部で gojson の polygon 処理に、rfc7946-to-d3.js を使っています。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1