maplair
Version:
JavaScript library for mobile-friendly interactive maps
192 lines (191 loc) • 7.03 kB
JavaScript
import { formatNum } from "../core/Util.js";
import { LatLng } from "../geo/LatLng.js";
import { isFlat } from "../geometry/LineUtil.js";
import { LayerGroup } from "./LayerGroup.js";
import { FeatureGroup } from "./FeatureGroup.js";
import { Marker } from "./marker/Marker.js";
import { CircleMarker } from "./vector/CircleMarker.js";
import { Circle } from "./vector/Circle.js";
import { Polyline } from "./vector/Polyline.js";
import { Polygon } from "./vector/Polygon.js";
//#region src/layer/GeoJSON.js
var GeoJSON = class GeoJSON extends FeatureGroup {
constructor(geojson, options) {
super(void 0, options);
if (geojson) this.addData(geojson);
this.callInitHooks(GeoJSON);
}
addData(geojson) {
const features = Array.isArray(geojson) ? geojson : geojson.features;
if (features) {
for (const feature of features) if (feature.geometries || feature.geometry || feature.features || feature.coordinates) this.addData(feature);
return this;
}
const options = this.options;
if (options.filter && !options.filter(geojson)) return this;
const layer = GeoJSON.geometryToLayer(geojson, options);
if (!layer) return this;
layer.feature = GeoJSON.asFeature(geojson);
layer.defaultOptions = layer.options;
this.resetStyle(layer);
if (options.onEachFeature) options.onEachFeature(geojson, layer);
return this.addLayer(layer);
}
resetStyle(layer) {
if (layer === void 0) return this.eachLayer(this.resetStyle, this);
layer.options = Object.create(layer.defaultOptions);
this._setLayerStyle(layer, this.options.style);
return this;
}
setStyle(style) {
return this.eachLayer((layer) => this._setLayerStyle(layer, style));
}
_setLayerStyle(layer, style) {
if (layer.setStyle) {
if (typeof style === "function") style = style(layer.feature);
layer.setStyle(style);
}
}
static geometryToLayer(geojson, options) {
const geometry = geojson.type === "Feature" ? geojson.geometry : geojson, coords = geometry?.coordinates, layers = [], pointToLayer = options?.pointToLayer, _coordsToLatLng = options?.coordsToLatLng ?? GeoJSON.coordsToLatLng;
let latlng, latlngs;
if (!coords && !geometry) return null;
switch (geometry.type) {
case "Point":
latlng = _coordsToLatLng(coords);
return GeoJSON._pointToLayer(pointToLayer, geojson, latlng, options);
case "MultiPoint":
for (const coord of coords) {
latlng = _coordsToLatLng(coord);
layers.push(GeoJSON._pointToLayer(pointToLayer, geojson, latlng, options));
}
return new FeatureGroup(layers);
case "LineString":
case "MultiLineString":
latlngs = GeoJSON.coordsToLatLngs(coords, geometry.type === "LineString" ? 0 : 1, _coordsToLatLng);
return new Polyline(latlngs, options);
case "Polygon":
case "MultiPolygon":
latlngs = GeoJSON.coordsToLatLngs(coords, geometry.type === "Polygon" ? 1 : 2, _coordsToLatLng);
return new Polygon(latlngs, options);
case "GeometryCollection":
for (const g of geometry.geometries) {
const geoLayer = GeoJSON.geometryToLayer({
geometry: g,
type: "Feature",
properties: geojson.properties
}, options);
if (geoLayer) layers.push(geoLayer);
}
return new FeatureGroup(layers);
case "FeatureCollection":
for (const f of geometry.features) {
const featureLayer = GeoJSON.geometryToLayer(f, options);
if (featureLayer) layers.push(featureLayer);
}
return new FeatureGroup(layers);
default: throw new Error("Invalid GeoJSON object.");
}
}
static _pointToLayer(pointToLayerFn, geojson, latlng, options) {
return pointToLayerFn ? pointToLayerFn(geojson, latlng) : new Marker(latlng, options?.markersInheritOptions && options);
}
static coordsToLatLng(coords) {
return new LatLng(coords[1], coords[0], coords[2]);
}
static coordsToLatLngs(coords, levelsDeep, _coordsToLatLng) {
return coords.map((coord) => levelsDeep ? GeoJSON.coordsToLatLngs(coord, levelsDeep - 1, _coordsToLatLng) : (_coordsToLatLng || GeoJSON.coordsToLatLng)(coord));
}
static latLngToCoords(latlng, precision) {
latlng = new LatLng(latlng);
return latlng.alt !== void 0 ? [
formatNum(latlng.lng, precision),
formatNum(latlng.lat, precision),
formatNum(latlng.alt, precision)
] : [formatNum(latlng.lng, precision), formatNum(latlng.lat, precision)];
}
static latLngsToCoords(latlngs, levelsDeep, close, precision) {
const coords = latlngs.map((latlng) => levelsDeep ? GeoJSON.latLngsToCoords(latlng, isFlat(latlng) ? 0 : levelsDeep - 1, close, precision) : GeoJSON.latLngToCoords(latlng, precision));
if (!levelsDeep && close && coords.length > 0) coords.push(coords[0].slice());
return coords;
}
static getFeature(layer, newGeometry) {
return layer.feature ? {
...layer.feature,
geometry: newGeometry
} : GeoJSON.asFeature(newGeometry);
}
static asFeature(geojson) {
if (geojson.type === "Feature" || geojson.type === "FeatureCollection") return geojson;
return {
type: "Feature",
properties: {},
geometry: geojson
};
}
};
const PointToGeoJSON = { toGeoJSON(precision) {
return GeoJSON.getFeature(this, {
type: "Point",
coordinates: GeoJSON.latLngToCoords(this.getLatLng(), precision)
});
} };
Marker.include(PointToGeoJSON);
Circle.include(PointToGeoJSON);
CircleMarker.include(PointToGeoJSON);
Polyline.include({ toGeoJSON(precision) {
const multi = !isFlat(this._latlngs);
const coords = GeoJSON.latLngsToCoords(this._latlngs, multi ? 1 : 0, false, precision);
return GeoJSON.getFeature(this, {
type: `${multi ? "Multi" : ""}LineString`,
coordinates: coords
});
} });
Polygon.include({ toGeoJSON(precision) {
const holes = !isFlat(this._latlngs), multi = holes && !isFlat(this._latlngs[0]);
let coords = GeoJSON.latLngsToCoords(this._latlngs, multi ? 2 : holes ? 1 : 0, true, precision);
if (!holes) coords = [coords];
return GeoJSON.getFeature(this, {
type: `${multi ? "Multi" : ""}Polygon`,
coordinates: coords
});
} });
LayerGroup.include({
toMultiPoint(precision) {
const coords = [];
this.eachLayer((layer) => {
coords.push(layer.toGeoJSON(precision).geometry.coordinates);
});
return GeoJSON.getFeature(this, {
type: "MultiPoint",
coordinates: coords
});
},
toGeoJSON(precision) {
const type = this.feature?.geometry?.type;
if (type === "MultiPoint") return this.toMultiPoint(precision);
const isGeometryCollection = type === "GeometryCollection", jsons = [];
this.eachLayer((layer) => {
if (layer.toGeoJSON) {
const json = layer.toGeoJSON(precision);
if (isGeometryCollection) jsons.push(json.geometry);
else {
const feature = GeoJSON.asFeature(json);
if (feature.type === "FeatureCollection") jsons.push(...feature.features);
else jsons.push(feature);
}
}
});
if (isGeometryCollection) return GeoJSON.getFeature(this, {
geometries: jsons,
type: "GeometryCollection"
});
return {
type: "FeatureCollection",
features: jsons
};
}
});
//#endregion
export { GeoJSON };
//# sourceMappingURL=GeoJSON.js.map