1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

(マイナーな)EPSGコードの座標変換

1
Last updated at Posted at 2026-03-07

序論

javascript で、proj4jsライブラリを利用し、EPSGコードの座標の変換を行う方法を示す。
ここで想定しているEPSGコードは、proj4jがデフォルトでサポートしていないもの(例えば 平面直角座標系(EPSG:30161~30179))。
proj4j側でサポートされているものについては、proj4js公式の「Named Projections」を参照。

結論

  1. EPSG公式でEPSGコードを検索し、「proj.4 string」を取得する。具体的には以下のURLをGETする。
https://epsg.io/{epsgのコード部分}.proj4

(例えば 「EPSG:30169」なら「https://epsg.io/30169.proj4」)
2. 取得した「proj.4 string」を引数(fromProjection、toProjection)として、proj4jsのproj4関数を実行する。
(例えば平面直角座標系第9系での(x, y)=(10, 20)を、緯度経度での座標に変換するなら以下のようになる。

const [lon, lat] = proj4(
    "+proj=tmerc +lat_0=36 +lon_0=139.833333333333 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs",
    "WGS84",
    [10, 20]
);

)

付録

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>サンプル</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.19.10/proj4.min.js"></script>
    <script>
        window.onload = async () => {
            convertXY();
            document.getElementById("fromEpsg").addEventListener("change", () => { convertXY() });
            document.getElementById("fromX").addEventListener("input", () => { convertXY() });
            document.getElementById("fromY").addEventListener("input", () => { convertXY() });
            document.getElementById("toEpsg").addEventListener("change", () => { convertXY() });
        };

        function convertXY() {
            const fromEpsgStr = document.getElementById("fromEpsg").value;
            const fromXStr = document.getElementById("fromX").value;
            const fromYStr = document.getElementById("fromY").value;
            const toEpsgStr = document.getElementById("toEpsg").value;
            const fromPoint = [Number(fromXStr), Number(fromYStr)];
            // const from = await (await fetch(`https://epsg.io/${codeOfEpsgCode}.proj4`)).text();
            const from = projMap.get(fromEpsgStr);
            const to = projMap.get(toEpsgStr)
            const [toX, toY] = proj4(from, to, fromPoint);
            document.getElementById("toXY").value = `${toX}\n${toY}`;
        }

        const projMap = new Map([
            ["3857", "+proj=merc +a=6378137 +b=6378137 +lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 +k=1 +units=m +nadgrids=@null +wktext +no_defs +type=crs"],
            ["4326", "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees"],
            ["30161", "+proj=tmerc +lat_0=33 +lon_0=129.5 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30162", "+proj=tmerc +lat_0=33 +lon_0=131 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30163", "+proj=tmerc +lat_0=36 +lon_0=132.166666666667 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30164", "+proj=tmerc +lat_0=33 +lon_0=133.5 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30165", "+proj=tmerc +lat_0=36 +lon_0=134.333333333333 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30166", "+proj=tmerc +lat_0=36 +lon_0=136 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30167", "+proj=tmerc +lat_0=36 +lon_0=137.166666666667 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30168", "+proj=tmerc +lat_0=36 +lon_0=138.5 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30169", "+proj=tmerc +lat_0=36 +lon_0=139.833333333333 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30170", "+proj=tmerc +lat_0=40 +lon_0=140.833333333333 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30171", "+proj=tmerc +lat_0=44 +lon_0=140.25 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30172", "+proj=tmerc +lat_0=44 +lon_0=142.25 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30173", "+proj=tmerc +lat_0=44 +lon_0=144.25 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30174", "+proj=tmerc +lat_0=26 +lon_0=142 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30175", "+proj=tmerc +lat_0=26 +lon_0=127.5 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30176", "+proj=tmerc +lat_0=26 +lon_0=124 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30177", "+proj=tmerc +lat_0=26 +lon_0=131 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30178", "+proj=tmerc +lat_0=20 +lon_0=136 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30179", "+proj=tmerc +lat_0=26 +lon_0=154 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
        ]);
    </script>
</head>

<body>
    <div>
        <div>
            <div>
                <label>from</label>
            </div>
            <div style="margin:10px">
                <label>EPSG:</label>
                <select id="fromEpsg">
                    <option value="3857">3857(WebMercator)</option>
                    <option value="4326">4326(WGS48)</option>
                    <option value="30161">30161(Japan Plane Rectangular CS I)</option>
                    <option value="30162">30162(Japan Plane Rectangular CS II)</option>
                    <option value="30163">30163(Japan Plane Rectangular CS III)</option>
                    <option value="30164">30164(Japan Plane Rectangular CS IV)</option>
                    <option value="30165">30165(Japan Plane Rectangular CS V)</option>
                    <option value="30166">30166(Japan Plane Rectangular CS VI)</option>
                    <option value="30167">30167(Japan Plane Rectangular CS VII)</option>
                    <option value="30168">30168(Japan Plane Rectangular CS VIII)</option>
                    <option value="30169">30169(Japan Plane Rectangular CS IX)</option>
                    <option value="30170">30170(Japan Plane Rectangular CS X)</option>
                    <option value="30171">30171(Japan Plane Rectangular CS XI)</option>
                    <option value="30172">30172(Japan Plane Rectangular CS XII)</option>
                    <option value="30173">30173(Japan Plane Rectangular CS XIII)</option>
                    <option value="30174">30174(Japan Plane Rectangular CS XIV)</option>
                    <option value="30175">30175(Japan Plane Rectangular CS XV)</option>
                    <option value="30176">30176(Japan Plane Rectangular CS XVI)</option>
                    <option value="30177">30177(Japan Plane Rectangular CS XVII)</option>
                    <option value="30178">30178(Japan Plane Rectangular CS XVIII)</option>
                    <option value="30179">30179(Japan Plane Rectangular CS XIX)</option>
                </select>
            </div>
            <div style="margin:10px">
                <label>x, y(longitude, latitude): </label>
                <input id="fromX" type="number" placeholder="0" />
                <label>,</label>
                <input id="fromY" type="number" placeholder="0" />
            </div>
        </div>
        <div>
            <div>
                <label>to</label>
            </div>
            <div style="margin:10px">
                <label>EPSG:</label>
                <select id="toEpsg">
                    <option value="3857">3857(WebMercator)</option>
                    <option value="4326">4326(WGS48)</option>
                    <option value="30161">30161(Japan Plane Rectangular CS I)</option>
                    <option value="30162">30162(Japan Plane Rectangular CS II)</option>
                    <option value="30163">30163(Japan Plane Rectangular CS III)</option>
                    <option value="30164">30164(Japan Plane Rectangular CS IV)</option>
                    <option value="30165">30165(Japan Plane Rectangular CS V)</option>
                    <option value="30166">30166(Japan Plane Rectangular CS VI)</option>
                    <option value="30167">30167(Japan Plane Rectangular CS VII)</option>
                    <option value="30168">30168(Japan Plane Rectangular CS VIII)</option>
                    <option value="30169">30169(Japan Plane Rectangular CS IX)</option>
                    <option value="30170">30170(Japan Plane Rectangular CS X)</option>
                    <option value="30171">30171(Japan Plane Rectangular CS XI)</option>
                    <option value="30172">30172(Japan Plane Rectangular CS XII)</option>
                    <option value="30173">30173(Japan Plane Rectangular CS XIII)</option>
                    <option value="30174">30174(Japan Plane Rectangular CS XIV)</option>
                    <option value="30175">30175(Japan Plane Rectangular CS XV)</option>
                    <option value="30176">30176(Japan Plane Rectangular CS XVI)</option>
                    <option value="30177">30177(Japan Plane Rectangular CS XVII)</option>
                    <option value="30178">30178(Japan Plane Rectangular CS XVIII)</option>
                    <option value="30179">30179(Japan Plane Rectangular CS XIX)</option>
                </select>
            </div>
            <div style="margin:10px">
                <label>x, y(longitude, latitude): </label>
                <textarea id="toXY" readonly style="width:200px;height:50px;"></textarea>
            </div>
        </div>
    </div>
</body>

</html>
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>サンプル</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
        integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
        integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.19.10/proj4.min.js"></script>
    <style>
        body {
            padding: 0;
            margin: 0
        }

        html,
        body,
        #map {
            height: 100%;
            width: 100%;
        }
    </style>
    <script>
        window.onload = async () => {
            const map = L.map('map');
            L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
                maxZoom: 19,
                attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
            }).addTo(map);
            map.setView(
                [36.0031693, 138.4968616],
                5
            );
            addOriginPoint(map, "30161");
            addOriginPoint(map, "30162");
            addOriginPoint(map, "30163");
            addOriginPoint(map, "30164");
            addOriginPoint(map, "30165");
            addOriginPoint(map, "30166");
            addOriginPoint(map, "30167");
            addOriginPoint(map, "30168");
            addOriginPoint(map, "30169");
            addOriginPoint(map, "30170");
            addOriginPoint(map, "30171");
            addOriginPoint(map, "30172");
            addOriginPoint(map, "30173");
            addOriginPoint(map, "30174");
            addOriginPoint(map, "30175");
            addOriginPoint(map, "30176");
            addOriginPoint(map, "30177");
            addOriginPoint(map, "30178");
            addOriginPoint(map, "30179");
        };

        const projMap = new Map([
            ["30161", "+proj=tmerc +lat_0=33 +lon_0=129.5 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30162", "+proj=tmerc +lat_0=33 +lon_0=131 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30163", "+proj=tmerc +lat_0=36 +lon_0=132.166666666667 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30164", "+proj=tmerc +lat_0=33 +lon_0=133.5 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30165", "+proj=tmerc +lat_0=36 +lon_0=134.333333333333 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30166", "+proj=tmerc +lat_0=36 +lon_0=136 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30167", "+proj=tmerc +lat_0=36 +lon_0=137.166666666667 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30168", "+proj=tmerc +lat_0=36 +lon_0=138.5 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30169", "+proj=tmerc +lat_0=36 +lon_0=139.833333333333 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30170", "+proj=tmerc +lat_0=40 +lon_0=140.833333333333 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30171", "+proj=tmerc +lat_0=44 +lon_0=140.25 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30172", "+proj=tmerc +lat_0=44 +lon_0=142.25 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30173", "+proj=tmerc +lat_0=44 +lon_0=144.25 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30174", "+proj=tmerc +lat_0=26 +lon_0=142 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30175", "+proj=tmerc +lat_0=26 +lon_0=127.5 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30176", "+proj=tmerc +lat_0=26 +lon_0=124 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30177", "+proj=tmerc +lat_0=26 +lon_0=131 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30178", "+proj=tmerc +lat_0=20 +lon_0=136 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
            ["30179", "+proj=tmerc +lat_0=26 +lon_0=154 +k=0.9999 +x_0=0 +y_0=0 +ellps=bessel +towgs84=-146.414,507.337,680.507,0,0,0,0 +units=m +no_defs +type=crs"],
        ]);

        function addOriginPoint(map, codeOfEpsgCode) {
            const originPoint = [0, 0];
            // const from = await (await fetch(`https://epsg.io/${codeOfEpsgCode}.proj4`)).text();
            const from = projMap.get(codeOfEpsgCode);
            const [lon, lat] = proj4(from, "WGS84", originPoint);
            L.marker([lat, lon])
                .addTo(map)
                .bindPopup(`EPSG:${codeOfEpsgCode}, (${lat}, ${lon})`);
        }
    </script>
</head>

<body>
    <div id="map"></div>
</body>

</html>
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?