5

キャンバス要素 (実際にはキャンバスにロードされた単なる画像) のコンテンツを取得し、d3 を使用してそれらをさまざまなマップ投影に歪めようとしています。したがって、これを行う例を1つだけ見つけました( this other SO question )。

問題は、すべての投影で機能しないことです。コード:

var height = 375,
    width = 750;

var canvas = document.createElement('canvas');
document.body.appendChild(canvas);
canvas.width = width;
canvas.height = height;

var context = canvas.getContext('2d');

var projection = d3.geo.lagrange()
    .translate([width/2, height/2])
    .scale(100); //SET SCALE HERE

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

var image = new Image();
image.crossOrigin = 'anonymous';
image.src = 'http://i.imgur.com/zZkxbz7.png';
image.onload = function() {
    var dx = width,
        dy = height;

    context.drawImage(image, 0, 0, dx, dy);

    var sourceData = context.getImageData(0, 0, dx, dy).data,
        target = context.createImageData(dx, dy),
        targetData = target.data;

    for (var y = 0, i = -1; y < height; ++y) {
        for (var x = 0; x < width; ++x) {
            var p = projection.invert([x, y]),    //ERROR HERE
                λ = p[0],
                φ = p[1];
            if (λ > 180 || λ < -180 || φ > 90 || φ < -90) {
                i += 4;
                continue;
            }
            var q = ((90 - φ) / 180 * dy | 0) * dx + ((180 + λ) / 360 * dx | 0) << 2;
            targetData[++i] = sourceData[q];
            targetData[++i] = sourceData[++q];
            targetData[++i] = sourceData[++q];
            targetData[++i] = 255;
        }
    }

    context.clearRect(0, 0, width, height);
    context.putImageData(target, 0, 0);
}

上記の例では、投影のスケールを低く設定しすぎると (たとえば 80)、(for ループ内の) 変数 p は になりますnull。なぜこれが起こるのかわかりません。投影がキャンバス領域内に収まるようにスケールを設定する必要があります。

動作中の jsfiddle の例: http://jsfiddle.net/vjnfyd8t/

4

1 に答える 1

1

(これは興味深い質問です)

ここで何が起こっているのか完全には解読できませんが、FWIW、これはラグランジュinvert()の実装です。明らかに、おそらく x または y が一部の範囲外にある場合 (x、y はここで事前に変換されます)、null を返す場合があります。したがって、ヌルを無視することになっていると思いますが(たとえば、出力ピクセルを透明に設定することにより)、最後に適切にスケーリングされたマップを取得できます。

これは、 sを無視するだけで得られるものですnull(ただし、s がどこで発生するかを示すために、それらを赤で強調表示しています)

if (!p) {
  targetData[++i] = 255;
  targetData[++i] = 0;
  targetData[++i] = 0;
  targetData[++i] = 255;
  continue;
}

スケールが 94 に設定されている場合、赤いバンドは完全に消え、(少なくともそのスケールでは) ベスト フィットのように見えます。それはあなたが望んでいたものですか?

于 2014-12-12T02:05:15.617 に答える