Files
ArchiTools/src/modules/parcel-sync/services/reproject.ts
T
AI Assistant ba579d75c1 feat(parcel-sync): include no-geometry rows in Magic GPKG + HAS_GEOMETRY column
- Magic GPKG (terenuri_magic.gpkg) now contains ALL records:
  rows with geometry render as polygons, rows without have null geom
  but still carry all attribute/enrichment data (QGIS shows them fine)
- Added HAS_GEOMETRY column to Magic GPKG fields (0 or 1)
- GPKG builder now supports includeNullGeometry option: splits features
  into spatial-first (creates table), then appends null-geom rows
- Base terenuri.gpkg / cladiri.gpkg unchanged (spatial only)
- CSV still has all records as before
- GeoJsonFeature type now allows null geometry
- Reproject: null geometry guard added
- UI text updated: no longer says 'Nu apar in GPKG'
2026-03-07 18:06:28 +02:00

60 lines
2.3 KiB
TypeScript

/**
* Coordinate reprojection between EPSG:3844 (Stereo 70) and EPSG:4326 (WGS84).
*/
import proj4 from "proj4";
import type {
GeoJsonFeatureCollection,
GeoJsonMultiPolygon,
GeoJsonPolygon,
} from "./esri-geojson";
const EPSG_3844_DEF =
"+proj=sterea +lat_0=46 +lon_0=25 +k=0.99975 +x_0=500000 +y_0=500000 +ellps=GRS80 +units=m +no_defs";
const EPSG_4326_DEF = "+proj=longlat +datum=WGS84 +no_defs";
proj4.defs("EPSG:3844", EPSG_3844_DEF);
proj4.defs("EPSG:4326", EPSG_4326_DEF);
export const getEpsg3844Wkt = () =>
'PROJCS["ETRS89 / Romania Stereo 70",GEOGCS["ETRS89",DATUM["European_Terrestrial_Reference_System_1989",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6258"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4258"]],PROJECTION["Oblique_Stereographic"],PARAMETER["latitude_of_origin",46],PARAMETER["central_meridian",25],PARAMETER["scale_factor",0.99975],PARAMETER["false_easting",500000],PARAMETER["false_northing",500000],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","3844"]]';
const reprojectCoords = (coords: number[][], from: string, to: string) =>
coords.map(([x, y]) => {
const [nx, ny] = proj4(from, to, [x!, y!]);
return [nx!, ny!];
});
const reprojectPolygon = (polygon: number[][][], from: string, to: string) =>
polygon.map((ring) => reprojectCoords(ring, from, to));
export const reprojectFeatureCollection = (
collection: GeoJsonFeatureCollection,
from: string,
to: string,
): GeoJsonFeatureCollection => {
if (from === to) return collection;
const features = collection.features.map((feature) => {
if (!feature.geometry) return feature;
if (feature.geometry.type === "Polygon") {
const geometry: GeoJsonPolygon = {
type: "Polygon",
coordinates: reprojectPolygon(feature.geometry.coordinates, from, to),
};
return { ...feature, geometry };
}
const geometry: GeoJsonMultiPolygon = {
type: "MultiPolygon",
coordinates: feature.geometry.coordinates.map((polygon) =>
reprojectPolygon(polygon, from, to),
),
};
return { ...feature, geometry };
});
return { ...collection, features };
};