@koopjs/geoservice-utils
Advanced tools
Comparing version 2.2.3 to 3.0.0
import joi from 'joi'; | ||
import { IEnvelope, IPoint, IPolyline, IPolygon } from '@esri/arcgis-rest-types'; | ||
import { GeometryFilter } from './common-types'; | ||
export declare const spatialReferenceSchema: joi.ObjectSchema<any>; | ||
export declare const filterSchema: joi.AlternativesSchema<any>; | ||
type GeometryFilter = IEnvelope | IPoint | IPolyline | IPolygon | number[] | string; | ||
export declare function isArcgisObject(input: GeometryFilter): boolean; | ||
export declare function isSinglePointArray(input: GeometryFilter): boolean; | ||
export declare function isEnvelopeArray(input: GeometryFilter): boolean; | ||
export {}; | ||
export declare function isSinglePointArray(input: GeometryFilter | string): boolean; | ||
export declare function isEnvelopeArray(input: GeometryFilter | string): boolean; | ||
export declare const wgsWkt: any; | ||
export declare const wgsExtentEnvelope: { | ||
ymin: any; | ||
ymax: any; | ||
xmin: any; | ||
xmax: any; | ||
}; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -6,4 +29,13 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.isEnvelopeArray = exports.isSinglePointArray = exports.isArcgisObject = exports.filterSchema = void 0; | ||
exports.wgsExtentEnvelope = exports.wgsWkt = exports.isEnvelopeArray = exports.isSinglePointArray = exports.filterSchema = exports.spatialReferenceSchema = void 0; | ||
const joi_1 = __importDefault(require("joi")); | ||
const esriProjCodes = __importStar(require("@esri/proj-codes")); | ||
exports.spatialReferenceSchema = joi_1.default.object({ | ||
wkid: joi_1.default.number().strict().integer().optional(), | ||
latestWkid: joi_1.default.number().strict().integer().optional(), | ||
vcsWkid: joi_1.default.number().strict().integer().optional(), | ||
latestVcsWkid: joi_1.default.number().strict().integer().optional(), | ||
wkt: joi_1.default.string().optional(), | ||
}).unknown() | ||
.or('wkid', 'latestWkid', 'vcsWkid', 'latestVcsWkid', 'wkt'); | ||
const envelopeSchema = joi_1.default | ||
@@ -15,8 +47,3 @@ .object({ | ||
xmax: joi_1.default.number().strict().required(), | ||
spatialReference: joi_1.default | ||
.object({ | ||
wkid: joi_1.default.number().strict().required(), | ||
}) | ||
.unknown(true) | ||
.optional(), | ||
spatialReference: exports.spatialReferenceSchema.optional() | ||
}) | ||
@@ -96,16 +123,2 @@ .unknown(true); | ||
.required(); | ||
function passesValidation(schema, input) { | ||
const { error } = schema.validate(input); | ||
return !error; | ||
} | ||
function isArcgisObject(input) { | ||
return (passesValidation(envelopeSchema, input) || | ||
passesValidation(pointSchema, input) || | ||
passesValidation(lineStringSchema, input) || | ||
passesValidation(polygonSchema, input) || | ||
passesValidation(multiPointSchema, input) || | ||
passesValidation(multiLineStringSchema, input) || | ||
passesValidation(multipolygonSchema, input)); | ||
} | ||
exports.isArcgisObject = isArcgisObject; | ||
function isSinglePointArray(input) { | ||
@@ -121,2 +134,10 @@ const { error } = pointArraySchema.validate(input); | ||
exports.isEnvelopeArray = isEnvelopeArray; | ||
const wgs = esriProjCodes.lookup(4326); | ||
exports.wgsWkt = wgs.wkt; | ||
exports.wgsExtentEnvelope = { | ||
ymin: wgs.extent.slat, | ||
ymax: wgs.extent.nlat, | ||
xmin: wgs.extent.llon, | ||
xmax: wgs.extent.rlon | ||
}; | ||
//# sourceMappingURL=helpers.js.map |
@@ -1,17 +0,15 @@ | ||
import { IEnvelope, IPoint, IPolyline, IPolygon, ISpatialReference, SpatialRelationship } from '@esri/arcgis-rest-types'; | ||
import { LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon } from 'geojson'; | ||
type Geometry = Point | MultiPoint | LineString | MultiLineString | Polygon | MultiPolygon; | ||
type GeometryFilter = IEnvelope | IPoint | IPolyline | IPolygon | number[]; | ||
type ArcgisSpatialReference = string | number | ISpatialReference; | ||
import { ISpatialReference, SpatialRelationship } from '@esri/arcgis-rest-types'; | ||
import { ArcgisSpatialReference, Geometry, GeometryFilter } from './common-types'; | ||
export interface IStandardizedGeometryFilter { | ||
geometry: Geometry; | ||
spatialReference?: ArcgisSpatialReference; | ||
spatialReference?: ISpatialReference; | ||
relation: string; | ||
} | ||
export declare function standardizeGeometryFilter<T extends ArcgisSpatialReference>(params: { | ||
export declare function standardizeGeometryFilter(params: IStandardizedGeometryFilterParams): IStandardizedGeometryFilter; | ||
interface IStandardizedGeometryFilterParams { | ||
geometry: GeometryFilter | string; | ||
inSR?: T; | ||
reprojectionSR?: T; | ||
inSR?: ArcgisSpatialReference; | ||
reprojectionSR?: ArcgisSpatialReference; | ||
spatialRel?: SpatialRelationship; | ||
}): IStandardizedGeometryFilter; | ||
} | ||
export {}; |
@@ -31,31 +31,155 @@ "use strict"; | ||
const _ = __importStar(require("lodash")); | ||
const joi_1 = __importDefault(require("joi")); | ||
const wkt_parser_1 = __importDefault(require("wkt-parser")); | ||
const esriProjCodes = __importStar(require("@esri/proj-codes")); | ||
const arcgis_1 = require("@terraformer/arcgis"); | ||
const bbox_polygon_1 = __importDefault(require("@turf/bbox-polygon")); | ||
const transform_spatial_reference_to_wkt_1 = require("./transform-spatial-reference-to-wkt"); | ||
const project_coordinates_1 = require("./project-coordinates"); | ||
const helpers_1 = require("./helpers"); | ||
const clip_to_envelope_1 = require("./clip-to-envelope"); | ||
const traverse_coordinates_1 = require("./traverse-coordinates"); | ||
const inputSpatialReferenceSchema = joi_1.default.any() | ||
.when(joi_1.default.number(), { | ||
then: joi_1.default.number().strict().integer(), | ||
otherwise: helpers_1.spatialReferenceSchema, | ||
}) | ||
.optional(); | ||
function standardizeGeometryFilter(params) { | ||
const { geometry, inSR, reprojectionSR, spatialRel } = params; | ||
const filter = (_.isString(geometry) ? parseString(geometry) : geometry); | ||
validateFilter(filter); | ||
const spatialReference = extractGeometryFilterSpatialReference(filter) || inSR || reprojectionSR; | ||
const filterCrsWkt = spatialReference && (0, transform_spatial_reference_to_wkt_1.transformSpatialReferenceToWkt)(spatialReference); | ||
const targetCrsWkt = reprojectionSR && (0, transform_spatial_reference_to_wkt_1.transformSpatialReferenceToWkt)(reprojectionSR); | ||
const geojsonGeometry = transformGeometryToGeojson(filter); | ||
const projectedGeometry = shouldReproject(filterCrsWkt, targetCrsWkt) | ||
? reproject(geojsonGeometry, filterCrsWkt, targetCrsWkt) | ||
: geojsonGeometry; | ||
return StandardizedGeometryFilter.build(params); | ||
} | ||
exports.standardizeGeometryFilter = standardizeGeometryFilter; | ||
class StandardizedGeometryFilter { | ||
geometry; | ||
spatialReference; | ||
relation; | ||
filter; | ||
filterSpatialReference; | ||
reprojectionSpatialReference; | ||
static build(params) { | ||
const { geometry, relation, spatialReference } = new StandardizedGeometryFilter(params); | ||
return { geometry, relation, spatialReference }; | ||
} | ||
constructor(params) { | ||
const { geometry, inSR, reprojectionSR, spatialRel } = params; | ||
this.filter = _.isString(geometry) ? parseString(geometry) : geometry; | ||
this.relation = spatialRel || 'esriSpatialRelIntersects'; | ||
this.filterSpatialReference = this.extractSR('inSR', this.filter?.spatialReference || inSR); | ||
this.reprojectionSpatialReference = this.extractSR('reprojectionSR', reprojectionSR); | ||
this.validateFilterShape(); | ||
this.geometry = this.transformGeometry(); | ||
this.spatialReference = packageSpatialReference(this.filterSpatialReference); | ||
if (this.shouldClipOutOfBoundsFilter()) { | ||
this.geometry.coordinates = (0, clip_to_envelope_1.clipToEnvelope)(this.geometry.coordinates, helpers_1.wgsExtentEnvelope); | ||
} | ||
if (reprojectionSR && this.validateReproject()) { | ||
this.geometry.coordinates = (0, project_coordinates_1.projectCoordinates)(this.geometry.coordinates, this.filterSpatialReference.wkt, this.reprojectionSpatialReference.wkt); | ||
this.spatialReference = packageSpatialReference(this.reprojectionSpatialReference); | ||
} | ||
} | ||
validateFilterShape() { | ||
const { error } = helpers_1.filterSchema.validate(this.filter); | ||
if (error) { | ||
throw new Error(`Unsupported geometry filter format: ${JSON.stringify(this.filter)}; must be a spatial reference ID or object`); | ||
} | ||
return this; | ||
} | ||
extractSR(srSource, spatialReference) { | ||
if (!spatialReference) { | ||
return; | ||
} | ||
const { error } = inputSpatialReferenceSchema.validate(spatialReference); | ||
if (error) { | ||
throw new Error(`Unsupported ${srSource} format; must be a spatial reference ID or object`); | ||
} | ||
if (Number.isInteger(spatialReference) || | ||
getSrid(spatialReference)) { | ||
return getSpatialReferenceFromCode(spatialReference); | ||
} | ||
if (spatialReference.wkt) { | ||
weakValidateWkt(spatialReference.wkt); | ||
return spatialReference; | ||
} | ||
} | ||
validateReproject() { | ||
if (!this.filterSpatialReference) { | ||
throw new Error('Unknown geometry filter spatial reference; unable to reproject'); | ||
} | ||
if (!this.filterSpatialReference.wkt) { | ||
throw new Error(`Unknown geometry filter spatial reference WKT; unable to reproject`); | ||
} | ||
if (!this.reprojectionSpatialReference) { | ||
throw new Error(`Unknown reprojection spatial reference; unable to reproject`); | ||
} | ||
if (!this.reprojectionSpatialReference.wkt) { | ||
throw new Error(`Unknown reprojection spatial reference WKT; unable to reproject`); | ||
} | ||
return true; | ||
} | ||
shouldClipOutOfBoundsFilter() { | ||
return this.filterSpatialReference?.wkt === helpers_1.wgsWkt && this.hasOOBCoords(); | ||
} | ||
hasOOBCoords() { | ||
const extent = helpers_1.wgsExtentEnvelope; | ||
const predicate = (coords) => { | ||
const [lon, lat] = coords; | ||
return (lon > extent.xmax || | ||
lon < extent.xmin || | ||
lat > extent.ymax || | ||
lat < extent.ymin); | ||
}; | ||
return (0, traverse_coordinates_1.someCoordinates)(this.geometry.coordinates, predicate); | ||
} | ||
transformGeometry() { | ||
if ((0, helpers_1.isSinglePointArray)(this.filter)) { | ||
return { | ||
type: 'Point', | ||
coordinates: this.filter.map(Number), | ||
}; | ||
} | ||
if ((0, helpers_1.isEnvelopeArray)(this.filter)) { | ||
return (0, bbox_polygon_1.default)(this.filter).geometry; | ||
} | ||
return (0, arcgis_1.arcgisToGeoJSON)(this.filter); | ||
} | ||
} | ||
function packageSpatialReference(spatialReference) { | ||
if (!spatialReference) { | ||
return; | ||
} | ||
const { wkid, wkt } = spatialReference; | ||
return { wkid, wkt }; | ||
} | ||
function getSpatialReferenceFromCode(sr) { | ||
const srid = Number.isInteger(sr) ? sr : getSrid(sr); | ||
const spatialReferenceDefinition = esriProjCodes.lookup(srid); | ||
if (!spatialReferenceDefinition) { | ||
console.warn(`Unknown spatial reference: ${srid}; ignoring`); | ||
return; | ||
} | ||
const extentEnvelope = getSpatialReferenceExtent(spatialReferenceDefinition); | ||
return { | ||
geometry: projectedGeometry, | ||
spatialReference: reprojectionSR || spatialReference, | ||
relation: spatialRel || 'esriSpatialRelIntersects', | ||
wkid: spatialReferenceDefinition.wkid, | ||
wkt: spatialReferenceDefinition.wkt, | ||
extent: extentEnvelope, | ||
}; | ||
} | ||
exports.standardizeGeometryFilter = standardizeGeometryFilter; | ||
function validateFilter(filter) { | ||
const { error } = helpers_1.filterSchema.validate(filter); | ||
if (error) { | ||
throw new Error(`Unsupported geometry filter format: ${JSON.stringify(filter)}`); | ||
function getSrid(sr) { | ||
return sr.wkid || sr.latestWkid || sr.vcsWkid || sr.latestVcsWkid; | ||
} | ||
function getSpatialReferenceExtent(spatialReferenceDefinition) { | ||
const { extent } = spatialReferenceDefinition; | ||
if (!extent) { | ||
return; | ||
} | ||
const { llon, slat, rlon, nlat } = extent; | ||
return { xmin: llon, ymin: slat, xmax: rlon, ymax: nlat }; | ||
} | ||
function weakValidateWkt(wkt) { | ||
try { | ||
(0, wkt_parser_1.default)(wkt); | ||
} | ||
catch (error) { | ||
throw new Error(`Spatial reference WKT is unparseable: "${wkt}"`); | ||
} | ||
} | ||
function parseString(param) { | ||
@@ -69,27 +193,2 @@ try { | ||
} | ||
function extractGeometryFilterSpatialReference(filter) { | ||
if ((0, helpers_1.isArcgisObject)(filter)) { | ||
return filter.spatialReference; | ||
} | ||
} | ||
function transformGeometryToGeojson(input) { | ||
if ((0, helpers_1.isSinglePointArray)(input)) { | ||
return { | ||
type: 'Point', | ||
coordinates: input.map(Number), | ||
}; | ||
} | ||
if ((0, helpers_1.isEnvelopeArray)(input)) { | ||
const { geometry } = (0, bbox_polygon_1.default)(input); | ||
return geometry; | ||
} | ||
return (0, arcgis_1.arcgisToGeoJSON)(input); | ||
} | ||
function shouldReproject(fromSr, toSr) { | ||
return toSr && toSr !== fromSr; | ||
} | ||
function reproject(geometry, fromSr, toSr) { | ||
const coordinates = (0, project_coordinates_1.projectCoordinates)(geometry.coordinates, fromSr, toSr); | ||
return Object.assign(Object.assign({}, geometry), { coordinates }); | ||
} | ||
//# sourceMappingURL=index.js.map |
@@ -1,4 +0,2 @@ | ||
import { Position } from 'geojson'; | ||
type Coordinates = Position | Position[] | Position[][] | Position[][][]; | ||
export declare function projectCoordinates(coordinates: Coordinates, fromSR?: string, toSR?: string): Coordinates; | ||
export {}; | ||
import { Coordinates } from './common-types'; | ||
export declare function projectCoordinates(coordinates: Coordinates, fromSR: string, toSR: string): Coordinates; |
@@ -32,23 +32,30 @@ "use strict"; | ||
const _ = __importStar(require("lodash")); | ||
const traverse_coordinates_1 = require("./traverse-coordinates"); | ||
const helpers_1 = require("./helpers"); | ||
const WGS_MIN_LAT = helpers_1.wgsExtentEnvelope.ymin; | ||
const WGS_MAX_LAT = helpers_1.wgsExtentEnvelope.ymax; | ||
function projectCoordinates(coordinates, fromSR, toSR) { | ||
if (!toSR || fromSR === toSR) { | ||
return coordinates; | ||
} | ||
return recursiveCoordinatesReproject(coordinates, fromSR, toSR); | ||
const reproject = (coords) => { | ||
if (shouldReproject(coords)) { | ||
const [, lat] = coords; | ||
if (shouldConstrainSourceX(fromSR, lat)) { | ||
coords[1] = constrainX(lat); | ||
} | ||
return (0, proj4_1.default)(fromSR, toSR, coords); | ||
} | ||
return coords; | ||
}; | ||
return (0, traverse_coordinates_1.transformCoordinates)(coordinates, reproject); | ||
} | ||
exports.projectCoordinates = projectCoordinates; | ||
function recursiveCoordinatesReproject(coordinates, fromSr, toSr) { | ||
if (Array.isArray(coordinates[0])) { | ||
return coordinates.map((coords) => { | ||
return recursiveCoordinatesReproject(coords, fromSr, toSr); | ||
}); | ||
} | ||
if (shouldReproject(coordinates)) { | ||
return (0, proj4_1.default)(fromSr, toSr, coordinates); | ||
} | ||
return coordinates; | ||
} | ||
// Prevent error in event of null or undefined coordinates | ||
function shouldReproject(coordinates) { | ||
return _.isNumber(coordinates[0]) && _.isNumber(coordinates[1]); | ||
return coordinates && _.isNumber(coordinates[0]) && _.isNumber(coordinates[1]); | ||
} | ||
function shouldConstrainSourceX(fromSR, x) { | ||
return fromSR === helpers_1.wgsWkt && (x === WGS_MIN_LAT || x === WGS_MAX_LAT); | ||
} | ||
function constrainX(x) { | ||
return x === WGS_MAX_LAT ? WGS_MAX_LAT - 1e-8 : WGS_MIN_LAT + 1e-8; | ||
} | ||
//# sourceMappingURL=project-coordinates.js.map |
{ | ||
"name": "@koopjs/geoservice-utils", | ||
"version": "2.2.3", | ||
"version": "3.0.0", | ||
"description": "A set of utilities for working with Geoservice requests and parameters.", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
38794
27
543