feat(parcel-sync): full GPKG export workflow with UAT autocomplete, hero buttons, layer catalog
- Fix login button (return success instead of ok) - Add UAT autocomplete with NFD-normalized search (3186 entries) - Add export-bundle API: base mode (terenuri+cladiri) + magic mode (enriched parcels) - Add export-layer-gpkg API: individual layer GPKG download - Add gpkg-export service: ogr2ogr with GeoJSON fallback - Add reproject service: EPSG:3844 projection support - Add magic-mode methods to eterra-client (immApps, folosinte, immovableList, docs, parcelDetails) - Rewrite UI: 3-tab layout (Export/Catalog/Search), progress tracking, phase trail
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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.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 };
|
||||
};
|
||||
Reference in New Issue
Block a user