Created
November 7, 2025 19:39
-
-
Save ichernev/559215ec6186decf7133edc5963b41ba to your computer and use it in GitHub Desktop.
https://www.cadastre.bg/ polygon to geojson converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Sample code to convert from https://www.cadastre.bg/ polygons to geojson for | |
| * viewing on a standartized mapping software. | |
| */ | |
| var proj4 = require('proj4'); | |
| class Parser { | |
| constructor(s) { | |
| this.s = s; | |
| this.i = 0; | |
| } | |
| skip_ws() { | |
| while (this._is_space()) | |
| ++ this.i; | |
| } | |
| read_char() { | |
| this.skip_ws(); | |
| ++ this.i; | |
| return this._sub(this.i - 1); | |
| } | |
| read_str() { | |
| this.skip_ws(); | |
| let start = this.i; | |
| while (this._is_alnum()) { | |
| ++ this.i; | |
| } | |
| return this._sub(start); | |
| } | |
| read_float() { | |
| this.skip_ws(); | |
| let start = this.i; | |
| while (this._is_digit() || this._cc() == '.') | |
| ++ this.i; | |
| return parseFloat(this._sub(start)); | |
| } | |
| _is_space(c) { | |
| if (c == null) c = this._cc(); | |
| return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\v' || c == '\f'; | |
| } | |
| _is_alpha(c) { | |
| if (c == null) c = this._cc(); | |
| return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'; | |
| } | |
| _is_digit(c) { | |
| if (c == null) c = this._cc(); | |
| return '0' <= c && c <= '9'; | |
| } | |
| _is_alnum(c) { | |
| if (c == null) c = this._cc(); | |
| return this._is_alpha(c) || this._is_digit(c); | |
| } | |
| _cc() { | |
| return this.s[this.i]; | |
| } | |
| _sub(start) { | |
| return this.s.substring(start, this.i); | |
| } | |
| _assert(expr, msg) { | |
| if (!expr) { | |
| throw new Error("parsing error: " + msg); | |
| } | |
| } | |
| } | |
| class GeomParser extends Parser { | |
| read_geom() { | |
| var type = this.read_str(); | |
| switch (type) { | |
| case 'POLYGON': | |
| return new PlainGeom(type, this._read_poly()); | |
| default: | |
| throw new Error("can not handle geometry " + type); | |
| } | |
| } | |
| _read_poly() { | |
| this._assert(this.read_char() == '(', "_read_poly: expected '('"); | |
| var delim; | |
| var seqs = [] | |
| while (true) { | |
| var seq = this._read_braced_pair_seq(); | |
| seqs.push(seq); | |
| delim = this.read_char(); | |
| if (delim != ',') | |
| break; | |
| } | |
| this._assert(delim == ')', "_read_poly: expected ')'"); | |
| return seqs; | |
| } | |
| _read_braced_pair_seq() { | |
| this._assert(this.read_char() == '(', "_read_braced_pair_seq: expected '('"); | |
| var delim; | |
| var seq = []; | |
| while (true) { | |
| var a = this.read_float(); | |
| var b = this.read_float(); | |
| seq.push([a, b]); | |
| delim = this.read_char(); | |
| if (delim != ',') | |
| break; | |
| } | |
| this._assert(delim == ')', "_read_braced_pair_seq: expected ')'"); | |
| return seq; | |
| } | |
| } | |
| class PlainGeom { | |
| constructor(type, coords) { | |
| this.type = type; | |
| this.coords = coords; | |
| } | |
| transform(from, to, proj4) { | |
| this.coords = this.coords.map((a) => a.map((b) => proj4(from, to, b))); | |
| } | |
| toGeoJson() { | |
| if (this.type !== 'POLYGON') throw new Error("unsupported geom type " + this.type); | |
| return { | |
| type: 'Feature', | |
| 'properties': {}, | |
| 'geometry': { | |
| type: 'Polygon', | |
| coordinates: this.coords | |
| } | |
| } | |
| } | |
| } | |
| b_geom_str = "POLYGON (( 588345.77500000 4812013.14700000, 588354.37500000 4812013.22100000, 588371.24700000 4812004.86500000, 588409.79800000 4812045.79800000, 588353.19600000 4812092.41500000, 588234.76100000 4812223.90800000, 588179.54100000 4812284.33800000, 588117.73600000 4812401.11500000, 588059.21800000 4812461.11600000, 588045.81200000 4812450.00100000, 588025.51000000 4812461.82800000, 588007.98100000 4812465.07800000, 587978.13200000 4812470.62200000, 587951.28500000 4812475.89200000, 587846.45500000 4812501.99500000, 587789.45300000 4812513.50700000, 587758.22500000 4812516.53900000, 587675.08000000 4812521.32700000, 587619.15100000 4812512.64700000, 587578.20800000 4812505.69500000, 587589.01000000 4812334.13500000, 587594.64700000 4812244.62100000, 587597.24800000 4812244.54400000, 587639.56200000 4812243.20600000, 587719.19600000 4812239.68900000, 587722.99800000 4812239.63700000, 587796.76000000 4812221.05200000, 587864.85000000 4812222.73700000, 587890.48100000 4812219.35600000, 587924.53000000 4812213.84800000, 587924.84200000 4812154.14700000, 587931.32300000 4812074.69800000, 587954.41200000 4812041.19400000, 588003.56500000 4811988.61200000, 588055.50900000 4811948.85500000, 588108.98600000 4811928.61300000, 588111.76800000 4811930.73600000, 588105.51900000 4811936.38300000, 588046.90100000 4811973.08300000, 588038.64900000 4811980.49600000, 588031.68300000 4811986.75300000, 588024.42400000 4812028.49300000, 588013.94600000 4812049.30500000, 588009.85900000 4812071.07100000, 588001.57100000 4812104.60200000, 587978.19300000 4812130.07300000, 587963.84700000 4812145.70100000, 587955.03300000 4812155.30600000, 587954.17900000 4812173.30000000, 587969.93400000 4812201.93600000, 587990.08500000 4812219.51000000, 588037.29700000 4812241.71600000, 588082.00100000 4812264.90100000, 588104.50100000 4812265.09400000, 588139.64800000 4812236.49300000, 588148.11900000 4812216.66500000, 588199.86400000 4812165.00500000, 588231.60500000 4812125.47500000, 588236.95300000 4812119.73600000, 588278.94300000 4812074.67800000, 588301.90900000 4812055.47400000, 588315.72400000 4812042.14100000, 588330.86100000 4812027.54100000, 588343.55500000 4812015.28800000, 588345.77500000 4812013.14700000),( 587970.60600000 4812240.24400000, 587976.00200000 4812217.48900000, 587972.12600000 4812214.65600000, 587958.28000000 4812219.83700000, 587933.01300000 4812250.82300000, 587923.57200000 4812255.54200000, 587896.05400000 4812269.20700000, 587854.01300000 4812297.04800000, 587844.95000000 4812315.87100000, 587861.47700000 4812324.51300000, 587898.26400000 4812303.02800000, 587932.44200000 4812282.51900000, 587960.87700000 4812255.26100000, 587970.60600000 4812240.24400000))" | |
| // var coords = coords_s.split(',').map((a) => a.trim().split(' ').map((c) => parseFloat(c))); | |
| // console.log(coords[0]); | |
| // proj4.defs('EPSG:25835', '+proj=utm +zone=35 +ellps=GRS80 +units=m +no_defs'); | |
| proj4.defs('EPSG:8122', 'PROJCS["BGS2005", GEOGCS["GCS_WGS_1984", DATUM["D_WGS_1984", SPHEROID["WGS_1984", 6378137.0, 298.257223563]], PRIMEM["Greenwich", 0.0], UNIT["degree", 0.017453292519943295], AXIS["Longitude", EAST], AXIS["Latitude", NORTH]], PROJECTION["Lambert_Conformal_Conic_2SP"], PARAMETER["central_meridian", 25.5], PARAMETER["latitude_of_origin", 42.66787568333], PARAMETER["standard_parallel_1", 43.33333333333], PARAMETER["false_easting", 500000.0], PARAMETER["false_northing", 4725824.3591], PARAMETER["scale_factor", 1.0], PARAMETER["standard_parallel_2", 42.0], UNIT["m", 1.0], AXIS["x", EAST], AXIS["y", NORTH], AUTHORITY["EPSG","8122"]]'); | |
| let geom_a = new GeomParser(a_geom_str).read_geom(); | |
| // console.log(geom_a.coords); | |
| geom_a.transform('EPSG:8122', 'WGS84', proj4); | |
| console.log(JSON.stringify({ | |
| type: 'FeatureCollection', | |
| features: [a_geom_str, a_geom_str].map((s) => { let g = new GeomParser(s).read_geom(); g.transform('EPSG:8122', 'WGS84', proj4); return g.toGeoJson() }), | |
| }, null, 4)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment