GeoJSONパスがLeafletの別の機能と交差するかどうかを確認するにはどうすればよいですか?


8

ユーザーがパス(一連の接続された直線)を描画し、このパスが特定のGeoJSONレイヤーのフィーチャと交差しない可能性があるアプリケーションがあります。

これらの線に沿った点が、端点だけでなく、GeoJSONレイヤーと交差していないことを確認する必要があります。

このチェックを実行するにはどうすればよいですか?



Turf.jsで特に注意すべき点はありますか?
LavaHot 2015年

turf.jsがこれを行うとは思いません。他の交差点検出コードを目的に適合させることができる場合があります。例えば、にGeoJSONのラインストリング上で動作するように設計されているが、あなたの最も道のを得ることができるが、あなたはポリゴンレイヤで動作するようにそれを必要とする場合は、どちらかとポリゴンの入力を受け付けるようにそれを適応させるか、ポリゴンを抽出する必要があると思います最初にGeoJSONレイヤーのラインストリング。
nathansnider 2015年

2
すごい印象的な作品!:-) turf.intersectがうまくいくと思いましたか?(あなたのjsfiddle上に構築する:fiddle.jshell.net/tyt4oeux/1)しかし、多分私は質問を見過ごしていました。
ghybs 2015年

あはは、でももちろんうまくいきます!私はturf.intersectが入力としてポリゴンを必要とするという彼らの言葉でAPIドキュメントをちょうど取りました。試してみるのに害がないと思います。turf.intersectには、ラインが完全にポリゴン内にあることを検出するだけでなく、単純であるという利点があるので、それが明らかにここに行く方法だと思います。
nathansnider 2015年

回答:


4

あなたはTurfライブラリとintersectのような方法を試すことができます:http//turfjs.org/docs/#intersect

これがそのライブラリのコード例です。

var poly1 = {
    "type": "Feature",
    "geometry": {
        "type": "Polygon",
        "coordinates": [[
            [-122.801742, 45.48565],
            [-122.801742, 45.60491],
            [-122.584762, 45.60491],
            [-122.584762, 45.48565],
            [-122.801742, 45.48565]
        ]]
    }
}
var poly2 = {
    "type": "Feature",
    "geometry": {
        "type": "Polygon",
        "coordinates": [[
            [-122.520217, 45.535693],
            [-122.64038, 45.553967],
            [-122.720031, 45.526554],
            [-122.669906, 45.507309],
            [-122.723464, 45.446643],
            [-122.532577, 45.408574],
            [-122.487258, 45.477466],
            [-122.520217, 45.535693]
         ]]
     }
}

var intersection = turf.intersect(poly1, poly2);

これを行う方法の例を追加する必要があります。リンクは時間とともに腐敗します。
alphabetasoup

そのリンクが時間の経過とともに腐敗すると、私の答え全体が無効になります。例全体は、Turfライブラリの存在に基づいており、Turfライブラリが存在しない場合は...しかし、その例を私の回答にコピーしました。
エイドリアンBer

4
リンクが腐った、これが新しいturfjs.org/docs/#intersect
Calvein

リンクが再び腐敗する(または間違い)。スラッシュなし、ただ:turfjs.org/docs#intersect
ヘンディ

1

編集:turf.jsを使用したより簡単でより良い解決策については、上記のコメントからghybsのフィドルを参照してください。元の答えは次のとおりです:


以下は、geoJson-js-utilsライブラリの交差ルーチンの変更バージョンで、GeoJSONラインストリングを入力として受け取り、交差のGeoJSONポイントを出力として生成します。

function lineStringsIntersect(l1, l2) {
    var intersects = [];
    for (var i = 0; i <= l1.coordinates.length - 2; ++i) {
        for (var j = 0; j <= l2.coordinates.length - 2; ++j) {
            var a1Latlon = L.latLng(l1.coordinates[i][1], l1.coordinates[i][0]),
                a2Latlon = L.latLng(l1.coordinates[i + 1][1], l1.coordinates[i + 1][0]),
                b1Latlon = L.latLng(l2.coordinates[j][1], l2.coordinates[j][0]),
                b2Latlon = L.latLng(l2.coordinates[j + 1][1], l2.coordinates[j + 1][0]),
                a1 = L.Projection.SphericalMercator.project(a1Latlon),
                a2 = L.Projection.SphericalMercator.project(a2Latlon),
                b1 = L.Projection.SphericalMercator.project(b1Latlon),
                b2 = L.Projection.SphericalMercator.project(b2Latlon),
                ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x),
                ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x),
                u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y);
            if (u_b != 0) {
                var ua = ua_t / u_b,
                    ub = ub_t / u_b;
                if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
                    var pt_x = a1.x + ua * (a2.x - a1.x),
                        pt_y = a1.y + ua * (a2.y - a1.y),
                        pt_xy = {"x": pt_x, "y": pt_y},
                        pt_latlon = L.Projection.SphericalMercator.unproject(pt_xy);
                    intersects.push({
                        'type': 'Point',
                            'coordinates': [pt_latlon.lng, pt_latlon.lat]
                    });
                }
            }
        }
    }
    if (intersects.length == 0) intersects = false;
    return intersects;
}

元の関数は緯度と経度のみから交差を計算し、平面上の単なる座標であるかのように修正されたため、不正確な結果が生成されました(特に、高緯度または長距離にわたって)。を使用L.Projectionして、計算中に等角投影(またはこの場合はほぼ等角投影)投影座標系に変換すると、これが修正されます。

LineStringだけでなく、Leafletジオメトリオブジェクトを受け入れるようにさらに変更することもできますが、代わりにこの扱いにくい関数を使用して、交差関数に渡されるLineStringを作成しました。

function lineify(inputGeom) {
    var outputLines = {
        "type": "GeometryCollection",
            "geometries": []
    }
    switch (inputGeom.type) {
        case "GeometryCollection":
            for (var i in inputGeom.geometries) {
                var geomLines = lineify(inputGeom.geometries[i]);
                if (geomLines) {
                    for (var j in geomLines.geometries) {
                        outputLines.geometries.push(geomLines.geometries[j]);
                    }
                } else {
                    outputLines = false;
                }
            }
            break;
        case "Feature":
            var geomLines = lineify(inputGeom.geometry);
            if (geomLines) {
                for (var j in geomLines.geometries) {
                    outputLines.geometries.push(geomLines.geometries[j]);
                }
            } else {
                outputLines = false;
            }
            break;
        case "FeatureCollection":
            for (var i in inputGeom.features) {
                var geomLines = lineify(inputGeom.features[i].geometry);
                if (geomLines) {
                    for (var j in geomLines.geometries) {
                        outputLines.geometries.push(geomLines.geometries[j]);
                    }
                } else {
                    outputLines = false;
                }
            }
            break;
        case "LineString":
            outputLines.geometries.push(inputGeom);
            break;
        case "MultiLineString":
        case "Polygon":
            for (var i in inputGeom.coordinates) {
                outputLines.geometries.push({
                    "type": "LineString",
                        "coordinates": inputGeom.coordinates[i]
                });
            }
            break;
        case "MultiPolygon":
            for (var i in inputGeom.coordinates) {
                for (var j in inputGeom.coordinates[i]) {
                    outputLines.geometries.push({
                        "type": "LineString",
                            "coordinates": inputGeom.coordinates[i][j]
                    });
                }
            }
            break;
        default:
            outputLines = false;
    }
    return outputLines;
}

この関数は、Leafletオブジェクトを取得し、それらをLineStringに変換して、交差をチェックします。

function crossCheck(baseLayer, drawLayer) {
    var baseJson = baseLayer.toGeoJSON(),
        drawJson = drawLayer.toGeoJSON(),
        baseLines = lineify(baseJson),
        drawLines = lineify(drawJson),
        crossPoints = {
            type: "GeometryCollection",
            geometries: []
        };
    if (baseLines && drawLines) {
        for (var i in drawLines.geometries) {
            for (var j in baseLines.geometries) {
                var crossTest = lineStringsIntersect(drawLines.geometries[i], baseLines.geometries[j]);
                if (crossTest) {
                    for (var k in crossTest) {
                        crossPoints.geometries.push(crossTest[k]);
                    }
                }
            }
        }
    }
    return crossPoints;
}

これは、Leaflet.drawでこれを使用するフィドルの例です。

http://fiddle.jshell.net/nathansnider/egzxw86h/

オブジェクトの描画が完了すると、描画されたオブジェクトがベースジオメトリと交差するポイントにマップ上のマーカーが配置されます。Leaflet.drawは描画の進行中に使用するイベントハンドラーを提供しないため、パスが描画されている間は交差点を確認できません。ただし、ドローイベントが完了するとすぐにチェックされます。

また、これは、チェック対象のポリゴン内に完全にあるパスの交差を検出しないことにも注意してください。turf.jsを使用してこれらのチェックを実行できます(おそらくturf.explodeturf.withinを組み合わせます)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.