/** * CesiumPro is a GIS engine based on cesium, integrating common functions and methods in GIS, * including data loading, visualization, Spatial analysis, etc * @version 1.1.1 * @datetime 2024-03-02 */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CesiumPro = {})) })(this, (function (exports) { 'use strict' /** * @module helpers */ /** * Earth Radius used with the Harvesine formula and approximates using a spherical (non-ellipsoid) Earth. * * @memberof helpers * @type {number} */ var earthRadius = 6371008.8 /** * Unit of measurement factors using a spherical (non-ellipsoid) earth radius. * * @memberof helpers * @type {Object} */ var factors = { centimeters: earthRadius * 100, centimetres: earthRadius * 100, degrees: earthRadius / 111325, feet: earthRadius * 3.28084, inches: earthRadius * 39.37, kilometers: earthRadius / 1000, kilometres: earthRadius / 1000, meters: earthRadius, metres: earthRadius, miles: earthRadius / 1609.344, millimeters: earthRadius * 1000, millimetres: earthRadius * 1000, nauticalmiles: earthRadius / 1852, radians: 1, yards: earthRadius * 1.0936, } /** * Wraps a GeoJSON {@link Geometry} in a GeoJSON {@link Feature}. * * @name feature * @param {Geometry} geometry input geometry * @param {Object} [properties={}] an Object of key-value pairs to add as properties * @param {Object} [options={}] Optional Parameters * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature * @param {string|number} [options.id] Identifier associated with the Feature * @returns {Feature} a GeoJSON Feature * @example * var geometry = { * "type": "Point", * "coordinates": [110, 50] * }; * * var feature = turf.feature(geometry); * * //=feature */ function feature (geom, properties, options) { if (options === void 0) { options = {} } var feat = { type: "Feature" } if (options.id === 0 || options.id) { feat.id = options.id } if (options.bbox) { feat.bbox = options.bbox } feat.properties = properties || {} feat.geometry = geom return feat } /** * Creates a {@link Point} {@link Feature} from a Position. * * @name point * @param {Array} coordinates longitude, latitude position (each in decimal degrees) * @param {Object} [properties={}] an Object of key-value pairs to add as properties * @param {Object} [options={}] Optional Parameters * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature * @param {string|number} [options.id] Identifier associated with the Feature * @returns {Feature} a Point feature * @example * var point = turf.point([-75.343, 39.984]); * * //=point */ function point (coordinates, properties, options) { if (options === void 0) { options = {} } if (!coordinates) { throw new Error("coordinates is required") } if (!Array.isArray(coordinates)) { throw new Error("coordinates must be an Array") } if (coordinates.length < 2) { throw new Error("coordinates must be at least 2 numbers long") } if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) { throw new Error("coordinates must contain numbers") } var geom = { type: "Point", coordinates: coordinates, } return feature(geom, properties, options) } /** * Creates a {@link Polygon} {@link Feature} from an Array of LinearRings. * * @name polygon * @param {Array>>} coordinates an array of LinearRings * @param {Object} [properties={}] an Object of key-value pairs to add as properties * @param {Object} [options={}] Optional Parameters * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature * @param {string|number} [options.id] Identifier associated with the Feature * @returns {Feature} Polygon Feature * @example * var polygon = turf.polygon([[[-5, 52], [-4, 56], [-2, 51], [-7, 54], [-5, 52]]], { name: 'poly1' }); * * //=polygon */ function polygon (coordinates, properties, options) { if (options === void 0) { options = {} } for (var _i = 0, coordinates_1 = coordinates; _i < coordinates_1.length; _i++) { var ring = coordinates_1[_i] if (ring.length < 4) { throw new Error("Each LinearRing of a Polygon must have 4 or more Positions.") } for (var j = 0; j < ring[ring.length - 1].length; j++) { // Check if first point of Polygon contains two numbers if (ring[ring.length - 1][j] !== ring[0][j]) { throw new Error("First and last Position are not equivalent.") } } } var geom = { type: "Polygon", coordinates: coordinates, } return feature(geom, properties, options) } /** * Creates a {@link LineString} {@link Feature} from an Array of Positions. * * @name lineString * @param {Array>} coordinates an array of Positions * @param {Object} [properties={}] an Object of key-value pairs to add as properties * @param {Object} [options={}] Optional Parameters * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature * @param {string|number} [options.id] Identifier associated with the Feature * @returns {Feature} LineString Feature * @example * var linestring1 = turf.lineString([[-24, 63], [-23, 60], [-25, 65], [-20, 69]], {name: 'line 1'}); * var linestring2 = turf.lineString([[-14, 43], [-13, 40], [-15, 45], [-10, 49]], {name: 'line 2'}); * * //=linestring1 * //=linestring2 */ function lineString (coordinates, properties, options) { if (options === void 0) { options = {} } if (coordinates.length < 2) { throw new Error("coordinates must be an array of two or more positions") } var geom = { type: "LineString", coordinates: coordinates, } return feature(geom, properties, options) } /** * Takes one or more {@link Feature|Features} and creates a {@link FeatureCollection}. * * @name featureCollection * @param {Feature[]} features input features * @param {Object} [options={}] Optional Parameters * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature * @param {string|number} [options.id] Identifier associated with the Feature * @returns {FeatureCollection} FeatureCollection of Features * @example * var locationA = turf.point([-75.343, 39.984], {name: 'Location A'}); * var locationB = turf.point([-75.833, 39.284], {name: 'Location B'}); * var locationC = turf.point([-75.534, 39.123], {name: 'Location C'}); * * var collection = turf.featureCollection([ * locationA, * locationB, * locationC * ]); * * //=collection */ function featureCollection (features, options) { if (options === void 0) { options = {} } var fc = { type: "FeatureCollection" } if (options.id) { fc.id = options.id } if (options.bbox) { fc.bbox = options.bbox } fc.features = features return fc } /** * Creates a {@link Feature} based on a * coordinate array. Properties can be added optionally. * * @name multiPolygon * @param {Array>>>} coordinates an array of Polygons * @param {Object} [properties={}] an Object of key-value pairs to add as properties * @param {Object} [options={}] Optional Parameters * @param {Array} [options.bbox] Bounding Box Array [west, south, east, north] associated with the Feature * @param {string|number} [options.id] Identifier associated with the Feature * @returns {Feature} a multipolygon feature * @throws {Error} if no coordinates are passed * @example * var multiPoly = turf.multiPolygon([[[[0,0],[0,10],[10,10],[10,0],[0,0]]]]); * * //=multiPoly * */ function multiPolygon (coordinates, properties, options) { if (options === void 0) { options = {} } var geom = { type: "MultiPolygon", coordinates: coordinates, } return feature(geom, properties, options) } /** * Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit. * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet * * @name radiansToLength * @param {number} radians in radians across the sphere * @param {string} [units="kilometers"] can be degrees, radians, miles, inches, yards, metres, * meters, kilometres, kilometers. * @returns {number} distance */ function radiansToLength (radians, units) { if (units === void 0) { units = "kilometers" } var factor = factors[units] if (!factor) { throw new Error(units + " units is invalid") } return radians * factor } /** * Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians * Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet * * @name lengthToRadians * @param {number} distance in real units * @param {string} [units="kilometers"] can be degrees, radians, miles, inches, yards, metres, * meters, kilometres, kilometers. * @returns {number} radians */ function lengthToRadians (distance, units) { if (units === void 0) { units = "kilometers" } var factor = factors[units] if (!factor) { throw new Error(units + " units is invalid") } return distance / factor } /** * Converts an angle in radians to degrees * * @name radiansToDegrees * @param {number} radians angle in radians * @returns {number} degrees between 0 and 360 degrees */ function radiansToDegrees (radians) { var degrees = radians % (2 * Math.PI) return (degrees * 180) / Math.PI } /** * Converts an angle in degrees to radians * * @name degreesToRadians * @param {number} degrees angle between 0 and 360 degrees * @returns {number} angle in radians */ function degreesToRadians (degrees) { var radians = degrees % 360 return (radians * Math.PI) / 180 } /** * isNumber * * @param {*} num Number to validate * @returns {boolean} true/false * @example * turf.isNumber(123) * //=true * turf.isNumber('foo') * //=false */ function isNumber (num) { return !isNaN(num) && num !== null && !Array.isArray(num) } /** * isObject * * @param {*} input variable to validate * @returns {boolean} true/false * @example * turf.isObject({elevation: 10}) * //=true * turf.isObject('foo') * //=false */ function isObject (input) { return !!input && input.constructor === Object } /** * Unwrap a coordinate from a Point Feature, Geometry or a single coordinate. * * @name getCoord * @param {Array|Geometry|Feature} coord GeoJSON Point or an Array of numbers * @returns {Array} coordinates * @example * var pt = turf.point([10, 10]); * * var coord = turf.getCoord(pt); * //= [10, 10] */ function getCoord (coord) { if (!coord) { throw new Error("coord is required") } if (!Array.isArray(coord)) { if (coord.type === "Feature" && coord.geometry !== null && coord.geometry.type === "Point") { return coord.geometry.coordinates } if (coord.type === "Point") { return coord.coordinates } } if (Array.isArray(coord) && coord.length >= 2 && !Array.isArray(coord[0]) && !Array.isArray(coord[1])) { return coord } throw new Error("coord must be GeoJSON Point or an Array of numbers") } /** * Unwrap coordinates from a Feature, Geometry Object or an Array * * @name getCoords * @param {Array|Geometry|Feature} coords Feature, Geometry Object or an Array * @returns {Array} coordinates * @example * var poly = turf.polygon([[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]); * * var coords = turf.getCoords(poly); * //= [[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]] */ function getCoords (coords) { if (Array.isArray(coords)) { return coords } // Feature if (coords.type === "Feature") { if (coords.geometry !== null) { return coords.geometry.coordinates } } else { // Geometry if (coords.coordinates) { return coords.coordinates } } throw new Error("coords must be GeoJSON Feature, Geometry Object or an Array") } /** * Enforce expectations about types of {@link FeatureCollection} inputs for Turf. * Internally this uses {@link geojsonType} to judge geometry types. * * @name collectionOf * @param {FeatureCollection} featureCollection a FeatureCollection for which features will be judged * @param {string} type expected GeoJSON type * @param {string} name name of calling function * @throws {Error} if value is not the expected type. */ function collectionOf (featureCollection, type, name) { if (!featureCollection) { throw new Error("No featureCollection passed") } if (!name) { throw new Error(".collectionOf() requires a name") } if (!featureCollection || featureCollection.type !== "FeatureCollection") { throw new Error("Invalid input to " + name + ", FeatureCollection required") } for (var _i = 0, _a = featureCollection.features; _i < _a.length; _i++) { var feature = _a[_i] if (!feature || feature.type !== "Feature" || !feature.geometry) { throw new Error("Invalid input to " + name + ", Feature with geometry required") } if (!feature.geometry || feature.geometry.type !== type) { throw new Error("Invalid input to " + name + ": must be a " + type + ", given " + feature.geometry.type) } } } /** * Get Geometry from Feature or Geometry Object * * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object * @returns {Geometry|null} GeoJSON Geometry Object * @throws {Error} if geojson is not a Feature or Geometry Object * @example * var point = { * "type": "Feature", * "properties": {}, * "geometry": { * "type": "Point", * "coordinates": [110, 40] * } * } * var geom = turf.getGeom(point) * //={"type": "Point", "coordinates": [110, 40]} */ function getGeom (geojson) { if (geojson.type === "Feature") { return geojson.geometry } return geojson } //http://en.wikipedia.org/wiki/Haversine_formula //http://www.movable-type.co.uk/scripts/latlong.html /** * Calculates the distance between two {@link Point|points} in degrees, radians, miles, or kilometers. * This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature. * * @name distance * @param {Coord | Point} from origin point or coordinate * @param {Coord | Point} to destination point or coordinate * @param {Object} [options={}] Optional parameters * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers * @returns {number} distance between the two points * @example * var from = turf.point([-75.343, 39.984]); * var to = turf.point([-75.534, 39.123]); * var options = {units: 'miles'}; * * var distance = turf.distance(from, to, options); * * //addToMap * var addToMap = [from, to]; * from.properties.distance = distance; * to.properties.distance = distance; */ function distance (from, to, options) { if (options === void 0) { options = {} } var coordinates1 = getCoord(from) var coordinates2 = getCoord(to) var dLat = degreesToRadians(coordinates2[1] - coordinates1[1]) var dLon = degreesToRadians(coordinates2[0] - coordinates1[0]) var lat1 = degreesToRadians(coordinates1[1]) var lat2 = degreesToRadians(coordinates2[1]) var a = Math.pow(Math.sin(dLat / 2), 2) + Math.pow(Math.sin(dLon / 2), 2) * Math.cos(lat1) * Math.cos(lat2) return radiansToLength(2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)), options.units) } /** * Callback for coordEach * * @callback coordEachCallback * @param {Array} currentCoord The current coordinate being processed. * @param {number} coordIndex The current index of the coordinate being processed. * @param {number} featureIndex The current index of the Feature being processed. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. * @param {number} geometryIndex The current index of the Geometry being processed. */ /** * Iterate over coordinates in any GeoJSON object, similar to Array.forEach() * * @name coordEach * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object * @param {Function} callback a method that takes (currentCoord, coordIndex, featureIndex, multiFeatureIndex) * @param {boolean} [excludeWrapCoord=false] whether or not to include the final coordinate of LinearRings that wraps the ring in its iteration. * @returns {void} * @example * var features = turf.featureCollection([ * turf.point([26, 37], {"foo": "bar"}), * turf.point([36, 53], {"hello": "world"}) * ]); * * turf.coordEach(features, function (currentCoord, coordIndex, featureIndex, multiFeatureIndex, geometryIndex) { * //=currentCoord * //=coordIndex * //=featureIndex * //=multiFeatureIndex * //=geometryIndex * }); */ function coordEach (geojson, callback, excludeWrapCoord) { // Handles null Geometry -- Skips this GeoJSON if (geojson === null) return var j, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type = geojson.type, isFeatureCollection = type === "FeatureCollection", isFeature = type === "Feature", stop = isFeatureCollection ? geojson.features.length : 1 // This logic may look a little weird. The reason why it is that way // is because it's trying to be fast. GeoJSON supports multiple kinds // of objects at its root: FeatureCollection, Features, Geometries. // This function has the responsibility of handling all of them, and that // means that some of the `for` loops you see below actually just don't apply // to certain inputs. For instance, if you give this just a // Point geometry, then both loops are short-circuited and all we do // is gradually rename the input until it's called 'geometry'. // // This also aims to allocate as few resources as possible: just a // few numbers and booleans, rather than any temporary arrays as would // be required with the normalization approach. for (var featureIndex = 0; featureIndex < stop; featureIndex++) { geometryMaybeCollection = isFeatureCollection ? geojson.features[featureIndex].geometry : isFeature ? geojson.geometry : geojson isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1 for (var geomIndex = 0; geomIndex < stopG; geomIndex++) { var multiFeatureIndex = 0 var geometryIndex = 0 geometry = isGeometryCollection ? geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection // Handles null Geometry -- Skips this geometry if (geometry === null) continue coords = geometry.coordinates var geomType = geometry.type wrapShrink = excludeWrapCoord && (geomType === "Polygon" || geomType === "MultiPolygon") ? 1 : 0 switch (geomType) { case null: break case "Point": if ( callback( coords, coordIndex, featureIndex, multiFeatureIndex, geometryIndex ) === false ) return false coordIndex++ multiFeatureIndex++ break case "LineString": case "MultiPoint": for (j = 0; j < coords.length; j++) { if ( callback( coords[j], coordIndex, featureIndex, multiFeatureIndex, geometryIndex ) === false ) return false coordIndex++ if (geomType === "MultiPoint") multiFeatureIndex++ } if (geomType === "LineString") multiFeatureIndex++ break case "Polygon": case "MultiLineString": for (j = 0; j < coords.length; j++) { for (k = 0; k < coords[j].length - wrapShrink; k++) { if ( callback( coords[j][k], coordIndex, featureIndex, multiFeatureIndex, geometryIndex ) === false ) return false coordIndex++ } if (geomType === "MultiLineString") multiFeatureIndex++ if (geomType === "Polygon") geometryIndex++ } if (geomType === "Polygon") multiFeatureIndex++ break case "MultiPolygon": for (j = 0; j < coords.length; j++) { geometryIndex = 0 for (k = 0; k < coords[j].length; k++) { for (l = 0; l < coords[j][k].length - wrapShrink; l++) { if ( callback( coords[j][k][l], coordIndex, featureIndex, multiFeatureIndex, geometryIndex ) === false ) return false coordIndex++ } geometryIndex++ } multiFeatureIndex++ } break case "GeometryCollection": for (j = 0; j < geometry.geometries.length; j++) if ( coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false ) return false break default: throw new Error("Unknown Geometry Type") } } } } /** * Callback for featureEach * * @callback featureEachCallback * @param {Feature} currentFeature The current Feature being processed. * @param {number} featureIndex The current index of the Feature being processed. */ /** * Iterate over features in any GeoJSON object, similar to * Array.forEach. * * @name featureEach * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object * @param {Function} callback a method that takes (currentFeature, featureIndex) * @returns {void} * @example * var features = turf.featureCollection([ * turf.point([26, 37], {foo: 'bar'}), * turf.point([36, 53], {hello: 'world'}) * ]); * * turf.featureEach(features, function (currentFeature, featureIndex) { * //=currentFeature * //=featureIndex * }); */ function featureEach (geojson, callback) { if (geojson.type === "Feature") { callback(geojson, 0) } else if (geojson.type === "FeatureCollection") { for (var i = 0; i < geojson.features.length; i++) { if (callback(geojson.features[i], i) === false) break } } } /** * Callback for geomEach * * @callback geomEachCallback * @param {Geometry} currentGeometry The current Geometry being processed. * @param {number} featureIndex The current index of the Feature being processed. * @param {Object} featureProperties The current Feature Properties being processed. * @param {Array} featureBBox The current Feature BBox being processed. * @param {number|string} featureId The current Feature Id being processed. */ /** * Iterate over each geometry in any GeoJSON object, similar to Array.forEach() * * @name geomEach * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object * @param {Function} callback a method that takes (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) * @returns {void} * @example * var features = turf.featureCollection([ * turf.point([26, 37], {foo: 'bar'}), * turf.point([36, 53], {hello: 'world'}) * ]); * * turf.geomEach(features, function (currentGeometry, featureIndex, featureProperties, featureBBox, featureId) { * //=currentGeometry * //=featureIndex * //=featureProperties * //=featureBBox * //=featureId * }); */ function geomEach (geojson, callback) { var i, j, g, geometry, stopG, geometryMaybeCollection, isGeometryCollection, featureProperties, featureBBox, featureId, featureIndex = 0, isFeatureCollection = geojson.type === "FeatureCollection", isFeature = geojson.type === "Feature", stop = isFeatureCollection ? geojson.features.length : 1 // This logic may look a little weird. The reason why it is that way // is because it's trying to be fast. GeoJSON supports multiple kinds // of objects at its root: FeatureCollection, Features, Geometries. // This function has the responsibility of handling all of them, and that // means that some of the `for` loops you see below actually just don't apply // to certain inputs. For instance, if you give this just a // Point geometry, then both loops are short-circuited and all we do // is gradually rename the input until it's called 'geometry'. // // This also aims to allocate as few resources as possible: just a // few numbers and booleans, rather than any temporary arrays as would // be required with the normalization approach. for (i = 0; i < stop; i++) { geometryMaybeCollection = isFeatureCollection ? geojson.features[i].geometry : isFeature ? geojson.geometry : geojson featureProperties = isFeatureCollection ? geojson.features[i].properties : isFeature ? geojson.properties : {} featureBBox = isFeatureCollection ? geojson.features[i].bbox : isFeature ? geojson.bbox : undefined featureId = isFeatureCollection ? geojson.features[i].id : isFeature ? geojson.id : undefined isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1 for (g = 0; g < stopG; g++) { geometry = isGeometryCollection ? geometryMaybeCollection.geometries[g] : geometryMaybeCollection // Handle null Geometry if (geometry === null) { if ( callback( null, featureIndex, featureProperties, featureBBox, featureId ) === false ) return false continue } switch (geometry.type) { case "Point": case "LineString": case "MultiPoint": case "Polygon": case "MultiLineString": case "MultiPolygon": { if ( callback( geometry, featureIndex, featureProperties, featureBBox, featureId ) === false ) return false break } case "GeometryCollection": { for (j = 0; j < geometry.geometries.length; j++) { if ( callback( geometry.geometries[j], featureIndex, featureProperties, featureBBox, featureId ) === false ) return false } break } default: throw new Error("Unknown Geometry Type") } } // Only increase `featureIndex` per each feature featureIndex++ } } /** * Callback for geomReduce * * The first time the callback function is called, the values provided as arguments depend * on whether the reduce method has an initialValue argument. * * If an initialValue is provided to the reduce method: * - The previousValue argument is initialValue. * - The currentValue argument is the value of the first element present in the array. * * If an initialValue is not provided: * - The previousValue argument is the value of the first element present in the array. * - The currentValue argument is the value of the second element present in the array. * * @callback geomReduceCallback * @param {*} previousValue The accumulated value previously returned in the last invocation * of the callback, or initialValue, if supplied. * @param {Geometry} currentGeometry The current Geometry being processed. * @param {number} featureIndex The current index of the Feature being processed. * @param {Object} featureProperties The current Feature Properties being processed. * @param {Array} featureBBox The current Feature BBox being processed. * @param {number|string} featureId The current Feature Id being processed. */ /** * Reduce geometry in any GeoJSON object, similar to Array.reduce(). * * @name geomReduce * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object * @param {Function} callback a method that takes (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId) * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. * @returns {*} The value that results from the reduction. * @example * var features = turf.featureCollection([ * turf.point([26, 37], {foo: 'bar'}), * turf.point([36, 53], {hello: 'world'}) * ]); * * turf.geomReduce(features, function (previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId) { * //=previousValue * //=currentGeometry * //=featureIndex * //=featureProperties * //=featureBBox * //=featureId * return currentGeometry * }); */ function geomReduce (geojson, callback, initialValue) { var previousValue = initialValue geomEach( geojson, function ( currentGeometry, featureIndex, featureProperties, featureBBox, featureId ) { if (featureIndex === 0 && initialValue === undefined) previousValue = currentGeometry else previousValue = callback( previousValue, currentGeometry, featureIndex, featureProperties, featureBBox, featureId ) } ) return previousValue } /** * Callback for flattenEach * * @callback flattenEachCallback * @param {Feature} currentFeature The current flattened feature being processed. * @param {number} featureIndex The current index of the Feature being processed. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. */ /** * Iterate over flattened features in any GeoJSON object, similar to * Array.forEach. * * @name flattenEach * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON object * @param {Function} callback a method that takes (currentFeature, featureIndex, multiFeatureIndex) * @example * var features = turf.featureCollection([ * turf.point([26, 37], {foo: 'bar'}), * turf.multiPoint([[40, 30], [36, 53]], {hello: 'world'}) * ]); * * turf.flattenEach(features, function (currentFeature, featureIndex, multiFeatureIndex) { * //=currentFeature * //=featureIndex * //=multiFeatureIndex * }); */ function flattenEach (geojson, callback) { geomEach(geojson, function (geometry, featureIndex, properties, bbox, id) { // Callback for single geometry var type = geometry === null ? null : geometry.type switch (type) { case null: case "Point": case "LineString": case "Polygon": if ( callback( feature(geometry, properties, { bbox: bbox, id: id }), featureIndex, 0 ) === false ) return false return } var geomType // Callback for multi-geometry switch (type) { case "MultiPoint": geomType = "Point" break case "MultiLineString": geomType = "LineString" break case "MultiPolygon": geomType = "Polygon" break } for ( var multiFeatureIndex = 0; multiFeatureIndex < geometry.coordinates.length; multiFeatureIndex++ ) { var coordinate = geometry.coordinates[multiFeatureIndex] var geom = { type: geomType, coordinates: coordinate, } if ( callback(feature(geom, properties), featureIndex, multiFeatureIndex) === false ) return false } }) } /** * Callback for segmentEach * * @callback segmentEachCallback * @param {Feature} currentSegment The current Segment being processed. * @param {number} featureIndex The current index of the Feature being processed. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. * @param {number} geometryIndex The current index of the Geometry being processed. * @param {number} segmentIndex The current index of the Segment being processed. * @returns {void} */ /** * Iterate over 2-vertex line segment in any GeoJSON object, similar to Array.forEach() * (Multi)Point geometries do not contain segments therefore they are ignored during this operation. * * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON * @param {Function} callback a method that takes (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) * @returns {void} * @example * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]); * * // Iterate over GeoJSON by 2-vertex segments * turf.segmentEach(polygon, function (currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) { * //=currentSegment * //=featureIndex * //=multiFeatureIndex * //=geometryIndex * //=segmentIndex * }); * * // Calculate the total number of segments * var total = 0; * turf.segmentEach(polygon, function () { * total++; * }); */ function segmentEach (geojson, callback) { flattenEach(geojson, function (feature, featureIndex, multiFeatureIndex) { var segmentIndex = 0 // Exclude null Geometries if (!feature.geometry) return // (Multi)Point geometries do not contain segments therefore they are ignored during this operation. var type = feature.geometry.type if (type === "Point" || type === "MultiPoint") return // Generate 2-vertex line segments var previousCoords var previousFeatureIndex = 0 var previousMultiIndex = 0 var prevGeomIndex = 0 if ( coordEach( feature, function ( currentCoord, coordIndex, featureIndexCoord, multiPartIndexCoord, geometryIndex ) { // Simulating a meta.coordReduce() since `reduce` operations cannot be stopped by returning `false` if ( previousCoords === undefined || featureIndex > previousFeatureIndex || multiPartIndexCoord > previousMultiIndex || geometryIndex > prevGeomIndex ) { previousCoords = currentCoord previousFeatureIndex = featureIndex previousMultiIndex = multiPartIndexCoord prevGeomIndex = geometryIndex segmentIndex = 0 return } var currentSegment = lineString( [previousCoords, currentCoord], feature.properties ) if ( callback( currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex ) === false ) return false segmentIndex++ previousCoords = currentCoord } ) === false ) return false }) } /** * Callback for segmentReduce * * The first time the callback function is called, the values provided as arguments depend * on whether the reduce method has an initialValue argument. * * If an initialValue is provided to the reduce method: * - The previousValue argument is initialValue. * - The currentValue argument is the value of the first element present in the array. * * If an initialValue is not provided: * - The previousValue argument is the value of the first element present in the array. * - The currentValue argument is the value of the second element present in the array. * * @callback segmentReduceCallback * @param {*} previousValue The accumulated value previously returned in the last invocation * of the callback, or initialValue, if supplied. * @param {Feature} currentSegment The current Segment being processed. * @param {number} featureIndex The current index of the Feature being processed. * @param {number} multiFeatureIndex The current index of the Multi-Feature being processed. * @param {number} geometryIndex The current index of the Geometry being processed. * @param {number} segmentIndex The current index of the Segment being processed. */ /** * Reduce 2-vertex line segment in any GeoJSON object, similar to Array.reduce() * (Multi)Point geometries do not contain segments therefore they are ignored during this operation. * * @param {FeatureCollection|Feature|Geometry} geojson any GeoJSON * @param {Function} callback a method that takes (previousValue, currentSegment, currentIndex) * @param {*} [initialValue] Value to use as the first argument to the first call of the callback. * @returns {void} * @example * var polygon = turf.polygon([[[-50, 5], [-40, -10], [-50, -10], [-40, 5], [-50, 5]]]); * * // Iterate over GeoJSON by 2-vertex segments * turf.segmentReduce(polygon, function (previousSegment, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex) { * //= previousSegment * //= currentSegment * //= featureIndex * //= multiFeatureIndex * //= geometryIndex * //= segmentIndex * return currentSegment * }); * * // Calculate the total number of segments * var initialValue = 0 * var total = turf.segmentReduce(polygon, function (previousValue) { * previousValue++; * return previousValue; * }, initialValue); */ function segmentReduce (geojson, callback, initialValue) { var previousValue = initialValue var started = false segmentEach( geojson, function ( currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex ) { if (started === false && initialValue === undefined) previousValue = currentSegment else previousValue = callback( previousValue, currentSegment, featureIndex, multiFeatureIndex, geometryIndex, segmentIndex ) started = true } ) return previousValue } /** * Takes a {@link GeoJSON} and measures its length in the specified units, {@link (Multi)Point}'s distance are ignored. * * @name length * @param {Feature} geojson GeoJSON to measure * @param {Object} [options={}] Optional parameters * @param {string} [options.units=kilometers] can be degrees, radians, miles, or kilometers * @returns {number} length of GeoJSON * @example * var line = turf.lineString([[115, -32], [131, -22], [143, -25], [150, -34]]); * var length = turf.length(line, {units: 'miles'}); * * //addToMap * var addToMap = [line]; * line.properties.distance = length; */ function length$1 (geojson, options) { if (options === void 0) { options = {} } // Calculate distance from 2-vertex line segments return segmentReduce(geojson, function (previousValue, segment) { var coords = segment.geometry.coordinates return previousValue + distance(coords[0], coords[1], options) }, 0) } // http://en.wikipedia.org/wiki/Haversine_formula // http://www.movable-type.co.uk/scripts/latlong.html /** * Takes two {@link Point|points} and finds the geographic bearing between them, * i.e. the angle measured in degrees from the north line (0 degrees) * * @name bearing * @param {Coord} start starting Point * @param {Coord} end ending Point * @param {Object} [options={}] Optional parameters * @param {boolean} [options.final=false] calculates the final bearing if true * @returns {number} bearing in decimal degrees, between -180 and 180 degrees (positive clockwise) * @example * var point1 = turf.point([-75.343, 39.984]); * var point2 = turf.point([-75.534, 39.123]); * * var bearing = turf.bearing(point1, point2); * * //addToMap * var addToMap = [point1, point2] * point1.properties['marker-color'] = '#f00' * point2.properties['marker-color'] = '#0f0' * point1.properties.bearing = bearing */ function bearing (start, end, options) { if (options === void 0) { options = {} } // Reverse calculation if (options.final === true) { return calculateFinalBearing(start, end) } var coordinates1 = getCoord(start) var coordinates2 = getCoord(end) var lon1 = degreesToRadians(coordinates1[0]) var lon2 = degreesToRadians(coordinates2[0]) var lat1 = degreesToRadians(coordinates1[1]) var lat2 = degreesToRadians(coordinates2[1]) var a = Math.sin(lon2 - lon1) * Math.cos(lat2) var b = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1) return radiansToDegrees(Math.atan2(a, b)) } /** * Calculates Final Bearing * * @private * @param {Coord} start starting Point * @param {Coord} end ending Point * @returns {number} bearing */ function calculateFinalBearing (start, end) { // Swap start & end var bear = bearing(end, start) bear = (bear + 180) % 360 return bear } // http://en.wikipedia.org/wiki/Haversine_formula // http://www.movable-type.co.uk/scripts/latlong.html /** * Takes a {@link Point} and calculates the location of a destination point given a distance in * degrees, radians, miles, or kilometers; and bearing in degrees. * This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature. * * @name destination * @param {Coord} origin starting point * @param {number} distance distance from the origin point * @param {number} bearing ranging from -180 to 180 * @param {Object} [options={}] Optional parameters * @param {string} [options.units='kilometers'] miles, kilometers, degrees, or radians * @param {Object} [options.properties={}] Translate properties to Point * @returns {Feature} destination point * @example * var point = turf.point([-75.343, 39.984]); * var distance = 50; * var bearing = 90; * var options = {units: 'miles'}; * * var destination = turf.destination(point, distance, bearing, options); * * //addToMap * var addToMap = [point, destination] * destination.properties['marker-color'] = '#f00'; * point.properties['marker-color'] = '#0f0'; */ function destination (origin, distance, bearing, options) { if (options === void 0) { options = {} } // Handle input var coordinates1 = getCoord(origin) var longitude1 = degreesToRadians(coordinates1[0]) var latitude1 = degreesToRadians(coordinates1[1]) var bearingRad = degreesToRadians(bearing) var radians = lengthToRadians(distance, options.units) // Main var latitude2 = Math.asin(Math.sin(latitude1) * Math.cos(radians) + Math.cos(latitude1) * Math.sin(radians) * Math.cos(bearingRad)) var longitude2 = longitude1 + Math.atan2(Math.sin(bearingRad) * Math.sin(radians) * Math.cos(latitude1), Math.cos(radians) - Math.sin(latitude1) * Math.sin(latitude2)) var lng = radiansToDegrees(longitude2) var lat = radiansToDegrees(latitude2) return point([lng, lat], options.properties) } /** * Takes a {@link LineString|line}, a specified distance along the line to a start {@link Point}, * and a specified distance along the line to a stop point * and returns a subsection of the line in-between those points. * * This can be useful for extracting only the part of a route between two distances. * * @name lineSliceAlong * @param {Feature|LineString} line input line * @param {number} startDist distance along the line to starting point * @param {number} stopDist distance along the line to ending point * @param {Object} [options={}] Optional parameters * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers * @returns {Feature} sliced line * @example * var line = turf.lineString([[7, 45], [9, 45], [14, 40], [14, 41]]); * var start = 12.5; * var stop = 25; * var sliced = turf.lineSliceAlong(line, start, stop, {units: 'miles'}); * * //addToMap * var addToMap = [line, start, stop, sliced] */ function lineSliceAlong (line, startDist, stopDist, options) { // Optional parameters options = options || {} if (!isObject(options)) throw new Error("options is invalid") var coords var slice = [] // Validation if (line.type === "Feature") coords = line.geometry.coordinates else if (line.type === "LineString") coords = line.coordinates else throw new Error("input must be a LineString Feature or Geometry") var origCoordsLength = coords.length var travelled = 0 var overshot, direction, interpolated for (var i = 0; i < coords.length; i++) { if (startDist >= travelled && i === coords.length - 1) break else if (travelled > startDist && slice.length === 0) { overshot = startDist - travelled if (!overshot) { slice.push(coords[i]) return lineString(slice) } direction = bearing(coords[i], coords[i - 1]) - 180 interpolated = destination(coords[i], overshot, direction, options) slice.push(interpolated.geometry.coordinates) } if (travelled >= stopDist) { overshot = stopDist - travelled if (!overshot) { slice.push(coords[i]) return lineString(slice) } direction = bearing(coords[i], coords[i - 1]) - 180 interpolated = destination(coords[i], overshot, direction, options) slice.push(interpolated.geometry.coordinates) return lineString(slice) } if (travelled >= startDist) { slice.push(coords[i]) } if (i === coords.length - 1) { return lineString(slice) } travelled += distance(coords[i], coords[i + 1], options) } if (travelled < startDist && coords.length === origCoordsLength) throw new Error("Start position is beyond line") var last = coords[coords.length - 1] return lineString([last, last]) } /** * Divides a {@link LineString} into chunks of a specified length. * If the line is shorter than the segment length then the original line is returned. * * @name lineChunk * @param {FeatureCollection|Geometry|Feature} geojson the lines to split * @param {number} segmentLength how long to make each segment * @param {Object} [options={}] Optional parameters * @param {string} [options.units='kilometers'] units can be degrees, radians, miles, or kilometers * @param {boolean} [options.reverse=false] reverses coordinates to start the first chunked segment at the end * @returns {FeatureCollection} collection of line segments * @example * var line = turf.lineString([[-95, 40], [-93, 45], [-85, 50]]); * * var chunk = turf.lineChunk(line, 15, {units: 'miles'}); * * //addToMap * var addToMap = [chunk]; */ function lineChunk (geojson, segmentLength, options) { // Optional parameters options = options || {} if (!isObject(options)) throw new Error("options is invalid") var units = options.units var reverse = options.reverse // Validation if (!geojson) throw new Error("geojson is required") if (segmentLength <= 0) throw new Error("segmentLength must be greater than 0") // Container var results = [] // Flatten each feature to simple LineString flattenEach(geojson, function (feature) { // reverses coordinates to start the first chunked segment at the end if (reverse) feature.geometry.coordinates = feature.geometry.coordinates.reverse() sliceLineSegments(feature, segmentLength, units, function (segment) { results.push(segment) }) }) return featureCollection(results) } /** * Slice Line Segments * * @private * @param {Feature} line GeoJSON LineString * @param {number} segmentLength how long to make each segment * @param {string}[units='kilometers'] units can be degrees, radians, miles, or kilometers * @param {Function} callback iterate over sliced line segments * @returns {void} */ function sliceLineSegments (line, segmentLength, units, callback) { var lineLength = length$1(line, { units: units }) // If the line is shorter than the segment length then the orginal line is returned. if (lineLength <= segmentLength) return callback(line) var numberOfSegments = lineLength / segmentLength // If numberOfSegments is integer, no need to plus 1 if (!Number.isInteger(numberOfSegments)) { numberOfSegments = Math.floor(numberOfSegments) + 1 } for (var i = 0; i < numberOfSegments; i++) { var outline = lineSliceAlong( line, segmentLength * i, segmentLength * (i + 1), { units: units } ) callback(outline, i) } } /** * Takes a set of features, calculates the bbox of all input features, and returns a bounding box. * * @name bbox * @param {GeoJSON} geojson any GeoJSON object * @returns {BBox} bbox extent in [minX, minY, maxX, maxY] order * @example * var line = turf.lineString([[-74, 40], [-78, 42], [-82, 35]]); * var bbox = turf.bbox(line); * var bboxPolygon = turf.bboxPolygon(bbox); * * //addToMap * var addToMap = [line, bboxPolygon] */ function bbox (geojson) { var result = [Infinity, Infinity, -Infinity, -Infinity] coordEach(geojson, function (coord) { if (result[0] > coord[0]) { result[0] = coord[0] } if (result[1] > coord[1]) { result[1] = coord[1] } if (result[2] < coord[0]) { result[2] = coord[0] } if (result[3] < coord[1]) { result[3] = coord[1] } }) return result } bbox["default"] = bbox var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {} function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x } function getAugmentedNamespace (n) { if (n.__esModule) return n var f = n.default if (typeof f == "function") { var a = function a () { if (this instanceof a) { var args = [null] args.push.apply(args, arguments) var Ctor = Function.bind.apply(f, args) return new Ctor() } return f.apply(this, arguments) } a.prototype = f.prototype } else a = {} Object.defineProperty(a, '__esModule', { value: true }) Object.keys(n).forEach(function (k) { var d = Object.getOwnPropertyDescriptor(n, k) Object.defineProperty(a, k, d.get ? d : { enumerable: true, get: function () { return n[k] } }) }) return a } // http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule // modified from: https://github.com/substack/point-in-polygon/blob/master/index.js // which was modified from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html /** * Takes a {@link Point} and a {@link Polygon} or {@link MultiPolygon} and determines if the point * resides inside the polygon. The polygon can be convex or concave. The function accounts for holes. * * @name booleanPointInPolygon * @param {Coord} point input point * @param {Feature} polygon input polygon or multipolygon * @param {Object} [options={}] Optional parameters * @param {boolean} [options.ignoreBoundary=false] True if polygon boundary should be ignored when determining if * the point is inside the polygon otherwise false. * @returns {boolean} `true` if the Point is inside the Polygon; `false` if the Point is not inside the Polygon * @example * var pt = turf.point([-77, 44]); * var poly = turf.polygon([[ * [-81, 41], * [-81, 47], * [-72, 47], * [-72, 41], * [-81, 41] * ]]); * * turf.booleanPointInPolygon(pt, poly); * //= true */ function booleanPointInPolygon (point, polygon, options) { if (options === void 0) { options = {} } // validation if (!point) { throw new Error("point is required") } if (!polygon) { throw new Error("polygon is required") } var pt = getCoord(point) var geom = getGeom(polygon) var type = geom.type var bbox = polygon.bbox var polys = geom.coordinates // Quick elimination if point is not inside bbox if (bbox && inBBox(pt, bbox) === false) { return false } // normalize to multipolygon if (type === "Polygon") { polys = [polys] } var insidePoly = false for (var i = 0; i < polys.length && !insidePoly; i++) { // check if it is in the outer ring first if (inRing(pt, polys[i][0], options.ignoreBoundary)) { var inHole = false var k = 1 // check for the point in any of the holes while (k < polys[i].length && !inHole) { if (inRing(pt, polys[i][k], !options.ignoreBoundary)) { inHole = true } k++ } if (!inHole) { insidePoly = true } } } return insidePoly } /** * inRing * * @private * @param {Array} pt [x,y] * @param {Array>} ring [[x,y], [x,y],..] * @param {boolean} ignoreBoundary ignoreBoundary * @returns {boolean} inRing */ function inRing (pt, ring, ignoreBoundary) { var isInside = false if (ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]) { ring = ring.slice(0, ring.length - 1) } for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) { var xi = ring[i][0] var yi = ring[i][1] var xj = ring[j][0] var yj = ring[j][1] var onBoundary = pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0 && (xi - pt[0]) * (xj - pt[0]) <= 0 && (yi - pt[1]) * (yj - pt[1]) <= 0 if (onBoundary) { return !ignoreBoundary } var intersect = yi > pt[1] !== yj > pt[1] && pt[0] < ((xj - xi) * (pt[1] - yi)) / (yj - yi) + xi if (intersect) { isInside = !isInside } } return isInside } /** * inBBox * * @private * @param {Position} pt point [x,y] * @param {BBox} bbox BBox [west, south, east, north] * @returns {boolean} true/false if point is inside BBox */ function inBBox (pt, bbox) { return (bbox[0] <= pt[0] && bbox[1] <= pt[1] && bbox[2] >= pt[0] && bbox[3] >= pt[1]) } /** * Takes a bbox and returns an equivalent {@link Polygon|polygon}. * * @name bboxPolygon * @param {BBox} bbox extent in [minX, minY, maxX, maxY] order * @param {Object} [options={}] Optional parameters * @param {Properties} [options.properties={}] Translate properties to Polygon * @param {string|number} [options.id={}] Translate Id to Polygon * @returns {Feature} a Polygon representation of the bounding box * @example * var bbox = [0, 0, 10, 10]; * * var poly = turf.bboxPolygon(bbox); * * //addToMap * var addToMap = [poly] */ function bboxPolygon (bbox, options) { if (options === void 0) { options = {} } // Convert BBox positions to Numbers // No performance loss for including Number() // https://github.com/Turfjs/turf/issues/1119 var west = Number(bbox[0]) var south = Number(bbox[1]) var east = Number(bbox[2]) var north = Number(bbox[3]) if (bbox.length === 6) { throw new Error("@turf/bbox-polygon does not support BBox with 6 positions") } var lowLeft = [west, south] var topLeft = [west, north] var topRight = [east, north] var lowRight = [east, south] return polygon([[lowLeft, lowRight, topRight, topLeft, lowLeft]], options.properties, { bbox: bbox, id: options.id }) } /** * Takes a {@link Feature} or {@link FeatureCollection} and returns the absolute center point of all features. * * @name center * @param {GeoJSON} geojson GeoJSON to be centered * @param {Object} [options={}] Optional parameters * @param {Object} [options.properties={}] Translate GeoJSON Properties to Point * @param {Object} [options.bbox={}] Translate GeoJSON BBox to Point * @param {Object} [options.id={}] Translate GeoJSON Id to Point * @returns {Feature} a Point feature at the absolute center point of all input features * @example * var features = turf.points([ * [-97.522259, 35.4691], * [-97.502754, 35.463455], * [-97.508269, 35.463245] * ]); * * var center = turf.center(features); * * //addToMap * var addToMap = [features, center] * center.properties['marker-size'] = 'large'; * center.properties['marker-color'] = '#000'; */ function center (geojson, options) { if (options === void 0) { options = {} } var ext = bbox(geojson) var x = (ext[0] + ext[2]) / 2 var y = (ext[1] + ext[3]) / 2 return point([x, y], options.properties, options) } // Note: change RADIUS => earthRadius var RADIUS$1 = 6378137 /** * Takes one or more features and returns their area in square meters. * * @name area * @param {GeoJSON} geojson input GeoJSON feature(s) * @returns {number} area in square meters * @example * var polygon = turf.polygon([[[125, -15], [113, -22], [154, -27], [144, -15], [125, -15]]]); * * var area = turf.area(polygon); * * //addToMap * var addToMap = [polygon] * polygon.properties.area = area */ function area (geojson) { return geomReduce(geojson, function (value, geom) { return value + calculateArea(geom) }, 0) } /** * Calculate Area * * @private * @param {Geometry} geom GeoJSON Geometries * @returns {number} area */ function calculateArea (geom) { var total = 0 var i switch (geom.type) { case "Polygon": return polygonArea(geom.coordinates) case "MultiPolygon": for (i = 0; i < geom.coordinates.length; i++) { total += polygonArea(geom.coordinates[i]) } return total case "Point": case "MultiPoint": case "LineString": case "MultiLineString": return 0 } return 0 } function polygonArea (coords) { var total = 0 if (coords && coords.length > 0) { total += Math.abs(ringArea(coords[0])) for (var i = 1; i < coords.length; i++) { total -= Math.abs(ringArea(coords[i])) } } return total } /** * @private * Calculate the approximate area of the polygon were it projected onto the earth. * Note that this area will be positive if ring is oriented clockwise, otherwise it will be negative. * * Reference: * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for Polygons on a Sphere", * JPL Publication 07-03, Jet Propulsion * Laboratory, Pasadena, CA, June 2007 https://trs.jpl.nasa.gov/handle/2014/40409 * * @param {Array>} coords Ring Coordinates * @returns {number} The approximate signed geodesic area of the polygon in square meters. */ function ringArea (coords) { var p1 var p2 var p3 var lowerIndex var middleIndex var upperIndex var i var total = 0 var coordsLength = coords.length if (coordsLength > 2) { for (i = 0; i < coordsLength; i++) { if (i === coordsLength - 2) { // i = N-2 lowerIndex = coordsLength - 2 middleIndex = coordsLength - 1 upperIndex = 0 } else if (i === coordsLength - 1) { // i = N-1 lowerIndex = coordsLength - 1 middleIndex = 0 upperIndex = 1 } else { // i = 0 to N-3 lowerIndex = i middleIndex = i + 1 upperIndex = i + 2 } p1 = coords[lowerIndex] p2 = coords[middleIndex] p3 = coords[upperIndex] total += (rad(p3[0]) - rad(p1[0])) * Math.sin(rad(p2[1])) } total = (total * RADIUS$1 * RADIUS$1) / 2 } return total } function rad (num) { return (num * Math.PI) / 180 } /** * Returns true if a point is on a line. Accepts a optional parameter to ignore the * start and end vertices of the linestring. * * @name booleanPointOnLine * @param {Coord} pt GeoJSON Point * @param {Feature} line GeoJSON LineString * @param {Object} [options={}] Optional parameters * @param {boolean} [options.ignoreEndVertices=false] whether to ignore the start and end vertices. * @param {number} [options.epsilon] Fractional number to compare with the cross product result. Useful for dealing with floating points such as lng/lat points * @returns {boolean} true/false * @example * var pt = turf.point([0, 0]); * var line = turf.lineString([[-1, -1],[1, 1],[1.5, 2.2]]); * var isPointOnLine = turf.booleanPointOnLine(pt, line); * //=true */ function booleanPointOnLine (pt, line, options) { if (options === void 0) { options = {} } // Normalize inputs var ptCoords = getCoord(pt) var lineCoords = getCoords(line) // Main for (var i = 0; i < lineCoords.length - 1; i++) { var ignoreBoundary = false if (options.ignoreEndVertices) { if (i === 0) { ignoreBoundary = "start" } if (i === lineCoords.length - 2) { ignoreBoundary = "end" } if (i === 0 && i + 1 === lineCoords.length - 1) { ignoreBoundary = "both" } } if (isPointOnLineSegment(lineCoords[i], lineCoords[i + 1], ptCoords, ignoreBoundary, typeof options.epsilon === "undefined" ? null : options.epsilon)) { return true } } return false } // See http://stackoverflow.com/a/4833823/1979085 // See https://stackoverflow.com/a/328122/1048847 /** * @private * @param {Position} lineSegmentStart coord pair of start of line * @param {Position} lineSegmentEnd coord pair of end of line * @param {Position} pt coord pair of point to check * @param {boolean|string} excludeBoundary whether the point is allowed to fall on the line ends. * @param {number} epsilon Fractional number to compare with the cross product result. Useful for dealing with floating points such as lng/lat points * If true which end to ignore. * @returns {boolean} true/false */ function isPointOnLineSegment (lineSegmentStart, lineSegmentEnd, pt, excludeBoundary, epsilon) { var x = pt[0] var y = pt[1] var x1 = lineSegmentStart[0] var y1 = lineSegmentStart[1] var x2 = lineSegmentEnd[0] var y2 = lineSegmentEnd[1] var dxc = pt[0] - x1 var dyc = pt[1] - y1 var dxl = x2 - x1 var dyl = y2 - y1 var cross = dxc * dyl - dyc * dxl if (epsilon !== null) { if (Math.abs(cross) > epsilon) { return false } } else if (cross !== 0) { return false } if (!excludeBoundary) { if (Math.abs(dxl) >= Math.abs(dyl)) { return dxl > 0 ? x1 <= x && x <= x2 : x2 <= x && x <= x1 } return dyl > 0 ? y1 <= y && y <= y2 : y2 <= y && y <= y1 } else if (excludeBoundary === "start") { if (Math.abs(dxl) >= Math.abs(dyl)) { return dxl > 0 ? x1 < x && x <= x2 : x2 <= x && x < x1 } return dyl > 0 ? y1 < y && y <= y2 : y2 <= y && y < y1 } else if (excludeBoundary === "end") { if (Math.abs(dxl) >= Math.abs(dyl)) { return dxl > 0 ? x1 <= x && x < x2 : x2 < x && x <= x1 } return dyl > 0 ? y1 <= y && y < y2 : y2 < y && y <= y1 } else if (excludeBoundary === "both") { if (Math.abs(dxl) >= Math.abs(dyl)) { return dxl > 0 ? x1 < x && x < x2 : x2 < x && x < x1 } return dyl > 0 ? y1 < y && y < y2 : y2 < y && y < y1 } return false } /** * Boolean-within returns true if the first geometry is completely within the second geometry. * The interiors of both geometries must intersect and, the interior and boundary of the primary (geometry a) * must not intersect the exterior of the secondary (geometry b). * Boolean-within returns the exact opposite result of the `@turf/boolean-contains`. * * @name booleanWithin * @param {Geometry|Feature} feature1 GeoJSON Feature or Geometry * @param {Geometry|Feature} feature2 GeoJSON Feature or Geometry * @returns {boolean} true/false * @example * var line = turf.lineString([[1, 1], [1, 2], [1, 3], [1, 4]]); * var point = turf.point([1, 2]); * * turf.booleanWithin(point, line); * //=true */ function booleanWithin (feature1, feature2) { var geom1 = getGeom(feature1) var geom2 = getGeom(feature2) var type1 = geom1.type var type2 = geom2.type switch (type1) { case "Point": switch (type2) { case "MultiPoint": return isPointInMultiPoint(geom1, geom2) case "LineString": return booleanPointOnLine(geom1, geom2, { ignoreEndVertices: true }) case "Polygon": case "MultiPolygon": return booleanPointInPolygon(geom1, geom2, { ignoreBoundary: true }) default: throw new Error("feature2 " + type2 + " geometry not supported") } case "MultiPoint": switch (type2) { case "MultiPoint": return isMultiPointInMultiPoint(geom1, geom2) case "LineString": return isMultiPointOnLine(geom1, geom2) case "Polygon": case "MultiPolygon": return isMultiPointInPoly(geom1, geom2) default: throw new Error("feature2 " + type2 + " geometry not supported") } case "LineString": switch (type2) { case "LineString": return isLineOnLine(geom1, geom2) case "Polygon": case "MultiPolygon": return isLineInPoly(geom1, geom2) default: throw new Error("feature2 " + type2 + " geometry not supported") } case "Polygon": switch (type2) { case "Polygon": case "MultiPolygon": return isPolyInPoly(geom1, geom2) default: throw new Error("feature2 " + type2 + " geometry not supported") } default: throw new Error("feature1 " + type1 + " geometry not supported") } } function isPointInMultiPoint (point, multiPoint) { var i var output = false for (i = 0; i < multiPoint.coordinates.length; i++) { if (compareCoords(multiPoint.coordinates[i], point.coordinates)) { output = true break } } return output } function isMultiPointInMultiPoint (multiPoint1, multiPoint2) { for (var i = 0; i < multiPoint1.coordinates.length; i++) { var anyMatch = false for (var i2 = 0; i2 < multiPoint2.coordinates.length; i2++) { if (compareCoords(multiPoint1.coordinates[i], multiPoint2.coordinates[i2])) { anyMatch = true } } if (!anyMatch) { return false } } return true } function isMultiPointOnLine (multiPoint, lineString) { var foundInsidePoint = false for (var i = 0; i < multiPoint.coordinates.length; i++) { if (!booleanPointOnLine(multiPoint.coordinates[i], lineString)) { return false } if (!foundInsidePoint) { foundInsidePoint = booleanPointOnLine(multiPoint.coordinates[i], lineString, { ignoreEndVertices: true }) } } return foundInsidePoint } function isMultiPointInPoly (multiPoint, polygon) { var output = true var isInside = false for (var i = 0; i < multiPoint.coordinates.length; i++) { isInside = booleanPointInPolygon(multiPoint.coordinates[1], polygon) if (!isInside) { output = false break } { isInside = booleanPointInPolygon(multiPoint.coordinates[1], polygon, { ignoreBoundary: true, }) } } return output && isInside } function isLineOnLine (lineString1, lineString2) { for (var i = 0; i < lineString1.coordinates.length; i++) { if (!booleanPointOnLine(lineString1.coordinates[i], lineString2)) { return false } } return true } function isLineInPoly (linestring, polygon) { var polyBbox = bbox(polygon) var lineBbox = bbox(linestring) if (!doBBoxOverlap(polyBbox, lineBbox)) { return false } var foundInsidePoint = false for (var i = 0; i < linestring.coordinates.length - 1; i++) { if (!booleanPointInPolygon(linestring.coordinates[i], polygon)) { return false } if (!foundInsidePoint) { foundInsidePoint = booleanPointInPolygon(linestring.coordinates[i], polygon, { ignoreBoundary: true }) } if (!foundInsidePoint) { var midpoint = getMidpoint(linestring.coordinates[i], linestring.coordinates[i + 1]) foundInsidePoint = booleanPointInPolygon(midpoint, polygon, { ignoreBoundary: true, }) } } return foundInsidePoint } /** * Is Polygon2 in Polygon1 * Only takes into account outer rings * * @private * @param {Polygon} geometry1 * @param {Polygon|MultiPolygon} geometry2 * @returns {boolean} true/false */ function isPolyInPoly (geometry1, geometry2) { var poly1Bbox = bbox(geometry1) var poly2Bbox = bbox(geometry2) if (!doBBoxOverlap(poly2Bbox, poly1Bbox)) { return false } for (var i = 0; i < geometry1.coordinates[0].length; i++) { if (!booleanPointInPolygon(geometry1.coordinates[0][i], geometry2)) { return false } } return true } function doBBoxOverlap (bbox1, bbox2) { if (bbox1[0] > bbox2[0]) return false if (bbox1[2] < bbox2[2]) return false if (bbox1[1] > bbox2[1]) return false if (bbox1[3] < bbox2[3]) return false return true } /** * compareCoords * * @private * @param {Position} pair1 point [x,y] * @param {Position} pair2 point [x,y] * @returns {boolean} true/false if coord pairs match */ function compareCoords (pair1, pair2) { return pair1[0] === pair2[0] && pair1[1] === pair2[1] } /** * getMidpoint * * @private * @param {Position} pair1 point [x,y] * @param {Position} pair2 point [x,y] * @returns {Position} midpoint of pair1 and pair2 */ function getMidpoint (pair1, pair2) { return [(pair1[0] + pair2[0]) / 2, (pair1[1] + pair2[1]) / 2] } /** * Creates a {@link Point} grid from a bounding box, {@link FeatureCollection} or {@link Feature}. * * @name pointGrid * @param {Array} bbox extent in [minX, minY, maxX, maxY] order * @param {number} cellSide the distance between points, in units * @param {Object} [options={}] Optional parameters * @param {string} [options.units='kilometers'] used in calculating cellSide, can be degrees, radians, miles, or kilometers * @param {Feature} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it * @param {Object} [options.properties={}] passed to each point of the grid * @returns {FeatureCollection} grid of points * @example * var extent = [-70.823364, -33.553984, -70.473175, -33.302986]; * var cellSide = 3; * var options = {units: 'miles'}; * * var grid = turf.pointGrid(extent, cellSide, options); * * //addToMap * var addToMap = [grid]; */ function pointGrid (bbox, cellSide, options) { if (options === void 0) { options = {} } // Default parameters if (options.mask && !options.units) options.units = "kilometers" // Containers var results = [] // Typescript handles the Type Validation // if (cellSide === null || cellSide === undefined) throw new Error('cellSide is required'); // if (!isNumber(cellSide)) throw new Error('cellSide is invalid'); // if (!bbox) throw new Error('bbox is required'); // if (!Array.isArray(bbox)) throw new Error('bbox must be array'); // if (bbox.length !== 4) throw new Error('bbox must contain 4 numbers'); // if (mask && ['Polygon', 'MultiPolygon'].indexOf(getType(mask)) === -1) throw new Error('options.mask must be a (Multi)Polygon'); var west = bbox[0] var south = bbox[1] var east = bbox[2] var north = bbox[3] var xFraction = cellSide / distance([west, south], [east, south], options) var cellWidth = xFraction * (east - west) var yFraction = cellSide / distance([west, south], [west, north], options) var cellHeight = yFraction * (north - south) var bboxWidth = east - west var bboxHeight = north - south var columns = Math.floor(bboxWidth / cellWidth) var rows = Math.floor(bboxHeight / cellHeight) // adjust origin of the grid var deltaX = (bboxWidth - columns * cellWidth) / 2 var deltaY = (bboxHeight - rows * cellHeight) / 2 var currentX = west + deltaX while (currentX <= east) { var currentY = south + deltaY while (currentY <= north) { var cellPt = point([currentX, currentY], options.properties) if (options.mask) { if (booleanWithin(cellPt, options.mask)) results.push(cellPt) } else { results.push(cellPt) } currentY += cellHeight } currentX += cellWidth } return featureCollection(results) } function constant (x) { return function () { return x } } function x (d) { return d[0] } function y (d) { return d[1] } function RedBlackTree () { this._ = null // root node } function RedBlackNode (node) { node.U = // parent node node.C = // color - true for red, false for black node.L = // left node node.R = // right node node.P = // previous node node.N = null // next node } RedBlackTree.prototype = { constructor: RedBlackTree, insert: function (after, node) { var parent, grandpa, uncle if (after) { node.P = after node.N = after.N if (after.N) after.N.P = node after.N = node if (after.R) { after = after.R while (after.L) after = after.L after.L = node } else { after.R = node } parent = after } else if (this._) { after = RedBlackFirst(this._) node.P = null node.N = after after.P = after.L = node parent = after } else { node.P = node.N = null this._ = node parent = null } node.L = node.R = null node.U = parent node.C = true after = node while (parent && parent.C) { grandpa = parent.U if (parent === grandpa.L) { uncle = grandpa.R if (uncle && uncle.C) { parent.C = uncle.C = false grandpa.C = true after = grandpa } else { if (after === parent.R) { RedBlackRotateLeft(this, parent) after = parent parent = after.U } parent.C = false grandpa.C = true RedBlackRotateRight(this, grandpa) } } else { uncle = grandpa.L if (uncle && uncle.C) { parent.C = uncle.C = false grandpa.C = true after = grandpa } else { if (after === parent.L) { RedBlackRotateRight(this, parent) after = parent parent = after.U } parent.C = false grandpa.C = true RedBlackRotateLeft(this, grandpa) } } parent = after.U } this._.C = false }, remove: function (node) { if (node.N) node.N.P = node.P if (node.P) node.P.N = node.N node.N = node.P = null var parent = node.U, sibling, left = node.L, right = node.R, next, red if (!left) next = right else if (!right) next = left else next = RedBlackFirst(right) if (parent) { if (parent.L === node) parent.L = next else parent.R = next } else { this._ = next } if (left && right) { red = next.C next.C = node.C next.L = left left.U = next if (next !== right) { parent = next.U next.U = node.U node = next.R parent.L = node next.R = right right.U = next } else { next.U = parent parent = next node = next.R } } else { red = node.C node = next } if (node) node.U = parent if (red) return if (node && node.C) { node.C = false; return } do { if (node === this._) break if (node === parent.L) { sibling = parent.R if (sibling.C) { sibling.C = false parent.C = true RedBlackRotateLeft(this, parent) sibling = parent.R } if ((sibling.L && sibling.L.C) || (sibling.R && sibling.R.C)) { if (!sibling.R || !sibling.R.C) { sibling.L.C = false sibling.C = true RedBlackRotateRight(this, sibling) sibling = parent.R } sibling.C = parent.C parent.C = sibling.R.C = false RedBlackRotateLeft(this, parent) node = this._ break } } else { sibling = parent.L if (sibling.C) { sibling.C = false parent.C = true RedBlackRotateRight(this, parent) sibling = parent.L } if ((sibling.L && sibling.L.C) || (sibling.R && sibling.R.C)) { if (!sibling.L || !sibling.L.C) { sibling.R.C = false sibling.C = true RedBlackRotateLeft(this, sibling) sibling = parent.L } sibling.C = parent.C parent.C = sibling.L.C = false RedBlackRotateRight(this, parent) node = this._ break } } sibling.C = true node = parent parent = parent.U } while (!node.C) if (node) node.C = false } } function RedBlackRotateLeft (tree, node) { var p = node, q = node.R, parent = p.U if (parent) { if (parent.L === p) parent.L = q else parent.R = q } else { tree._ = q } q.U = parent p.U = q p.R = q.L if (p.R) p.R.U = p q.L = p } function RedBlackRotateRight (tree, node) { var p = node, q = node.L, parent = p.U if (parent) { if (parent.L === p) parent.L = q else parent.R = q } else { tree._ = q } q.U = parent p.U = q p.L = q.R if (p.L) p.L.U = p q.R = p } function RedBlackFirst (node) { while (node.L) node = node.L return node } function createEdge (left, right, v0, v1) { var edge = [null, null], index = edges.push(edge) - 1 edge.left = left edge.right = right if (v0) setEdgeEnd(edge, left, right, v0) if (v1) setEdgeEnd(edge, right, left, v1) cells[left.index].halfedges.push(index) cells[right.index].halfedges.push(index) return edge } function createBorderEdge (left, v0, v1) { var edge = [v0, v1] edge.left = left return edge } function setEdgeEnd (edge, left, right, vertex) { if (!edge[0] && !edge[1]) { edge[0] = vertex edge.left = left edge.right = right } else if (edge.left === right) { edge[1] = vertex } else { edge[0] = vertex } } // Liang–Barsky line clipping. function clipEdge (edge, x0, y0, x1, y1) { var a = edge[0], b = edge[1], ax = a[0], ay = a[1], bx = b[0], by = b[1], t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r r = x0 - ax if (!dx && r > 0) return r /= dx if (dx < 0) { if (r < t0) return if (r < t1) t1 = r } else if (dx > 0) { if (r > t1) return if (r > t0) t0 = r } r = x1 - ax if (!dx && r < 0) return r /= dx if (dx < 0) { if (r > t1) return if (r > t0) t0 = r } else if (dx > 0) { if (r < t0) return if (r < t1) t1 = r } r = y0 - ay if (!dy && r > 0) return r /= dy if (dy < 0) { if (r < t0) return if (r < t1) t1 = r } else if (dy > 0) { if (r > t1) return if (r > t0) t0 = r } r = y1 - ay if (!dy && r < 0) return r /= dy if (dy < 0) { if (r > t1) return if (r > t0) t0 = r } else if (dy > 0) { if (r < t0) return if (r < t1) t1 = r } if (!(t0 > 0) && !(t1 < 1)) return true // TODO Better check? if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy] if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy] return true } function connectEdge (edge, x0, y0, x1, y1) { var v1 = edge[1] if (v1) return true var v0 = edge[0], left = edge.left, right = edge.right, lx = left[0], ly = left[1], rx = right[0], ry = right[1], fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb if (ry === ly) { if (fx < x0 || fx >= x1) return if (lx > rx) { if (!v0) v0 = [fx, y0] else if (v0[1] >= y1) return v1 = [fx, y1] } else { if (!v0) v0 = [fx, y1] else if (v0[1] < y0) return v1 = [fx, y0] } } else { fm = (lx - rx) / (ry - ly) fb = fy - fm * fx if (fm < -1 || fm > 1) { if (lx > rx) { if (!v0) v0 = [(y0 - fb) / fm, y0] else if (v0[1] >= y1) return v1 = [(y1 - fb) / fm, y1] } else { if (!v0) v0 = [(y1 - fb) / fm, y1] else if (v0[1] < y0) return v1 = [(y0 - fb) / fm, y0] } } else { if (ly < ry) { if (!v0) v0 = [x0, fm * x0 + fb] else if (v0[0] >= x1) return v1 = [x1, fm * x1 + fb] } else { if (!v0) v0 = [x1, fm * x1 + fb] else if (v0[0] < x0) return v1 = [x0, fm * x0 + fb] } } } edge[0] = v0 edge[1] = v1 return true } function clipEdges (x0, y0, x1, y1) { var i = edges.length, edge while (i--) { if (!connectEdge(edge = edges[i], x0, y0, x1, y1) || !clipEdge(edge, x0, y0, x1, y1) || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$2 || Math.abs(edge[0][1] - edge[1][1]) > epsilon$2)) { delete edges[i] } } } function createCell (site) { return cells[site.index] = { site: site, halfedges: [] } } function cellHalfedgeAngle (cell, edge) { var site = cell.site, va = edge.left, vb = edge.right if (site === vb) vb = va, va = site if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]) if (site === va) va = edge[1], vb = edge[0] else va = edge[0], vb = edge[1] return Math.atan2(va[0] - vb[0], vb[1] - va[1]) } function cellHalfedgeStart (cell, edge) { return edge[+(edge.left !== cell.site)] } function cellHalfedgeEnd (cell, edge) { return edge[+(edge.left === cell.site)] } function sortCellHalfedges () { for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) { if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) { var index = new Array(m), array = new Array(m) for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]) index.sort(function (i, j) { return array[j] - array[i] }) for (j = 0; j < m; ++j) array[j] = halfedges[index[j]] for (j = 0; j < m; ++j) halfedges[j] = array[j] } } } function clipCells (x0, y0, x1, y1) { var nCells = cells.length, iCell, cell, site, iHalfedge, halfedges, nHalfedges, start, startX, startY, end, endX, endY, cover = true for (iCell = 0; iCell < nCells; ++iCell) { if (cell = cells[iCell]) { site = cell.site halfedges = cell.halfedges iHalfedge = halfedges.length // Remove any dangling clipped edges. while (iHalfedge--) { if (!edges[halfedges[iHalfedge]]) { halfedges.splice(iHalfedge, 1) } } // Insert any border edges as necessary. iHalfedge = 0, nHalfedges = halfedges.length while (iHalfedge < nHalfedges) { end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1] start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1] if (Math.abs(endX - startX) > epsilon$2 || Math.abs(endY - startY) > epsilon$2) { halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end, Math.abs(endX - x0) < epsilon$2 && y1 - endY > epsilon$2 ? [x0, Math.abs(startX - x0) < epsilon$2 ? startY : y1] : Math.abs(endY - y1) < epsilon$2 && x1 - endX > epsilon$2 ? [Math.abs(startY - y1) < epsilon$2 ? startX : x1, y1] : Math.abs(endX - x1) < epsilon$2 && endY - y0 > epsilon$2 ? [x1, Math.abs(startX - x1) < epsilon$2 ? startY : y0] : Math.abs(endY - y0) < epsilon$2 && endX - x0 > epsilon$2 ? [Math.abs(startY - y0) < epsilon$2 ? startX : x0, y0] : null)) - 1) ++nHalfedges } } if (nHalfedges) cover = false } } // If there weren’t any edges, have the closest site cover the extent. // It doesn’t matter which corner of the extent we measure! if (cover) { var dx, dy, d2, dc = Infinity for (iCell = 0, cover = null; iCell < nCells; ++iCell) { if (cell = cells[iCell]) { site = cell.site dx = site[0] - x0 dy = site[1] - y0 d2 = dx * dx + dy * dy if (d2 < dc) dc = d2, cover = cell } } if (cover) { var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0] cover.halfedges.push( edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1, edges.push(createBorderEdge(site, v01, v11)) - 1, edges.push(createBorderEdge(site, v11, v10)) - 1, edges.push(createBorderEdge(site, v10, v00)) - 1 ) } } // Lastly delete any cells with no edges; these were entirely clipped. for (iCell = 0; iCell < nCells; ++iCell) { if (cell = cells[iCell]) { if (!cell.halfedges.length) { delete cells[iCell] } } } } var circlePool = [] var firstCircle function Circle () { RedBlackNode(this) this.x = this.y = this.arc = this.site = this.cy = null } function attachCircle (arc) { var lArc = arc.P, rArc = arc.N if (!lArc || !rArc) return var lSite = lArc.site, cSite = arc.site, rSite = rArc.site if (lSite === rSite) return var bx = cSite[0], by = cSite[1], ax = lSite[0] - bx, ay = lSite[1] - by, cx = rSite[0] - bx, cy = rSite[1] - by var d = 2 * (ax * cy - ay * cx) if (d >= -epsilon2) return var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d var circle = circlePool.pop() || new Circle circle.arc = arc circle.site = cSite circle.x = x + bx circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y) // y bottom arc.circle = circle var before = null, node = circles._ while (node) { if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) { if (node.L) node = node.L else { before = node.P; break } } else { if (node.R) node = node.R else { before = node; break } } } circles.insert(before, circle) if (!before) firstCircle = circle } function detachCircle (arc) { var circle = arc.circle if (circle) { if (!circle.P) firstCircle = circle.N circles.remove(circle) circlePool.push(circle) RedBlackNode(circle) arc.circle = null } } var beachPool = [] function Beach () { RedBlackNode(this) this.edge = this.site = this.circle = null } function createBeach (site) { var beach = beachPool.pop() || new Beach beach.site = site return beach } function detachBeach (beach) { detachCircle(beach) beaches.remove(beach) beachPool.push(beach) RedBlackNode(beach) } function removeBeach (beach) { var circle = beach.circle, x = circle.x, y = circle.cy, vertex = [x, y], previous = beach.P, next = beach.N, disappearing = [beach] detachBeach(beach) var lArc = previous while (lArc.circle && Math.abs(x - lArc.circle.x) < epsilon$2 && Math.abs(y - lArc.circle.cy) < epsilon$2) { previous = lArc.P disappearing.unshift(lArc) detachBeach(lArc) lArc = previous } disappearing.unshift(lArc) detachCircle(lArc) var rArc = next while (rArc.circle && Math.abs(x - rArc.circle.x) < epsilon$2 && Math.abs(y - rArc.circle.cy) < epsilon$2) { next = rArc.N disappearing.push(rArc) detachBeach(rArc) rArc = next } disappearing.push(rArc) detachCircle(rArc) var nArcs = disappearing.length, iArc for (iArc = 1; iArc < nArcs; ++iArc) { rArc = disappearing[iArc] lArc = disappearing[iArc - 1] setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex) } lArc = disappearing[0] rArc = disappearing[nArcs - 1] rArc.edge = createEdge(lArc.site, rArc.site, null, vertex) attachCircle(lArc) attachCircle(rArc) } function addBeach (site) { var x = site[0], directrix = site[1], lArc, rArc, dxl, dxr, node = beaches._ while (node) { dxl = leftBreakPoint(node, directrix) - x if (dxl > epsilon$2) node = node.L; else { dxr = x - rightBreakPoint(node, directrix) if (dxr > epsilon$2) { if (!node.R) { lArc = node break } node = node.R } else { if (dxl > -epsilon$2) { lArc = node.P rArc = node } else if (dxr > -epsilon$2) { lArc = node rArc = node.N } else { lArc = rArc = node } break } } } createCell(site) var newArc = createBeach(site) beaches.insert(lArc, newArc) if (!lArc && !rArc) return if (lArc === rArc) { detachCircle(lArc) rArc = createBeach(lArc.site) beaches.insert(newArc, rArc) newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site) attachCircle(lArc) attachCircle(rArc) return } if (!rArc) { // && lArc newArc.edge = createEdge(lArc.site, newArc.site) return } // else lArc !== rArc detachCircle(lArc) detachCircle(rArc) var lSite = lArc.site, ax = lSite[0], ay = lSite[1], bx = site[0] - ax, by = site[1] - ay, rSite = rArc.site, cx = rSite[0] - ax, cy = rSite[1] - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay] setEdgeEnd(rArc.edge, lSite, rSite, vertex) newArc.edge = createEdge(lSite, site, null, vertex) rArc.edge = createEdge(site, rSite, null, vertex) attachCircle(lArc) attachCircle(rArc) } function leftBreakPoint (arc, directrix) { var site = arc.site, rfocx = site[0], rfocy = site[1], pby2 = rfocy - directrix if (!pby2) return rfocx var lArc = arc.P if (!lArc) return -Infinity site = lArc.site var lfocx = site[0], lfocy = site[1], plby2 = lfocy - directrix if (!plby2) return lfocx var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2 if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx return (rfocx + lfocx) / 2 } function rightBreakPoint (arc, directrix) { var rArc = arc.N if (rArc) return leftBreakPoint(rArc, directrix) var site = arc.site return site[1] === directrix ? site[0] : Infinity } var epsilon$2 = 1e-6 var epsilon2 = 1e-12 var beaches var cells var circles var edges function triangleArea (a, b, c) { return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]) } function lexicographic (a, b) { return b[1] - a[1] || b[0] - a[0] } function Diagram (sites, extent) { var site = sites.sort(lexicographic).pop(), x, y, circle edges = [] cells = new Array(sites.length) beaches = new RedBlackTree circles = new RedBlackTree while (true) { circle = firstCircle if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) { if (site[0] !== x || site[1] !== y) { addBeach(site) x = site[0], y = site[1] } site = sites.pop() } else if (circle) { removeBeach(circle.arc) } else { break } } sortCellHalfedges() if (extent) { var x0 = +extent[0][0], y0 = +extent[0][1], x1 = +extent[1][0], y1 = +extent[1][1] clipEdges(x0, y0, x1, y1) clipCells(x0, y0, x1, y1) } this.edges = edges this.cells = cells beaches = circles = edges = cells = null } Diagram.prototype = { constructor: Diagram, polygons: function () { var edges = this.edges return this.cells.map(function (cell) { var polygon = cell.halfedges.map(function (i) { return cellHalfedgeStart(cell, edges[i]) }) polygon.data = cell.site.data return polygon }) }, triangles: function () { var triangles = [], edges = this.edges this.cells.forEach(function (cell, i) { if (!(m = (halfedges = cell.halfedges).length)) return var site = cell.site, halfedges, j = -1, m, s0, e1 = edges[halfedges[m - 1]], s1 = e1.left === site ? e1.right : e1.left while (++j < m) { s0 = s1 e1 = edges[halfedges[j]] s1 = e1.left === site ? e1.right : e1.left if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) { triangles.push([site.data, s0.data, s1.data]) } } }) return triangles }, links: function () { return this.edges.filter(function (edge) { return edge.right }).map(function (edge) { return { source: edge.left.data, target: edge.right.data } }) }, find: function (x, y, radius) { var that = this, i0, i1 = that._found || 0, n = that.cells.length, cell // Use the previously-found cell, or start with an arbitrary one. while (!(cell = that.cells[i1])) if (++i1 >= n) return null var dx = x - cell.site[0], dy = y - cell.site[1], d2 = dx * dx + dy * dy // Traverse the half-edges to find a closer cell, if any. do { cell = that.cells[i0 = i1], i1 = null cell.halfedges.forEach(function (e) { var edge = that.edges[e], v = edge.left if ((v === cell.site || !v) && !(v = edge.right)) return var vx = x - v[0], vy = y - v[1], v2 = vx * vx + vy * vy if (v2 < d2) d2 = v2, i1 = v.index }) } while (i1 !== null) that._found = i0 return radius == null || d2 <= radius * radius ? cell.site : null } } function voronoi$1 () { var x$1 = x, y$1 = y, extent = null function voronoi (data) { return new Diagram(data.map(function (d, i) { var s = [Math.round(x$1(d, i, data) / epsilon$2) * epsilon$2, Math.round(y$1(d, i, data) / epsilon$2) * epsilon$2] s.index = i s.data = d return s }), extent) } voronoi.polygons = function (data) { return voronoi(data).polygons() } voronoi.links = function (data) { return voronoi(data).links() } voronoi.triangles = function (data) { return voronoi(data).triangles() } voronoi.x = function (_) { return arguments.length ? (x$1 = typeof _ === "function" ? _ : constant(+_), voronoi) : x$1 } voronoi.y = function (_) { return arguments.length ? (y$1 = typeof _ === "function" ? _ : constant(+_), voronoi) : y$1 } voronoi.extent = function (_) { return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]] } voronoi.size = function (_) { return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]] } return voronoi } /** * @private * @param {Array>} coords representing a polygon * @returns {Feature} polygon */ function coordsToPolygon (coords) { coords = coords.slice() coords.push(coords[0]) return polygon([coords]) } /** * Takes a FeatureCollection of points, and a bounding box, and returns a FeatureCollection * of Voronoi polygons. * * The Voronoi algorithim used comes from the d3-voronoi package. * * @name voronoi * @param {FeatureCollection} points to find the Voronoi polygons around. * @param {Object} [options={}] Optional parameters * @param {number[]} [options.bbox=[-180, -85, 180, -85]] clipping rectangle, in [minX, minY, maxX, MaxY] order. * @returns {FeatureCollection} a set of polygons, one per input point. * @example * var options = { * bbox: [-70, 40, -60, 60] * }; * var points = turf.randomPoint(100, options); * var voronoiPolygons = turf.voronoi(points, options); * * //addToMap * var addToMap = [voronoiPolygons, points]; */ function voronoi (points, options) { // Optional params options = options || {} if (!isObject(options)) throw new Error("options is invalid") var bbox = options.bbox || [-180, -85, 180, 85] // Input Validation if (!points) throw new Error("points is required") if (!Array.isArray(bbox)) throw new Error("bbox is invalid") collectionOf(points, "Point", "points") // Main return featureCollection( voronoi$1() .x(function (feature) { return feature.geometry.coordinates[0] }) .y(function (feature) { return feature.geometry.coordinates[1] }) .extent([ [bbox[0], bbox[1]], [bbox[2], bbox[3]], ]) .polygons(points.features) .map(coordsToPolygon) ) } /** * splaytree v3.1.2 * Fast Splay tree for Node and browser * * @author Alexander Milevski * @license MIT * @preserve */ /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ function __generator (thisArg, body) { var _ = { label: 0, sent: function () { if (t[0] & 1) throw t[1]; return t[1] }, trys: [], ops: [] }, f, y, t, g return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function () { return this }), g function verb (n) { return function (v) { return step([n, v]) } } function step (op) { if (f) throw new TypeError("Generator is already executing.") while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t if (y = 0, t) op = [op[0] & 2, t.value] switch (op[0]) { case 0: case 1: t = op; break case 4: _.label++; return { value: op[1], done: false } case 5: _.label++; y = op[1]; op = [0]; continue case 7: op = _.ops.pop(); _.trys.pop(); continue default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break } if (t[2]) _.ops.pop() _.trys.pop(); continue } op = body.call(thisArg, _) } catch (e) { op = [6, e]; y = 0 } finally { f = t = 0 } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true } } } var Node$1 = /** @class */ (function () { function Node (key, data) { this.next = null this.key = key this.data = data this.left = null this.right = null } return Node }()) /* follows "An implementation of top-down splaying" * by D. Sleator March 1992 */ function DEFAULT_COMPARE (a, b) { return a > b ? 1 : a < b ? -1 : 0 } /** * Simple top down splay, not requiring i to be in the tree t. */ function splay (i, t, comparator) { var N = new Node$1(null, null) var l = N var r = N while (true) { var cmp = comparator(i, t.key) //if (i < t.key) { if (cmp < 0) { if (t.left === null) break //if (i < t.left.key) { if (comparator(i, t.left.key) < 0) { var y = t.left /* rotate right */ t.left = y.right y.right = t t = y if (t.left === null) break } r.left = t /* link right */ r = t t = t.left //} else if (i > t.key) { } else if (cmp > 0) { if (t.right === null) break //if (i > t.right.key) { if (comparator(i, t.right.key) > 0) { var y = t.right /* rotate left */ t.right = y.left y.left = t t = y if (t.right === null) break } l.right = t /* link left */ l = t t = t.right } else break } /* assemble */ l.right = t.left r.left = t.right t.left = N.right t.right = N.left return t } function insert (i, data, t, comparator) { var node = new Node$1(i, data) if (t === null) { node.left = node.right = null return node } t = splay(i, t, comparator) var cmp = comparator(i, t.key) if (cmp < 0) { node.left = t.left node.right = t t.left = null } else if (cmp >= 0) { node.right = t.right node.left = t t.right = null } return node } function split (key, v, comparator) { var left = null var right = null if (v) { v = splay(key, v, comparator) var cmp = comparator(v.key, key) if (cmp === 0) { left = v.left right = v.right } else if (cmp < 0) { right = v.right v.right = null left = v } else { left = v.left v.left = null right = v } } return { left: left, right: right } } function merge$1 (left, right, comparator) { if (right === null) return left if (left === null) return right right = splay(left.key, right, comparator) right.left = left return right } /** * Prints level of the tree */ function printRow (root, prefix, isTail, out, printNode) { if (root) { out("" + prefix + (isTail ? '└── ' : '├── ') + printNode(root) + "\n") var indent = prefix + (isTail ? ' ' : '│ ') if (root.left) printRow(root.left, indent, false, out, printNode) if (root.right) printRow(root.right, indent, true, out, printNode) } } var Tree = /** @class */ (function () { function Tree (comparator) { if (comparator === void 0) { comparator = DEFAULT_COMPARE } this._root = null this._size = 0 this._comparator = comparator } /** * Inserts a key, allows duplicates */ Tree.prototype.insert = function (key, data) { this._size++ return this._root = insert(key, data, this._root, this._comparator) } /** * Adds a key, if it is not present in the tree */ Tree.prototype.add = function (key, data) { var node = new Node$1(key, data) if (this._root === null) { node.left = node.right = null this._size++ this._root = node } var comparator = this._comparator var t = splay(key, this._root, comparator) var cmp = comparator(key, t.key) if (cmp === 0) this._root = t else { if (cmp < 0) { node.left = t.left node.right = t t.left = null } else if (cmp > 0) { node.right = t.right node.left = t t.right = null } this._size++ this._root = node } return this._root } /** * @param {Key} key * @return {Node|null} */ Tree.prototype.remove = function (key) { this._root = this._remove(key, this._root, this._comparator) } /** * Deletes i from the tree if it's there */ Tree.prototype._remove = function (i, t, comparator) { var x if (t === null) return null t = splay(i, t, comparator) var cmp = comparator(i, t.key) if (cmp === 0) { /* found it */ if (t.left === null) { x = t.right } else { x = splay(i, t.left, comparator) x.right = t.right } this._size-- return x } return t /* It wasn't there */ } /** * Removes and returns the node with smallest key */ Tree.prototype.pop = function () { var node = this._root if (node) { while (node.left) node = node.left this._root = splay(node.key, this._root, this._comparator) this._root = this._remove(node.key, this._root, this._comparator) return { key: node.key, data: node.data } } return null } /** * Find without splaying */ Tree.prototype.findStatic = function (key) { var current = this._root var compare = this._comparator while (current) { var cmp = compare(key, current.key) if (cmp === 0) return current else if (cmp < 0) current = current.left else current = current.right } return null } Tree.prototype.find = function (key) { if (this._root) { this._root = splay(key, this._root, this._comparator) if (this._comparator(key, this._root.key) !== 0) return null } return this._root } Tree.prototype.contains = function (key) { var current = this._root var compare = this._comparator while (current) { var cmp = compare(key, current.key) if (cmp === 0) return true else if (cmp < 0) current = current.left else current = current.right } return false } Tree.prototype.forEach = function (visitor, ctx) { var current = this._root var Q = [] /* Initialize stack s */ var done = false while (!done) { if (current !== null) { Q.push(current) current = current.left } else { if (Q.length !== 0) { current = Q.pop() visitor.call(ctx, current) current = current.right } else done = true } } return this } /** * Walk key range from `low` to `high`. Stops if `fn` returns a value. */ Tree.prototype.range = function (low, high, fn, ctx) { var Q = [] var compare = this._comparator var node = this._root var cmp while (Q.length !== 0 || node) { if (node) { Q.push(node) node = node.left } else { node = Q.pop() cmp = compare(node.key, high) if (cmp > 0) { break } else if (compare(node.key, low) >= 0) { if (fn.call(ctx, node)) return this // stop if smth is returned } node = node.right } } return this } /** * Returns array of keys */ Tree.prototype.keys = function () { var keys = [] this.forEach(function (_a) { var key = _a.key return keys.push(key) }) return keys } /** * Returns array of all the data in the nodes */ Tree.prototype.values = function () { var values = [] this.forEach(function (_a) { var data = _a.data return values.push(data) }) return values } Tree.prototype.min = function () { if (this._root) return this.minNode(this._root).key return null } Tree.prototype.max = function () { if (this._root) return this.maxNode(this._root).key return null } Tree.prototype.minNode = function (t) { if (t === void 0) { t = this._root } if (t) while (t.left) t = t.left return t } Tree.prototype.maxNode = function (t) { if (t === void 0) { t = this._root } if (t) while (t.right) t = t.right return t } /** * Returns node at given index */ Tree.prototype.at = function (index) { var current = this._root var done = false var i = 0 var Q = [] while (!done) { if (current) { Q.push(current) current = current.left } else { if (Q.length > 0) { current = Q.pop() if (i === index) return current i++ current = current.right } else done = true } } return null } Tree.prototype.next = function (d) { var root = this._root var successor = null if (d.right) { successor = d.right while (successor.left) successor = successor.left return successor } var comparator = this._comparator while (root) { var cmp = comparator(d.key, root.key) if (cmp === 0) break else if (cmp < 0) { successor = root root = root.left } else root = root.right } return successor } Tree.prototype.prev = function (d) { var root = this._root var predecessor = null if (d.left !== null) { predecessor = d.left while (predecessor.right) predecessor = predecessor.right return predecessor } var comparator = this._comparator while (root) { var cmp = comparator(d.key, root.key) if (cmp === 0) break else if (cmp < 0) root = root.left else { predecessor = root root = root.right } } return predecessor } Tree.prototype.clear = function () { this._root = null this._size = 0 return this } Tree.prototype.toList = function () { return toList(this._root) } /** * Bulk-load items. Both array have to be same size */ Tree.prototype.load = function (keys, values, presort) { if (values === void 0) { values = [] } if (presort === void 0) { presort = false } var size = keys.length var comparator = this._comparator // sort if needed if (presort) sort(keys, values, 0, size - 1, comparator) if (this._root === null) { // empty tree this._root = loadRecursive(keys, values, 0, size) this._size = size } else { // that re-builds the whole tree from two in-order traversals var mergedList = mergeLists(this.toList(), createList(keys, values), comparator) size = this._size + size this._root = sortedListToBST({ head: mergedList }, 0, size) } return this } Tree.prototype.isEmpty = function () { return this._root === null } Object.defineProperty(Tree.prototype, "size", { get: function () { return this._size }, enumerable: true, configurable: true }) Object.defineProperty(Tree.prototype, "root", { get: function () { return this._root }, enumerable: true, configurable: true }) Tree.prototype.toString = function (printNode) { if (printNode === void 0) { printNode = function (n) { return String(n.key) } } var out = [] printRow(this._root, '', true, function (v) { return out.push(v) }, printNode) return out.join('') } Tree.prototype.update = function (key, newKey, newData) { var comparator = this._comparator var _a = split(key, this._root, comparator), left = _a.left, right = _a.right if (comparator(key, newKey) < 0) { right = insert(newKey, newData, right, comparator) } else { left = insert(newKey, newData, left, comparator) } this._root = merge$1(left, right, comparator) } Tree.prototype.split = function (key) { return split(key, this._root, this._comparator) } Tree.prototype[Symbol.iterator] = function () { var current, Q, done return __generator(this, function (_a) { switch (_a.label) { case 0: current = this._root Q = [] done = false _a.label = 1 case 1: if (!!done) return [3 /*break*/, 6] if (!(current !== null)) return [3 /*break*/, 2] Q.push(current) current = current.left return [3 /*break*/, 5] case 2: if (!(Q.length !== 0)) return [3 /*break*/, 4] current = Q.pop() return [4 /*yield*/, current] case 3: _a.sent() current = current.right return [3 /*break*/, 5] case 4: done = true _a.label = 5 case 5: return [3 /*break*/, 1] case 6: return [2 /*return*/] } }) } return Tree }()) function loadRecursive (keys, values, start, end) { var size = end - start if (size > 0) { var middle = start + Math.floor(size / 2) var key = keys[middle] var data = values[middle] var node = new Node$1(key, data) node.left = loadRecursive(keys, values, start, middle) node.right = loadRecursive(keys, values, middle + 1, end) return node } return null } function createList (keys, values) { var head = new Node$1(null, null) var p = head for (var i = 0; i < keys.length; i++) { p = p.next = new Node$1(keys[i], values[i]) } p.next = null return head.next } function toList (root) { var current = root var Q = [] var done = false var head = new Node$1(null, null) var p = head while (!done) { if (current) { Q.push(current) current = current.left } else { if (Q.length > 0) { current = p = p.next = Q.pop() current = current.right } else done = true } } p.next = null // that'll work even if the tree was empty return head.next } function sortedListToBST (list, start, end) { var size = end - start if (size > 0) { var middle = start + Math.floor(size / 2) var left = sortedListToBST(list, start, middle) var root = list.head root.left = left list.head = list.head.next root.right = sortedListToBST(list, middle + 1, end) return root } return null } function mergeLists (l1, l2, compare) { var head = new Node$1(null, null) // dummy var p = head var p1 = l1 var p2 = l2 while (p1 !== null && p2 !== null) { if (compare(p1.key, p2.key) < 0) { p.next = p1 p1 = p1.next } else { p.next = p2 p2 = p2.next } p = p.next } if (p1 !== null) { p.next = p1 } else if (p2 !== null) { p.next = p2 } return head.next } function sort (keys, values, left, right, compare) { if (left >= right) return var pivot = keys[(left + right) >> 1] var i = left - 1 var j = right + 1 while (true) { do i++ while (compare(keys[i], pivot) < 0) do j-- while (compare(keys[j], pivot) > 0) if (i >= j) break var tmp = keys[i] keys[i] = keys[j] keys[j] = tmp tmp = values[i] values[i] = values[j] values[j] = tmp } sort(keys, values, left, j, compare) sort(keys, values, j + 1, right, compare) } function _classCallCheck$1 (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function") } } function _defineProperties$1 (target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i] descriptor.enumerable = descriptor.enumerable || false descriptor.configurable = true if ("value" in descriptor) descriptor.writable = true Object.defineProperty(target, descriptor.key, descriptor) } } function _createClass$1 (Constructor, protoProps, staticProps) { if (protoProps) _defineProperties$1(Constructor.prototype, protoProps) if (staticProps) _defineProperties$1(Constructor, staticProps) return Constructor } /** * A bounding box has the format: * * { ll: { x: xmin, y: ymin }, ur: { x: xmax, y: ymax } } * */ var isInBbox = function isInBbox (bbox, point) { return bbox.ll.x <= point.x && point.x <= bbox.ur.x && bbox.ll.y <= point.y && point.y <= bbox.ur.y } /* Returns either null, or a bbox (aka an ordered pair of points) * If there is only one point of overlap, a bbox with identical points * will be returned */ var getBboxOverlap = function getBboxOverlap (b1, b2) { // check if the bboxes overlap at all if (b2.ur.x < b1.ll.x || b1.ur.x < b2.ll.x || b2.ur.y < b1.ll.y || b1.ur.y < b2.ll.y) return null // find the middle two X values var lowerX = b1.ll.x < b2.ll.x ? b2.ll.x : b1.ll.x var upperX = b1.ur.x < b2.ur.x ? b1.ur.x : b2.ur.x // find the middle two Y values var lowerY = b1.ll.y < b2.ll.y ? b2.ll.y : b1.ll.y var upperY = b1.ur.y < b2.ur.y ? b1.ur.y : b2.ur.y // put those middle values together to get the overlap return { ll: { x: lowerX, y: lowerY }, ur: { x: upperX, y: upperY } } } /* Javascript doesn't do integer math. Everything is * floating point with percision Number.EPSILON. * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON */ var epsilon$1 = Number.EPSILON // IE Polyfill if (epsilon$1 === undefined) epsilon$1 = Math.pow(2, -52) var EPSILON_SQ = epsilon$1 * epsilon$1 /* FLP comparator */ var cmp = function cmp (a, b) { // check if they're both 0 if (-epsilon$1 < a && a < epsilon$1) { if (-epsilon$1 < b && b < epsilon$1) { return 0 } } // check if they're flp equal var ab = a - b if (ab * ab < EPSILON_SQ * a * b) { return 0 } // normal comparison return a < b ? -1 : 1 } /** * This class rounds incoming values sufficiently so that * floating points problems are, for the most part, avoided. * * Incoming points are have their x & y values tested against * all previously seen x & y values. If either is 'too close' * to a previously seen value, it's value is 'snapped' to the * previously seen value. * * All points should be rounded by this class before being * stored in any data structures in the rest of this algorithm. */ var PtRounder = /*#__PURE__*/function () { function PtRounder () { _classCallCheck$1(this, PtRounder) this.reset() } _createClass$1(PtRounder, [{ key: "reset", value: function reset () { this.xRounder = new CoordRounder() this.yRounder = new CoordRounder() } }, { key: "round", value: function round (x, y) { return { x: this.xRounder.round(x), y: this.yRounder.round(y) } } }]) return PtRounder }() var CoordRounder = /*#__PURE__*/function () { function CoordRounder () { _classCallCheck$1(this, CoordRounder) this.tree = new Tree() // preseed with 0 so we don't end up with values < Number.EPSILON this.round(0) } // Note: this can rounds input values backwards or forwards. // You might ask, why not restrict this to just rounding // forwards? Wouldn't that allow left endpoints to always // remain left endpoints during splitting (never change to // right). No - it wouldn't, because we snap intersections // to endpoints (to establish independence from the segment // angle for t-intersections). _createClass$1(CoordRounder, [{ key: "round", value: function round (coord) { var node = this.tree.add(coord) var prevNode = this.tree.prev(node) if (prevNode !== null && cmp(node.key, prevNode.key) === 0) { this.tree.remove(coord) return prevNode.key } var nextNode = this.tree.next(node) if (nextNode !== null && cmp(node.key, nextNode.key) === 0) { this.tree.remove(coord) return nextNode.key } return coord } }]) return CoordRounder }() // singleton available by import var rounder = new PtRounder() /* Cross Product of two vectors with first point at origin */ var crossProduct = function crossProduct (a, b) { return a.x * b.y - a.y * b.x } /* Dot Product of two vectors with first point at origin */ var dotProduct = function dotProduct (a, b) { return a.x * b.x + a.y * b.y } /* Comparator for two vectors with same starting point */ var compareVectorAngles = function compareVectorAngles (basePt, endPt1, endPt2) { var v1 = { x: endPt1.x - basePt.x, y: endPt1.y - basePt.y } var v2 = { x: endPt2.x - basePt.x, y: endPt2.y - basePt.y } var kross = crossProduct(v1, v2) return cmp(kross, 0) } var length = function length (v) { return Math.sqrt(dotProduct(v, v)) } /* Get the sine of the angle from pShared -> pAngle to pShaed -> pBase */ var sineOfAngle = function sineOfAngle (pShared, pBase, pAngle) { var vBase = { x: pBase.x - pShared.x, y: pBase.y - pShared.y } var vAngle = { x: pAngle.x - pShared.x, y: pAngle.y - pShared.y } return crossProduct(vAngle, vBase) / length(vAngle) / length(vBase) } /* Get the cosine of the angle from pShared -> pAngle to pShaed -> pBase */ var cosineOfAngle = function cosineOfAngle (pShared, pBase, pAngle) { var vBase = { x: pBase.x - pShared.x, y: pBase.y - pShared.y } var vAngle = { x: pAngle.x - pShared.x, y: pAngle.y - pShared.y } return dotProduct(vAngle, vBase) / length(vAngle) / length(vBase) } /* Get the x coordinate where the given line (defined by a point and vector) * crosses the horizontal line with the given y coordiante. * In the case of parrallel lines (including overlapping ones) returns null. */ var horizontalIntersection = function horizontalIntersection (pt, v, y) { if (v.y === 0) return null return { x: pt.x + v.x / v.y * (y - pt.y), y: y } } /* Get the y coordinate where the given line (defined by a point and vector) * crosses the vertical line with the given x coordiante. * In the case of parrallel lines (including overlapping ones) returns null. */ var verticalIntersection = function verticalIntersection (pt, v, x) { if (v.x === 0) return null return { x: x, y: pt.y + v.y / v.x * (x - pt.x) } } /* Get the intersection of two lines, each defined by a base point and a vector. * In the case of parrallel lines (including overlapping ones) returns null. */ var intersection = function intersection (pt1, v1, pt2, v2) { // take some shortcuts for vertical and horizontal lines // this also ensures we don't calculate an intersection and then discover // it's actually outside the bounding box of the line if (v1.x === 0) return verticalIntersection(pt2, v2, pt1.x) if (v2.x === 0) return verticalIntersection(pt1, v1, pt2.x) if (v1.y === 0) return horizontalIntersection(pt2, v2, pt1.y) if (v2.y === 0) return horizontalIntersection(pt1, v1, pt2.y) // General case for non-overlapping segments. // This algorithm is based on Schneider and Eberly. // http://www.cimec.org.ar/~ncalvo/Schneider_Eberly.pdf - pg 244 var kross = crossProduct(v1, v2) if (kross == 0) return null var ve = { x: pt2.x - pt1.x, y: pt2.y - pt1.y } var d1 = crossProduct(ve, v1) / kross var d2 = crossProduct(ve, v2) / kross // take the average of the two calculations to minimize rounding error var x1 = pt1.x + d2 * v1.x, x2 = pt2.x + d1 * v2.x var y1 = pt1.y + d2 * v1.y, y2 = pt2.y + d1 * v2.y var x = (x1 + x2) / 2 var y = (y1 + y2) / 2 return { x: x, y: y } } var SweepEvent = /*#__PURE__*/function () { _createClass$1(SweepEvent, null, [{ key: "compare", // for ordering sweep events in the sweep event queue value: function compare (a, b) { // favor event with a point that the sweep line hits first var ptCmp = SweepEvent.comparePoints(a.point, b.point) if (ptCmp !== 0) return ptCmp // the points are the same, so link them if needed if (a.point !== b.point) a.link(b) // favor right events over left if (a.isLeft !== b.isLeft) return a.isLeft ? 1 : -1 // we have two matching left or right endpoints // ordering of this case is the same as for their segments return Segment.compare(a.segment, b.segment) } // for ordering points in sweep line order }, { key: "comparePoints", value: function comparePoints (aPt, bPt) { if (aPt.x < bPt.x) return -1 if (aPt.x > bPt.x) return 1 if (aPt.y < bPt.y) return -1 if (aPt.y > bPt.y) return 1 return 0 } // Warning: 'point' input will be modified and re-used (for performance) }]) function SweepEvent (point, isLeft) { _classCallCheck$1(this, SweepEvent) if (point.events === undefined) point.events = [this]; else point.events.push(this) this.point = point this.isLeft = isLeft // this.segment, this.otherSE set by factory } _createClass$1(SweepEvent, [{ key: "link", value: function link (other) { if (other.point === this.point) { throw new Error('Tried to link already linked events') } var otherEvents = other.point.events for (var i = 0, iMax = otherEvents.length; i < iMax; i++) { var evt = otherEvents[i] this.point.events.push(evt) evt.point = this.point } this.checkForConsuming() } /* Do a pass over our linked events and check to see if any pair * of segments match, and should be consumed. */ }, { key: "checkForConsuming", value: function checkForConsuming () { // FIXME: The loops in this method run O(n^2) => no good. // Maintain little ordered sweep event trees? // Can we maintaining an ordering that avoids the need // for the re-sorting with getLeftmostComparator in geom-out? // Compare each pair of events to see if other events also match var numEvents = this.point.events.length for (var i = 0; i < numEvents; i++) { var evt1 = this.point.events[i] if (evt1.segment.consumedBy !== undefined) continue for (var j = i + 1; j < numEvents; j++) { var evt2 = this.point.events[j] if (evt2.consumedBy !== undefined) continue if (evt1.otherSE.point.events !== evt2.otherSE.point.events) continue evt1.segment.consume(evt2.segment) } } } }, { key: "getAvailableLinkedEvents", value: function getAvailableLinkedEvents () { // point.events is always of length 2 or greater var events = [] for (var i = 0, iMax = this.point.events.length; i < iMax; i++) { var evt = this.point.events[i] if (evt !== this && !evt.segment.ringOut && evt.segment.isInResult()) { events.push(evt) } } return events } /** * Returns a comparator function for sorting linked events that will * favor the event that will give us the smallest left-side angle. * All ring construction starts as low as possible heading to the right, * so by always turning left as sharp as possible we'll get polygons * without uncessary loops & holes. * * The comparator function has a compute cache such that it avoids * re-computing already-computed values. */ }, { key: "getLeftmostComparator", value: function getLeftmostComparator (baseEvent) { var _this = this var cache = new Map() var fillCache = function fillCache (linkedEvent) { var nextEvent = linkedEvent.otherSE cache.set(linkedEvent, { sine: sineOfAngle(_this.point, baseEvent.point, nextEvent.point), cosine: cosineOfAngle(_this.point, baseEvent.point, nextEvent.point) }) } return function (a, b) { if (!cache.has(a)) fillCache(a) if (!cache.has(b)) fillCache(b) var _cache$get = cache.get(a), asine = _cache$get.sine, acosine = _cache$get.cosine var _cache$get2 = cache.get(b), bsine = _cache$get2.sine, bcosine = _cache$get2.cosine // both on or above x-axis if (asine >= 0 && bsine >= 0) { if (acosine < bcosine) return 1 if (acosine > bcosine) return -1 return 0 } // both below x-axis if (asine < 0 && bsine < 0) { if (acosine < bcosine) return -1 if (acosine > bcosine) return 1 return 0 } // one above x-axis, one below if (bsine < asine) return -1 if (bsine > asine) return 1 return 0 } } }]) return SweepEvent }() // segments and sweep events when all else is identical var segmentId = 0 var Segment = /*#__PURE__*/function () { _createClass$1(Segment, null, [{ key: "compare", /* This compare() function is for ordering segments in the sweep * line tree, and does so according to the following criteria: * * Consider the vertical line that lies an infinestimal step to the * right of the right-more of the two left endpoints of the input * segments. Imagine slowly moving a point up from negative infinity * in the increasing y direction. Which of the two segments will that * point intersect first? That segment comes 'before' the other one. * * If neither segment would be intersected by such a line, (if one * or more of the segments are vertical) then the line to be considered * is directly on the right-more of the two left inputs. */ value: function compare (a, b) { var alx = a.leftSE.point.x var blx = b.leftSE.point.x var arx = a.rightSE.point.x var brx = b.rightSE.point.x // check if they're even in the same vertical plane if (brx < alx) return 1 if (arx < blx) return -1 var aly = a.leftSE.point.y var bly = b.leftSE.point.y var ary = a.rightSE.point.y var bry = b.rightSE.point.y // is left endpoint of segment B the right-more? if (alx < blx) { // are the two segments in the same horizontal plane? if (bly < aly && bly < ary) return 1 if (bly > aly && bly > ary) return -1 // is the B left endpoint colinear to segment A? var aCmpBLeft = a.comparePoint(b.leftSE.point) if (aCmpBLeft < 0) return 1 if (aCmpBLeft > 0) return -1 // is the A right endpoint colinear to segment B ? var bCmpARight = b.comparePoint(a.rightSE.point) if (bCmpARight !== 0) return bCmpARight // colinear segments, consider the one with left-more // left endpoint to be first (arbitrary?) return -1 } // is left endpoint of segment A the right-more? if (alx > blx) { if (aly < bly && aly < bry) return -1 if (aly > bly && aly > bry) return 1 // is the A left endpoint colinear to segment B? var bCmpALeft = b.comparePoint(a.leftSE.point) if (bCmpALeft !== 0) return bCmpALeft // is the B right endpoint colinear to segment A? var aCmpBRight = a.comparePoint(b.rightSE.point) if (aCmpBRight < 0) return 1 if (aCmpBRight > 0) return -1 // colinear segments, consider the one with left-more // left endpoint to be first (arbitrary?) return 1 } // if we get here, the two left endpoints are in the same // vertical plane, ie alx === blx // consider the lower left-endpoint to come first if (aly < bly) return -1 if (aly > bly) return 1 // left endpoints are identical // check for colinearity by using the left-more right endpoint // is the A right endpoint more left-more? if (arx < brx) { var _bCmpARight = b.comparePoint(a.rightSE.point) if (_bCmpARight !== 0) return _bCmpARight } // is the B right endpoint more left-more? if (arx > brx) { var _aCmpBRight = a.comparePoint(b.rightSE.point) if (_aCmpBRight < 0) return 1 if (_aCmpBRight > 0) return -1 } if (arx !== brx) { // are these two [almost] vertical segments with opposite orientation? // if so, the one with the lower right endpoint comes first var ay = ary - aly var ax = arx - alx var by = bry - bly var bx = brx - blx if (ay > ax && by < bx) return 1 if (ay < ax && by > bx) return -1 } // we have colinear segments with matching orientation // consider the one with more left-more right endpoint to be first if (arx > brx) return 1 if (arx < brx) return -1 // if we get here, two two right endpoints are in the same // vertical plane, ie arx === brx // consider the lower right-endpoint to come first if (ary < bry) return -1 if (ary > bry) return 1 // right endpoints identical as well, so the segments are idential // fall back on creation order as consistent tie-breaker if (a.id < b.id) return -1 if (a.id > b.id) return 1 // identical segment, ie a === b return 0 } /* Warning: a reference to ringWindings input will be stored, * and possibly will be later modified */ }]) function Segment (leftSE, rightSE, rings, windings) { _classCallCheck$1(this, Segment) this.id = ++segmentId this.leftSE = leftSE leftSE.segment = this leftSE.otherSE = rightSE this.rightSE = rightSE rightSE.segment = this rightSE.otherSE = leftSE this.rings = rings this.windings = windings // left unset for performance, set later in algorithm // this.ringOut, this.consumedBy, this.prev } _createClass$1(Segment, [{ key: "replaceRightSE", /* When a segment is split, the rightSE is replaced with a new sweep event */ value: function replaceRightSE (newRightSE) { this.rightSE = newRightSE this.rightSE.segment = this this.rightSE.otherSE = this.leftSE this.leftSE.otherSE = this.rightSE } }, { key: "bbox", value: function bbox () { var y1 = this.leftSE.point.y var y2 = this.rightSE.point.y return { ll: { x: this.leftSE.point.x, y: y1 < y2 ? y1 : y2 }, ur: { x: this.rightSE.point.x, y: y1 > y2 ? y1 : y2 } } } /* A vector from the left point to the right */ }, { key: "vector", value: function vector () { return { x: this.rightSE.point.x - this.leftSE.point.x, y: this.rightSE.point.y - this.leftSE.point.y } } }, { key: "isAnEndpoint", value: function isAnEndpoint (pt) { return pt.x === this.leftSE.point.x && pt.y === this.leftSE.point.y || pt.x === this.rightSE.point.x && pt.y === this.rightSE.point.y } /* Compare this segment with a point. * * A point P is considered to be colinear to a segment if there * exists a distance D such that if we travel along the segment * from one * endpoint towards the other a distance D, we find * ourselves at point P. * * Return value indicates: * * 1: point lies above the segment (to the left of vertical) * 0: point is colinear to segment * -1: point lies below the segment (to the right of vertical) */ }, { key: "comparePoint", value: function comparePoint (point) { if (this.isAnEndpoint(point)) return 0 var lPt = this.leftSE.point var rPt = this.rightSE.point var v = this.vector() // Exactly vertical segments. if (lPt.x === rPt.x) { if (point.x === lPt.x) return 0 return point.x < lPt.x ? 1 : -1 } // Nearly vertical segments with an intersection. // Check to see where a point on the line with matching Y coordinate is. var yDist = (point.y - lPt.y) / v.y var xFromYDist = lPt.x + yDist * v.x if (point.x === xFromYDist) return 0 // General case. // Check to see where a point on the line with matching X coordinate is. var xDist = (point.x - lPt.x) / v.x var yFromXDist = lPt.y + xDist * v.y if (point.y === yFromXDist) return 0 return point.y < yFromXDist ? -1 : 1 } /** * Given another segment, returns the first non-trivial intersection * between the two segments (in terms of sweep line ordering), if it exists. * * A 'non-trivial' intersection is one that will cause one or both of the * segments to be split(). As such, 'trivial' vs. 'non-trivial' intersection: * * * endpoint of segA with endpoint of segB --> trivial * * endpoint of segA with point along segB --> non-trivial * * endpoint of segB with point along segA --> non-trivial * * point along segA with point along segB --> non-trivial * * If no non-trivial intersection exists, return null * Else, return null. */ }, { key: "getIntersection", value: function getIntersection (other) { // If bboxes don't overlap, there can't be any intersections var tBbox = this.bbox() var oBbox = other.bbox() var bboxOverlap = getBboxOverlap(tBbox, oBbox) if (bboxOverlap === null) return null // We first check to see if the endpoints can be considered intersections. // This will 'snap' intersections to endpoints if possible, and will // handle cases of colinearity. var tlp = this.leftSE.point var trp = this.rightSE.point var olp = other.leftSE.point var orp = other.rightSE.point // does each endpoint touch the other segment? // note that we restrict the 'touching' definition to only allow segments // to touch endpoints that lie forward from where we are in the sweep line pass var touchesOtherLSE = isInBbox(tBbox, olp) && this.comparePoint(olp) === 0 var touchesThisLSE = isInBbox(oBbox, tlp) && other.comparePoint(tlp) === 0 var touchesOtherRSE = isInBbox(tBbox, orp) && this.comparePoint(orp) === 0 var touchesThisRSE = isInBbox(oBbox, trp) && other.comparePoint(trp) === 0 // do left endpoints match? if (touchesThisLSE && touchesOtherLSE) { // these two cases are for colinear segments with matching left // endpoints, and one segment being longer than the other if (touchesThisRSE && !touchesOtherRSE) return trp if (!touchesThisRSE && touchesOtherRSE) return orp // either the two segments match exactly (two trival intersections) // or just on their left endpoint (one trivial intersection return null } // does this left endpoint matches (other doesn't) if (touchesThisLSE) { // check for segments that just intersect on opposing endpoints if (touchesOtherRSE) { if (tlp.x === orp.x && tlp.y === orp.y) return null } // t-intersection on left endpoint return tlp } // does other left endpoint matches (this doesn't) if (touchesOtherLSE) { // check for segments that just intersect on opposing endpoints if (touchesThisRSE) { if (trp.x === olp.x && trp.y === olp.y) return null } // t-intersection on left endpoint return olp } // trivial intersection on right endpoints if (touchesThisRSE && touchesOtherRSE) return null // t-intersections on just one right endpoint if (touchesThisRSE) return trp if (touchesOtherRSE) return orp // None of our endpoints intersect. Look for a general intersection between // infinite lines laid over the segments var pt = intersection(tlp, this.vector(), olp, other.vector()) // are the segments parrallel? Note that if they were colinear with overlap, // they would have an endpoint intersection and that case was already handled above if (pt === null) return null // is the intersection found between the lines not on the segments? if (!isInBbox(bboxOverlap, pt)) return null // round the the computed point if needed return rounder.round(pt.x, pt.y) } /** * Split the given segment into multiple segments on the given points. * * Each existing segment will retain its leftSE and a new rightSE will be * generated for it. * * A new segment will be generated which will adopt the original segment's * rightSE, and a new leftSE will be generated for it. * * If there are more than two points given to split on, new segments * in the middle will be generated with new leftSE and rightSE's. * * An array of the newly generated SweepEvents will be returned. * * Warning: input array of points is modified */ }, { key: "split", value: function split (point) { var newEvents = [] var alreadyLinked = point.events !== undefined var newLeftSE = new SweepEvent(point, true) var newRightSE = new SweepEvent(point, false) var oldRightSE = this.rightSE this.replaceRightSE(newRightSE) newEvents.push(newRightSE) newEvents.push(newLeftSE) var newSeg = new Segment(newLeftSE, oldRightSE, this.rings.slice(), this.windings.slice()) // when splitting a nearly vertical downward-facing segment, // sometimes one of the resulting new segments is vertical, in which // case its left and right events may need to be swapped if (SweepEvent.comparePoints(newSeg.leftSE.point, newSeg.rightSE.point) > 0) { newSeg.swapEvents() } if (SweepEvent.comparePoints(this.leftSE.point, this.rightSE.point) > 0) { this.swapEvents() } // in the point we just used to create new sweep events with was already // linked to other events, we need to check if either of the affected // segments should be consumed if (alreadyLinked) { newLeftSE.checkForConsuming() newRightSE.checkForConsuming() } return newEvents } /* Swap which event is left and right */ }, { key: "swapEvents", value: function swapEvents () { var tmpEvt = this.rightSE this.rightSE = this.leftSE this.leftSE = tmpEvt this.leftSE.isLeft = true this.rightSE.isLeft = false for (var i = 0, iMax = this.windings.length; i < iMax; i++) { this.windings[i] *= -1 } } /* Consume another segment. We take their rings under our wing * and mark them as consumed. Use for perfectly overlapping segments */ }, { key: "consume", value: function consume (other) { var consumer = this var consumee = other while (consumer.consumedBy) { consumer = consumer.consumedBy } while (consumee.consumedBy) { consumee = consumee.consumedBy } var cmp = Segment.compare(consumer, consumee) if (cmp === 0) return // already consumed // the winner of the consumption is the earlier segment // according to sweep line ordering if (cmp > 0) { var tmp = consumer consumer = consumee consumee = tmp } // make sure a segment doesn't consume it's prev if (consumer.prev === consumee) { var _tmp = consumer consumer = consumee consumee = _tmp } for (var i = 0, iMax = consumee.rings.length; i < iMax; i++) { var ring = consumee.rings[i] var winding = consumee.windings[i] var index = consumer.rings.indexOf(ring) if (index === -1) { consumer.rings.push(ring) consumer.windings.push(winding) } else consumer.windings[index] += winding } consumee.rings = null consumee.windings = null consumee.consumedBy = consumer // mark sweep events consumed as to maintain ordering in sweep event queue consumee.leftSE.consumedBy = consumer.leftSE consumee.rightSE.consumedBy = consumer.rightSE } /* The first segment previous segment chain that is in the result */ }, { key: "prevInResult", value: function prevInResult () { if (this._prevInResult !== undefined) return this._prevInResult if (!this.prev) this._prevInResult = null; else if (this.prev.isInResult()) this._prevInResult = this.prev; else this._prevInResult = this.prev.prevInResult() return this._prevInResult } }, { key: "beforeState", value: function beforeState () { if (this._beforeState !== undefined) return this._beforeState if (!this.prev) this._beforeState = { rings: [], windings: [], multiPolys: [] }; else { var seg = this.prev.consumedBy || this.prev this._beforeState = seg.afterState() } return this._beforeState } }, { key: "afterState", value: function afterState () { if (this._afterState !== undefined) return this._afterState var beforeState = this.beforeState() this._afterState = { rings: beforeState.rings.slice(0), windings: beforeState.windings.slice(0), multiPolys: [] } var ringsAfter = this._afterState.rings var windingsAfter = this._afterState.windings var mpsAfter = this._afterState.multiPolys // calculate ringsAfter, windingsAfter for (var i = 0, iMax = this.rings.length; i < iMax; i++) { var ring = this.rings[i] var winding = this.windings[i] var index = ringsAfter.indexOf(ring) if (index === -1) { ringsAfter.push(ring) windingsAfter.push(winding) } else windingsAfter[index] += winding } // calcualte polysAfter var polysAfter = [] var polysExclude = [] for (var _i = 0, _iMax = ringsAfter.length; _i < _iMax; _i++) { if (windingsAfter[_i] === 0) continue // non-zero rule var _ring = ringsAfter[_i] var poly = _ring.poly if (polysExclude.indexOf(poly) !== -1) continue if (_ring.isExterior) polysAfter.push(poly); else { if (polysExclude.indexOf(poly) === -1) polysExclude.push(poly) var _index = polysAfter.indexOf(_ring.poly) if (_index !== -1) polysAfter.splice(_index, 1) } } // calculate multiPolysAfter for (var _i2 = 0, _iMax2 = polysAfter.length; _i2 < _iMax2; _i2++) { var mp = polysAfter[_i2].multiPoly if (mpsAfter.indexOf(mp) === -1) mpsAfter.push(mp) } return this._afterState } /* Is this segment part of the final result? */ }, { key: "isInResult", value: function isInResult () { // if we've been consumed, we're not in the result if (this.consumedBy) return false if (this._isInResult !== undefined) return this._isInResult var mpsBefore = this.beforeState().multiPolys var mpsAfter = this.afterState().multiPolys switch (operation.type) { case 'union': { // UNION - included iff: // * On one side of us there is 0 poly interiors AND // * On the other side there is 1 or more. var noBefores = mpsBefore.length === 0 var noAfters = mpsAfter.length === 0 this._isInResult = noBefores !== noAfters break } case 'intersection': { // INTERSECTION - included iff: // * on one side of us all multipolys are rep. with poly interiors AND // * on the other side of us, not all multipolys are repsented // with poly interiors var least var most if (mpsBefore.length < mpsAfter.length) { least = mpsBefore.length most = mpsAfter.length } else { least = mpsAfter.length most = mpsBefore.length } this._isInResult = most === operation.numMultiPolys && least < most break } case 'xor': { // XOR - included iff: // * the difference between the number of multipolys represented // with poly interiors on our two sides is an odd number var diff = Math.abs(mpsBefore.length - mpsAfter.length) this._isInResult = diff % 2 === 1 break } case 'difference': { // DIFFERENCE included iff: // * on exactly one side, we have just the subject var isJustSubject = function isJustSubject (mps) { return mps.length === 1 && mps[0].isSubject } this._isInResult = isJustSubject(mpsBefore) !== isJustSubject(mpsAfter) break } default: throw new Error("Unrecognized operation type found ".concat(operation.type)) } return this._isInResult } }], [{ key: "fromRing", value: function fromRing (pt1, pt2, ring) { var leftPt, rightPt, winding // ordering the two points according to sweep line ordering var cmpPts = SweepEvent.comparePoints(pt1, pt2) if (cmpPts < 0) { leftPt = pt1 rightPt = pt2 winding = 1 } else if (cmpPts > 0) { leftPt = pt2 rightPt = pt1 winding = -1 } else throw new Error("Tried to create degenerate segment at [".concat(pt1.x, ", ").concat(pt1.y, "]")) var leftSE = new SweepEvent(leftPt, true) var rightSE = new SweepEvent(rightPt, false) return new Segment(leftSE, rightSE, [ring], [winding]) } }]) return Segment }() var RingIn = /*#__PURE__*/function () { function RingIn (geomRing, poly, isExterior) { _classCallCheck$1(this, RingIn) if (!Array.isArray(geomRing) || geomRing.length === 0) { throw new Error('Input geometry is not a valid Polygon or MultiPolygon') } this.poly = poly this.isExterior = isExterior this.segments = [] if (typeof geomRing[0][0] !== 'number' || typeof geomRing[0][1] !== 'number') { throw new Error('Input geometry is not a valid Polygon or MultiPolygon') } var firstPoint = rounder.round(geomRing[0][0], geomRing[0][1]) this.bbox = { ll: { x: firstPoint.x, y: firstPoint.y }, ur: { x: firstPoint.x, y: firstPoint.y } } var prevPoint = firstPoint for (var i = 1, iMax = geomRing.length; i < iMax; i++) { if (typeof geomRing[i][0] !== 'number' || typeof geomRing[i][1] !== 'number') { throw new Error('Input geometry is not a valid Polygon or MultiPolygon') } var point = rounder.round(geomRing[i][0], geomRing[i][1]) // skip repeated points if (point.x === prevPoint.x && point.y === prevPoint.y) continue this.segments.push(Segment.fromRing(prevPoint, point, this)) if (point.x < this.bbox.ll.x) this.bbox.ll.x = point.x if (point.y < this.bbox.ll.y) this.bbox.ll.y = point.y if (point.x > this.bbox.ur.x) this.bbox.ur.x = point.x if (point.y > this.bbox.ur.y) this.bbox.ur.y = point.y prevPoint = point } // add segment from last to first if last is not the same as first if (firstPoint.x !== prevPoint.x || firstPoint.y !== prevPoint.y) { this.segments.push(Segment.fromRing(prevPoint, firstPoint, this)) } } _createClass$1(RingIn, [{ key: "getSweepEvents", value: function getSweepEvents () { var sweepEvents = [] for (var i = 0, iMax = this.segments.length; i < iMax; i++) { var segment = this.segments[i] sweepEvents.push(segment.leftSE) sweepEvents.push(segment.rightSE) } return sweepEvents } }]) return RingIn }() var PolyIn = /*#__PURE__*/function () { function PolyIn (geomPoly, multiPoly) { _classCallCheck$1(this, PolyIn) if (!Array.isArray(geomPoly)) { throw new Error('Input geometry is not a valid Polygon or MultiPolygon') } this.exteriorRing = new RingIn(geomPoly[0], this, true) // copy by value this.bbox = { ll: { x: this.exteriorRing.bbox.ll.x, y: this.exteriorRing.bbox.ll.y }, ur: { x: this.exteriorRing.bbox.ur.x, y: this.exteriorRing.bbox.ur.y } } this.interiorRings = [] for (var i = 1, iMax = geomPoly.length; i < iMax; i++) { var ring = new RingIn(geomPoly[i], this, false) if (ring.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = ring.bbox.ll.x if (ring.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = ring.bbox.ll.y if (ring.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = ring.bbox.ur.x if (ring.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = ring.bbox.ur.y this.interiorRings.push(ring) } this.multiPoly = multiPoly } _createClass$1(PolyIn, [{ key: "getSweepEvents", value: function getSweepEvents () { var sweepEvents = this.exteriorRing.getSweepEvents() for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) { var ringSweepEvents = this.interiorRings[i].getSweepEvents() for (var j = 0, jMax = ringSweepEvents.length; j < jMax; j++) { sweepEvents.push(ringSweepEvents[j]) } } return sweepEvents } }]) return PolyIn }() var MultiPolyIn = /*#__PURE__*/function () { function MultiPolyIn (geom, isSubject) { _classCallCheck$1(this, MultiPolyIn) if (!Array.isArray(geom)) { throw new Error('Input geometry is not a valid Polygon or MultiPolygon') } try { // if the input looks like a polygon, convert it to a multipolygon if (typeof geom[0][0][0] === 'number') geom = [geom] } catch (ex) {// The input is either malformed or has empty arrays. // In either case, it will be handled later on. } this.polys = [] this.bbox = { ll: { x: Number.POSITIVE_INFINITY, y: Number.POSITIVE_INFINITY }, ur: { x: Number.NEGATIVE_INFINITY, y: Number.NEGATIVE_INFINITY } } for (var i = 0, iMax = geom.length; i < iMax; i++) { var poly = new PolyIn(geom[i], this) if (poly.bbox.ll.x < this.bbox.ll.x) this.bbox.ll.x = poly.bbox.ll.x if (poly.bbox.ll.y < this.bbox.ll.y) this.bbox.ll.y = poly.bbox.ll.y if (poly.bbox.ur.x > this.bbox.ur.x) this.bbox.ur.x = poly.bbox.ur.x if (poly.bbox.ur.y > this.bbox.ur.y) this.bbox.ur.y = poly.bbox.ur.y this.polys.push(poly) } this.isSubject = isSubject } _createClass$1(MultiPolyIn, [{ key: "getSweepEvents", value: function getSweepEvents () { var sweepEvents = [] for (var i = 0, iMax = this.polys.length; i < iMax; i++) { var polySweepEvents = this.polys[i].getSweepEvents() for (var j = 0, jMax = polySweepEvents.length; j < jMax; j++) { sweepEvents.push(polySweepEvents[j]) } } return sweepEvents } }]) return MultiPolyIn }() var RingOut = /*#__PURE__*/function () { _createClass$1(RingOut, null, [{ key: "factory", /* Given the segments from the sweep line pass, compute & return a series * of closed rings from all the segments marked to be part of the result */ value: function factory (allSegments) { var ringsOut = [] for (var i = 0, iMax = allSegments.length; i < iMax; i++) { var segment = allSegments[i] if (!segment.isInResult() || segment.ringOut) continue var prevEvent = null var event = segment.leftSE var nextEvent = segment.rightSE var events = [event] var startingPoint = event.point var intersectionLEs = [] /* Walk the chain of linked events to form a closed ring */ while (true) { prevEvent = event event = nextEvent events.push(event) /* Is the ring complete? */ if (event.point === startingPoint) break while (true) { var availableLEs = event.getAvailableLinkedEvents() /* Did we hit a dead end? This shouldn't happen. Indicates some earlier * part of the algorithm malfunctioned... please file a bug report. */ if (availableLEs.length === 0) { var firstPt = events[0].point var lastPt = events[events.length - 1].point throw new Error("Unable to complete output ring starting at [".concat(firstPt.x, ",") + " ".concat(firstPt.y, "]. Last matching segment found ends at") + " [".concat(lastPt.x, ", ").concat(lastPt.y, "].")) } /* Only one way to go, so cotinue on the path */ if (availableLEs.length === 1) { nextEvent = availableLEs[0].otherSE break } /* We must have an intersection. Check for a completed loop */ var indexLE = null for (var j = 0, jMax = intersectionLEs.length; j < jMax; j++) { if (intersectionLEs[j].point === event.point) { indexLE = j break } } /* Found a completed loop. Cut that off and make a ring */ if (indexLE !== null) { var intersectionLE = intersectionLEs.splice(indexLE)[0] var ringEvents = events.splice(intersectionLE.index) ringEvents.unshift(ringEvents[0].otherSE) ringsOut.push(new RingOut(ringEvents.reverse())) continue } /* register the intersection */ intersectionLEs.push({ index: events.length, point: event.point }) /* Choose the left-most option to continue the walk */ var comparator = event.getLeftmostComparator(prevEvent) nextEvent = availableLEs.sort(comparator)[0].otherSE break } } ringsOut.push(new RingOut(events)) } return ringsOut } }]) function RingOut (events) { _classCallCheck$1(this, RingOut) this.events = events for (var i = 0, iMax = events.length; i < iMax; i++) { events[i].segment.ringOut = this } this.poly = null } _createClass$1(RingOut, [{ key: "getGeom", value: function getGeom () { // Remove superfluous points (ie extra points along a straight line), var prevPt = this.events[0].point var points = [prevPt] for (var i = 1, iMax = this.events.length - 1; i < iMax; i++) { var _pt = this.events[i].point var _nextPt = this.events[i + 1].point if (compareVectorAngles(_pt, prevPt, _nextPt) === 0) continue points.push(_pt) prevPt = _pt } // ring was all (within rounding error of angle calc) colinear points if (points.length === 1) return null // check if the starting point is necessary var pt = points[0] var nextPt = points[1] if (compareVectorAngles(pt, prevPt, nextPt) === 0) points.shift() points.push(points[0]) var step = this.isExteriorRing() ? 1 : -1 var iStart = this.isExteriorRing() ? 0 : points.length - 1 var iEnd = this.isExteriorRing() ? points.length : -1 var orderedPoints = [] for (var _i = iStart; _i != iEnd; _i += step) { orderedPoints.push([points[_i].x, points[_i].y]) } return orderedPoints } }, { key: "isExteriorRing", value: function isExteriorRing () { if (this._isExteriorRing === undefined) { var enclosing = this.enclosingRing() this._isExteriorRing = enclosing ? !enclosing.isExteriorRing() : true } return this._isExteriorRing } }, { key: "enclosingRing", value: function enclosingRing () { if (this._enclosingRing === undefined) { this._enclosingRing = this._calcEnclosingRing() } return this._enclosingRing } /* Returns the ring that encloses this one, if any */ }, { key: "_calcEnclosingRing", value: function _calcEnclosingRing () { // start with the ealier sweep line event so that the prevSeg // chain doesn't lead us inside of a loop of ours var leftMostEvt = this.events[0] for (var i = 1, iMax = this.events.length; i < iMax; i++) { var evt = this.events[i] if (SweepEvent.compare(leftMostEvt, evt) > 0) leftMostEvt = evt } var prevSeg = leftMostEvt.segment.prevInResult() var prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null while (true) { // no segment found, thus no ring can enclose us if (!prevSeg) return null // no segments below prev segment found, thus the ring of the prev // segment must loop back around and enclose us if (!prevPrevSeg) return prevSeg.ringOut // if the two segments are of different rings, the ring of the prev // segment must either loop around us or the ring of the prev prev // seg, which would make us and the ring of the prev peers if (prevPrevSeg.ringOut !== prevSeg.ringOut) { if (prevPrevSeg.ringOut.enclosingRing() !== prevSeg.ringOut) { return prevSeg.ringOut } else return prevSeg.ringOut.enclosingRing() } // two segments are from the same ring, so this was a penisula // of that ring. iterate downward, keep searching prevSeg = prevPrevSeg.prevInResult() prevPrevSeg = prevSeg ? prevSeg.prevInResult() : null } } }]) return RingOut }() var PolyOut = /*#__PURE__*/function () { function PolyOut (exteriorRing) { _classCallCheck$1(this, PolyOut) this.exteriorRing = exteriorRing exteriorRing.poly = this this.interiorRings = [] } _createClass$1(PolyOut, [{ key: "addInterior", value: function addInterior (ring) { this.interiorRings.push(ring) ring.poly = this } }, { key: "getGeom", value: function getGeom () { var geom = [this.exteriorRing.getGeom()] // exterior ring was all (within rounding error of angle calc) colinear points if (geom[0] === null) return null for (var i = 0, iMax = this.interiorRings.length; i < iMax; i++) { var ringGeom = this.interiorRings[i].getGeom() // interior ring was all (within rounding error of angle calc) colinear points if (ringGeom === null) continue geom.push(ringGeom) } return geom } }]) return PolyOut }() var MultiPolyOut = /*#__PURE__*/function () { function MultiPolyOut (rings) { _classCallCheck$1(this, MultiPolyOut) this.rings = rings this.polys = this._composePolys(rings) } _createClass$1(MultiPolyOut, [{ key: "getGeom", value: function getGeom () { var geom = [] for (var i = 0, iMax = this.polys.length; i < iMax; i++) { var polyGeom = this.polys[i].getGeom() // exterior ring was all (within rounding error of angle calc) colinear points if (polyGeom === null) continue geom.push(polyGeom) } return geom } }, { key: "_composePolys", value: function _composePolys (rings) { var polys = [] for (var i = 0, iMax = rings.length; i < iMax; i++) { var ring = rings[i] if (ring.poly) continue if (ring.isExteriorRing()) polys.push(new PolyOut(ring)); else { var enclosingRing = ring.enclosingRing() if (!enclosingRing.poly) polys.push(new PolyOut(enclosingRing)) enclosingRing.poly.addInterior(ring) } } return polys } }]) return MultiPolyOut }() /** * NOTE: We must be careful not to change any segments while * they are in the SplayTree. AFAIK, there's no way to tell * the tree to rebalance itself - thus before splitting * a segment that's in the tree, we remove it from the tree, * do the split, then re-insert it. (Even though splitting a * segment *shouldn't* change its correct position in the * sweep line tree, the reality is because of rounding errors, * it sometimes does.) */ var SweepLine = /*#__PURE__*/function () { function SweepLine (queue) { var comparator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Segment.compare _classCallCheck$1(this, SweepLine) this.queue = queue this.tree = new Tree(comparator) this.segments = [] } _createClass$1(SweepLine, [{ key: "process", value: function process (event) { var segment = event.segment var newEvents = [] // if we've already been consumed by another segment, // clean up our body parts and get out if (event.consumedBy) { if (event.isLeft) this.queue.remove(event.otherSE); else this.tree.remove(segment) return newEvents } var node = event.isLeft ? this.tree.insert(segment) : this.tree.find(segment) if (!node) throw new Error("Unable to find segment #".concat(segment.id, " ") + "[".concat(segment.leftSE.point.x, ", ").concat(segment.leftSE.point.y, "] -> ") + "[".concat(segment.rightSE.point.x, ", ").concat(segment.rightSE.point.y, "] ") + 'in SweepLine tree. Please submit a bug report.') var prevNode = node var nextNode = node var prevSeg = undefined var nextSeg = undefined // skip consumed segments still in tree while (prevSeg === undefined) { prevNode = this.tree.prev(prevNode) if (prevNode === null) prevSeg = null; else if (prevNode.key.consumedBy === undefined) prevSeg = prevNode.key } // skip consumed segments still in tree while (nextSeg === undefined) { nextNode = this.tree.next(nextNode) if (nextNode === null) nextSeg = null; else if (nextNode.key.consumedBy === undefined) nextSeg = nextNode.key } if (event.isLeft) { // Check for intersections against the previous segment in the sweep line var prevMySplitter = null if (prevSeg) { var prevInter = prevSeg.getIntersection(segment) if (prevInter !== null) { if (!segment.isAnEndpoint(prevInter)) prevMySplitter = prevInter if (!prevSeg.isAnEndpoint(prevInter)) { var newEventsFromSplit = this._splitSafely(prevSeg, prevInter) for (var i = 0, iMax = newEventsFromSplit.length; i < iMax; i++) { newEvents.push(newEventsFromSplit[i]) } } } } // Check for intersections against the next segment in the sweep line var nextMySplitter = null if (nextSeg) { var nextInter = nextSeg.getIntersection(segment) if (nextInter !== null) { if (!segment.isAnEndpoint(nextInter)) nextMySplitter = nextInter if (!nextSeg.isAnEndpoint(nextInter)) { var _newEventsFromSplit = this._splitSafely(nextSeg, nextInter) for (var _i = 0, _iMax = _newEventsFromSplit.length; _i < _iMax; _i++) { newEvents.push(_newEventsFromSplit[_i]) } } } } // For simplicity, even if we find more than one intersection we only // spilt on the 'earliest' (sweep-line style) of the intersections. // The other intersection will be handled in a future process(). if (prevMySplitter !== null || nextMySplitter !== null) { var mySplitter = null if (prevMySplitter === null) mySplitter = nextMySplitter; else if (nextMySplitter === null) mySplitter = prevMySplitter; else { var cmpSplitters = SweepEvent.comparePoints(prevMySplitter, nextMySplitter) mySplitter = cmpSplitters <= 0 ? prevMySplitter : nextMySplitter } // Rounding errors can cause changes in ordering, // so remove afected segments and right sweep events before splitting this.queue.remove(segment.rightSE) newEvents.push(segment.rightSE) var _newEventsFromSplit2 = segment.split(mySplitter) for (var _i2 = 0, _iMax2 = _newEventsFromSplit2.length; _i2 < _iMax2; _i2++) { newEvents.push(_newEventsFromSplit2[_i2]) } } if (newEvents.length > 0) { // We found some intersections, so re-do the current event to // make sure sweep line ordering is totally consistent for later // use with the segment 'prev' pointers this.tree.remove(segment) newEvents.push(event) } else { // done with left event this.segments.push(segment) segment.prev = prevSeg } } else { // event.isRight // since we're about to be removed from the sweep line, check for // intersections between our previous and next segments if (prevSeg && nextSeg) { var inter = prevSeg.getIntersection(nextSeg) if (inter !== null) { if (!prevSeg.isAnEndpoint(inter)) { var _newEventsFromSplit3 = this._splitSafely(prevSeg, inter) for (var _i3 = 0, _iMax3 = _newEventsFromSplit3.length; _i3 < _iMax3; _i3++) { newEvents.push(_newEventsFromSplit3[_i3]) } } if (!nextSeg.isAnEndpoint(inter)) { var _newEventsFromSplit4 = this._splitSafely(nextSeg, inter) for (var _i4 = 0, _iMax4 = _newEventsFromSplit4.length; _i4 < _iMax4; _i4++) { newEvents.push(_newEventsFromSplit4[_i4]) } } } } this.tree.remove(segment) } return newEvents } /* Safely split a segment that is currently in the datastructures * IE - a segment other than the one that is currently being processed. */ }, { key: "_splitSafely", value: function _splitSafely (seg, pt) { // Rounding errors can cause changes in ordering, // so remove afected segments and right sweep events before splitting // removeNode() doesn't work, so have re-find the seg // https://github.com/w8r/splay-tree/pull/5 this.tree.remove(seg) var rightSE = seg.rightSE this.queue.remove(rightSE) var newEvents = seg.split(pt) newEvents.push(rightSE) // splitting can trigger consumption if (seg.consumedBy === undefined) this.tree.insert(seg) return newEvents } }]) return SweepLine }() var POLYGON_CLIPPING_MAX_QUEUE_SIZE = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_QUEUE_SIZE || 1000000 var POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS = typeof process !== 'undefined' && process.env.POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS || 1000000 var Operation = /*#__PURE__*/function () { function Operation () { _classCallCheck$1(this, Operation) } _createClass$1(Operation, [{ key: "run", value: function run (type, geom, moreGeoms) { operation.type = type rounder.reset() /* Convert inputs to MultiPoly objects */ var multipolys = [new MultiPolyIn(geom, true)] for (var i = 0, iMax = moreGeoms.length; i < iMax; i++) { multipolys.push(new MultiPolyIn(moreGeoms[i], false)) } operation.numMultiPolys = multipolys.length /* BBox optimization for difference operation * If the bbox of a multipolygon that's part of the clipping doesn't * intersect the bbox of the subject at all, we can just drop that * multiploygon. */ if (operation.type === 'difference') { // in place removal var subject = multipolys[0] var _i = 1 while (_i < multipolys.length) { if (getBboxOverlap(multipolys[_i].bbox, subject.bbox) !== null) _i++; else multipolys.splice(_i, 1) } } /* BBox optimization for intersection operation * If we can find any pair of multipolygons whose bbox does not overlap, * then the result will be empty. */ if (operation.type === 'intersection') { // TODO: this is O(n^2) in number of polygons. By sorting the bboxes, // it could be optimized to O(n * ln(n)) for (var _i2 = 0, _iMax = multipolys.length; _i2 < _iMax; _i2++) { var mpA = multipolys[_i2] for (var j = _i2 + 1, jMax = multipolys.length; j < jMax; j++) { if (getBboxOverlap(mpA.bbox, multipolys[j].bbox) === null) return [] } } } /* Put segment endpoints in a priority queue */ var queue = new Tree(SweepEvent.compare) for (var _i3 = 0, _iMax2 = multipolys.length; _i3 < _iMax2; _i3++) { var sweepEvents = multipolys[_i3].getSweepEvents() for (var _j = 0, _jMax = sweepEvents.length; _j < _jMax; _j++) { queue.insert(sweepEvents[_j]) if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) { // prevents an infinite loop, an otherwise common manifestation of bugs throw new Error('Infinite loop when putting segment endpoints in a priority queue ' + '(queue size too big). Please file a bug report.') } } } /* Pass the sweep line over those endpoints */ var sweepLine = new SweepLine(queue) var prevQueueSize = queue.size var node = queue.pop() while (node) { var evt = node.key if (queue.size === prevQueueSize) { // prevents an infinite loop, an otherwise common manifestation of bugs var seg = evt.segment throw new Error("Unable to pop() ".concat(evt.isLeft ? 'left' : 'right', " SweepEvent ") + "[".concat(evt.point.x, ", ").concat(evt.point.y, "] from segment #").concat(seg.id, " ") + "[".concat(seg.leftSE.point.x, ", ").concat(seg.leftSE.point.y, "] -> ") + "[".concat(seg.rightSE.point.x, ", ").concat(seg.rightSE.point.y, "] from queue. ") + 'Please file a bug report.') } if (queue.size > POLYGON_CLIPPING_MAX_QUEUE_SIZE) { // prevents an infinite loop, an otherwise common manifestation of bugs throw new Error('Infinite loop when passing sweep line over endpoints ' + '(queue size too big). Please file a bug report.') } if (sweepLine.segments.length > POLYGON_CLIPPING_MAX_SWEEPLINE_SEGMENTS) { // prevents an infinite loop, an otherwise common manifestation of bugs throw new Error('Infinite loop when passing sweep line over endpoints ' + '(too many sweep line segments). Please file a bug report.') } var newEvents = sweepLine.process(evt) for (var _i4 = 0, _iMax3 = newEvents.length; _i4 < _iMax3; _i4++) { var _evt = newEvents[_i4] if (_evt.consumedBy === undefined) queue.insert(_evt) } prevQueueSize = queue.size node = queue.pop() } // free some memory we don't need anymore rounder.reset() /* Collect and compile segments we're keeping into a multipolygon */ var ringsOut = RingOut.factory(sweepLine.segments) var result = new MultiPolyOut(ringsOut) return result.getGeom() } }]) return Operation }() // singleton available by import var operation = new Operation() var union$1 = function union (geom) { for (var _len = arguments.length, moreGeoms = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { moreGeoms[_key - 1] = arguments[_key] } return operation.run('union', geom, moreGeoms) } var intersection$1 = function intersection (geom) { for (var _len2 = arguments.length, moreGeoms = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { moreGeoms[_key2 - 1] = arguments[_key2] } return operation.run('intersection', geom, moreGeoms) } var xor = function xor (geom) { for (var _len3 = arguments.length, moreGeoms = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { moreGeoms[_key3 - 1] = arguments[_key3] } return operation.run('xor', geom, moreGeoms) } var difference = function difference (subjectGeom) { for (var _len4 = arguments.length, clippingGeoms = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { clippingGeoms[_key4 - 1] = arguments[_key4] } return operation.run('difference', subjectGeom, clippingGeoms) } var index = { union: union$1, intersection: intersection$1, xor: xor, difference: difference } var polygonClipping = index /* Polyfill service v3.13.0 * For detailed credits and licence information see http://github.com/financial-times/polyfill-service * * - Array.prototype.fill, License: CC0 */ if (!('fill' in Array.prototype)) { Object.defineProperty(Array.prototype, 'fill', { configurable: true, value: function fill (value) { if (this === undefined || this === null) { throw new TypeError(this + ' is not an object') } var arrayLike = Object(this) var length = Math.max(Math.min(arrayLike.length, 9007199254740991), 0) || 0 var relativeStart = 1 in arguments ? parseInt(Number(arguments[1]), 10) || 0 : 0 relativeStart = relativeStart < 0 ? Math.max(length + relativeStart, 0) : Math.min(relativeStart, length) var relativeEnd = 2 in arguments && arguments[2] !== undefined ? parseInt(Number(arguments[2]), 10) || 0 : length relativeEnd = relativeEnd < 0 ? Math.max(length + arguments[2], 0) : Math.min(relativeEnd, length) while (relativeStart < relativeEnd) { arrayLike[relativeStart] = value ++relativeStart } return arrayLike }, writable: true }) } /** * Polyfill for IE support */ Number.isFinite = Number.isFinite || function (value) { return typeof value === 'number' && isFinite(value) } Number.isInteger = Number.isInteger || function (val) { return typeof val === 'number' && isFinite(val) && Math.floor(val) === val } Number.parseFloat = Number.parseFloat || parseFloat Number.isNaN = Number.isNaN || function (value) { return value !== value // eslint-disable-line } /** * Polyfill for IE support */ Math.trunc = Math.trunc || function (x) { return x < 0 ? Math.ceil(x) : Math.floor(x) } var NumberUtil = function NumberUtil () { } NumberUtil.prototype.interfaces_ = function interfaces_ () { return [] } NumberUtil.prototype.getClass = function getClass () { return NumberUtil } NumberUtil.prototype.equalsWithTolerance = function equalsWithTolerance (x1, x2, tolerance) { return Math.abs(x1 - x2) <= tolerance } var IllegalArgumentException = (function (Error) { function IllegalArgumentException (message) { Error.call(this, message) this.name = 'IllegalArgumentException' this.message = message this.stack = (new Error()).stack } if (Error) IllegalArgumentException.__proto__ = Error IllegalArgumentException.prototype = Object.create(Error && Error.prototype) IllegalArgumentException.prototype.constructor = IllegalArgumentException return IllegalArgumentException }(Error)) var Double = function Double () { } var staticAccessors$1 = { MAX_VALUE: { configurable: true } } Double.isNaN = function isNaN (n) { return Number.isNaN(n) } Double.doubleToLongBits = function doubleToLongBits (n) { return n } Double.longBitsToDouble = function longBitsToDouble (n) { return n } Double.isInfinite = function isInfinite (n) { return !Number.isFinite(n) } staticAccessors$1.MAX_VALUE.get = function () { return Number.MAX_VALUE } Object.defineProperties(Double, staticAccessors$1) var Comparable = function Comparable () { } var Clonable = function Clonable () { } var Comparator = function Comparator () { } function Serializable () { } // import Assert from '../util/Assert' var Coordinate = function Coordinate () { this.x = null this.y = null this.z = null if (arguments.length === 0) { this.x = 0.0 this.y = 0.0 this.z = Coordinate.NULL_ORDINATE } else if (arguments.length === 1) { var c = arguments[0] this.x = c.x this.y = c.y this.z = c.z } else if (arguments.length === 2) { this.x = arguments[0] this.y = arguments[1] this.z = Coordinate.NULL_ORDINATE } else if (arguments.length === 3) { this.x = arguments[0] this.y = arguments[1] this.z = arguments[2] } } var staticAccessors = { DimensionalComparator: { configurable: true }, serialVersionUID: { configurable: true }, NULL_ORDINATE: { configurable: true }, X: { configurable: true }, Y: { configurable: true }, Z: { configurable: true } } Coordinate.prototype.setOrdinate = function setOrdinate (ordinateIndex, value) { switch (ordinateIndex) { case Coordinate.X: this.x = value break case Coordinate.Y: this.y = value break case Coordinate.Z: this.z = value break default: throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex) } } Coordinate.prototype.equals2D = function equals2D () { if (arguments.length === 1) { var other = arguments[0] if (this.x !== other.x) { return false } if (this.y !== other.y) { return false } return true } else if (arguments.length === 2) { var c = arguments[0] var tolerance = arguments[1] if (!NumberUtil.equalsWithTolerance(this.x, c.x, tolerance)) { return false } if (!NumberUtil.equalsWithTolerance(this.y, c.y, tolerance)) { return false } return true } } Coordinate.prototype.getOrdinate = function getOrdinate (ordinateIndex) { switch (ordinateIndex) { case Coordinate.X: return this.x case Coordinate.Y: return this.y case Coordinate.Z: return this.z } throw new IllegalArgumentException('Invalid ordinate index: ' + ordinateIndex) } Coordinate.prototype.equals3D = function equals3D (other) { return this.x === other.x && this.y === other.y && ((this.z === other.z || Double.isNaN(this.z)) && Double.isNaN(other.z)) } Coordinate.prototype.equals = function equals (other) { if (!(other instanceof Coordinate)) { return false } return this.equals2D(other) } Coordinate.prototype.equalInZ = function equalInZ (c, tolerance) { return NumberUtil.equalsWithTolerance(this.z, c.z, tolerance) } Coordinate.prototype.compareTo = function compareTo (o) { var other = o if (this.x < other.x) { return -1 } if (this.x > other.x) { return 1 } if (this.y < other.y) { return -1 } if (this.y > other.y) { return 1 } return 0 } Coordinate.prototype.clone = function clone () { // try { // var coord = null // return coord // } catch (e) { // if (e instanceof CloneNotSupportedException) { // Assert.shouldNeverReachHere("this shouldn't happen because this class is Cloneable") // return null // } else throw e // } finally {} } Coordinate.prototype.copy = function copy () { return new Coordinate(this) } Coordinate.prototype.toString = function toString () { return '(' + this.x + ', ' + this.y + ', ' + this.z + ')' } Coordinate.prototype.distance3D = function distance3D (c) { var dx = this.x - c.x var dy = this.y - c.y var dz = this.z - c.z return Math.sqrt(dx * dx + dy * dy + dz * dz) } Coordinate.prototype.distance = function distance (c) { var dx = this.x - c.x var dy = this.y - c.y return Math.sqrt(dx * dx + dy * dy) } Coordinate.prototype.hashCode = function hashCode () { var result = 17 result = 37 * result + Coordinate.hashCode(this.x) result = 37 * result + Coordinate.hashCode(this.y) return result } Coordinate.prototype.setCoordinate = function setCoordinate (other) { this.x = other.x this.y = other.y this.z = other.z } Coordinate.prototype.interfaces_ = function interfaces_ () { return [Comparable, Clonable, Serializable] } Coordinate.prototype.getClass = function getClass () { return Coordinate } Coordinate.hashCode = function hashCode () { if (arguments.length === 1) { var x = arguments[0] var f = Double.doubleToLongBits(x) return Math.trunc((f ^ f) >>> 32) } } staticAccessors.DimensionalComparator.get = function () { return DimensionalComparator } staticAccessors.serialVersionUID.get = function () { return 6683108902428366910 } staticAccessors.NULL_ORDINATE.get = function () { return Double.NaN } staticAccessors.X.get = function () { return 0 } staticAccessors.Y.get = function () { return 1 } staticAccessors.Z.get = function () { return 2 } Object.defineProperties(Coordinate, staticAccessors) var DimensionalComparator = function DimensionalComparator (dimensionsToTest) { this._dimensionsToTest = 2 if (arguments.length === 0); else if (arguments.length === 1) { var dimensionsToTest$1 = arguments[0] if (dimensionsToTest$1 !== 2 && dimensionsToTest$1 !== 3) { throw new IllegalArgumentException('only 2 or 3 dimensions may be specified') } this._dimensionsToTest = dimensionsToTest$1 } } DimensionalComparator.prototype.compare = function compare (o1, o2) { var c1 = o1 var c2 = o2 var compX = DimensionalComparator.compare(c1.x, c2.x) if (compX !== 0) { return compX } var compY = DimensionalComparator.compare(c1.y, c2.y) if (compY !== 0) { return compY } if (this._dimensionsToTest <= 2) { return 0 } var compZ = DimensionalComparator.compare(c1.z, c2.z) return compZ } DimensionalComparator.prototype.interfaces_ = function interfaces_ () { return [Comparator] } DimensionalComparator.prototype.getClass = function getClass () { return DimensionalComparator } DimensionalComparator.compare = function compare (a, b) { if (a < b) { return -1 } if (a > b) { return 1 } if (Double.isNaN(a)) { if (Double.isNaN(b)) { return 0 } return -1 } if (Double.isNaN(b)) { return 1 } return 0 } // import hasInterface from '../../../../hasInterface' // import CoordinateSequence from './CoordinateSequence' var CoordinateSequenceFactory = function CoordinateSequenceFactory () { } CoordinateSequenceFactory.prototype.create = function create () { // if (arguments.length === 1) { // if (arguments[0] instanceof Array) { // let coordinates = arguments[0] // } else if (hasInterface(arguments[0], CoordinateSequence)) { // let coordSeq = arguments[0] // } // } else if (arguments.length === 2) { // let size = arguments[0] // let dimension = arguments[1] // } } CoordinateSequenceFactory.prototype.interfaces_ = function interfaces_ () { return [] } CoordinateSequenceFactory.prototype.getClass = function getClass () { return CoordinateSequenceFactory } var Location = function Location () { } var staticAccessors$4 = { INTERIOR: { configurable: true }, BOUNDARY: { configurable: true }, EXTERIOR: { configurable: true }, NONE: { configurable: true } } Location.prototype.interfaces_ = function interfaces_ () { return [] } Location.prototype.getClass = function getClass () { return Location } Location.toLocationSymbol = function toLocationSymbol (locationValue) { switch (locationValue) { case Location.EXTERIOR: return 'e' case Location.BOUNDARY: return 'b' case Location.INTERIOR: return 'i' case Location.NONE: return '-' } throw new IllegalArgumentException('Unknown location value: ' + locationValue) } staticAccessors$4.INTERIOR.get = function () { return 0 } staticAccessors$4.BOUNDARY.get = function () { return 1 } staticAccessors$4.EXTERIOR.get = function () { return 2 } staticAccessors$4.NONE.get = function () { return -1 } Object.defineProperties(Location, staticAccessors$4) var hasInterface = function (o, i) { return o.interfaces_ && o.interfaces_().indexOf(i) > -1 } var MathUtil = function MathUtil () { } var staticAccessors$5 = { LOG_10: { configurable: true } } MathUtil.prototype.interfaces_ = function interfaces_ () { return [] } MathUtil.prototype.getClass = function getClass () { return MathUtil } MathUtil.log10 = function log10 (x) { var ln = Math.log(x) if (Double.isInfinite(ln)) { return ln } if (Double.isNaN(ln)) { return ln } return ln / MathUtil.LOG_10 } MathUtil.min = function min (v1, v2, v3, v4) { var min = v1 if (v2 < min) { min = v2 } if (v3 < min) { min = v3 } if (v4 < min) { min = v4 } return min } MathUtil.clamp = function clamp () { if (typeof arguments[2] === 'number' && (typeof arguments[0] === 'number' && typeof arguments[1] === 'number')) { var x = arguments[0] var min = arguments[1] var max = arguments[2] if (x < min) { return min } if (x > max) { return max } return x } else if (Number.isInteger(arguments[2]) && (Number.isInteger(arguments[0]) && Number.isInteger(arguments[1]))) { var x$1 = arguments[0] var min$1 = arguments[1] var max$1 = arguments[2] if (x$1 < min$1) { return min$1 } if (x$1 > max$1) { return max$1 } return x$1 } } MathUtil.wrap = function wrap (index, max) { if (index < 0) { return max - -index % max } return index % max } MathUtil.max = function max () { if (arguments.length === 3) { var v1 = arguments[0] var v2 = arguments[1] var v3 = arguments[2] var max = v1 if (v2 > max) { max = v2 } if (v3 > max) { max = v3 } return max } else if (arguments.length === 4) { var v1$1 = arguments[0] var v2$1 = arguments[1] var v3$1 = arguments[2] var v4 = arguments[3] var max$1 = v1$1 if (v2$1 > max$1) { max$1 = v2$1 } if (v3$1 > max$1) { max$1 = v3$1 } if (v4 > max$1) { max$1 = v4 } return max$1 } } MathUtil.average = function average (x1, x2) { return (x1 + x2) / 2.0 } staticAccessors$5.LOG_10.get = function () { return Math.log(10) } Object.defineProperties(MathUtil, staticAccessors$5) var StringBuffer = function StringBuffer (str) { this.str = str } StringBuffer.prototype.append = function append (e) { this.str += e } StringBuffer.prototype.setCharAt = function setCharAt (i, c) { this.str = this.str.substr(0, i) + c + this.str.substr(i + 1) } StringBuffer.prototype.toString = function toString (e) { return this.str } var Integer = function Integer (value) { this.value = value } Integer.prototype.intValue = function intValue () { return this.value } Integer.prototype.compareTo = function compareTo (o) { if (this.value < o) { return -1 } if (this.value > o) { return 1 } return 0 } Integer.isNaN = function isNaN (n) { return Number.isNaN(n) } var Character = function Character () { } Character.isWhitespace = function isWhitespace (c) { return ((c <= 32 && c >= 0) || c === 127) } Character.toUpperCase = function toUpperCase (c) { return c.toUpperCase() } var DD = function DD () { this._hi = 0.0 this._lo = 0.0 if (arguments.length === 0) { this.init(0.0) } else if (arguments.length === 1) { if (typeof arguments[0] === 'number') { var x = arguments[0] this.init(x) } else if (arguments[0] instanceof DD) { var dd = arguments[0] this.init(dd) } else if (typeof arguments[0] === 'string') { var str = arguments[0] DD.call(this, DD.parse(str)) } } else if (arguments.length === 2) { var hi = arguments[0] var lo = arguments[1] this.init(hi, lo) } } var staticAccessors$7 = { PI: { configurable: true }, TWO_PI: { configurable: true }, PI_2: { configurable: true }, E: { configurable: true }, NaN: { configurable: true }, EPS: { configurable: true }, SPLIT: { configurable: true }, MAX_PRINT_DIGITS: { configurable: true }, TEN: { configurable: true }, ONE: { configurable: true }, SCI_NOT_EXPONENT_CHAR: { configurable: true }, SCI_NOT_ZERO: { configurable: true } } DD.prototype.le = function le (y) { return (this._hi < y._hi || this._hi === y._hi) && this._lo <= y._lo } DD.prototype.extractSignificantDigits = function extractSignificantDigits (insertDecimalPoint, magnitude) { var y = this.abs() var mag = DD.magnitude(y._hi) var scale = DD.TEN.pow(mag) y = y.divide(scale) if (y.gt(DD.TEN)) { y = y.divide(DD.TEN) mag += 1 } else if (y.lt(DD.ONE)) { y = y.multiply(DD.TEN) mag -= 1 } var decimalPointPos = mag + 1 var buf = new StringBuffer() var numDigits = DD.MAX_PRINT_DIGITS - 1 for (var i = 0; i <= numDigits; i++) { if (insertDecimalPoint && i === decimalPointPos) { buf.append('.') } var digit = Math.trunc(y._hi) if (digit < 0) { break } var rebiasBy10 = false var digitChar = 0 if (digit > 9) { rebiasBy10 = true digitChar = '9' } else { digitChar = '0' + digit } buf.append(digitChar) y = y.subtract(DD.valueOf(digit)).multiply(DD.TEN) if (rebiasBy10) { y.selfAdd(DD.TEN) } var continueExtractingDigits = true var remMag = DD.magnitude(y._hi) if (remMag < 0 && Math.abs(remMag) >= numDigits - i) { continueExtractingDigits = false } if (!continueExtractingDigits) { break } } magnitude[0] = mag return buf.toString() } DD.prototype.sqr = function sqr () { return this.multiply(this) } DD.prototype.doubleValue = function doubleValue () { return this._hi + this._lo } DD.prototype.subtract = function subtract () { if (arguments[0] instanceof DD) { var y = arguments[0] return this.add(y.negate()) } else if (typeof arguments[0] === 'number') { var y$1 = arguments[0] return this.add(-y$1) } } DD.prototype.equals = function equals () { if (arguments.length === 1) { var y = arguments[0] return this._hi === y._hi && this._lo === y._lo } } DD.prototype.isZero = function isZero () { return this._hi === 0.0 && this._lo === 0.0 } DD.prototype.selfSubtract = function selfSubtract () { if (arguments[0] instanceof DD) { var y = arguments[0] if (this.isNaN()) { return this } return this.selfAdd(-y._hi, -y._lo) } else if (typeof arguments[0] === 'number') { var y$1 = arguments[0] if (this.isNaN()) { return this } return this.selfAdd(-y$1, 0.0) } } DD.prototype.getSpecialNumberString = function getSpecialNumberString () { if (this.isZero()) { return '0.0' } if (this.isNaN()) { return 'NaN ' } return null } DD.prototype.min = function min (x) { if (this.le(x)) { return this } else { return x } } DD.prototype.selfDivide = function selfDivide () { if (arguments.length === 1) { if (arguments[0] instanceof DD) { var y = arguments[0] return this.selfDivide(y._hi, y._lo) } else if (typeof arguments[0] === 'number') { var y$1 = arguments[0] return this.selfDivide(y$1, 0.0) } } else if (arguments.length === 2) { var yhi = arguments[0] var ylo = arguments[1] var hc = null var tc = null var hy = null var ty = null var C = null var c = null var U = null var u = null C = this._hi / yhi c = DD.SPLIT * C hc = c - C u = DD.SPLIT * yhi hc = c - hc tc = C - hc hy = u - yhi U = C * yhi hy = u - hy ty = yhi - hy u = hc * hy - U + hc * ty + tc * hy + tc * ty c = (this._hi - U - u + this._lo - C * ylo) / yhi u = C + c this._hi = u this._lo = C - u + c return this } } DD.prototype.dump = function dump () { return 'DD<' + this._hi + ', ' + this._lo + '>' } DD.prototype.divide = function divide () { if (arguments[0] instanceof DD) { var y = arguments[0] var hc = null var tc = null var hy = null var ty = null var C = null var c = null var U = null var u = null C = this._hi / y._hi c = DD.SPLIT * C hc = c - C u = DD.SPLIT * y._hi hc = c - hc tc = C - hc hy = u - y._hi U = C * y._hi hy = u - hy ty = y._hi - hy u = hc * hy - U + hc * ty + tc * hy + tc * ty c = (this._hi - U - u + this._lo - C * y._lo) / y._hi u = C + c var zhi = u var zlo = C - u + c return new DD(zhi, zlo) } else if (typeof arguments[0] === 'number') { var y$1 = arguments[0] if (Double.isNaN(y$1)) { return DD.createNaN() } return DD.copy(this).selfDivide(y$1, 0.0) } } DD.prototype.ge = function ge (y) { return (this._hi > y._hi || this._hi === y._hi) && this._lo >= y._lo } DD.prototype.pow = function pow (exp) { if (exp === 0.0) { return DD.valueOf(1.0) } var r = new DD(this) var s = DD.valueOf(1.0) var n = Math.abs(exp) if (n > 1) { while (n > 0) { if (n % 2 === 1) { s.selfMultiply(r) } n /= 2 if (n > 0) { r = r.sqr() } } } else { s = r } if (exp < 0) { return s.reciprocal() } return s } DD.prototype.ceil = function ceil () { if (this.isNaN()) { return DD.NaN } var fhi = Math.ceil(this._hi) var flo = 0.0 if (fhi === this._hi) { flo = Math.ceil(this._lo) } return new DD(fhi, flo) } DD.prototype.compareTo = function compareTo (o) { var other = o if (this._hi < other._hi) { return -1 } if (this._hi > other._hi) { return 1 } if (this._lo < other._lo) { return -1 } if (this._lo > other._lo) { return 1 } return 0 } DD.prototype.rint = function rint () { if (this.isNaN()) { return this } var plus5 = this.add(0.5) return plus5.floor() } DD.prototype.setValue = function setValue () { if (arguments[0] instanceof DD) { var value = arguments[0] this.init(value) return this } else if (typeof arguments[0] === 'number') { var value$1 = arguments[0] this.init(value$1) return this } } DD.prototype.max = function max (x) { if (this.ge(x)) { return this } else { return x } } DD.prototype.sqrt = function sqrt () { if (this.isZero()) { return DD.valueOf(0.0) } if (this.isNegative()) { return DD.NaN } var x = 1.0 / Math.sqrt(this._hi) var ax = this._hi * x var axdd = DD.valueOf(ax) var diffSq = this.subtract(axdd.sqr()) var d2 = diffSq._hi * (x * 0.5) return axdd.add(d2) } DD.prototype.selfAdd = function selfAdd () { if (arguments.length === 1) { if (arguments[0] instanceof DD) { var y = arguments[0] return this.selfAdd(y._hi, y._lo) } else if (typeof arguments[0] === 'number') { var y$1 = arguments[0] var H = null var h = null var S = null var s = null var e = null var f = null S = this._hi + y$1 e = S - this._hi s = S - e s = y$1 - e + (this._hi - s) f = s + this._lo H = S + f h = f + (S - H) this._hi = H + h this._lo = h + (H - this._hi) return this } } else if (arguments.length === 2) { var yhi = arguments[0] var ylo = arguments[1] var H$1 = null var h$1 = null var T = null var t = null var S$1 = null var s$1 = null var e$1 = null var f$1 = null S$1 = this._hi + yhi T = this._lo + ylo e$1 = S$1 - this._hi f$1 = T - this._lo s$1 = S$1 - e$1 t = T - f$1 s$1 = yhi - e$1 + (this._hi - s$1) t = ylo - f$1 + (this._lo - t) e$1 = s$1 + T H$1 = S$1 + e$1 h$1 = e$1 + (S$1 - H$1) e$1 = t + h$1 var zhi = H$1 + e$1 var zlo = e$1 + (H$1 - zhi) this._hi = zhi this._lo = zlo return this } } DD.prototype.selfMultiply = function selfMultiply () { if (arguments.length === 1) { if (arguments[0] instanceof DD) { var y = arguments[0] return this.selfMultiply(y._hi, y._lo) } else if (typeof arguments[0] === 'number') { var y$1 = arguments[0] return this.selfMultiply(y$1, 0.0) } } else if (arguments.length === 2) { var yhi = arguments[0] var ylo = arguments[1] var hx = null var tx = null var hy = null var ty = null var C = null var c = null C = DD.SPLIT * this._hi hx = C - this._hi c = DD.SPLIT * yhi hx = C - hx tx = this._hi - hx hy = c - yhi C = this._hi * yhi hy = c - hy ty = yhi - hy c = hx * hy - C + hx * ty + tx * hy + tx * ty + (this._hi * ylo + this._lo * yhi) var zhi = C + c hx = C - zhi var zlo = c + hx this._hi = zhi this._lo = zlo return this } } DD.prototype.selfSqr = function selfSqr () { return this.selfMultiply(this) } DD.prototype.floor = function floor () { if (this.isNaN()) { return DD.NaN } var fhi = Math.floor(this._hi) var flo = 0.0 if (fhi === this._hi) { flo = Math.floor(this._lo) } return new DD(fhi, flo) } DD.prototype.negate = function negate () { if (this.isNaN()) { return this } return new DD(-this._hi, -this._lo) } DD.prototype.clone = function clone () { // try { // return null // } catch (ex) { // if (ex instanceof CloneNotSupportedException) { // return null // } else throw ex // } finally {} } DD.prototype.multiply = function multiply () { if (arguments[0] instanceof DD) { var y = arguments[0] if (y.isNaN()) { return DD.createNaN() } return DD.copy(this).selfMultiply(y) } else if (typeof arguments[0] === 'number') { var y$1 = arguments[0] if (Double.isNaN(y$1)) { return DD.createNaN() } return DD.copy(this).selfMultiply(y$1, 0.0) } } DD.prototype.isNaN = function isNaN () { return Double.isNaN(this._hi) } DD.prototype.intValue = function intValue () { return Math.trunc(this._hi) } DD.prototype.toString = function toString () { var mag = DD.magnitude(this._hi) if (mag >= -3 && mag <= 20) { return this.toStandardNotation() } return this.toSciNotation() } DD.prototype.toStandardNotation = function toStandardNotation () { var specialStr = this.getSpecialNumberString() if (specialStr !== null) { return specialStr } var magnitude = new Array(1).fill(null) var sigDigits = this.extractSignificantDigits(true, magnitude) var decimalPointPos = magnitude[0] + 1 var num = sigDigits if (sigDigits.charAt(0) === '.') { num = '0' + sigDigits } else if (decimalPointPos < 0) { num = '0.' + DD.stringOfChar('0', -decimalPointPos) + sigDigits } else if (sigDigits.indexOf('.') === -1) { var numZeroes = decimalPointPos - sigDigits.length var zeroes = DD.stringOfChar('0', numZeroes) num = sigDigits + zeroes + '.0' } if (this.isNegative()) { return '-' + num } return num } DD.prototype.reciprocal = function reciprocal () { var hc = null var tc = null var hy = null var ty = null var C = null var c = null var U = null var u = null C = 1.0 / this._hi c = DD.SPLIT * C hc = c - C u = DD.SPLIT * this._hi hc = c - hc tc = C - hc hy = u - this._hi U = C * this._hi hy = u - hy ty = this._hi - hy u = hc * hy - U + hc * ty + tc * hy + tc * ty c = (1.0 - U - u - C * this._lo) / this._hi var zhi = C + c var zlo = C - zhi + c return new DD(zhi, zlo) } DD.prototype.toSciNotation = function toSciNotation () { if (this.isZero()) { return DD.SCI_NOT_ZERO } var specialStr = this.getSpecialNumberString() if (specialStr !== null) { return specialStr } var magnitude = new Array(1).fill(null) var digits = this.extractSignificantDigits(false, magnitude) var expStr = DD.SCI_NOT_EXPONENT_CHAR + magnitude[0] if (digits.charAt(0) === '0') { throw new Error('Found leading zero: ' + digits) } var trailingDigits = '' if (digits.length > 1) { trailingDigits = digits.substring(1) } var digitsWithDecimal = digits.charAt(0) + '.' + trailingDigits if (this.isNegative()) { return '-' + digitsWithDecimal + expStr } return digitsWithDecimal + expStr } DD.prototype.abs = function abs () { if (this.isNaN()) { return DD.NaN } if (this.isNegative()) { return this.negate() } return new DD(this) } DD.prototype.isPositive = function isPositive () { return (this._hi > 0.0 || this._hi === 0.0) && this._lo > 0.0 } DD.prototype.lt = function lt (y) { return (this._hi < y._hi || this._hi === y._hi) && this._lo < y._lo } DD.prototype.add = function add () { if (arguments[0] instanceof DD) { var y = arguments[0] return DD.copy(this).selfAdd(y) } else if (typeof arguments[0] === 'number') { var y$1 = arguments[0] return DD.copy(this).selfAdd(y$1) } } DD.prototype.init = function init () { if (arguments.length === 1) { if (typeof arguments[0] === 'number') { var x = arguments[0] this._hi = x this._lo = 0.0 } else if (arguments[0] instanceof DD) { var dd = arguments[0] this._hi = dd._hi this._lo = dd._lo } } else if (arguments.length === 2) { var hi = arguments[0] var lo = arguments[1] this._hi = hi this._lo = lo } } DD.prototype.gt = function gt (y) { return (this._hi > y._hi || this._hi === y._hi) && this._lo > y._lo } DD.prototype.isNegative = function isNegative () { return (this._hi < 0.0 || this._hi === 0.0) && this._lo < 0.0 } DD.prototype.trunc = function trunc () { if (this.isNaN()) { return DD.NaN } if (this.isPositive()) { return this.floor() } else { return this.ceil() } } DD.prototype.signum = function signum () { if (this._hi > 0) { return 1 } if (this._hi < 0) { return -1 } if (this._lo > 0) { return 1 } if (this._lo < 0) { return -1 } return 0 } DD.prototype.interfaces_ = function interfaces_ () { return [Serializable, Comparable, Clonable] } DD.prototype.getClass = function getClass () { return DD } DD.sqr = function sqr (x) { return DD.valueOf(x).selfMultiply(x) } DD.valueOf = function valueOf () { if (typeof arguments[0] === 'string') { var str = arguments[0] return DD.parse(str) } else if (typeof arguments[0] === 'number') { var x = arguments[0] return new DD(x) } } DD.sqrt = function sqrt (x) { return DD.valueOf(x).sqrt() } DD.parse = function parse (str) { var i = 0 var strlen = str.length while (Character.isWhitespace(str.charAt(i))) { i++ } var isNegative = false if (i < strlen) { var signCh = str.charAt(i) if (signCh === '-' || signCh === '+') { i++ if (signCh === '-') { isNegative = true } } } var val = new DD() var numDigits = 0 var numBeforeDec = 0 var exp = 0 while (true) { if (i >= strlen) { break } var ch = str.charAt(i) i++ if (Character.isDigit(ch)) { var d = ch - '0' val.selfMultiply(DD.TEN) val.selfAdd(d) numDigits++ continue } if (ch === '.') { numBeforeDec = numDigits continue } if (ch === 'e' || ch === 'E') { var expStr = str.substring(i) try { exp = Integer.parseInt(expStr) } catch (ex) { if (ex instanceof Error) { throw new Error('Invalid exponent ' + expStr + ' in string ' + str) } else { throw ex } } finally { } break } throw new Error("Unexpected character '" + ch + "' at position " + i + ' in string ' + str) } var val2 = val var numDecPlaces = numDigits - numBeforeDec - exp if (numDecPlaces === 0) { val2 = val } else if (numDecPlaces > 0) { var scale = DD.TEN.pow(numDecPlaces) val2 = val.divide(scale) } else if (numDecPlaces < 0) { var scale$1 = DD.TEN.pow(-numDecPlaces) val2 = val.multiply(scale$1) } if (isNegative) { return val2.negate() } return val2 } DD.createNaN = function createNaN () { return new DD(Double.NaN, Double.NaN) } DD.copy = function copy (dd) { return new DD(dd) } DD.magnitude = function magnitude (x) { var xAbs = Math.abs(x) var xLog10 = Math.log(xAbs) / Math.log(10) var xMag = Math.trunc(Math.floor(xLog10)) var xApprox = Math.pow(10, xMag) if (xApprox * 10 <= xAbs) { xMag += 1 } return xMag } DD.stringOfChar = function stringOfChar (ch, len) { var buf = new StringBuffer() for (var i = 0; i < len; i++) { buf.append(ch) } return buf.toString() } staticAccessors$7.PI.get = function () { return new DD(3.141592653589793116e+00, 1.224646799147353207e-16) } staticAccessors$7.TWO_PI.get = function () { return new DD(6.283185307179586232e+00, 2.449293598294706414e-16) } staticAccessors$7.PI_2.get = function () { return new DD(1.570796326794896558e+00, 6.123233995736766036e-17) } staticAccessors$7.E.get = function () { return new DD(2.718281828459045091e+00, 1.445646891729250158e-16) } staticAccessors$7.NaN.get = function () { return new DD(Double.NaN, Double.NaN) } staticAccessors$7.EPS.get = function () { return 1.23259516440783e-32 } staticAccessors$7.SPLIT.get = function () { return 134217729.0 } staticAccessors$7.MAX_PRINT_DIGITS.get = function () { return 32 } staticAccessors$7.TEN.get = function () { return DD.valueOf(10.0) } staticAccessors$7.ONE.get = function () { return DD.valueOf(1.0) } staticAccessors$7.SCI_NOT_EXPONENT_CHAR.get = function () { return 'E' } staticAccessors$7.SCI_NOT_ZERO.get = function () { return '0.0E0' } Object.defineProperties(DD, staticAccessors$7) var CGAlgorithmsDD = function CGAlgorithmsDD () { } var staticAccessors$6 = { DP_SAFE_EPSILON: { configurable: true } } CGAlgorithmsDD.prototype.interfaces_ = function interfaces_ () { return [] } CGAlgorithmsDD.prototype.getClass = function getClass () { return CGAlgorithmsDD } CGAlgorithmsDD.orientationIndex = function orientationIndex (p1, p2, q) { var index = CGAlgorithmsDD.orientationIndexFilter(p1, p2, q) if (index <= 1) { return index } var dx1 = DD.valueOf(p2.x).selfAdd(-p1.x) var dy1 = DD.valueOf(p2.y).selfAdd(-p1.y) var dx2 = DD.valueOf(q.x).selfAdd(-p2.x) var dy2 = DD.valueOf(q.y).selfAdd(-p2.y) return dx1.selfMultiply(dy2).selfSubtract(dy1.selfMultiply(dx2)).signum() } CGAlgorithmsDD.signOfDet2x2 = function signOfDet2x2 (x1, y1, x2, y2) { var det = x1.multiply(y2).selfSubtract(y1.multiply(x2)) return det.signum() } CGAlgorithmsDD.intersection = function intersection (p1, p2, q1, q2) { var denom1 = DD.valueOf(q2.y).selfSubtract(q1.y).selfMultiply(DD.valueOf(p2.x).selfSubtract(p1.x)) var denom2 = DD.valueOf(q2.x).selfSubtract(q1.x).selfMultiply(DD.valueOf(p2.y).selfSubtract(p1.y)) var denom = denom1.subtract(denom2) var numx1 = DD.valueOf(q2.x).selfSubtract(q1.x).selfMultiply(DD.valueOf(p1.y).selfSubtract(q1.y)) var numx2 = DD.valueOf(q2.y).selfSubtract(q1.y).selfMultiply(DD.valueOf(p1.x).selfSubtract(q1.x)) var numx = numx1.subtract(numx2) var fracP = numx.selfDivide(denom).doubleValue() var x = DD.valueOf(p1.x).selfAdd(DD.valueOf(p2.x).selfSubtract(p1.x).selfMultiply(fracP)).doubleValue() var numy1 = DD.valueOf(p2.x).selfSubtract(p1.x).selfMultiply(DD.valueOf(p1.y).selfSubtract(q1.y)) var numy2 = DD.valueOf(p2.y).selfSubtract(p1.y).selfMultiply(DD.valueOf(p1.x).selfSubtract(q1.x)) var numy = numy1.subtract(numy2) var fracQ = numy.selfDivide(denom).doubleValue() var y = DD.valueOf(q1.y).selfAdd(DD.valueOf(q2.y).selfSubtract(q1.y).selfMultiply(fracQ)).doubleValue() return new Coordinate(x, y) } CGAlgorithmsDD.orientationIndexFilter = function orientationIndexFilter (pa, pb, pc) { var detsum = null var detleft = (pa.x - pc.x) * (pb.y - pc.y) var detright = (pa.y - pc.y) * (pb.x - pc.x) var det = detleft - detright if (detleft > 0.0) { if (detright <= 0.0) { return CGAlgorithmsDD.signum(det) } else { detsum = detleft + detright } } else if (detleft < 0.0) { if (detright >= 0.0) { return CGAlgorithmsDD.signum(det) } else { detsum = -detleft - detright } } else { return CGAlgorithmsDD.signum(det) } var errbound = CGAlgorithmsDD.DP_SAFE_EPSILON * detsum if (det >= errbound || -det >= errbound) { return CGAlgorithmsDD.signum(det) } return 2 } CGAlgorithmsDD.signum = function signum (x) { if (x > 0) { return 1 } if (x < 0) { return -1 } return 0 } staticAccessors$6.DP_SAFE_EPSILON.get = function () { return 1e-15 } Object.defineProperties(CGAlgorithmsDD, staticAccessors$6) var CoordinateSequence = function CoordinateSequence () { } var staticAccessors$8 = { X: { configurable: true }, Y: { configurable: true }, Z: { configurable: true }, M: { configurable: true } } staticAccessors$8.X.get = function () { return 0 } staticAccessors$8.Y.get = function () { return 1 } staticAccessors$8.Z.get = function () { return 2 } staticAccessors$8.M.get = function () { return 3 } CoordinateSequence.prototype.setOrdinate = function setOrdinate (index, ordinateIndex, value) { } CoordinateSequence.prototype.size = function size () { } CoordinateSequence.prototype.getOrdinate = function getOrdinate (index, ordinateIndex) { } CoordinateSequence.prototype.getCoordinate = function getCoordinate () { } CoordinateSequence.prototype.getCoordinateCopy = function getCoordinateCopy (i) { } CoordinateSequence.prototype.getDimension = function getDimension () { } CoordinateSequence.prototype.getX = function getX (index) { } CoordinateSequence.prototype.clone = function clone () { } CoordinateSequence.prototype.expandEnvelope = function expandEnvelope (env) { } CoordinateSequence.prototype.copy = function copy () { } CoordinateSequence.prototype.getY = function getY (index) { } CoordinateSequence.prototype.toCoordinateArray = function toCoordinateArray () { } CoordinateSequence.prototype.interfaces_ = function interfaces_ () { return [Clonable] } CoordinateSequence.prototype.getClass = function getClass () { return CoordinateSequence } Object.defineProperties(CoordinateSequence, staticAccessors$8) var Exception = function Exception () { } var NotRepresentableException = (function (Exception$$1) { function NotRepresentableException () { Exception$$1.call(this, 'Projective point not representable on the Cartesian plane.') } if (Exception$$1) NotRepresentableException.__proto__ = Exception$$1 NotRepresentableException.prototype = Object.create(Exception$$1 && Exception$$1.prototype) NotRepresentableException.prototype.constructor = NotRepresentableException NotRepresentableException.prototype.interfaces_ = function interfaces_ () { return [] } NotRepresentableException.prototype.getClass = function getClass () { return NotRepresentableException } return NotRepresentableException }(Exception)) var System = function System () { } System.arraycopy = function arraycopy (src, srcPos, dest, destPos, len) { var c = 0 for (var i = srcPos; i < srcPos + len; i++) { dest[destPos + c] = src[i] c++ } } System.getProperty = function getProperty (name) { return { 'line.separator': '\n' }[name] } var HCoordinate = function HCoordinate () { this.x = null this.y = null this.w = null if (arguments.length === 0) { this.x = 0.0 this.y = 0.0 this.w = 1.0 } else if (arguments.length === 1) { var p = arguments[0] this.x = p.x this.y = p.y this.w = 1.0 } else if (arguments.length === 2) { if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') { var _x = arguments[0] var _y = arguments[1] this.x = _x this.y = _y this.w = 1.0 } else if (arguments[0] instanceof HCoordinate && arguments[1] instanceof HCoordinate) { var p1 = arguments[0] var p2 = arguments[1] this.x = p1.y * p2.w - p2.y * p1.w this.y = p2.x * p1.w - p1.x * p2.w this.w = p1.x * p2.y - p2.x * p1.y } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) { var p1$1 = arguments[0] var p2$1 = arguments[1] this.x = p1$1.y - p2$1.y this.y = p2$1.x - p1$1.x this.w = p1$1.x * p2$1.y - p2$1.x * p1$1.y } } else if (arguments.length === 3) { var _x$1 = arguments[0] var _y$1 = arguments[1] var _w = arguments[2] this.x = _x$1 this.y = _y$1 this.w = _w } else if (arguments.length === 4) { var p1$2 = arguments[0] var p2$2 = arguments[1] var q1 = arguments[2] var q2 = arguments[3] var px = p1$2.y - p2$2.y var py = p2$2.x - p1$2.x var pw = p1$2.x * p2$2.y - p2$2.x * p1$2.y var qx = q1.y - q2.y var qy = q2.x - q1.x var qw = q1.x * q2.y - q2.x * q1.y this.x = py * qw - qy * pw this.y = qx * pw - px * qw this.w = px * qy - qx * py } } HCoordinate.prototype.getY = function getY () { var a = this.y / this.w if (Double.isNaN(a) || Double.isInfinite(a)) { throw new NotRepresentableException() } return a } HCoordinate.prototype.getX = function getX () { var a = this.x / this.w if (Double.isNaN(a) || Double.isInfinite(a)) { throw new NotRepresentableException() } return a } HCoordinate.prototype.getCoordinate = function getCoordinate () { var p = new Coordinate() p.x = this.getX() p.y = this.getY() return p } HCoordinate.prototype.interfaces_ = function interfaces_ () { return [] } HCoordinate.prototype.getClass = function getClass () { return HCoordinate } HCoordinate.intersection = function intersection (p1, p2, q1, q2) { var px = p1.y - p2.y var py = p2.x - p1.x var pw = p1.x * p2.y - p2.x * p1.y var qx = q1.y - q2.y var qy = q2.x - q1.x var qw = q1.x * q2.y - q2.x * q1.y var x = py * qw - qy * pw var y = qx * pw - px * qw var w = px * qy - qx * py var xInt = x / w var yInt = y / w if (Double.isNaN(xInt) || (Double.isInfinite(xInt) || Double.isNaN(yInt)) || Double.isInfinite(yInt)) { throw new NotRepresentableException() } return new Coordinate(xInt, yInt) } var Envelope = function Envelope () { this._minx = null this._maxx = null this._miny = null this._maxy = null if (arguments.length === 0) { this.init() } else if (arguments.length === 1) { if (arguments[0] instanceof Coordinate) { var p = arguments[0] this.init(p.x, p.x, p.y, p.y) } else if (arguments[0] instanceof Envelope) { var env = arguments[0] this.init(env) } } else if (arguments.length === 2) { var p1 = arguments[0] var p2 = arguments[1] this.init(p1.x, p2.x, p1.y, p2.y) } else if (arguments.length === 4) { var x1 = arguments[0] var x2 = arguments[1] var y1 = arguments[2] var y2 = arguments[3] this.init(x1, x2, y1, y2) } } var staticAccessors$9 = { serialVersionUID: { configurable: true } } Envelope.prototype.getArea = function getArea () { return this.getWidth() * this.getHeight() } Envelope.prototype.equals = function equals (other) { if (!(other instanceof Envelope)) { return false } var otherEnvelope = other if (this.isNull()) { return otherEnvelope.isNull() } return this._maxx === otherEnvelope.getMaxX() && this._maxy === otherEnvelope.getMaxY() && this._minx === otherEnvelope.getMinX() && this._miny === otherEnvelope.getMinY() } Envelope.prototype.intersection = function intersection (env) { if (this.isNull() || env.isNull() || !this.intersects(env)) { return new Envelope() } var intMinX = this._minx > env._minx ? this._minx : env._minx var intMinY = this._miny > env._miny ? this._miny : env._miny var intMaxX = this._maxx < env._maxx ? this._maxx : env._maxx var intMaxY = this._maxy < env._maxy ? this._maxy : env._maxy return new Envelope(intMinX, intMaxX, intMinY, intMaxY) } Envelope.prototype.isNull = function isNull () { return this._maxx < this._minx } Envelope.prototype.getMaxX = function getMaxX () { return this._maxx } Envelope.prototype.covers = function covers () { if (arguments.length === 1) { if (arguments[0] instanceof Coordinate) { var p = arguments[0] return this.covers(p.x, p.y) } else if (arguments[0] instanceof Envelope) { var other = arguments[0] if (this.isNull() || other.isNull()) { return false } return other.getMinX() >= this._minx && other.getMaxX() <= this._maxx && other.getMinY() >= this._miny && other.getMaxY() <= this._maxy } } else if (arguments.length === 2) { var x = arguments[0] var y = arguments[1] if (this.isNull()) { return false } return x >= this._minx && x <= this._maxx && y >= this._miny && y <= this._maxy } } Envelope.prototype.intersects = function intersects () { if (arguments.length === 1) { if (arguments[0] instanceof Envelope) { var other = arguments[0] if (this.isNull() || other.isNull()) { return false } return !(other._minx > this._maxx || other._maxx < this._minx || other._miny > this._maxy || other._maxy < this._miny) } else if (arguments[0] instanceof Coordinate) { var p = arguments[0] return this.intersects(p.x, p.y) } } else if (arguments.length === 2) { var x = arguments[0] var y = arguments[1] if (this.isNull()) { return false } return !(x > this._maxx || x < this._minx || y > this._maxy || y < this._miny) } } Envelope.prototype.getMinY = function getMinY () { return this._miny } Envelope.prototype.getMinX = function getMinX () { return this._minx } Envelope.prototype.expandToInclude = function expandToInclude () { if (arguments.length === 1) { if (arguments[0] instanceof Coordinate) { var p = arguments[0] this.expandToInclude(p.x, p.y) } else if (arguments[0] instanceof Envelope) { var other = arguments[0] if (other.isNull()) { return null } if (this.isNull()) { this._minx = other.getMinX() this._maxx = other.getMaxX() this._miny = other.getMinY() this._maxy = other.getMaxY() } else { if (other._minx < this._minx) { this._minx = other._minx } if (other._maxx > this._maxx) { this._maxx = other._maxx } if (other._miny < this._miny) { this._miny = other._miny } if (other._maxy > this._maxy) { this._maxy = other._maxy } } } } else if (arguments.length === 2) { var x = arguments[0] var y = arguments[1] if (this.isNull()) { this._minx = x this._maxx = x this._miny = y this._maxy = y } else { if (x < this._minx) { this._minx = x } if (x > this._maxx) { this._maxx = x } if (y < this._miny) { this._miny = y } if (y > this._maxy) { this._maxy = y } } } } Envelope.prototype.minExtent = function minExtent () { if (this.isNull()) { return 0.0 } var w = this.getWidth() var h = this.getHeight() if (w < h) { return w } return h } Envelope.prototype.getWidth = function getWidth () { if (this.isNull()) { return 0 } return this._maxx - this._minx } Envelope.prototype.compareTo = function compareTo (o) { var env = o if (this.isNull()) { if (env.isNull()) { return 0 } return -1 } else { if (env.isNull()) { return 1 } } if (this._minx < env._minx) { return -1 } if (this._minx > env._minx) { return 1 } if (this._miny < env._miny) { return -1 } if (this._miny > env._miny) { return 1 } if (this._maxx < env._maxx) { return -1 } if (this._maxx > env._maxx) { return 1 } if (this._maxy < env._maxy) { return -1 } if (this._maxy > env._maxy) { return 1 } return 0 } Envelope.prototype.translate = function translate (transX, transY) { if (this.isNull()) { return null } this.init(this.getMinX() + transX, this.getMaxX() + transX, this.getMinY() + transY, this.getMaxY() + transY) } Envelope.prototype.toString = function toString () { return 'Env[' + this._minx + ' : ' + this._maxx + ', ' + this._miny + ' : ' + this._maxy + ']' } Envelope.prototype.setToNull = function setToNull () { this._minx = 0 this._maxx = -1 this._miny = 0 this._maxy = -1 } Envelope.prototype.getHeight = function getHeight () { if (this.isNull()) { return 0 } return this._maxy - this._miny } Envelope.prototype.maxExtent = function maxExtent () { if (this.isNull()) { return 0.0 } var w = this.getWidth() var h = this.getHeight() if (w > h) { return w } return h } Envelope.prototype.expandBy = function expandBy () { if (arguments.length === 1) { var distance = arguments[0] this.expandBy(distance, distance) } else if (arguments.length === 2) { var deltaX = arguments[0] var deltaY = arguments[1] if (this.isNull()) { return null } this._minx -= deltaX this._maxx += deltaX this._miny -= deltaY this._maxy += deltaY if (this._minx > this._maxx || this._miny > this._maxy) { this.setToNull() } } } Envelope.prototype.contains = function contains () { if (arguments.length === 1) { if (arguments[0] instanceof Envelope) { var other = arguments[0] return this.covers(other) } else if (arguments[0] instanceof Coordinate) { var p = arguments[0] return this.covers(p) } } else if (arguments.length === 2) { var x = arguments[0] var y = arguments[1] return this.covers(x, y) } } Envelope.prototype.centre = function centre () { if (this.isNull()) { return null } return new Coordinate((this.getMinX() + this.getMaxX()) / 2.0, (this.getMinY() + this.getMaxY()) / 2.0) } Envelope.prototype.init = function init () { if (arguments.length === 0) { this.setToNull() } else if (arguments.length === 1) { if (arguments[0] instanceof Coordinate) { var p = arguments[0] this.init(p.x, p.x, p.y, p.y) } else if (arguments[0] instanceof Envelope) { var env = arguments[0] this._minx = env._minx this._maxx = env._maxx this._miny = env._miny this._maxy = env._maxy } } else if (arguments.length === 2) { var p1 = arguments[0] var p2 = arguments[1] this.init(p1.x, p2.x, p1.y, p2.y) } else if (arguments.length === 4) { var x1 = arguments[0] var x2 = arguments[1] var y1 = arguments[2] var y2 = arguments[3] if (x1 < x2) { this._minx = x1 this._maxx = x2 } else { this._minx = x2 this._maxx = x1 } if (y1 < y2) { this._miny = y1 this._maxy = y2 } else { this._miny = y2 this._maxy = y1 } } } Envelope.prototype.getMaxY = function getMaxY () { return this._maxy } Envelope.prototype.distance = function distance (env) { if (this.intersects(env)) { return 0 } var dx = 0.0 if (this._maxx < env._minx) { dx = env._minx - this._maxx } else if (this._minx > env._maxx) { dx = this._minx - env._maxx } var dy = 0.0 if (this._maxy < env._miny) { dy = env._miny - this._maxy } else if (this._miny > env._maxy) { dy = this._miny - env._maxy } if (dx === 0.0) { return dy } if (dy === 0.0) { return dx } return Math.sqrt(dx * dx + dy * dy) } Envelope.prototype.hashCode = function hashCode () { var result = 17 result = 37 * result + Coordinate.hashCode(this._minx) result = 37 * result + Coordinate.hashCode(this._maxx) result = 37 * result + Coordinate.hashCode(this._miny) result = 37 * result + Coordinate.hashCode(this._maxy) return result } Envelope.prototype.interfaces_ = function interfaces_ () { return [Comparable, Serializable] } Envelope.prototype.getClass = function getClass () { return Envelope } Envelope.intersects = function intersects () { if (arguments.length === 3) { var p1 = arguments[0] var p2 = arguments[1] var q = arguments[2] if (q.x >= (p1.x < p2.x ? p1.x : p2.x) && q.x <= (p1.x > p2.x ? p1.x : p2.x) && (q.y >= (p1.y < p2.y ? p1.y : p2.y) && q.y <= (p1.y > p2.y ? p1.y : p2.y))) { return true } return false } else if (arguments.length === 4) { var p1$1 = arguments[0] var p2$1 = arguments[1] var q1 = arguments[2] var q2 = arguments[3] var minq = Math.min(q1.x, q2.x) var maxq = Math.max(q1.x, q2.x) var minp = Math.min(p1$1.x, p2$1.x) var maxp = Math.max(p1$1.x, p2$1.x) if (minp > maxq) { return false } if (maxp < minq) { return false } minq = Math.min(q1.y, q2.y) maxq = Math.max(q1.y, q2.y) minp = Math.min(p1$1.y, p2$1.y) maxp = Math.max(p1$1.y, p2$1.y) if (minp > maxq) { return false } if (maxp < minq) { return false } return true } } staticAccessors$9.serialVersionUID.get = function () { return 5873921885273102420 } Object.defineProperties(Envelope, staticAccessors$9) var regExes = { 'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/, 'emptyTypeStr': /^\s*(\w+)\s*EMPTY\s*$/, 'spaces': /\s+/, 'parenComma': /\)\s*,\s*\(/, 'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/, // can't use {2} here 'trimParens': /^\s*\(?(.*?)\)?\s*$/ } /** * Class for reading and writing Well-Known Text. * * NOTE: Adapted from OpenLayers 2.11 implementation. */ /** Create a new parser for WKT * * @param {GeometryFactory} geometryFactory * @return An instance of WKTParser. * @constructor * @private */ var WKTParser = function WKTParser (geometryFactory) { this.geometryFactory = geometryFactory || new GeometryFactory() } /** * Deserialize a WKT string and return a geometry. Supports WKT for POINT, * MULTIPOINT, LINESTRING, LINEARRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, * and GEOMETRYCOLLECTION. * * @param {String} wkt A WKT string. * @return {Geometry} A geometry instance. * @private */ WKTParser.prototype.read = function read (wkt) { var geometry, type, str wkt = wkt.replace(/[\n\r]/g, ' ') var matches = regExes.typeStr.exec(wkt) if (wkt.search('EMPTY') !== -1) { matches = regExes.emptyTypeStr.exec(wkt) matches[2] = undefined } if (matches) { type = matches[1].toLowerCase() str = matches[2] if (parse$1[type]) { geometry = parse$1[type].apply(this, [str]) } } if (geometry === undefined) { throw new Error('Could not parse WKT ' + wkt) } return geometry } /** * Serialize a geometry into a WKT string. * * @param {Geometry} geometry A feature or array of features. * @return {String} The WKT string representation of the input geometries. * @private */ WKTParser.prototype.write = function write (geometry) { return this.extractGeometry(geometry) } /** * Entry point to construct the WKT for a single Geometry object. * * @param {Geometry} geometry * @return {String} A WKT string of representing the geometry. * @private */ WKTParser.prototype.extractGeometry = function extractGeometry (geometry) { var type = geometry.getGeometryType().toLowerCase() if (!extract$1[type]) { return null } var wktType = type.toUpperCase() var data if (geometry.isEmpty()) { data = wktType + ' EMPTY' } else { data = wktType + '(' + extract$1[type].apply(this, [geometry]) + ')' } return data } /** * Object with properties corresponding to the geometry types. Property values * are functions that do the actual data extraction. * @private */ var extract$1 = { coordinate: function coordinate (coordinate$1) { return coordinate$1.x + ' ' + coordinate$1.y }, /** * Return a space delimited string of point coordinates. * * @param {Point} * point * @return {String} A string of coordinates representing the point. */ point: function point (point$1) { return extract$1.coordinate.call(this, point$1._coordinates._coordinates[0]) }, /** * Return a comma delimited string of point coordinates from a multipoint. * * @param {MultiPoint} * multipoint * @return {String} A string of point coordinate strings representing the * multipoint. */ multipoint: function multipoint (multipoint$1) { var this$1$1 = this var array = [] for (var i = 0, len = multipoint$1._geometries.length; i < len; ++i) { array.push('(' + extract$1.point.apply(this$1$1, [multipoint$1._geometries[i]]) + ')') } return array.join(',') }, /** * Return a comma delimited string of point coordinates from a line. * * @param {LineString} linestring * @return {String} A string of point coordinate strings representing the linestring. */ linestring: function linestring (linestring$1) { var this$1$1 = this var array = [] for (var i = 0, len = linestring$1._points._coordinates.length; i < len; ++i) { array.push(extract$1.coordinate.apply(this$1$1, [linestring$1._points._coordinates[i]])) } return array.join(',') }, linearring: function linearring (linearring$1) { var this$1$1 = this var array = [] for (var i = 0, len = linearring$1._points._coordinates.length; i < len; ++i) { array.push(extract$1.coordinate.apply(this$1$1, [linearring$1._points._coordinates[i]])) } return array.join(',') }, /** * Return a comma delimited string of linestring strings from a * multilinestring. * * @param {MultiLineString} multilinestring * @return {String} A string of of linestring strings representing the multilinestring. */ multilinestring: function multilinestring (multilinestring$1) { var this$1$1 = this var array = [] for (var i = 0, len = multilinestring$1._geometries.length; i < len; ++i) { array.push('(' + extract$1.linestring.apply(this$1$1, [multilinestring$1._geometries[i]]) + ')') } return array.join(',') }, /** * Return a comma delimited string of linear ring arrays from a polygon. * * @param {Polygon} polygon * @return {String} An array of linear ring arrays representing the polygon. */ polygon: function polygon (polygon$1) { var this$1$1 = this var array = [] array.push('(' + extract$1.linestring.apply(this, [polygon$1._shell]) + ')') for (var i = 0, len = polygon$1._holes.length; i < len; ++i) { array.push('(' + extract$1.linestring.apply(this$1$1, [polygon$1._holes[i]]) + ')') } return array.join(',') }, /** * Return an array of polygon arrays from a multipolygon. * * @param {MultiPolygon} multipolygon * @return {String} An array of polygon arrays representing the multipolygon. */ multipolygon: function multipolygon (multipolygon$1) { var this$1$1 = this var array = [] for (var i = 0, len = multipolygon$1._geometries.length; i < len; ++i) { array.push('(' + extract$1.polygon.apply(this$1$1, [multipolygon$1._geometries[i]]) + ')') } return array.join(',') }, /** * Return the WKT portion between 'GEOMETRYCOLLECTION(' and ')' for an * geometrycollection. * * @param {GeometryCollection} collection * @return {String} internal WKT representation of the collection. */ geometrycollection: function geometrycollection (collection) { var this$1$1 = this var array = [] for (var i = 0, len = collection._geometries.length; i < len; ++i) { array.push(this$1$1.extractGeometry(collection._geometries[i])) } return array.join(',') } } /** * Object with properties corresponding to the geometry types. Property values * are functions that do the actual parsing. * @private */ var parse$1 = { /** * Return point geometry given a point WKT fragment. * * @param {String} str A WKT fragment representing the point. * @return {Point} A point geometry. * @private */ point: function point (str) { if (str === undefined) { return this.geometryFactory.createPoint() } var coords = str.trim().split(regExes.spaces) return this.geometryFactory.createPoint(new Coordinate(Number.parseFloat(coords[0]), Number.parseFloat(coords[1]))) }, /** * Return a multipoint geometry given a multipoint WKT fragment. * * @param {String} str A WKT fragment representing the multipoint. * @return {Point} A multipoint feature. * @private */ multipoint: function multipoint (str) { var this$1$1 = this if (str === undefined) { return this.geometryFactory.createMultiPoint() } var point var points = str.trim().split(',') var components = [] for (var i = 0, len = points.length; i < len; ++i) { point = points[i].replace(regExes.trimParens, '$1') components.push(parse$1.point.apply(this$1$1, [point])) } return this.geometryFactory.createMultiPoint(components) }, /** * Return a linestring geometry given a linestring WKT fragment. * * @param {String} str A WKT fragment representing the linestring. * @return {LineString} A linestring geometry. * @private */ linestring: function linestring (str) { if (str === undefined) { return this.geometryFactory.createLineString() } var points = str.trim().split(',') var components = [] var coords for (var i = 0, len = points.length; i < len; ++i) { coords = points[i].trim().split(regExes.spaces) components.push(new Coordinate(Number.parseFloat(coords[0]), Number.parseFloat(coords[1]))) } return this.geometryFactory.createLineString(components) }, /** * Return a linearring geometry given a linearring WKT fragment. * * @param {String} str A WKT fragment representing the linearring. * @return {LinearRing} A linearring geometry. * @private */ linearring: function linearring (str) { if (str === undefined) { return this.geometryFactory.createLinearRing() } var points = str.trim().split(',') var components = [] var coords for (var i = 0, len = points.length; i < len; ++i) { coords = points[i].trim().split(regExes.spaces) components.push(new Coordinate(Number.parseFloat(coords[0]), Number.parseFloat(coords[1]))) } return this.geometryFactory.createLinearRing(components) }, /** * Return a multilinestring geometry given a multilinestring WKT fragment. * * @param {String} str A WKT fragment representing the multilinestring. * @return {MultiLineString} A multilinestring geometry. * @private */ multilinestring: function multilinestring (str) { var this$1$1 = this if (str === undefined) { return this.geometryFactory.createMultiLineString() } var line var lines = str.trim().split(regExes.parenComma) var components = [] for (var i = 0, len = lines.length; i < len; ++i) { line = lines[i].replace(regExes.trimParens, '$1') components.push(parse$1.linestring.apply(this$1$1, [line])) } return this.geometryFactory.createMultiLineString(components) }, /** * Return a polygon geometry given a polygon WKT fragment. * * @param {String} str A WKT fragment representing the polygon. * @return {Polygon} A polygon geometry. * @private */ polygon: function polygon (str) { var this$1$1 = this if (str === undefined) { return this.geometryFactory.createPolygon() } var ring, linestring, linearring var rings = str.trim().split(regExes.parenComma) var shell var holes = [] for (var i = 0, len = rings.length; i < len; ++i) { ring = rings[i].replace(regExes.trimParens, '$1') linestring = parse$1.linestring.apply(this$1$1, [ring]) linearring = this$1$1.geometryFactory.createLinearRing(linestring._points) if (i === 0) { shell = linearring } else { holes.push(linearring) } } return this.geometryFactory.createPolygon(shell, holes) }, /** * Return a multipolygon geometry given a multipolygon WKT fragment. * * @param {String} str A WKT fragment representing the multipolygon. * @return {MultiPolygon} A multipolygon geometry. * @private */ multipolygon: function multipolygon (str) { var this$1$1 = this if (str === undefined) { return this.geometryFactory.createMultiPolygon() } var polygon var polygons = str.trim().split(regExes.doubleParenComma) var components = [] for (var i = 0, len = polygons.length; i < len; ++i) { polygon = polygons[i].replace(regExes.trimParens, '$1') components.push(parse$1.polygon.apply(this$1$1, [polygon])) } return this.geometryFactory.createMultiPolygon(components) }, /** * Return a geometrycollection given a geometrycollection WKT fragment. * * @param {String} str A WKT fragment representing the geometrycollection. * @return {GeometryCollection} * @private */ geometrycollection: function geometrycollection (str) { var this$1$1 = this if (str === undefined) { return this.geometryFactory.createGeometryCollection() } // separate components of the collection with | str = str.replace(/,\s*([A-Za-z])/g, '|$1') var wktArray = str.trim().split('|') var components = [] for (var i = 0, len = wktArray.length; i < len; ++i) { components.push(this$1$1.read(wktArray[i])) } return this.geometryFactory.createGeometryCollection(components) } } /** * Writes the Well-Known Text representation of a {@link Geometry}. The * Well-Known Text format is defined in the OGC Simple Features * Specification for SQL. *

* The WKTWriter outputs coordinates rounded to the precision * model. Only the maximum number of decimal places necessary to represent the * ordinates to the required precision will be output. *

* The SFS WKT spec does not define a special tag for {@link LinearRing}s. * Under the spec, rings are output as LINESTRINGs. */ /** * @param {GeometryFactory} geometryFactory * @constructor */ var WKTWriter = function WKTWriter (geometryFactory) { this.parser = new WKTParser(geometryFactory) } /** * Converts a Geometry to its Well-known Text representation. * * @param {Geometry} geometry a Geometry to process. * @return {string} a string (see the OpenGIS Simple * Features Specification). * @memberof WKTWriter */ WKTWriter.prototype.write = function write (geometry) { return this.parser.write(geometry) } /** * Generates the WKT for a LINESTRING specified by two * {@link Coordinate}s. * * @param p0 the first coordinate. * @param p1 the second coordinate. * * @return the WKT. * @private */ WKTWriter.toLineString = function toLineString (p0, p1) { if (arguments.length !== 2) { throw new Error('Not implemented') } return 'LINESTRING ( ' + p0.x + ' ' + p0.y + ', ' + p1.x + ' ' + p1.y + ' )' } var RuntimeException = (function (Error) { function RuntimeException (message) { Error.call(this, message) this.name = 'RuntimeException' this.message = message this.stack = (new Error()).stack } if (Error) RuntimeException.__proto__ = Error RuntimeException.prototype = Object.create(Error && Error.prototype) RuntimeException.prototype.constructor = RuntimeException return RuntimeException }(Error)) var AssertionFailedException = (function (RuntimeException$$1) { function AssertionFailedException () { RuntimeException$$1.call(this) if (arguments.length === 0) { RuntimeException$$1.call(this) } else if (arguments.length === 1) { var message = arguments[0] RuntimeException$$1.call(this, message) } } if (RuntimeException$$1) AssertionFailedException.__proto__ = RuntimeException$$1 AssertionFailedException.prototype = Object.create(RuntimeException$$1 && RuntimeException$$1.prototype) AssertionFailedException.prototype.constructor = AssertionFailedException AssertionFailedException.prototype.interfaces_ = function interfaces_ () { return [] } AssertionFailedException.prototype.getClass = function getClass () { return AssertionFailedException } return AssertionFailedException }(RuntimeException)) var Assert = function Assert () { } Assert.prototype.interfaces_ = function interfaces_ () { return [] } Assert.prototype.getClass = function getClass () { return Assert } Assert.shouldNeverReachHere = function shouldNeverReachHere () { if (arguments.length === 0) { Assert.shouldNeverReachHere(null) } else if (arguments.length === 1) { var message = arguments[0] throw new AssertionFailedException('Should never reach here' + (message !== null ? ': ' + message : '')) } } Assert.isTrue = function isTrue () { var assertion var message if (arguments.length === 1) { assertion = arguments[0] Assert.isTrue(assertion, null) } else if (arguments.length === 2) { assertion = arguments[0] message = arguments[1] if (!assertion) { if (message === null) { throw new AssertionFailedException() } else { throw new AssertionFailedException(message) } } } } Assert.equals = function equals () { var expectedValue var actualValue var message if (arguments.length === 2) { expectedValue = arguments[0] actualValue = arguments[1] Assert.equals(expectedValue, actualValue, null) } else if (arguments.length === 3) { expectedValue = arguments[0] actualValue = arguments[1] message = arguments[2] if (!actualValue.equals(expectedValue)) { throw new AssertionFailedException('Expected ' + expectedValue + ' but encountered ' + actualValue + (message !== null ? ': ' + message : '')) } } } var LineIntersector = function LineIntersector () { this._result = null this._inputLines = Array(2).fill().map(function () { return Array(2) }) this._intPt = new Array(2).fill(null) this._intLineIndex = null this._isProper = null this._pa = null this._pb = null this._precisionModel = null this._intPt[0] = new Coordinate() this._intPt[1] = new Coordinate() this._pa = this._intPt[0] this._pb = this._intPt[1] this._result = 0 } var staticAccessors$10 = { DONT_INTERSECT: { configurable: true }, DO_INTERSECT: { configurable: true }, COLLINEAR: { configurable: true }, NO_INTERSECTION: { configurable: true }, POINT_INTERSECTION: { configurable: true }, COLLINEAR_INTERSECTION: { configurable: true } } LineIntersector.prototype.getIndexAlongSegment = function getIndexAlongSegment (segmentIndex, intIndex) { this.computeIntLineIndex() return this._intLineIndex[segmentIndex][intIndex] } LineIntersector.prototype.getTopologySummary = function getTopologySummary () { var catBuf = new StringBuffer() if (this.isEndPoint()) { catBuf.append(' endpoint') } if (this._isProper) { catBuf.append(' proper') } if (this.isCollinear()) { catBuf.append(' collinear') } return catBuf.toString() } LineIntersector.prototype.computeIntersection = function computeIntersection (p1, p2, p3, p4) { this._inputLines[0][0] = p1 this._inputLines[0][1] = p2 this._inputLines[1][0] = p3 this._inputLines[1][1] = p4 this._result = this.computeIntersect(p1, p2, p3, p4) } LineIntersector.prototype.getIntersectionNum = function getIntersectionNum () { return this._result } LineIntersector.prototype.computeIntLineIndex = function computeIntLineIndex () { if (arguments.length === 0) { if (this._intLineIndex === null) { this._intLineIndex = Array(2).fill().map(function () { return Array(2) }) this.computeIntLineIndex(0) this.computeIntLineIndex(1) } } else if (arguments.length === 1) { var segmentIndex = arguments[0] var dist0 = this.getEdgeDistance(segmentIndex, 0) var dist1 = this.getEdgeDistance(segmentIndex, 1) if (dist0 > dist1) { this._intLineIndex[segmentIndex][0] = 0 this._intLineIndex[segmentIndex][1] = 1 } else { this._intLineIndex[segmentIndex][0] = 1 this._intLineIndex[segmentIndex][1] = 0 } } } LineIntersector.prototype.isProper = function isProper () { return this.hasIntersection() && this._isProper } LineIntersector.prototype.setPrecisionModel = function setPrecisionModel (precisionModel) { this._precisionModel = precisionModel } LineIntersector.prototype.isInteriorIntersection = function isInteriorIntersection () { var this$1$1 = this if (arguments.length === 0) { if (this.isInteriorIntersection(0)) { return true } if (this.isInteriorIntersection(1)) { return true } return false } else if (arguments.length === 1) { var inputLineIndex = arguments[0] for (var i = 0; i < this._result; i++) { if (!(this$1$1._intPt[i].equals2D(this$1$1._inputLines[inputLineIndex][0]) || this$1$1._intPt[i].equals2D(this$1$1._inputLines[inputLineIndex][1]))) { return true } } return false } } LineIntersector.prototype.getIntersection = function getIntersection (intIndex) { return this._intPt[intIndex] } LineIntersector.prototype.isEndPoint = function isEndPoint () { return this.hasIntersection() && !this._isProper } LineIntersector.prototype.hasIntersection = function hasIntersection () { return this._result !== LineIntersector.NO_INTERSECTION } LineIntersector.prototype.getEdgeDistance = function getEdgeDistance (segmentIndex, intIndex) { var dist = LineIntersector.computeEdgeDistance(this._intPt[intIndex], this._inputLines[segmentIndex][0], this._inputLines[segmentIndex][1]) return dist } LineIntersector.prototype.isCollinear = function isCollinear () { return this._result === LineIntersector.COLLINEAR_INTERSECTION } LineIntersector.prototype.toString = function toString () { return WKTWriter.toLineString(this._inputLines[0][0], this._inputLines[0][1]) + ' - ' + WKTWriter.toLineString(this._inputLines[1][0], this._inputLines[1][1]) + this.getTopologySummary() } LineIntersector.prototype.getEndpoint = function getEndpoint (segmentIndex, ptIndex) { return this._inputLines[segmentIndex][ptIndex] } LineIntersector.prototype.isIntersection = function isIntersection (pt) { var this$1$1 = this for (var i = 0; i < this._result; i++) { if (this$1$1._intPt[i].equals2D(pt)) { return true } } return false } LineIntersector.prototype.getIntersectionAlongSegment = function getIntersectionAlongSegment (segmentIndex, intIndex) { this.computeIntLineIndex() return this._intPt[this._intLineIndex[segmentIndex][intIndex]] } LineIntersector.prototype.interfaces_ = function interfaces_ () { return [] } LineIntersector.prototype.getClass = function getClass () { return LineIntersector } LineIntersector.computeEdgeDistance = function computeEdgeDistance (p, p0, p1) { var dx = Math.abs(p1.x - p0.x) var dy = Math.abs(p1.y - p0.y) var dist = -1.0 if (p.equals(p0)) { dist = 0.0 } else if (p.equals(p1)) { if (dx > dy) { dist = dx } else { dist = dy } } else { var pdx = Math.abs(p.x - p0.x) var pdy = Math.abs(p.y - p0.y) if (dx > dy) { dist = pdx } else { dist = pdy } if (dist === 0.0 && !p.equals(p0)) { dist = Math.max(pdx, pdy) } } Assert.isTrue(!(dist === 0.0 && !p.equals(p0)), 'Bad distance calculation') return dist } LineIntersector.nonRobustComputeEdgeDistance = function nonRobustComputeEdgeDistance (p, p1, p2) { var dx = p.x - p1.x var dy = p.y - p1.y var dist = Math.sqrt(dx * dx + dy * dy) Assert.isTrue(!(dist === 0.0 && !p.equals(p1)), 'Invalid distance calculation') return dist } staticAccessors$10.DONT_INTERSECT.get = function () { return 0 } staticAccessors$10.DO_INTERSECT.get = function () { return 1 } staticAccessors$10.COLLINEAR.get = function () { return 2 } staticAccessors$10.NO_INTERSECTION.get = function () { return 0 } staticAccessors$10.POINT_INTERSECTION.get = function () { return 1 } staticAccessors$10.COLLINEAR_INTERSECTION.get = function () { return 2 } Object.defineProperties(LineIntersector, staticAccessors$10) var RobustLineIntersector = (function (LineIntersector$$1) { function RobustLineIntersector () { LineIntersector$$1.apply(this, arguments) } if (LineIntersector$$1) RobustLineIntersector.__proto__ = LineIntersector$$1 RobustLineIntersector.prototype = Object.create(LineIntersector$$1 && LineIntersector$$1.prototype) RobustLineIntersector.prototype.constructor = RobustLineIntersector RobustLineIntersector.prototype.isInSegmentEnvelopes = function isInSegmentEnvelopes (intPt) { var env0 = new Envelope(this._inputLines[0][0], this._inputLines[0][1]) var env1 = new Envelope(this._inputLines[1][0], this._inputLines[1][1]) return env0.contains(intPt) && env1.contains(intPt) } RobustLineIntersector.prototype.computeIntersection = function computeIntersection () { if (arguments.length === 3) { var p = arguments[0] var p1 = arguments[1] var p2 = arguments[2] this._isProper = false if (Envelope.intersects(p1, p2, p)) { if (CGAlgorithms.orientationIndex(p1, p2, p) === 0 && CGAlgorithms.orientationIndex(p2, p1, p) === 0) { this._isProper = true if (p.equals(p1) || p.equals(p2)) { this._isProper = false } this._result = LineIntersector$$1.POINT_INTERSECTION return null } } this._result = LineIntersector$$1.NO_INTERSECTION } else { return LineIntersector$$1.prototype.computeIntersection.apply(this, arguments) } } RobustLineIntersector.prototype.normalizeToMinimum = function normalizeToMinimum (n1, n2, n3, n4, normPt) { normPt.x = this.smallestInAbsValue(n1.x, n2.x, n3.x, n4.x) normPt.y = this.smallestInAbsValue(n1.y, n2.y, n3.y, n4.y) n1.x -= normPt.x n1.y -= normPt.y n2.x -= normPt.x n2.y -= normPt.y n3.x -= normPt.x n3.y -= normPt.y n4.x -= normPt.x n4.y -= normPt.y } RobustLineIntersector.prototype.safeHCoordinateIntersection = function safeHCoordinateIntersection (p1, p2, q1, q2) { var intPt = null try { intPt = HCoordinate.intersection(p1, p2, q1, q2) } catch (e) { if (e instanceof NotRepresentableException) { intPt = RobustLineIntersector.nearestEndpoint(p1, p2, q1, q2) } else { throw e } } finally { } return intPt } RobustLineIntersector.prototype.intersection = function intersection (p1, p2, q1, q2) { var intPt = this.intersectionWithNormalization(p1, p2, q1, q2) if (!this.isInSegmentEnvelopes(intPt)) { intPt = new Coordinate(RobustLineIntersector.nearestEndpoint(p1, p2, q1, q2)) } if (this._precisionModel !== null) { this._precisionModel.makePrecise(intPt) } return intPt } RobustLineIntersector.prototype.smallestInAbsValue = function smallestInAbsValue (x1, x2, x3, x4) { var x = x1 var xabs = Math.abs(x) if (Math.abs(x2) < xabs) { x = x2 xabs = Math.abs(x2) } if (Math.abs(x3) < xabs) { x = x3 xabs = Math.abs(x3) } if (Math.abs(x4) < xabs) { x = x4 } return x } RobustLineIntersector.prototype.checkDD = function checkDD (p1, p2, q1, q2, intPt) { var intPtDD = CGAlgorithmsDD.intersection(p1, p2, q1, q2) var isIn = this.isInSegmentEnvelopes(intPtDD) System.out.println('DD in env = ' + isIn + ' --------------------- ' + intPtDD) if (intPt.distance(intPtDD) > 0.0001) { System.out.println('Distance = ' + intPt.distance(intPtDD)) } } RobustLineIntersector.prototype.intersectionWithNormalization = function intersectionWithNormalization (p1, p2, q1, q2) { var n1 = new Coordinate(p1) var n2 = new Coordinate(p2) var n3 = new Coordinate(q1) var n4 = new Coordinate(q2) var normPt = new Coordinate() this.normalizeToEnvCentre(n1, n2, n3, n4, normPt) var intPt = this.safeHCoordinateIntersection(n1, n2, n3, n4) intPt.x += normPt.x intPt.y += normPt.y return intPt } RobustLineIntersector.prototype.computeCollinearIntersection = function computeCollinearIntersection (p1, p2, q1, q2) { var p1q1p2 = Envelope.intersects(p1, p2, q1) var p1q2p2 = Envelope.intersects(p1, p2, q2) var q1p1q2 = Envelope.intersects(q1, q2, p1) var q1p2q2 = Envelope.intersects(q1, q2, p2) if (p1q1p2 && p1q2p2) { this._intPt[0] = q1 this._intPt[1] = q2 return LineIntersector$$1.COLLINEAR_INTERSECTION } if (q1p1q2 && q1p2q2) { this._intPt[0] = p1 this._intPt[1] = p2 return LineIntersector$$1.COLLINEAR_INTERSECTION } if (p1q1p2 && q1p1q2) { this._intPt[0] = q1 this._intPt[1] = p1 return q1.equals(p1) && !p1q2p2 && !q1p2q2 ? LineIntersector$$1.POINT_INTERSECTION : LineIntersector$$1.COLLINEAR_INTERSECTION } if (p1q1p2 && q1p2q2) { this._intPt[0] = q1 this._intPt[1] = p2 return q1.equals(p2) && !p1q2p2 && !q1p1q2 ? LineIntersector$$1.POINT_INTERSECTION : LineIntersector$$1.COLLINEAR_INTERSECTION } if (p1q2p2 && q1p1q2) { this._intPt[0] = q2 this._intPt[1] = p1 return q2.equals(p1) && !p1q1p2 && !q1p2q2 ? LineIntersector$$1.POINT_INTERSECTION : LineIntersector$$1.COLLINEAR_INTERSECTION } if (p1q2p2 && q1p2q2) { this._intPt[0] = q2 this._intPt[1] = p2 return q2.equals(p2) && !p1q1p2 && !q1p1q2 ? LineIntersector$$1.POINT_INTERSECTION : LineIntersector$$1.COLLINEAR_INTERSECTION } return LineIntersector$$1.NO_INTERSECTION } RobustLineIntersector.prototype.normalizeToEnvCentre = function normalizeToEnvCentre (n00, n01, n10, n11, normPt) { var minX0 = n00.x < n01.x ? n00.x : n01.x var minY0 = n00.y < n01.y ? n00.y : n01.y var maxX0 = n00.x > n01.x ? n00.x : n01.x var maxY0 = n00.y > n01.y ? n00.y : n01.y var minX1 = n10.x < n11.x ? n10.x : n11.x var minY1 = n10.y < n11.y ? n10.y : n11.y var maxX1 = n10.x > n11.x ? n10.x : n11.x var maxY1 = n10.y > n11.y ? n10.y : n11.y var intMinX = minX0 > minX1 ? minX0 : minX1 var intMaxX = maxX0 < maxX1 ? maxX0 : maxX1 var intMinY = minY0 > minY1 ? minY0 : minY1 var intMaxY = maxY0 < maxY1 ? maxY0 : maxY1 var intMidX = (intMinX + intMaxX) / 2.0 var intMidY = (intMinY + intMaxY) / 2.0 normPt.x = intMidX normPt.y = intMidY n00.x -= normPt.x n00.y -= normPt.y n01.x -= normPt.x n01.y -= normPt.y n10.x -= normPt.x n10.y -= normPt.y n11.x -= normPt.x n11.y -= normPt.y } RobustLineIntersector.prototype.computeIntersect = function computeIntersect (p1, p2, q1, q2) { this._isProper = false if (!Envelope.intersects(p1, p2, q1, q2)) { return LineIntersector$$1.NO_INTERSECTION } var Pq1 = CGAlgorithms.orientationIndex(p1, p2, q1) var Pq2 = CGAlgorithms.orientationIndex(p1, p2, q2) if ((Pq1 > 0 && Pq2 > 0) || (Pq1 < 0 && Pq2 < 0)) { return LineIntersector$$1.NO_INTERSECTION } var Qp1 = CGAlgorithms.orientationIndex(q1, q2, p1) var Qp2 = CGAlgorithms.orientationIndex(q1, q2, p2) if ((Qp1 > 0 && Qp2 > 0) || (Qp1 < 0 && Qp2 < 0)) { return LineIntersector$$1.NO_INTERSECTION } var collinear = Pq1 === 0 && Pq2 === 0 && Qp1 === 0 && Qp2 === 0 if (collinear) { return this.computeCollinearIntersection(p1, p2, q1, q2) } if (Pq1 === 0 || Pq2 === 0 || Qp1 === 0 || Qp2 === 0) { this._isProper = false if (p1.equals2D(q1) || p1.equals2D(q2)) { this._intPt[0] = p1 } else if (p2.equals2D(q1) || p2.equals2D(q2)) { this._intPt[0] = p2 } else if (Pq1 === 0) { this._intPt[0] = new Coordinate(q1) } else if (Pq2 === 0) { this._intPt[0] = new Coordinate(q2) } else if (Qp1 === 0) { this._intPt[0] = new Coordinate(p1) } else if (Qp2 === 0) { this._intPt[0] = new Coordinate(p2) } } else { this._isProper = true this._intPt[0] = this.intersection(p1, p2, q1, q2) } return LineIntersector$$1.POINT_INTERSECTION } RobustLineIntersector.prototype.interfaces_ = function interfaces_ () { return [] } RobustLineIntersector.prototype.getClass = function getClass () { return RobustLineIntersector } RobustLineIntersector.nearestEndpoint = function nearestEndpoint (p1, p2, q1, q2) { var nearestPt = p1 var minDist = CGAlgorithms.distancePointLine(p1, q1, q2) var dist = CGAlgorithms.distancePointLine(p2, q1, q2) if (dist < minDist) { minDist = dist nearestPt = p2 } dist = CGAlgorithms.distancePointLine(q1, p1, p2) if (dist < minDist) { minDist = dist nearestPt = q1 } dist = CGAlgorithms.distancePointLine(q2, p1, p2) if (dist < minDist) { minDist = dist nearestPt = q2 } return nearestPt } return RobustLineIntersector }(LineIntersector)) var RobustDeterminant = function RobustDeterminant () { } RobustDeterminant.prototype.interfaces_ = function interfaces_ () { return [] } RobustDeterminant.prototype.getClass = function getClass () { return RobustDeterminant } RobustDeterminant.orientationIndex = function orientationIndex (p1, p2, q) { var dx1 = p2.x - p1.x var dy1 = p2.y - p1.y var dx2 = q.x - p2.x var dy2 = q.y - p2.y return RobustDeterminant.signOfDet2x2(dx1, dy1, dx2, dy2) } RobustDeterminant.signOfDet2x2 = function signOfDet2x2 (x1, y1, x2, y2) { var sign = null var swap = null var k = null sign = 1 if (x1 === 0.0 || y2 === 0.0) { if (y1 === 0.0 || x2 === 0.0) { return 0 } else if (y1 > 0) { if (x2 > 0) { return -sign } else { return sign } } else { if (x2 > 0) { return sign } else { return -sign } } } if (y1 === 0.0 || x2 === 0.0) { if (y2 > 0) { if (x1 > 0) { return sign } else { return -sign } } else { if (x1 > 0) { return -sign } else { return sign } } } if (y1 > 0.0) { if (y2 > 0.0) { if (y1 <= y2); else { sign = -sign swap = x1 x1 = x2 x2 = swap swap = y1 y1 = y2 y2 = swap } } else { if (y1 <= -y2) { sign = -sign x2 = -x2 y2 = -y2 } else { swap = x1 x1 = -x2 x2 = swap swap = y1 y1 = -y2 y2 = swap } } } else { if (y2 > 0.0) { if (-y1 <= y2) { sign = -sign x1 = -x1 y1 = -y1 } else { swap = -x1 x1 = x2 x2 = swap swap = -y1 y1 = y2 y2 = swap } } else { if (y1 >= y2) { x1 = -x1 y1 = -y1 x2 = -x2 y2 = -y2 } else { sign = -sign swap = -x1 x1 = -x2 x2 = swap swap = -y1 y1 = -y2 y2 = swap } } } if (x1 > 0.0) { if (x2 > 0.0) { if (x1 <= x2); else { return sign } } else { return sign } } else { if (x2 > 0.0) { return -sign } else { if (x1 >= x2) { sign = -sign x1 = -x1 x2 = -x2 } else { return -sign } } } while (true) { k = Math.floor(x2 / x1) x2 = x2 - k * x1 y2 = y2 - k * y1 if (y2 < 0.0) { return -sign } if (y2 > y1) { return sign } if (x1 > x2 + x2) { if (y1 < y2 + y2) { return sign } } else { if (y1 > y2 + y2) { return -sign } else { x2 = x1 - x2 y2 = y1 - y2 sign = -sign } } if (y2 === 0.0) { if (x2 === 0.0) { return 0 } else { return -sign } } if (x2 === 0.0) { return sign } k = Math.floor(x1 / x2) x1 = x1 - k * x2 y1 = y1 - k * y2 if (y1 < 0.0) { return sign } if (y1 > y2) { return -sign } if (x2 > x1 + x1) { if (y2 < y1 + y1) { return -sign } } else { if (y2 > y1 + y1) { return sign } else { x1 = x2 - x1 y1 = y2 - y1 sign = -sign } } if (y1 === 0.0) { if (x1 === 0.0) { return 0 } else { return sign } } if (x1 === 0.0) { return -sign } } } var RayCrossingCounter = function RayCrossingCounter () { this._p = null this._crossingCount = 0 this._isPointOnSegment = false var p = arguments[0] this._p = p } RayCrossingCounter.prototype.countSegment = function countSegment (p1, p2) { if (p1.x < this._p.x && p2.x < this._p.x) { return null } if (this._p.x === p2.x && this._p.y === p2.y) { this._isPointOnSegment = true return null } if (p1.y === this._p.y && p2.y === this._p.y) { var minx = p1.x var maxx = p2.x if (minx > maxx) { minx = p2.x maxx = p1.x } if (this._p.x >= minx && this._p.x <= maxx) { this._isPointOnSegment = true } return null } if ((p1.y > this._p.y && p2.y <= this._p.y) || (p2.y > this._p.y && p1.y <= this._p.y)) { var x1 = p1.x - this._p.x var y1 = p1.y - this._p.y var x2 = p2.x - this._p.x var y2 = p2.y - this._p.y var xIntSign = RobustDeterminant.signOfDet2x2(x1, y1, x2, y2) if (xIntSign === 0.0) { this._isPointOnSegment = true return null } if (y2 < y1) { xIntSign = -xIntSign } if (xIntSign > 0.0) { this._crossingCount++ } } } RayCrossingCounter.prototype.isPointInPolygon = function isPointInPolygon () { return this.getLocation() !== Location.EXTERIOR } RayCrossingCounter.prototype.getLocation = function getLocation () { if (this._isPointOnSegment) { return Location.BOUNDARY } if (this._crossingCount % 2 === 1) { return Location.INTERIOR } return Location.EXTERIOR } RayCrossingCounter.prototype.isOnSegment = function isOnSegment () { return this._isPointOnSegment } RayCrossingCounter.prototype.interfaces_ = function interfaces_ () { return [] } RayCrossingCounter.prototype.getClass = function getClass () { return RayCrossingCounter } RayCrossingCounter.locatePointInRing = function locatePointInRing () { if (arguments[0] instanceof Coordinate && hasInterface(arguments[1], CoordinateSequence)) { var p = arguments[0] var ring = arguments[1] var counter = new RayCrossingCounter(p) var p1 = new Coordinate() var p2 = new Coordinate() for (var i = 1; i < ring.size(); i++) { ring.getCoordinate(i, p1) ring.getCoordinate(i - 1, p2) counter.countSegment(p1, p2) if (counter.isOnSegment()) { return counter.getLocation() } } return counter.getLocation() } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Array) { var p$1 = arguments[0] var ring$1 = arguments[1] var counter$1 = new RayCrossingCounter(p$1) for (var i$1 = 1; i$1 < ring$1.length; i$1++) { var p1$1 = ring$1[i$1] var p2$1 = ring$1[i$1 - 1] counter$1.countSegment(p1$1, p2$1) if (counter$1.isOnSegment()) { return counter$1.getLocation() } } return counter$1.getLocation() } } var CGAlgorithms = function CGAlgorithms () { } var staticAccessors$3 = { CLOCKWISE: { configurable: true }, RIGHT: { configurable: true }, COUNTERCLOCKWISE: { configurable: true }, LEFT: { configurable: true }, COLLINEAR: { configurable: true }, STRAIGHT: { configurable: true } } CGAlgorithms.prototype.interfaces_ = function interfaces_ () { return [] } CGAlgorithms.prototype.getClass = function getClass () { return CGAlgorithms } CGAlgorithms.orientationIndex = function orientationIndex (p1, p2, q) { return CGAlgorithmsDD.orientationIndex(p1, p2, q) } CGAlgorithms.signedArea = function signedArea () { if (arguments[0] instanceof Array) { var ring = arguments[0] if (ring.length < 3) { return 0.0 } var sum = 0.0 var x0 = ring[0].x for (var i = 1; i < ring.length - 1; i++) { var x = ring[i].x - x0 var y1 = ring[i + 1].y var y2 = ring[i - 1].y sum += x * (y2 - y1) } return sum / 2.0 } else if (hasInterface(arguments[0], CoordinateSequence)) { var ring$1 = arguments[0] var n = ring$1.size() if (n < 3) { return 0.0 } var p0 = new Coordinate() var p1 = new Coordinate() var p2 = new Coordinate() ring$1.getCoordinate(0, p1) ring$1.getCoordinate(1, p2) var x0$1 = p1.x p2.x -= x0$1 var sum$1 = 0.0 for (var i$1 = 1; i$1 < n - 1; i$1++) { p0.y = p1.y p1.x = p2.x p1.y = p2.y ring$1.getCoordinate(i$1 + 1, p2) p2.x -= x0$1 sum$1 += p1.x * (p0.y - p2.y) } return sum$1 / 2.0 } } CGAlgorithms.distanceLineLine = function distanceLineLine (A, B, C, D) { if (A.equals(B)) { return CGAlgorithms.distancePointLine(A, C, D) } if (C.equals(D)) { return CGAlgorithms.distancePointLine(D, A, B) } var noIntersection = false if (!Envelope.intersects(A, B, C, D)) { noIntersection = true } else { var denom = (B.x - A.x) * (D.y - C.y) - (B.y - A.y) * (D.x - C.x) if (denom === 0) { noIntersection = true } else { var rNumb = (A.y - C.y) * (D.x - C.x) - (A.x - C.x) * (D.y - C.y) var sNum = (A.y - C.y) * (B.x - A.x) - (A.x - C.x) * (B.y - A.y) var s = sNum / denom var r = rNumb / denom if (r < 0 || r > 1 || s < 0 || s > 1) { noIntersection = true } } } if (noIntersection) { return MathUtil.min(CGAlgorithms.distancePointLine(A, C, D), CGAlgorithms.distancePointLine(B, C, D), CGAlgorithms.distancePointLine(C, A, B), CGAlgorithms.distancePointLine(D, A, B)) } return 0.0 } CGAlgorithms.isPointInRing = function isPointInRing (p, ring) { return CGAlgorithms.locatePointInRing(p, ring) !== Location.EXTERIOR } CGAlgorithms.computeLength = function computeLength (pts) { var n = pts.size() if (n <= 1) { return 0.0 } var len = 0.0 var p = new Coordinate() pts.getCoordinate(0, p) var x0 = p.x var y0 = p.y for (var i = 1; i < n; i++) { pts.getCoordinate(i, p) var x1 = p.x var y1 = p.y var dx = x1 - x0 var dy = y1 - y0 len += Math.sqrt(dx * dx + dy * dy) x0 = x1 y0 = y1 } return len } CGAlgorithms.isCCW = function isCCW (ring) { var nPts = ring.length - 1 if (nPts < 3) { throw new IllegalArgumentException('Ring has fewer than 4 points, so orientation cannot be determined') } var hiPt = ring[0] var hiIndex = 0 for (var i = 1; i <= nPts; i++) { var p = ring[i] if (p.y > hiPt.y) { hiPt = p hiIndex = i } } var iPrev = hiIndex do { iPrev = iPrev - 1 if (iPrev < 0) { iPrev = nPts } } while (ring[iPrev].equals2D(hiPt) && iPrev !== hiIndex) var iNext = hiIndex do { iNext = (iNext + 1) % nPts } while (ring[iNext].equals2D(hiPt) && iNext !== hiIndex) var prev = ring[iPrev] var next = ring[iNext] if (prev.equals2D(hiPt) || next.equals2D(hiPt) || prev.equals2D(next)) { return false } var disc = CGAlgorithms.computeOrientation(prev, hiPt, next) var isCCW = false if (disc === 0) { isCCW = prev.x > next.x } else { isCCW = disc > 0 } return isCCW } CGAlgorithms.locatePointInRing = function locatePointInRing (p, ring) { return RayCrossingCounter.locatePointInRing(p, ring) } CGAlgorithms.distancePointLinePerpendicular = function distancePointLinePerpendicular (p, A, B) { var len2 = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y) var s = ((A.y - p.y) * (B.x - A.x) - (A.x - p.x) * (B.y - A.y)) / len2 return Math.abs(s) * Math.sqrt(len2) } CGAlgorithms.computeOrientation = function computeOrientation (p1, p2, q) { return CGAlgorithms.orientationIndex(p1, p2, q) } CGAlgorithms.distancePointLine = function distancePointLine () { if (arguments.length === 2) { var p = arguments[0] var line = arguments[1] if (line.length === 0) { throw new IllegalArgumentException('Line array must contain at least one vertex') } var minDistance = p.distance(line[0]) for (var i = 0; i < line.length - 1; i++) { var dist = CGAlgorithms.distancePointLine(p, line[i], line[i + 1]) if (dist < minDistance) { minDistance = dist } } return minDistance } else if (arguments.length === 3) { var p$1 = arguments[0] var A = arguments[1] var B = arguments[2] if (A.x === B.x && A.y === B.y) { return p$1.distance(A) } var len2 = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y) var r = ((p$1.x - A.x) * (B.x - A.x) + (p$1.y - A.y) * (B.y - A.y)) / len2 if (r <= 0.0) { return p$1.distance(A) } if (r >= 1.0) { return p$1.distance(B) } var s = ((A.y - p$1.y) * (B.x - A.x) - (A.x - p$1.x) * (B.y - A.y)) / len2 return Math.abs(s) * Math.sqrt(len2) } } CGAlgorithms.isOnLine = function isOnLine (p, pt) { var lineIntersector = new RobustLineIntersector() for (var i = 1; i < pt.length; i++) { var p0 = pt[i - 1] var p1 = pt[i] lineIntersector.computeIntersection(p, p0, p1) if (lineIntersector.hasIntersection()) { return true } } return false } staticAccessors$3.CLOCKWISE.get = function () { return -1 } staticAccessors$3.RIGHT.get = function () { return CGAlgorithms.CLOCKWISE } staticAccessors$3.COUNTERCLOCKWISE.get = function () { return 1 } staticAccessors$3.LEFT.get = function () { return CGAlgorithms.COUNTERCLOCKWISE } staticAccessors$3.COLLINEAR.get = function () { return 0 } staticAccessors$3.STRAIGHT.get = function () { return CGAlgorithms.COLLINEAR } Object.defineProperties(CGAlgorithms, staticAccessors$3) var GeometryComponentFilter = function GeometryComponentFilter () { } GeometryComponentFilter.prototype.filter = function filter (geom) { } GeometryComponentFilter.prototype.interfaces_ = function interfaces_ () { return [] } GeometryComponentFilter.prototype.getClass = function getClass () { return GeometryComponentFilter } var Geometry$2 = function Geometry () { var factory = arguments[0] this._envelope = null this._factory = null this._SRID = null this._userData = null this._factory = factory this._SRID = factory.getSRID() } var staticAccessors$11 = { serialVersionUID: { configurable: true }, SORTINDEX_POINT: { configurable: true }, SORTINDEX_MULTIPOINT: { configurable: true }, SORTINDEX_LINESTRING: { configurable: true }, SORTINDEX_LINEARRING: { configurable: true }, SORTINDEX_MULTILINESTRING: { configurable: true }, SORTINDEX_POLYGON: { configurable: true }, SORTINDEX_MULTIPOLYGON: { configurable: true }, SORTINDEX_GEOMETRYCOLLECTION: { configurable: true }, geometryChangedFilter: { configurable: true } } Geometry$2.prototype.isGeometryCollection = function isGeometryCollection () { return this.getSortIndex() === Geometry$2.SORTINDEX_GEOMETRYCOLLECTION } Geometry$2.prototype.getFactory = function getFactory () { return this._factory } Geometry$2.prototype.getGeometryN = function getGeometryN (n) { return this } Geometry$2.prototype.getArea = function getArea () { return 0.0 } Geometry$2.prototype.isRectangle = function isRectangle () { return false } Geometry$2.prototype.equals = function equals () { if (arguments[0] instanceof Geometry$2) { var g$1 = arguments[0] if (g$1 === null) { return false } return this.equalsTopo(g$1) } else if (arguments[0] instanceof Object) { var o = arguments[0] if (!(o instanceof Geometry$2)) { return false } var g = o return this.equalsExact(g) } } Geometry$2.prototype.equalsExact = function equalsExact (other) { return this === other || this.equalsExact(other, 0) } Geometry$2.prototype.geometryChanged = function geometryChanged () { this.apply(Geometry$2.geometryChangedFilter) } Geometry$2.prototype.geometryChangedAction = function geometryChangedAction () { this._envelope = null } Geometry$2.prototype.equalsNorm = function equalsNorm (g) { if (g === null) { return false } return this.norm().equalsExact(g.norm()) } Geometry$2.prototype.getLength = function getLength () { return 0.0 } Geometry$2.prototype.getNumGeometries = function getNumGeometries () { return 1 } Geometry$2.prototype.compareTo = function compareTo () { if (arguments.length === 1) { var o = arguments[0] var other = o if (this.getSortIndex() !== other.getSortIndex()) { return this.getSortIndex() - other.getSortIndex() } if (this.isEmpty() && other.isEmpty()) { return 0 } if (this.isEmpty()) { return -1 } if (other.isEmpty()) { return 1 } return this.compareToSameClass(o) } else if (arguments.length === 2) { var other$1 = arguments[0] var comp = arguments[1] if (this.getSortIndex() !== other$1.getSortIndex()) { return this.getSortIndex() - other$1.getSortIndex() } if (this.isEmpty() && other$1.isEmpty()) { return 0 } if (this.isEmpty()) { return -1 } if (other$1.isEmpty()) { return 1 } return this.compareToSameClass(other$1, comp) } } Geometry$2.prototype.getUserData = function getUserData () { return this._userData } Geometry$2.prototype.getSRID = function getSRID () { return this._SRID } Geometry$2.prototype.getEnvelope = function getEnvelope () { return this.getFactory().toGeometry(this.getEnvelopeInternal()) } Geometry$2.prototype.checkNotGeometryCollection = function checkNotGeometryCollection (g) { if (g.getSortIndex() === Geometry$2.SORTINDEX_GEOMETRYCOLLECTION) { throw new IllegalArgumentException('This method does not support GeometryCollection arguments') } } Geometry$2.prototype.equal = function equal (a, b, tolerance) { if (tolerance === 0) { return a.equals(b) } return a.distance(b) <= tolerance } Geometry$2.prototype.norm = function norm () { var copy = this.copy() copy.normalize() return copy } Geometry$2.prototype.getPrecisionModel = function getPrecisionModel () { return this._factory.getPrecisionModel() } Geometry$2.prototype.getEnvelopeInternal = function getEnvelopeInternal () { if (this._envelope === null) { this._envelope = this.computeEnvelopeInternal() } return new Envelope(this._envelope) } Geometry$2.prototype.setSRID = function setSRID (SRID) { this._SRID = SRID } Geometry$2.prototype.setUserData = function setUserData (userData) { this._userData = userData } Geometry$2.prototype.compare = function compare (a, b) { var i = a.iterator() var j = b.iterator() while (i.hasNext() && j.hasNext()) { var aElement = i.next() var bElement = j.next() var comparison = aElement.compareTo(bElement) if (comparison !== 0) { return comparison } } if (i.hasNext()) { return 1 } if (j.hasNext()) { return -1 } return 0 } Geometry$2.prototype.hashCode = function hashCode () { return this.getEnvelopeInternal().hashCode() } Geometry$2.prototype.isGeometryCollectionOrDerived = function isGeometryCollectionOrDerived () { if (this.getSortIndex() === Geometry$2.SORTINDEX_GEOMETRYCOLLECTION || this.getSortIndex() === Geometry$2.SORTINDEX_MULTIPOINT || this.getSortIndex() === Geometry$2.SORTINDEX_MULTILINESTRING || this.getSortIndex() === Geometry$2.SORTINDEX_MULTIPOLYGON) { return true } return false } Geometry$2.prototype.interfaces_ = function interfaces_ () { return [Clonable, Comparable, Serializable] } Geometry$2.prototype.getClass = function getClass () { return Geometry$2 } Geometry$2.hasNonEmptyElements = function hasNonEmptyElements (geometries) { for (var i = 0; i < geometries.length; i++) { if (!geometries[i].isEmpty()) { return true } } return false } Geometry$2.hasNullElements = function hasNullElements (array) { for (var i = 0; i < array.length; i++) { if (array[i] === null) { return true } } return false } staticAccessors$11.serialVersionUID.get = function () { return 8763622679187376702 } staticAccessors$11.SORTINDEX_POINT.get = function () { return 0 } staticAccessors$11.SORTINDEX_MULTIPOINT.get = function () { return 1 } staticAccessors$11.SORTINDEX_LINESTRING.get = function () { return 2 } staticAccessors$11.SORTINDEX_LINEARRING.get = function () { return 3 } staticAccessors$11.SORTINDEX_MULTILINESTRING.get = function () { return 4 } staticAccessors$11.SORTINDEX_POLYGON.get = function () { return 5 } staticAccessors$11.SORTINDEX_MULTIPOLYGON.get = function () { return 6 } staticAccessors$11.SORTINDEX_GEOMETRYCOLLECTION.get = function () { return 7 } staticAccessors$11.geometryChangedFilter.get = function () { return geometryChangedFilter } Object.defineProperties(Geometry$2, staticAccessors$11) var geometryChangedFilter = function geometryChangedFilter () { } geometryChangedFilter.interfaces_ = function interfaces_ () { return [GeometryComponentFilter] } geometryChangedFilter.filter = function filter (geom) { geom.geometryChangedAction() } var CoordinateFilter = function CoordinateFilter () { } CoordinateFilter.prototype.filter = function filter (coord) { } CoordinateFilter.prototype.interfaces_ = function interfaces_ () { return [] } CoordinateFilter.prototype.getClass = function getClass () { return CoordinateFilter } var BoundaryNodeRule = function BoundaryNodeRule () { } var staticAccessors$12 = { Mod2BoundaryNodeRule: { configurable: true }, EndPointBoundaryNodeRule: { configurable: true }, MultiValentEndPointBoundaryNodeRule: { configurable: true }, MonoValentEndPointBoundaryNodeRule: { configurable: true }, MOD2_BOUNDARY_RULE: { configurable: true }, ENDPOINT_BOUNDARY_RULE: { configurable: true }, MULTIVALENT_ENDPOINT_BOUNDARY_RULE: { configurable: true }, MONOVALENT_ENDPOINT_BOUNDARY_RULE: { configurable: true }, OGC_SFS_BOUNDARY_RULE: { configurable: true } } BoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) { } BoundaryNodeRule.prototype.interfaces_ = function interfaces_ () { return [] } BoundaryNodeRule.prototype.getClass = function getClass () { return BoundaryNodeRule } staticAccessors$12.Mod2BoundaryNodeRule.get = function () { return Mod2BoundaryNodeRule } staticAccessors$12.EndPointBoundaryNodeRule.get = function () { return EndPointBoundaryNodeRule } staticAccessors$12.MultiValentEndPointBoundaryNodeRule.get = function () { return MultiValentEndPointBoundaryNodeRule } staticAccessors$12.MonoValentEndPointBoundaryNodeRule.get = function () { return MonoValentEndPointBoundaryNodeRule } staticAccessors$12.MOD2_BOUNDARY_RULE.get = function () { return new Mod2BoundaryNodeRule() } staticAccessors$12.ENDPOINT_BOUNDARY_RULE.get = function () { return new EndPointBoundaryNodeRule() } staticAccessors$12.MULTIVALENT_ENDPOINT_BOUNDARY_RULE.get = function () { return new MultiValentEndPointBoundaryNodeRule() } staticAccessors$12.MONOVALENT_ENDPOINT_BOUNDARY_RULE.get = function () { return new MonoValentEndPointBoundaryNodeRule() } staticAccessors$12.OGC_SFS_BOUNDARY_RULE.get = function () { return BoundaryNodeRule.MOD2_BOUNDARY_RULE } Object.defineProperties(BoundaryNodeRule, staticAccessors$12) var Mod2BoundaryNodeRule = function Mod2BoundaryNodeRule () { } Mod2BoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) { return boundaryCount % 2 === 1 } Mod2BoundaryNodeRule.prototype.interfaces_ = function interfaces_ () { return [BoundaryNodeRule] } Mod2BoundaryNodeRule.prototype.getClass = function getClass () { return Mod2BoundaryNodeRule } var EndPointBoundaryNodeRule = function EndPointBoundaryNodeRule () { } EndPointBoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) { return boundaryCount > 0 } EndPointBoundaryNodeRule.prototype.interfaces_ = function interfaces_ () { return [BoundaryNodeRule] } EndPointBoundaryNodeRule.prototype.getClass = function getClass () { return EndPointBoundaryNodeRule } var MultiValentEndPointBoundaryNodeRule = function MultiValentEndPointBoundaryNodeRule () { } MultiValentEndPointBoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) { return boundaryCount > 1 } MultiValentEndPointBoundaryNodeRule.prototype.interfaces_ = function interfaces_ () { return [BoundaryNodeRule] } MultiValentEndPointBoundaryNodeRule.prototype.getClass = function getClass () { return MultiValentEndPointBoundaryNodeRule } var MonoValentEndPointBoundaryNodeRule = function MonoValentEndPointBoundaryNodeRule () { } MonoValentEndPointBoundaryNodeRule.prototype.isInBoundary = function isInBoundary (boundaryCount) { return boundaryCount === 1 } MonoValentEndPointBoundaryNodeRule.prototype.interfaces_ = function interfaces_ () { return [BoundaryNodeRule] } MonoValentEndPointBoundaryNodeRule.prototype.getClass = function getClass () { return MonoValentEndPointBoundaryNodeRule } // import Iterator from './Iterator' /** * @see http://download.oracle.com/javase/6/docs/api/java/util/Collection.html * * @constructor * @private */ var Collection = function Collection () { } Collection.prototype.add = function add () { } /** * Appends all of the elements in the specified collection to the end of this * list, in the order that they are returned by the specified collection's * iterator (optional operation). * @param {javascript.util.Collection} c * @return {boolean} */ Collection.prototype.addAll = function addAll () { } /** * Returns true if this collection contains no elements. * @return {boolean} */ Collection.prototype.isEmpty = function isEmpty () { } /** * Returns an iterator over the elements in this collection. * @return {javascript.util.Iterator} */ Collection.prototype.iterator = function iterator () { } /** * Returns an iterator over the elements in this collection. * @return {number} */ Collection.prototype.size = function size () { } /** * Returns an array containing all of the elements in this collection. * @return {Array} */ Collection.prototype.toArray = function toArray () { } /** * Removes a single instance of the specified element from this collection if it * is present. (optional) * @param {Object} e * @return {boolean} */ Collection.prototype.remove = function remove () { } /** * @param {string=} message Optional message * @extends {Error} * @constructor * @private */ function IndexOutOfBoundsException (message) { this.message = message || '' } IndexOutOfBoundsException.prototype = new Error() /** * @type {string} */ IndexOutOfBoundsException.prototype.name = 'IndexOutOfBoundsException' /** * @see http://download.oracle.com/javase/6/docs/api/java/util/Iterator.html * @constructor * @private */ var Iterator = function Iterator () { } Iterator.prototype.hasNext = function hasNext () { } /** * Returns the next element in the iteration. * @return {Object} */ Iterator.prototype.next = function next () { } /** * Removes from the underlying collection the last element returned by the * iterator (optional operation). */ Iterator.prototype.remove = function remove () { } /** * @see http://download.oracle.com/javase/6/docs/api/java/util/List.html * * @extends {javascript.util.Collection} * @constructor * @private */ var List = (function (Collection$$1) { function List () { Collection$$1.apply(this, arguments) } if (Collection$$1) List.__proto__ = Collection$$1 List.prototype = Object.create(Collection$$1 && Collection$$1.prototype) List.prototype.constructor = List List.prototype.get = function get () { } /** * Replaces the element at the specified position in this list with the * specified element (optional operation). * @param {number} index * @param {Object} e * @return {Object} */ List.prototype.set = function set () { } /** * Returns true if this collection contains no elements. * @return {boolean} */ List.prototype.isEmpty = function isEmpty () { } return List }(Collection)) /** * @param {string=} message Optional message * @extends {Error} * @constructor * @private */ function NoSuchElementException (message) { this.message = message || '' } NoSuchElementException.prototype = new Error() /** * @type {string} */ NoSuchElementException.prototype.name = 'NoSuchElementException' // import OperationNotSupported from './OperationNotSupported' /** * @see http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html * * @extends List * @private */ var ArrayList = (function (List$$1) { function ArrayList () { List$$1.call(this) this.array_ = [] if (arguments[0] instanceof Collection) { this.addAll(arguments[0]) } } if (List$$1) ArrayList.__proto__ = List$$1 ArrayList.prototype = Object.create(List$$1 && List$$1.prototype) ArrayList.prototype.constructor = ArrayList ArrayList.prototype.ensureCapacity = function ensureCapacity () { } ArrayList.prototype.interfaces_ = function interfaces_ () { return [List$$1, Collection] } /** * @override */ ArrayList.prototype.add = function add (e) { if (arguments.length === 1) { this.array_.push(e) } else { this.array_.splice(arguments[0], arguments[1]) } return true } ArrayList.prototype.clear = function clear () { this.array_ = [] } /** * @override */ ArrayList.prototype.addAll = function addAll (c) { var this$1$1 = this for (var i = c.iterator(); i.hasNext();) { this$1$1.add(i.next()) } return true } /** * @override */ ArrayList.prototype.set = function set (index, element) { var oldElement = this.array_[index] this.array_[index] = element return oldElement } /** * @override */ ArrayList.prototype.iterator = function iterator () { return new Iterator_(this) } /** * @override */ ArrayList.prototype.get = function get (index) { if (index < 0 || index >= this.size()) { throw new IndexOutOfBoundsException() } return this.array_[index] } /** * @override */ ArrayList.prototype.isEmpty = function isEmpty () { return this.array_.length === 0 } /** * @override */ ArrayList.prototype.size = function size () { return this.array_.length } /** * @override */ ArrayList.prototype.toArray = function toArray () { var this$1$1 = this var array = [] for (var i = 0, len = this.array_.length; i < len; i++) { array.push(this$1$1.array_[i]) } return array } /** * @override */ ArrayList.prototype.remove = function remove (o) { var this$1$1 = this var found = false for (var i = 0, len = this.array_.length; i < len; i++) { if (this$1$1.array_[i] === o) { this$1$1.array_.splice(i, 1) found = true break } } return found } return ArrayList }(List)) /** * @extends {Iterator} * @param {ArrayList} arrayList * @constructor * @private */ var Iterator_ = (function (Iterator$$1) { function Iterator_ (arrayList) { Iterator$$1.call(this) /** * @type {ArrayList} * @private */ this.arrayList_ = arrayList /** * @type {number} * @private */ this.position_ = 0 } if (Iterator$$1) Iterator_.__proto__ = Iterator$$1 Iterator_.prototype = Object.create(Iterator$$1 && Iterator$$1.prototype) Iterator_.prototype.constructor = Iterator_ /** * @override */ Iterator_.prototype.next = function next () { if (this.position_ === this.arrayList_.size()) { throw new NoSuchElementException() } return this.arrayList_.get(this.position_++) } /** * @override */ Iterator_.prototype.hasNext = function hasNext () { if (this.position_ < this.arrayList_.size()) { return true } else { return false } } /** * TODO: should be in ListIterator * @override */ Iterator_.prototype.set = function set (element) { return this.arrayList_.set(this.position_ - 1, element) } /** * @override */ Iterator_.prototype.remove = function remove () { this.arrayList_.remove(this.arrayList_.get(this.position_)) } return Iterator_ }(Iterator)) var CoordinateList = (function (ArrayList$$1) { function CoordinateList () { ArrayList$$1.call(this) if (arguments.length === 0); else if (arguments.length === 1) { var coord = arguments[0] this.ensureCapacity(coord.length) this.add(coord, true) } else if (arguments.length === 2) { var coord$1 = arguments[0] var allowRepeated = arguments[1] this.ensureCapacity(coord$1.length) this.add(coord$1, allowRepeated) } } if (ArrayList$$1) CoordinateList.__proto__ = ArrayList$$1 CoordinateList.prototype = Object.create(ArrayList$$1 && ArrayList$$1.prototype) CoordinateList.prototype.constructor = CoordinateList var staticAccessors = { coordArrayType: { configurable: true } } staticAccessors.coordArrayType.get = function () { return new Array(0).fill(null) } CoordinateList.prototype.getCoordinate = function getCoordinate (i) { return this.get(i) } CoordinateList.prototype.addAll = function addAll () { var this$1$1 = this if (arguments.length === 2) { var coll = arguments[0] var allowRepeated = arguments[1] var isChanged = false for (var i = coll.iterator(); i.hasNext();) { this$1$1.add(i.next(), allowRepeated) isChanged = true } return isChanged } else { return ArrayList$$1.prototype.addAll.apply(this, arguments) } } CoordinateList.prototype.clone = function clone () { var this$1$1 = this var clone = ArrayList$$1.prototype.clone.call(this) for (var i = 0; i < this.size(); i++) { clone.add(i, this$1$1.get(i).copy()) } return clone } CoordinateList.prototype.toCoordinateArray = function toCoordinateArray () { return this.toArray(CoordinateList.coordArrayType) } CoordinateList.prototype.add = function add () { var this$1$1 = this if (arguments.length === 1) { var coord = arguments[0] ArrayList$$1.prototype.add.call(this, coord) } else if (arguments.length === 2) { if (arguments[0] instanceof Array && typeof arguments[1] === 'boolean') { var coord$1 = arguments[0] var allowRepeated = arguments[1] this.add(coord$1, allowRepeated, true) return true } else if (arguments[0] instanceof Coordinate && typeof arguments[1] === 'boolean') { var coord$2 = arguments[0] var allowRepeated$1 = arguments[1] if (!allowRepeated$1) { if (this.size() >= 1) { var last = this.get(this.size() - 1) if (last.equals2D(coord$2)) { return null } } } ArrayList$$1.prototype.add.call(this, coord$2) } else if (arguments[0] instanceof Object && typeof arguments[1] === 'boolean') { var obj = arguments[0] var allowRepeated$2 = arguments[1] this.add(obj, allowRepeated$2) return true } } else if (arguments.length === 3) { if (typeof arguments[2] === 'boolean' && (arguments[0] instanceof Array && typeof arguments[1] === 'boolean')) { var coord$3 = arguments[0] var allowRepeated$3 = arguments[1] var direction = arguments[2] if (direction) { for (var i$1 = 0; i$1 < coord$3.length; i$1++) { this$1$1.add(coord$3[i$1], allowRepeated$3) } } else { for (var i$2 = coord$3.length - 1; i$2 >= 0; i$2--) { this$1$1.add(coord$3[i$2], allowRepeated$3) } } return true } else if (typeof arguments[2] === 'boolean' && (Number.isInteger(arguments[0]) && arguments[1] instanceof Coordinate)) { var i$3 = arguments[0] var coord$4 = arguments[1] var allowRepeated$4 = arguments[2] if (!allowRepeated$4) { var size = this.size() if (size > 0) { if (i$3 > 0) { var prev = this.get(i$3 - 1) if (prev.equals2D(coord$4)) { return null } } if (i$3 < size) { var next = this.get(i$3) if (next.equals2D(coord$4)) { return null } } } } ArrayList$$1.prototype.add.call(this, i$3, coord$4) } } else if (arguments.length === 4) { var coord$5 = arguments[0] var allowRepeated$5 = arguments[1] var start = arguments[2] var end = arguments[3] var inc = 1 if (start > end) { inc = -1 } for (var i = start; i !== end; i += inc) { this$1$1.add(coord$5[i], allowRepeated$5) } return true } } CoordinateList.prototype.closeRing = function closeRing () { if (this.size() > 0) { this.add(new Coordinate(this.get(0)), false) } } CoordinateList.prototype.interfaces_ = function interfaces_ () { return [] } CoordinateList.prototype.getClass = function getClass () { return CoordinateList } Object.defineProperties(CoordinateList, staticAccessors) return CoordinateList }(ArrayList)) var CoordinateArrays = function CoordinateArrays () { } var staticAccessors$13 = { ForwardComparator: { configurable: true }, BidirectionalComparator: { configurable: true }, coordArrayType: { configurable: true } } staticAccessors$13.ForwardComparator.get = function () { return ForwardComparator } staticAccessors$13.BidirectionalComparator.get = function () { return BidirectionalComparator } staticAccessors$13.coordArrayType.get = function () { return new Array(0).fill(null) } CoordinateArrays.prototype.interfaces_ = function interfaces_ () { return [] } CoordinateArrays.prototype.getClass = function getClass () { return CoordinateArrays } CoordinateArrays.isRing = function isRing (pts) { if (pts.length < 4) { return false } if (!pts[0].equals2D(pts[pts.length - 1])) { return false } return true } CoordinateArrays.ptNotInList = function ptNotInList (testPts, pts) { for (var i = 0; i < testPts.length; i++) { var testPt = testPts[i] if (CoordinateArrays.indexOf(testPt, pts) < 0) { return testPt } } return null } CoordinateArrays.scroll = function scroll (coordinates, firstCoordinate) { var i = CoordinateArrays.indexOf(firstCoordinate, coordinates) if (i < 0) { return null } var newCoordinates = new Array(coordinates.length).fill(null) System.arraycopy(coordinates, i, newCoordinates, 0, coordinates.length - i) System.arraycopy(coordinates, 0, newCoordinates, coordinates.length - i, i) System.arraycopy(newCoordinates, 0, coordinates, 0, coordinates.length) } CoordinateArrays.equals = function equals () { if (arguments.length === 2) { var coord1 = arguments[0] var coord2 = arguments[1] if (coord1 === coord2) { return true } if (coord1 === null || coord2 === null) { return false } if (coord1.length !== coord2.length) { return false } for (var i = 0; i < coord1.length; i++) { if (!coord1[i].equals(coord2[i])) { return false } } return true } else if (arguments.length === 3) { var coord1$1 = arguments[0] var coord2$1 = arguments[1] var coordinateComparator = arguments[2] if (coord1$1 === coord2$1) { return true } if (coord1$1 === null || coord2$1 === null) { return false } if (coord1$1.length !== coord2$1.length) { return false } for (var i$1 = 0; i$1 < coord1$1.length; i$1++) { if (coordinateComparator.compare(coord1$1[i$1], coord2$1[i$1]) !== 0) { return false } } return true } } CoordinateArrays.intersection = function intersection (coordinates, env) { var coordList = new CoordinateList() for (var i = 0; i < coordinates.length; i++) { if (env.intersects(coordinates[i])) { coordList.add(coordinates[i], true) } } return coordList.toCoordinateArray() } CoordinateArrays.hasRepeatedPoints = function hasRepeatedPoints (coord) { for (var i = 1; i < coord.length; i++) { if (coord[i - 1].equals(coord[i])) { return true } } return false } CoordinateArrays.removeRepeatedPoints = function removeRepeatedPoints (coord) { if (!CoordinateArrays.hasRepeatedPoints(coord)) { return coord } var coordList = new CoordinateList(coord, false) return coordList.toCoordinateArray() } CoordinateArrays.reverse = function reverse (coord) { var last = coord.length - 1 var mid = Math.trunc(last / 2) for (var i = 0; i <= mid; i++) { var tmp = coord[i] coord[i] = coord[last - i] coord[last - i] = tmp } } CoordinateArrays.removeNull = function removeNull (coord) { var nonNull = 0 for (var i = 0; i < coord.length; i++) { if (coord[i] !== null) { nonNull++ } } var newCoord = new Array(nonNull).fill(null) if (nonNull === 0) { return newCoord } var j = 0 for (var i$1 = 0; i$1 < coord.length; i$1++) { if (coord[i$1] !== null) { newCoord[j++] = coord[i$1] } } return newCoord } CoordinateArrays.copyDeep = function copyDeep () { if (arguments.length === 1) { var coordinates = arguments[0] var copy = new Array(coordinates.length).fill(null) for (var i = 0; i < coordinates.length; i++) { copy[i] = new Coordinate(coordinates[i]) } return copy } else if (arguments.length === 5) { var src = arguments[0] var srcStart = arguments[1] var dest = arguments[2] var destStart = arguments[3] var length = arguments[4] for (var i$1 = 0; i$1 < length; i$1++) { dest[destStart + i$1] = new Coordinate(src[srcStart + i$1]) } } } CoordinateArrays.isEqualReversed = function isEqualReversed (pts1, pts2) { for (var i = 0; i < pts1.length; i++) { var p1 = pts1[i] var p2 = pts2[pts1.length - i - 1] if (p1.compareTo(p2) !== 0) { return false } } return true } CoordinateArrays.envelope = function envelope (coordinates) { var env = new Envelope() for (var i = 0; i < coordinates.length; i++) { env.expandToInclude(coordinates[i]) } return env } CoordinateArrays.toCoordinateArray = function toCoordinateArray (coordList) { return coordList.toArray(CoordinateArrays.coordArrayType) } CoordinateArrays.atLeastNCoordinatesOrNothing = function atLeastNCoordinatesOrNothing (n, c) { return c.length >= n ? c : [] } CoordinateArrays.indexOf = function indexOf (coordinate, coordinates) { for (var i = 0; i < coordinates.length; i++) { if (coordinate.equals(coordinates[i])) { return i } } return -1 } CoordinateArrays.increasingDirection = function increasingDirection (pts) { for (var i = 0; i < Math.trunc(pts.length / 2); i++) { var j = pts.length - 1 - i var comp = pts[i].compareTo(pts[j]) if (comp !== 0) { return comp } } return 1 } CoordinateArrays.compare = function compare (pts1, pts2) { var i = 0 while (i < pts1.length && i < pts2.length) { var compare = pts1[i].compareTo(pts2[i]) if (compare !== 0) { return compare } i++ } if (i < pts2.length) { return -1 } if (i < pts1.length) { return 1 } return 0 } CoordinateArrays.minCoordinate = function minCoordinate (coordinates) { var minCoord = null for (var i = 0; i < coordinates.length; i++) { if (minCoord === null || minCoord.compareTo(coordinates[i]) > 0) { minCoord = coordinates[i] } } return minCoord } CoordinateArrays.extract = function extract (pts, start, end) { start = MathUtil.clamp(start, 0, pts.length) end = MathUtil.clamp(end, -1, pts.length) var npts = end - start + 1 if (end < 0) { npts = 0 } if (start >= pts.length) { npts = 0 } if (end < start) { npts = 0 } var extractPts = new Array(npts).fill(null) if (npts === 0) { return extractPts } var iPts = 0 for (var i = start; i <= end; i++) { extractPts[iPts++] = pts[i] } return extractPts } Object.defineProperties(CoordinateArrays, staticAccessors$13) var ForwardComparator = function ForwardComparator () { } ForwardComparator.prototype.compare = function compare (o1, o2) { var pts1 = o1 var pts2 = o2 return CoordinateArrays.compare(pts1, pts2) } ForwardComparator.prototype.interfaces_ = function interfaces_ () { return [Comparator] } ForwardComparator.prototype.getClass = function getClass () { return ForwardComparator } var BidirectionalComparator = function BidirectionalComparator () { } BidirectionalComparator.prototype.compare = function compare (o1, o2) { var pts1 = o1 var pts2 = o2 if (pts1.length < pts2.length) { return -1 } if (pts1.length > pts2.length) { return 1 } if (pts1.length === 0) { return 0 } var forwardComp = CoordinateArrays.compare(pts1, pts2) var isEqualRev = CoordinateArrays.isEqualReversed(pts1, pts2) if (isEqualRev) { return 0 } return forwardComp } BidirectionalComparator.prototype.OLDcompare = function OLDcompare (o1, o2) { var pts1 = o1 var pts2 = o2 if (pts1.length < pts2.length) { return -1 } if (pts1.length > pts2.length) { return 1 } if (pts1.length === 0) { return 0 } var dir1 = CoordinateArrays.increasingDirection(pts1) var dir2 = CoordinateArrays.increasingDirection(pts2) var i1 = dir1 > 0 ? 0 : pts1.length - 1 var i2 = dir2 > 0 ? 0 : pts1.length - 1 for (var i = 0; i < pts1.length; i++) { var comparePt = pts1[i1].compareTo(pts2[i2]) if (comparePt !== 0) { return comparePt } i1 += dir1 i2 += dir2 } return 0 } BidirectionalComparator.prototype.interfaces_ = function interfaces_ () { return [Comparator] } BidirectionalComparator.prototype.getClass = function getClass () { return BidirectionalComparator } /** * @see http://download.oracle.com/javase/6/docs/api/java/util/Map.html * * @constructor * @private */ var Map$1 = function Map () { } Map$1.prototype.get = function get () { } /** * Associates the specified value with the specified key in this map (optional * operation). * @param {Object} key * @param {Object} value * @return {Object} */ Map$1.prototype.put = function put () { } /** * Returns the number of key-value mappings in this map. * @return {number} */ Map$1.prototype.size = function size () { } /** * Returns a Collection view of the values contained in this map. * @return {javascript.util.Collection} */ Map$1.prototype.values = function values () { } /** * Returns a {@link Set} view of the mappings contained in this map. * The set is backed by the map, so changes to the map are * reflected in the set, and vice-versa.If the map is modified * while an iteration over the set is in progress (except through * the iterator's own remove operation, or through the * setValue operation on a map entry returned by the * iterator) the results of the iteration are undefined.The set * supports element removal, which removes the corresponding * mapping from the map, via the Iterator.remove, * Set.remove, removeAll, retainAll and * clear operations.It does not support the * add or addAll operations. * * @return {Set} a set view of the mappings contained in this map */ Map$1.prototype.entrySet = function entrySet () { } /** * @see http://download.oracle.com/javase/6/docs/api/java/util/SortedMap.html * * @extends {Map} * @constructor * @private */ var SortedMap = (function (Map) { function SortedMap () { Map.apply(this, arguments) } if (Map) SortedMap.__proto__ = Map SortedMap.prototype = Object.create(Map && Map.prototype) SortedMap.prototype.constructor = SortedMap return SortedMap }(Map$1)) /** * @param {string=} message Optional message * @extends {Error} * @constructor * @private */ function OperationNotSupported (message) { this.message = message || '' } OperationNotSupported.prototype = new Error() /** * @type {string} */ OperationNotSupported.prototype.name = 'OperationNotSupported' /** * @see http://download.oracle.com/javase/6/docs/api/java/util/Set.html * * @extends {Collection} * @constructor * @private */ function Set () { } Set.prototype = new Collection() /** * Returns true if this set contains the specified element. More formally, * returns true if and only if this set contains an element e such that (o==null ? * e==null : o.equals(e)). * @param {Object} e * @return {boolean} */ Set.prototype.contains = function () { } /** * @see http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html * * @extends {javascript.util.Set} * @constructor * @private */ var HashSet = (function (Set$$1) { function HashSet () { Set$$1.call(this) this.array_ = [] if (arguments[0] instanceof Collection) { this.addAll(arguments[0]) } } if (Set$$1) HashSet.__proto__ = Set$$1 HashSet.prototype = Object.create(Set$$1 && Set$$1.prototype) HashSet.prototype.constructor = HashSet /** * @override */ HashSet.prototype.contains = function contains (o) { var this$1$1 = this for (var i = 0, len = this.array_.length; i < len; i++) { var e = this$1$1.array_[i] if (e === o) { return true } } return false } /** * @override */ HashSet.prototype.add = function add (o) { if (this.contains(o)) { return false } this.array_.push(o) return true } /** * @override */ HashSet.prototype.addAll = function addAll (c) { var this$1$1 = this for (var i = c.iterator(); i.hasNext();) { this$1$1.add(i.next()) } return true } /** * @override */ HashSet.prototype.remove = function remove (o) { // throw new javascript.util.OperationNotSupported() throw new Error() } /** * @override */ HashSet.prototype.size = function size () { return this.array_.length } /** * @override */ HashSet.prototype.isEmpty = function isEmpty () { return this.array_.length === 0 } /** * @override */ HashSet.prototype.toArray = function toArray () { var this$1$1 = this var array = [] for (var i = 0, len = this.array_.length; i < len; i++) { array.push(this$1$1.array_[i]) } return array } /** * @override */ HashSet.prototype.iterator = function iterator () { return new Iterator_$1(this) } return HashSet }(Set)) /** * @extends {Iterator} * @param {HashSet} hashSet * @constructor * @private */ var Iterator_$1 = (function (Iterator$$1) { function Iterator_ (hashSet) { Iterator$$1.call(this) /** * @type {HashSet} * @private */ this.hashSet_ = hashSet /** * @type {number} * @private */ this.position_ = 0 } if (Iterator$$1) Iterator_.__proto__ = Iterator$$1 Iterator_.prototype = Object.create(Iterator$$1 && Iterator$$1.prototype) Iterator_.prototype.constructor = Iterator_ /** * @override */ Iterator_.prototype.next = function next () { if (this.position_ === this.hashSet_.size()) { throw new NoSuchElementException() } return this.hashSet_.array_[this.position_++] } /** * @override */ Iterator_.prototype.hasNext = function hasNext () { if (this.position_ < this.hashSet_.size()) { return true } else { return false } } /** * @override */ Iterator_.prototype.remove = function remove () { throw new OperationNotSupported() } return Iterator_ }(Iterator)) var BLACK = 0 var RED = 1 function colorOf (p) { return (p === null ? BLACK : p.color) } function parentOf (p) { return (p === null ? null : p.parent) } function setColor (p, c) { if (p !== null) { p.color = c } } function leftOf (p) { return (p === null ? null : p.left) } function rightOf (p) { return (p === null ? null : p.right) } /** * @see http://download.oracle.com/javase/6/docs/api/java/util/TreeMap.html * * @extends {SortedMap} * @constructor * @private */ function TreeMap () { /** * @type {Object} * @private */ this.root_ = null /** * @type {number} * @private */ this.size_ = 0 } TreeMap.prototype = new SortedMap() /** * @override */ TreeMap.prototype.get = function (key) { var p = this.root_ while (p !== null) { var cmp = key['compareTo'](p.key) if (cmp < 0) { p = p.left } else if (cmp > 0) { p = p.right } else { return p.value } } return null } /** * @override */ TreeMap.prototype.put = function (key, value) { if (this.root_ === null) { this.root_ = { key: key, value: value, left: null, right: null, parent: null, color: BLACK, getValue: function getValue () { return this.value }, getKey: function getKey () { return this.key } } this.size_ = 1 return null } var t = this.root_ var parent var cmp do { parent = t cmp = key['compareTo'](t.key) if (cmp < 0) { t = t.left } else if (cmp > 0) { t = t.right } else { var oldValue = t.value t.value = value return oldValue } } while (t !== null) var e = { key: key, left: null, right: null, value: value, parent: parent, color: BLACK, getValue: function getValue () { return this.value }, getKey: function getKey () { return this.key } } if (cmp < 0) { parent.left = e } else { parent.right = e } this.fixAfterInsertion(e) this.size_++ return null } /** * @param {Object} x */ TreeMap.prototype.fixAfterInsertion = function (x) { var this$1$1 = this x.color = RED while (x != null && x !== this.root_ && x.parent.color === RED) { if (parentOf(x) === leftOf(parentOf(parentOf(x)))) { var y = rightOf(parentOf(parentOf(x))) if (colorOf(y) === RED) { setColor(parentOf(x), BLACK) setColor(y, BLACK) setColor(parentOf(parentOf(x)), RED) x = parentOf(parentOf(x)) } else { if (x === rightOf(parentOf(x))) { x = parentOf(x) this$1$1.rotateLeft(x) } setColor(parentOf(x), BLACK) setColor(parentOf(parentOf(x)), RED) this$1$1.rotateRight(parentOf(parentOf(x))) } } else { var y$1 = leftOf(parentOf(parentOf(x))) if (colorOf(y$1) === RED) { setColor(parentOf(x), BLACK) setColor(y$1, BLACK) setColor(parentOf(parentOf(x)), RED) x = parentOf(parentOf(x)) } else { if (x === leftOf(parentOf(x))) { x = parentOf(x) this$1$1.rotateRight(x) } setColor(parentOf(x), BLACK) setColor(parentOf(parentOf(x)), RED) this$1$1.rotateLeft(parentOf(parentOf(x))) } } } this.root_.color = BLACK } /** * @override */ TreeMap.prototype.values = function () { var arrayList = new ArrayList() var p = this.getFirstEntry() if (p !== null) { arrayList.add(p.value) while ((p = TreeMap.successor(p)) !== null) { arrayList.add(p.value) } } return arrayList } /** * @override */ TreeMap.prototype.entrySet = function () { var hashSet = new HashSet() var p = this.getFirstEntry() if (p !== null) { hashSet.add(p) while ((p = TreeMap.successor(p)) !== null) { hashSet.add(p) } } return hashSet } /** * @param {Object} p */ TreeMap.prototype.rotateLeft = function (p) { if (p != null) { var r = p.right p.right = r.left if (r.left != null) { r.left.parent = p } r.parent = p.parent if (p.parent === null) { this.root_ = r } else if (p.parent.left === p) { p.parent.left = r } else { p.parent.right = r } r.left = p p.parent = r } } /** * @param {Object} p */ TreeMap.prototype.rotateRight = function (p) { if (p != null) { var l = p.left p.left = l.right if (l.right != null) { l.right.parent = p } l.parent = p.parent if (p.parent === null) { this.root_ = l } else if (p.parent.right === p) { p.parent.right = l } else { p.parent.left = l } l.right = p p.parent = l } } /** * @return {Object} */ TreeMap.prototype.getFirstEntry = function () { var p = this.root_ if (p != null) { while (p.left != null) { p = p.left } } return p } /** * @param {Object} t * @return {Object} * @private */ TreeMap.successor = function (t) { if (t === null) { return null } else if (t.right !== null) { var p = t.right while (p.left !== null) { p = p.left } return p } else { var p$1 = t.parent var ch = t while (p$1 !== null && ch === p$1.right) { ch = p$1 p$1 = p$1.parent } return p$1 } } /** * @override */ TreeMap.prototype.size = function () { return this.size_ } var Lineal = function Lineal () { } Lineal.prototype.interfaces_ = function interfaces_ () { return [] } Lineal.prototype.getClass = function getClass () { return Lineal } /** * @see http://download.oracle.com/javase/6/docs/api/java/util/SortedSet.html * * @extends {Set} * @constructor * @private */ function SortedSet () { } SortedSet.prototype = new Set() // import Iterator from './Iterator' /** * @see http://download.oracle.com/javase/6/docs/api/java/util/TreeSet.html * * @extends {SortedSet} * @constructor * @private */ function TreeSet () { /** * @type {Array} * @private */ this.array_ = [] if (arguments[0] instanceof Collection) { this.addAll(arguments[0]) } } TreeSet.prototype = new SortedSet() /** * @override */ TreeSet.prototype.contains = function (o) { var this$1$1 = this for (var i = 0, len = this.array_.length; i < len; i++) { var e = this$1$1.array_[i] if (e['compareTo'](o) === 0) { return true } } return false } /** * @override */ TreeSet.prototype.add = function (o) { var this$1$1 = this if (this.contains(o)) { return false } for (var i = 0, len = this.array_.length; i < len; i++) { var e = this$1$1.array_[i] if (e['compareTo'](o) === 1) { this$1$1.array_.splice(i, 0, o) return true } } this.array_.push(o) return true } /** * @override */ TreeSet.prototype.addAll = function (c) { var this$1$1 = this for (var i = c.iterator(); i.hasNext();) { this$1$1.add(i.next()) } return true } /** * @override */ TreeSet.prototype.remove = function (e) { throw new OperationNotSupported() } /** * @override */ TreeSet.prototype.size = function () { return this.array_.length } /** * @override */ TreeSet.prototype.isEmpty = function () { return this.array_.length === 0 } /** * @override */ TreeSet.prototype.toArray = function () { var this$1$1 = this var array = [] for (var i = 0, len = this.array_.length; i < len; i++) { array.push(this$1$1.array_[i]) } return array } /** * @override */ TreeSet.prototype.iterator = function () { return new Iterator_$2(this) } /** * @extends {javascript.util.Iterator} * @param {javascript.util.TreeSet} treeSet * @constructor * @private */ var Iterator_$2 = function (treeSet) { /** * @type {javascript.util.TreeSet} * @private */ this.treeSet_ = treeSet /** * @type {number} * @private */ this.position_ = 0 } /** * @override */ Iterator_$2.prototype.next = function () { if (this.position_ === this.treeSet_.size()) { throw new NoSuchElementException() } return this.treeSet_.array_[this.position_++] } /** * @override */ Iterator_$2.prototype.hasNext = function () { if (this.position_ < this.treeSet_.size()) { return true } else { return false } } /** * @override */ Iterator_$2.prototype.remove = function () { throw new OperationNotSupported() } /** * @see http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html * * @constructor * @private */ var Arrays = function Arrays () { } Arrays.sort = function sort () { var a = arguments[0] var i var t var comparator var compare if (arguments.length === 1) { compare = function (a, b) { return a.compareTo(b) } a.sort(compare) } else if (arguments.length === 2) { comparator = arguments[1] compare = function (a, b) { return comparator['compare'](a, b) } a.sort(compare) } else if (arguments.length === 3) { t = a.slice(arguments[1], arguments[2]) t.sort() var r = a.slice(0, arguments[1]).concat(t, a.slice(arguments[2], a.length)) a.splice(0, a.length) for (i = 0; i < r.length; i++) { a.push(r[i]) } } else if (arguments.length === 4) { t = a.slice(arguments[1], arguments[2]) comparator = arguments[3] compare = function (a, b) { return comparator['compare'](a, b) } t.sort(compare) r = a.slice(0, arguments[1]).concat(t, a.slice(arguments[2], a.length)) a.splice(0, a.length) for (i = 0; i < r.length; i++) { a.push(r[i]) } } } /** * @param {Array} array * @return {ArrayList} */ Arrays.asList = function asList (array) { var arrayList = new ArrayList() for (var i = 0, len = array.length; i < len; i++) { arrayList.add(array[i]) } return arrayList } var Dimension = function Dimension () { } var staticAccessors$14 = { P: { configurable: true }, L: { configurable: true }, A: { configurable: true }, FALSE: { configurable: true }, TRUE: { configurable: true }, DONTCARE: { configurable: true }, SYM_FALSE: { configurable: true }, SYM_TRUE: { configurable: true }, SYM_DONTCARE: { configurable: true }, SYM_P: { configurable: true }, SYM_L: { configurable: true }, SYM_A: { configurable: true } } staticAccessors$14.P.get = function () { return 0 } staticAccessors$14.L.get = function () { return 1 } staticAccessors$14.A.get = function () { return 2 } staticAccessors$14.FALSE.get = function () { return -1 } staticAccessors$14.TRUE.get = function () { return -2 } staticAccessors$14.DONTCARE.get = function () { return -3 } staticAccessors$14.SYM_FALSE.get = function () { return 'F' } staticAccessors$14.SYM_TRUE.get = function () { return 'T' } staticAccessors$14.SYM_DONTCARE.get = function () { return '*' } staticAccessors$14.SYM_P.get = function () { return '0' } staticAccessors$14.SYM_L.get = function () { return '1' } staticAccessors$14.SYM_A.get = function () { return '2' } Dimension.prototype.interfaces_ = function interfaces_ () { return [] } Dimension.prototype.getClass = function getClass () { return Dimension } Dimension.toDimensionSymbol = function toDimensionSymbol (dimensionValue) { switch (dimensionValue) { case Dimension.FALSE: return Dimension.SYM_FALSE case Dimension.TRUE: return Dimension.SYM_TRUE case Dimension.DONTCARE: return Dimension.SYM_DONTCARE case Dimension.P: return Dimension.SYM_P case Dimension.L: return Dimension.SYM_L case Dimension.A: return Dimension.SYM_A } throw new IllegalArgumentException('Unknown dimension value: ' + dimensionValue) } Dimension.toDimensionValue = function toDimensionValue (dimensionSymbol) { switch (Character.toUpperCase(dimensionSymbol)) { case Dimension.SYM_FALSE: return Dimension.FALSE case Dimension.SYM_TRUE: return Dimension.TRUE case Dimension.SYM_DONTCARE: return Dimension.DONTCARE case Dimension.SYM_P: return Dimension.P case Dimension.SYM_L: return Dimension.L case Dimension.SYM_A: return Dimension.A } throw new IllegalArgumentException('Unknown dimension symbol: ' + dimensionSymbol) } Object.defineProperties(Dimension, staticAccessors$14) var GeometryFilter = function GeometryFilter () { } GeometryFilter.prototype.filter = function filter (geom) { } GeometryFilter.prototype.interfaces_ = function interfaces_ () { return [] } GeometryFilter.prototype.getClass = function getClass () { return GeometryFilter } var CoordinateSequenceFilter = function CoordinateSequenceFilter () { } CoordinateSequenceFilter.prototype.filter = function filter (seq, i) { } CoordinateSequenceFilter.prototype.isDone = function isDone () { } CoordinateSequenceFilter.prototype.isGeometryChanged = function isGeometryChanged () { } CoordinateSequenceFilter.prototype.interfaces_ = function interfaces_ () { return [] } CoordinateSequenceFilter.prototype.getClass = function getClass () { return CoordinateSequenceFilter } var GeometryCollection = (function (Geometry$$1) { function GeometryCollection (geometries, factory) { Geometry$$1.call(this, factory) this._geometries = geometries || [] if (Geometry$$1.hasNullElements(this._geometries)) { throw new IllegalArgumentException('geometries must not contain null elements') } } if (Geometry$$1) GeometryCollection.__proto__ = Geometry$$1 GeometryCollection.prototype = Object.create(Geometry$$1 && Geometry$$1.prototype) GeometryCollection.prototype.constructor = GeometryCollection var staticAccessors = { serialVersionUID: { configurable: true } } GeometryCollection.prototype.computeEnvelopeInternal = function computeEnvelopeInternal () { var this$1$1 = this var envelope = new Envelope() for (var i = 0; i < this._geometries.length; i++) { envelope.expandToInclude(this$1$1._geometries[i].getEnvelopeInternal()) } return envelope } GeometryCollection.prototype.getGeometryN = function getGeometryN (n) { return this._geometries[n] } GeometryCollection.prototype.getSortIndex = function getSortIndex () { return Geometry$$1.SORTINDEX_GEOMETRYCOLLECTION } GeometryCollection.prototype.getCoordinates = function getCoordinates () { var this$1$1 = this var coordinates = new Array(this.getNumPoints()).fill(null) var k = -1 for (var i = 0; i < this._geometries.length; i++) { var childCoordinates = this$1$1._geometries[i].getCoordinates() for (var j = 0; j < childCoordinates.length; j++) { k++ coordinates[k] = childCoordinates[j] } } return coordinates } GeometryCollection.prototype.getArea = function getArea () { var this$1$1 = this var area = 0.0 for (var i = 0; i < this._geometries.length; i++) { area += this$1$1._geometries[i].getArea() } return area } GeometryCollection.prototype.equalsExact = function equalsExact () { var this$1$1 = this if (arguments.length === 2) { var other = arguments[0] var tolerance = arguments[1] if (!this.isEquivalentClass(other)) { return false } var otherCollection = other if (this._geometries.length !== otherCollection._geometries.length) { return false } for (var i = 0; i < this._geometries.length; i++) { if (!this$1$1._geometries[i].equalsExact(otherCollection._geometries[i], tolerance)) { return false } } return true } else { return Geometry$$1.prototype.equalsExact.apply(this, arguments) } } GeometryCollection.prototype.normalize = function normalize () { var this$1$1 = this for (var i = 0; i < this._geometries.length; i++) { this$1$1._geometries[i].normalize() } Arrays.sort(this._geometries) } GeometryCollection.prototype.getCoordinate = function getCoordinate () { if (this.isEmpty()) { return null } return this._geometries[0].getCoordinate() } GeometryCollection.prototype.getBoundaryDimension = function getBoundaryDimension () { var this$1$1 = this var dimension = Dimension.FALSE for (var i = 0; i < this._geometries.length; i++) { dimension = Math.max(dimension, this$1$1._geometries[i].getBoundaryDimension()) } return dimension } GeometryCollection.prototype.getDimension = function getDimension () { var this$1$1 = this var dimension = Dimension.FALSE for (var i = 0; i < this._geometries.length; i++) { dimension = Math.max(dimension, this$1$1._geometries[i].getDimension()) } return dimension } GeometryCollection.prototype.getLength = function getLength () { var this$1$1 = this var sum = 0.0 for (var i = 0; i < this._geometries.length; i++) { sum += this$1$1._geometries[i].getLength() } return sum } GeometryCollection.prototype.getNumPoints = function getNumPoints () { var this$1$1 = this var numPoints = 0 for (var i = 0; i < this._geometries.length; i++) { numPoints += this$1$1._geometries[i].getNumPoints() } return numPoints } GeometryCollection.prototype.getNumGeometries = function getNumGeometries () { return this._geometries.length } GeometryCollection.prototype.reverse = function reverse () { var this$1$1 = this var n = this._geometries.length var revGeoms = new Array(n).fill(null) for (var i = 0; i < this._geometries.length; i++) { revGeoms[i] = this$1$1._geometries[i].reverse() } return this.getFactory().createGeometryCollection(revGeoms) } GeometryCollection.prototype.compareToSameClass = function compareToSameClass () { var this$1$1 = this if (arguments.length === 1) { var o = arguments[0] var theseElements = new TreeSet(Arrays.asList(this._geometries)) var otherElements = new TreeSet(Arrays.asList(o._geometries)) return this.compare(theseElements, otherElements) } else if (arguments.length === 2) { var o$1 = arguments[0] var comp = arguments[1] var gc = o$1 var n1 = this.getNumGeometries() var n2 = gc.getNumGeometries() var i = 0 while (i < n1 && i < n2) { var thisGeom = this$1$1.getGeometryN(i) var otherGeom = gc.getGeometryN(i) var holeComp = thisGeom.compareToSameClass(otherGeom, comp) if (holeComp !== 0) { return holeComp } i++ } if (i < n1) { return 1 } if (i < n2) { return -1 } return 0 } } GeometryCollection.prototype.apply = function apply () { var this$1$1 = this if (hasInterface(arguments[0], CoordinateFilter)) { var filter = arguments[0] for (var i = 0; i < this._geometries.length; i++) { this$1$1._geometries[i].apply(filter) } } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) { var filter$1 = arguments[0] if (this._geometries.length === 0) { return null } for (var i$1 = 0; i$1 < this._geometries.length; i$1++) { this$1$1._geometries[i$1].apply(filter$1) if (filter$1.isDone()) { break } } if (filter$1.isGeometryChanged()) { this.geometryChanged() } } else if (hasInterface(arguments[0], GeometryFilter)) { var filter$2 = arguments[0] filter$2.filter(this) for (var i$2 = 0; i$2 < this._geometries.length; i$2++) { this$1$1._geometries[i$2].apply(filter$2) } } else if (hasInterface(arguments[0], GeometryComponentFilter)) { var filter$3 = arguments[0] filter$3.filter(this) for (var i$3 = 0; i$3 < this._geometries.length; i$3++) { this$1$1._geometries[i$3].apply(filter$3) } } } GeometryCollection.prototype.getBoundary = function getBoundary () { this.checkNotGeometryCollection(this) Assert.shouldNeverReachHere() return null } GeometryCollection.prototype.clone = function clone () { var this$1$1 = this var gc = Geometry$$1.prototype.clone.call(this) gc._geometries = new Array(this._geometries.length).fill(null) for (var i = 0; i < this._geometries.length; i++) { gc._geometries[i] = this$1$1._geometries[i].clone() } return gc } GeometryCollection.prototype.getGeometryType = function getGeometryType () { return 'GeometryCollection' } GeometryCollection.prototype.copy = function copy () { var this$1$1 = this var geometries = new Array(this._geometries.length).fill(null) for (var i = 0; i < geometries.length; i++) { geometries[i] = this$1$1._geometries[i].copy() } return new GeometryCollection(geometries, this._factory) } GeometryCollection.prototype.isEmpty = function isEmpty () { var this$1$1 = this for (var i = 0; i < this._geometries.length; i++) { if (!this$1$1._geometries[i].isEmpty()) { return false } } return true } GeometryCollection.prototype.interfaces_ = function interfaces_ () { return [] } GeometryCollection.prototype.getClass = function getClass () { return GeometryCollection } staticAccessors.serialVersionUID.get = function () { return -5694727726395021467 } Object.defineProperties(GeometryCollection, staticAccessors) return GeometryCollection }(Geometry$2)) var MultiLineString = (function (GeometryCollection$$1) { function MultiLineString () { GeometryCollection$$1.apply(this, arguments) } if (GeometryCollection$$1) MultiLineString.__proto__ = GeometryCollection$$1 MultiLineString.prototype = Object.create(GeometryCollection$$1 && GeometryCollection$$1.prototype) MultiLineString.prototype.constructor = MultiLineString var staticAccessors = { serialVersionUID: { configurable: true } } MultiLineString.prototype.getSortIndex = function getSortIndex () { return Geometry$2.SORTINDEX_MULTILINESTRING } MultiLineString.prototype.equalsExact = function equalsExact () { if (arguments.length === 2) { var other = arguments[0] var tolerance = arguments[1] if (!this.isEquivalentClass(other)) { return false } return GeometryCollection$$1.prototype.equalsExact.call(this, other, tolerance) } else { return GeometryCollection$$1.prototype.equalsExact.apply(this, arguments) } } MultiLineString.prototype.getBoundaryDimension = function getBoundaryDimension () { if (this.isClosed()) { return Dimension.FALSE } return 0 } MultiLineString.prototype.isClosed = function isClosed () { var this$1$1 = this if (this.isEmpty()) { return false } for (var i = 0; i < this._geometries.length; i++) { if (!this$1$1._geometries[i].isClosed()) { return false } } return true } MultiLineString.prototype.getDimension = function getDimension () { return 1 } MultiLineString.prototype.reverse = function reverse () { var this$1$1 = this var nLines = this._geometries.length var revLines = new Array(nLines).fill(null) for (var i = 0; i < this._geometries.length; i++) { revLines[nLines - 1 - i] = this$1$1._geometries[i].reverse() } return this.getFactory().createMultiLineString(revLines) } MultiLineString.prototype.getBoundary = function getBoundary () { return new BoundaryOp(this).getBoundary() } MultiLineString.prototype.getGeometryType = function getGeometryType () { return 'MultiLineString' } MultiLineString.prototype.copy = function copy () { var this$1$1 = this var lineStrings = new Array(this._geometries.length).fill(null) for (var i = 0; i < lineStrings.length; i++) { lineStrings[i] = this$1$1._geometries[i].copy() } return new MultiLineString(lineStrings, this._factory) } MultiLineString.prototype.interfaces_ = function interfaces_ () { return [Lineal] } MultiLineString.prototype.getClass = function getClass () { return MultiLineString } staticAccessors.serialVersionUID.get = function () { return 8166665132445433741 } Object.defineProperties(MultiLineString, staticAccessors) return MultiLineString }(GeometryCollection)) var BoundaryOp = function BoundaryOp () { this._geom = null this._geomFact = null this._bnRule = null this._endpointMap = null if (arguments.length === 1) { var geom = arguments[0] var bnRule = BoundaryNodeRule.MOD2_BOUNDARY_RULE this._geom = geom this._geomFact = geom.getFactory() this._bnRule = bnRule } else if (arguments.length === 2) { var geom$1 = arguments[0] var bnRule$1 = arguments[1] this._geom = geom$1 this._geomFact = geom$1.getFactory() this._bnRule = bnRule$1 } } BoundaryOp.prototype.boundaryMultiLineString = function boundaryMultiLineString (mLine) { if (this._geom.isEmpty()) { return this.getEmptyMultiPoint() } var bdyPts = this.computeBoundaryCoordinates(mLine) if (bdyPts.length === 1) { return this._geomFact.createPoint(bdyPts[0]) } return this._geomFact.createMultiPointFromCoords(bdyPts) } BoundaryOp.prototype.getBoundary = function getBoundary () { if (this._geom instanceof LineString) { return this.boundaryLineString(this._geom) } if (this._geom instanceof MultiLineString) { return this.boundaryMultiLineString(this._geom) } return this._geom.getBoundary() } BoundaryOp.prototype.boundaryLineString = function boundaryLineString (line) { if (this._geom.isEmpty()) { return this.getEmptyMultiPoint() } if (line.isClosed()) { var closedEndpointOnBoundary = this._bnRule.isInBoundary(2) if (closedEndpointOnBoundary) { return line.getStartPoint() } else { return this._geomFact.createMultiPoint() } } return this._geomFact.createMultiPoint([line.getStartPoint(), line.getEndPoint()]) } BoundaryOp.prototype.getEmptyMultiPoint = function getEmptyMultiPoint () { return this._geomFact.createMultiPoint() } BoundaryOp.prototype.computeBoundaryCoordinates = function computeBoundaryCoordinates (mLine) { var this$1$1 = this var bdyPts = new ArrayList() this._endpointMap = new TreeMap() for (var i = 0; i < mLine.getNumGeometries(); i++) { var line = mLine.getGeometryN(i) if (line.getNumPoints() === 0) { continue } this$1$1.addEndpoint(line.getCoordinateN(0)) this$1$1.addEndpoint(line.getCoordinateN(line.getNumPoints() - 1)) } for (var it = this._endpointMap.entrySet().iterator(); it.hasNext();) { var entry = it.next() var counter = entry.getValue() var valence = counter.count if (this$1$1._bnRule.isInBoundary(valence)) { bdyPts.add(entry.getKey()) } } return CoordinateArrays.toCoordinateArray(bdyPts) } BoundaryOp.prototype.addEndpoint = function addEndpoint (pt) { var counter = this._endpointMap.get(pt) if (counter === null) { counter = new Counter() this._endpointMap.put(pt, counter) } counter.count++ } BoundaryOp.prototype.interfaces_ = function interfaces_ () { return [] } BoundaryOp.prototype.getClass = function getClass () { return BoundaryOp } BoundaryOp.getBoundary = function getBoundary () { if (arguments.length === 1) { var g = arguments[0] var bop = new BoundaryOp(g) return bop.getBoundary() } else if (arguments.length === 2) { var g$1 = arguments[0] var bnRule = arguments[1] var bop$1 = new BoundaryOp(g$1, bnRule) return bop$1.getBoundary() } } var Counter = function Counter () { this.count = null } Counter.prototype.interfaces_ = function interfaces_ () { return [] } Counter.prototype.getClass = function getClass () { return Counter } // boundary function PrintStream () { } function StringReader () { } var DecimalFormat = function DecimalFormat () { } function ByteArrayOutputStream () { } function IOException () { } function LineNumberReader () { } var StringUtil = function StringUtil () { } var staticAccessors$15 = { NEWLINE: { configurable: true }, SIMPLE_ORDINATE_FORMAT: { configurable: true } } StringUtil.prototype.interfaces_ = function interfaces_ () { return [] } StringUtil.prototype.getClass = function getClass () { return StringUtil } StringUtil.chars = function chars (c, n) { var ch = new Array(n).fill(null) for (var i = 0; i < n; i++) { ch[i] = c } return String(ch) } StringUtil.getStackTrace = function getStackTrace () { if (arguments.length === 1) { var t = arguments[0] var os = new ByteArrayOutputStream() var ps = new PrintStream() t.printStackTrace(ps) return os.toString() } else if (arguments.length === 2) { var t$1 = arguments[0] var depth = arguments[1] var stackTrace = '' new StringReader(StringUtil.getStackTrace(t$1)) var lineNumberReader = new LineNumberReader() for (var i = 0; i < depth; i++) { try { stackTrace += lineNumberReader.readLine() + StringUtil.NEWLINE } catch (e) { if (e instanceof IOException) { Assert.shouldNeverReachHere() } else { throw e } } finally { } } return stackTrace } } StringUtil.split = function split (s, separator) { var separatorlen = separator.length var tokenList = new ArrayList() var tmpString = '' + s var pos = tmpString.indexOf(separator) while (pos >= 0) { var token = tmpString.substring(0, pos) tokenList.add(token) tmpString = tmpString.substring(pos + separatorlen) pos = tmpString.indexOf(separator) } if (tmpString.length > 0) { tokenList.add(tmpString) } var res = new Array(tokenList.size()).fill(null) for (var i = 0; i < res.length; i++) { res[i] = tokenList.get(i) } return res } StringUtil.toString = function toString () { if (arguments.length === 1) { var d = arguments[0] return StringUtil.SIMPLE_ORDINATE_FORMAT.format(d) } } StringUtil.spaces = function spaces (n) { return StringUtil.chars(' ', n) } staticAccessors$15.NEWLINE.get = function () { return System.getProperty('line.separator') } staticAccessors$15.SIMPLE_ORDINATE_FORMAT.get = function () { return new DecimalFormat() } Object.defineProperties(StringUtil, staticAccessors$15) var CoordinateSequences = function CoordinateSequences () { } CoordinateSequences.prototype.interfaces_ = function interfaces_ () { return [] } CoordinateSequences.prototype.getClass = function getClass () { return CoordinateSequences } CoordinateSequences.copyCoord = function copyCoord (src, srcPos, dest, destPos) { var minDim = Math.min(src.getDimension(), dest.getDimension()) for (var dim = 0; dim < minDim; dim++) { dest.setOrdinate(destPos, dim, src.getOrdinate(srcPos, dim)) } } CoordinateSequences.isRing = function isRing (seq) { var n = seq.size() if (n === 0) { return true } if (n <= 3) { return false } return seq.getOrdinate(0, CoordinateSequence.X) === seq.getOrdinate(n - 1, CoordinateSequence.X) && seq.getOrdinate(0, CoordinateSequence.Y) === seq.getOrdinate(n - 1, CoordinateSequence.Y) } CoordinateSequences.isEqual = function isEqual (cs1, cs2) { var cs1Size = cs1.size() var cs2Size = cs2.size() if (cs1Size !== cs2Size) { return false } var dim = Math.min(cs1.getDimension(), cs2.getDimension()) for (var i = 0; i < cs1Size; i++) { for (var d = 0; d < dim; d++) { var v1 = cs1.getOrdinate(i, d) var v2 = cs2.getOrdinate(i, d) if (cs1.getOrdinate(i, d) === cs2.getOrdinate(i, d)) { continue } if (Double.isNaN(v1) && Double.isNaN(v2)) { continue } return false } } return true } CoordinateSequences.extend = function extend (fact, seq, size) { var newseq = fact.create(size, seq.getDimension()) var n = seq.size() CoordinateSequences.copy(seq, 0, newseq, 0, n) if (n > 0) { for (var i = n; i < size; i++) { CoordinateSequences.copy(seq, n - 1, newseq, i, 1) } } return newseq } CoordinateSequences.reverse = function reverse (seq) { var last = seq.size() - 1 var mid = Math.trunc(last / 2) for (var i = 0; i <= mid; i++) { CoordinateSequences.swap(seq, i, last - i) } } CoordinateSequences.swap = function swap (seq, i, j) { if (i === j) { return null } for (var dim = 0; dim < seq.getDimension(); dim++) { var tmp = seq.getOrdinate(i, dim) seq.setOrdinate(i, dim, seq.getOrdinate(j, dim)) seq.setOrdinate(j, dim, tmp) } } CoordinateSequences.copy = function copy (src, srcPos, dest, destPos, length) { for (var i = 0; i < length; i++) { CoordinateSequences.copyCoord(src, srcPos + i, dest, destPos + i) } } CoordinateSequences.toString = function toString () { if (arguments.length === 1) { var cs = arguments[0] var size = cs.size() if (size === 0) { return '()' } var dim = cs.getDimension() var buf = new StringBuffer() buf.append('(') for (var i = 0; i < size; i++) { if (i > 0) { buf.append(' ') } for (var d = 0; d < dim; d++) { if (d > 0) { buf.append(',') } buf.append(StringUtil.toString(cs.getOrdinate(i, d))) } } buf.append(')') return buf.toString() } } CoordinateSequences.ensureValidRing = function ensureValidRing (fact, seq) { var n = seq.size() if (n === 0) { return seq } if (n <= 3) { return CoordinateSequences.createClosedRing(fact, seq, 4) } var isClosed = seq.getOrdinate(0, CoordinateSequence.X) === seq.getOrdinate(n - 1, CoordinateSequence.X) && seq.getOrdinate(0, CoordinateSequence.Y) === seq.getOrdinate(n - 1, CoordinateSequence.Y) if (isClosed) { return seq } return CoordinateSequences.createClosedRing(fact, seq, n + 1) } CoordinateSequences.createClosedRing = function createClosedRing (fact, seq, size) { var newseq = fact.create(size, seq.getDimension()) var n = seq.size() CoordinateSequences.copy(seq, 0, newseq, 0, n) for (var i = n; i < size; i++) { CoordinateSequences.copy(seq, 0, newseq, i, 1) } return newseq } var LineString = (function (Geometry$$1) { function LineString (points, factory) { Geometry$$1.call(this, factory) this._points = null this.init(points) } if (Geometry$$1) LineString.__proto__ = Geometry$$1 LineString.prototype = Object.create(Geometry$$1 && Geometry$$1.prototype) LineString.prototype.constructor = LineString var staticAccessors = { serialVersionUID: { configurable: true } } LineString.prototype.computeEnvelopeInternal = function computeEnvelopeInternal () { if (this.isEmpty()) { return new Envelope() } return this._points.expandEnvelope(new Envelope()) } LineString.prototype.isRing = function isRing () { return this.isClosed() && this.isSimple() } LineString.prototype.getSortIndex = function getSortIndex () { return Geometry$$1.SORTINDEX_LINESTRING } LineString.prototype.getCoordinates = function getCoordinates () { return this._points.toCoordinateArray() } LineString.prototype.equalsExact = function equalsExact () { var this$1$1 = this if (arguments.length === 2) { var other = arguments[0] var tolerance = arguments[1] if (!this.isEquivalentClass(other)) { return false } var otherLineString = other if (this._points.size() !== otherLineString._points.size()) { return false } for (var i = 0; i < this._points.size(); i++) { if (!this$1$1.equal(this$1$1._points.getCoordinate(i), otherLineString._points.getCoordinate(i), tolerance)) { return false } } return true } else { return Geometry$$1.prototype.equalsExact.apply(this, arguments) } } LineString.prototype.normalize = function normalize () { var this$1$1 = this for (var i = 0; i < Math.trunc(this._points.size() / 2); i++) { var j = this$1$1._points.size() - 1 - i if (!this$1$1._points.getCoordinate(i).equals(this$1$1._points.getCoordinate(j))) { if (this$1$1._points.getCoordinate(i).compareTo(this$1$1._points.getCoordinate(j)) > 0) { CoordinateSequences.reverse(this$1$1._points) } return null } } } LineString.prototype.getCoordinate = function getCoordinate () { if (this.isEmpty()) { return null } return this._points.getCoordinate(0) } LineString.prototype.getBoundaryDimension = function getBoundaryDimension () { if (this.isClosed()) { return Dimension.FALSE } return 0 } LineString.prototype.isClosed = function isClosed () { if (this.isEmpty()) { return false } return this.getCoordinateN(0).equals2D(this.getCoordinateN(this.getNumPoints() - 1)) } LineString.prototype.getEndPoint = function getEndPoint () { if (this.isEmpty()) { return null } return this.getPointN(this.getNumPoints() - 1) } LineString.prototype.getDimension = function getDimension () { return 1 } LineString.prototype.getLength = function getLength () { return CGAlgorithms.computeLength(this._points) } LineString.prototype.getNumPoints = function getNumPoints () { return this._points.size() } LineString.prototype.reverse = function reverse () { var seq = this._points.copy() CoordinateSequences.reverse(seq) var revLine = this.getFactory().createLineString(seq) return revLine } LineString.prototype.compareToSameClass = function compareToSameClass () { var this$1$1 = this if (arguments.length === 1) { var o = arguments[0] var line = o var i = 0 var j = 0 while (i < this._points.size() && j < line._points.size()) { var comparison = this$1$1._points.getCoordinate(i).compareTo(line._points.getCoordinate(j)) if (comparison !== 0) { return comparison } i++ j++ } if (i < this._points.size()) { return 1 } if (j < line._points.size()) { return -1 } return 0 } else if (arguments.length === 2) { var o$1 = arguments[0] var comp = arguments[1] var line$1 = o$1 return comp.compare(this._points, line$1._points) } } LineString.prototype.apply = function apply () { var this$1$1 = this if (hasInterface(arguments[0], CoordinateFilter)) { var filter = arguments[0] for (var i = 0; i < this._points.size(); i++) { filter.filter(this$1$1._points.getCoordinate(i)) } } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) { var filter$1 = arguments[0] if (this._points.size() === 0) { return null } for (var i$1 = 0; i$1 < this._points.size(); i$1++) { filter$1.filter(this$1$1._points, i$1) if (filter$1.isDone()) { break } } if (filter$1.isGeometryChanged()) { this.geometryChanged() } } else if (hasInterface(arguments[0], GeometryFilter)) { var filter$2 = arguments[0] filter$2.filter(this) } else if (hasInterface(arguments[0], GeometryComponentFilter)) { var filter$3 = arguments[0] filter$3.filter(this) } } LineString.prototype.getBoundary = function getBoundary () { return new BoundaryOp(this).getBoundary() } LineString.prototype.isEquivalentClass = function isEquivalentClass (other) { return other instanceof LineString } LineString.prototype.clone = function clone () { var ls = Geometry$$1.prototype.clone.call(this) ls._points = this._points.clone() return ls } LineString.prototype.getCoordinateN = function getCoordinateN (n) { return this._points.getCoordinate(n) } LineString.prototype.getGeometryType = function getGeometryType () { return 'LineString' } LineString.prototype.copy = function copy () { return new LineString(this._points.copy(), this._factory) } LineString.prototype.getCoordinateSequence = function getCoordinateSequence () { return this._points } LineString.prototype.isEmpty = function isEmpty () { return this._points.size() === 0 } LineString.prototype.init = function init (points) { if (points === null) { points = this.getFactory().getCoordinateSequenceFactory().create([]) } if (points.size() === 1) { throw new IllegalArgumentException('Invalid number of points in LineString (found ' + points.size() + ' - must be 0 or >= 2)') } this._points = points } LineString.prototype.isCoordinate = function isCoordinate (pt) { var this$1$1 = this for (var i = 0; i < this._points.size(); i++) { if (this$1$1._points.getCoordinate(i).equals(pt)) { return true } } return false } LineString.prototype.getStartPoint = function getStartPoint () { if (this.isEmpty()) { return null } return this.getPointN(0) } LineString.prototype.getPointN = function getPointN (n) { return this.getFactory().createPoint(this._points.getCoordinate(n)) } LineString.prototype.interfaces_ = function interfaces_ () { return [Lineal] } LineString.prototype.getClass = function getClass () { return LineString } staticAccessors.serialVersionUID.get = function () { return 3110669828065365560 } Object.defineProperties(LineString, staticAccessors) return LineString }(Geometry$2)) var Puntal = function Puntal () { } Puntal.prototype.interfaces_ = function interfaces_ () { return [] } Puntal.prototype.getClass = function getClass () { return Puntal } var Point = (function (Geometry$$1) { function Point (coordinates, factory) { Geometry$$1.call(this, factory) this._coordinates = coordinates || null this.init(this._coordinates) } if (Geometry$$1) Point.__proto__ = Geometry$$1 Point.prototype = Object.create(Geometry$$1 && Geometry$$1.prototype) Point.prototype.constructor = Point var staticAccessors = { serialVersionUID: { configurable: true } } Point.prototype.computeEnvelopeInternal = function computeEnvelopeInternal () { if (this.isEmpty()) { return new Envelope() } var env = new Envelope() env.expandToInclude(this._coordinates.getX(0), this._coordinates.getY(0)) return env } Point.prototype.getSortIndex = function getSortIndex () { return Geometry$$1.SORTINDEX_POINT } Point.prototype.getCoordinates = function getCoordinates () { return this.isEmpty() ? [] : [this.getCoordinate()] } Point.prototype.equalsExact = function equalsExact () { if (arguments.length === 2) { var other = arguments[0] var tolerance = arguments[1] if (!this.isEquivalentClass(other)) { return false } if (this.isEmpty() && other.isEmpty()) { return true } if (this.isEmpty() !== other.isEmpty()) { return false } return this.equal(other.getCoordinate(), this.getCoordinate(), tolerance) } else { return Geometry$$1.prototype.equalsExact.apply(this, arguments) } } Point.prototype.normalize = function normalize () { } Point.prototype.getCoordinate = function getCoordinate () { return this._coordinates.size() !== 0 ? this._coordinates.getCoordinate(0) : null } Point.prototype.getBoundaryDimension = function getBoundaryDimension () { return Dimension.FALSE } Point.prototype.getDimension = function getDimension () { return 0 } Point.prototype.getNumPoints = function getNumPoints () { return this.isEmpty() ? 0 : 1 } Point.prototype.reverse = function reverse () { return this.copy() } Point.prototype.getX = function getX () { if (this.getCoordinate() === null) { throw new Error('getX called on empty Point') } return this.getCoordinate().x } Point.prototype.compareToSameClass = function compareToSameClass () { if (arguments.length === 1) { var other = arguments[0] var point$1 = other return this.getCoordinate().compareTo(point$1.getCoordinate()) } else if (arguments.length === 2) { var other$1 = arguments[0] var comp = arguments[1] var point = other$1 return comp.compare(this._coordinates, point._coordinates) } } Point.prototype.apply = function apply () { if (hasInterface(arguments[0], CoordinateFilter)) { var filter = arguments[0] if (this.isEmpty()) { return null } filter.filter(this.getCoordinate()) } else if (hasInterface(arguments[0], CoordinateSequenceFilter)) { var filter$1 = arguments[0] if (this.isEmpty()) { return null } filter$1.filter(this._coordinates, 0) if (filter$1.isGeometryChanged()) { this.geometryChanged() } } else if (hasInterface(arguments[0], GeometryFilter)) { var filter$2 = arguments[0] filter$2.filter(this) } else if (hasInterface(arguments[0], GeometryComponentFilter)) { var filter$3 = arguments[0] filter$3.filter(this) } } Point.prototype.getBoundary = function getBoundary () { return this.getFactory().createGeometryCollection(null) } Point.prototype.clone = function clone () { var p = Geometry$$1.prototype.clone.call(this) p._coordinates = this._coordinates.clone() return p } Point.prototype.getGeometryType = function getGeometryType () { return 'Point' } Point.prototype.copy = function copy () { return new Point(this._coordinates.copy(), this._factory) } Point.prototype.getCoordinateSequence = function getCoordinateSequence () { return this._coordinates } Point.prototype.getY = function getY () { if (this.getCoordinate() === null) { throw new Error('getY called on empty Point') } return this.getCoordinate().y } Point.prototype.isEmpty = function isEmpty () { return this._coordinates.size() === 0 } Point.prototype.init = function init (coordinates) { if (coordinates === null) { coordinates = this.getFactory().getCoordinateSequenceFactory().create([]) } Assert.isTrue(coordinates.size() <= 1) this._coordinates = coordinates } Point.prototype.isSimple = function isSimple () { return true } Point.prototype.interfaces_ = function interfaces_ () { return [Puntal] } Point.prototype.getClass = function getClass () { return Point } staticAccessors.serialVersionUID.get = function () { return 4902022702746614570 } Object.defineProperties(Point, staticAccessors) return Point }(Geometry$2)) var Polygonal = function Polygonal () { } Polygonal.prototype.interfaces_ = function interfaces_ () { return [] } Polygonal.prototype.getClass = function getClass () { return Polygonal } var Polygon = (function (Geometry$$1) { function Polygon (shell, holes, factory) { Geometry$$1.call(this, factory) this._shell = null this._holes = null if (shell === null) { shell = this.getFactory().createLinearRing() } if (holes === null) { holes = [] } if (Geometry$$1.hasNullElements(holes)) { throw new IllegalArgumentException('holes must not contain null elements') } if (shell.isEmpty() && Geometry$$1.hasNonEmptyElements(holes)) { throw new IllegalArgumentException('shell is empty but holes are not') } this._shell = shell this._holes = holes } if (Geometry$$1) Polygon.__proto__ = Geometry$$1 Polygon.prototype = Object.create(Geometry$$1 && Geometry$$1.prototype) Polygon.prototype.constructor = Polygon var staticAccessors = { serialVersionUID: { configurable: true } } Polygon.prototype.computeEnvelopeInternal = function computeEnvelopeInternal () { return this._shell.getEnvelopeInternal() } Polygon.prototype.getSortIndex = function getSortIndex () { return Geometry$$1.SORTINDEX_POLYGON } Polygon.prototype.getCoordinates = function getCoordinates () { var this$1$1 = this if (this.isEmpty()) { return [] } var coordinates = new Array(this.getNumPoints()).fill(null) var k = -1 var shellCoordinates = this._shell.getCoordinates() for (var x = 0; x < shellCoordinates.length; x++) { k++ coordinates[k] = shellCoordinates[x] } for (var i = 0; i < this._holes.length; i++) { var childCoordinates = this$1$1._holes[i].getCoordinates() for (var j = 0; j < childCoordinates.length; j++) { k++ coordinates[k] = childCoordinates[j] } } return coordinates } Polygon.prototype.getArea = function getArea () { var this$1$1 = this var area = 0.0 area += Math.abs(CGAlgorithms.signedArea(this._shell.getCoordinateSequence())) for (var i = 0; i < this._holes.length; i++) { area -= Math.abs(CGAlgorithms.signedArea(this$1$1._holes[i].getCoordinateSequence())) } return area } Polygon.prototype.isRectangle = function isRectangle () { if (this.getNumInteriorRing() !== 0) { return false } if (this._shell === null) { return false } if (this._shell.getNumPoints() !== 5) { return false } var seq = this._shell.getCoordinateSequence() var env = this.getEnvelopeInternal() for (var i = 0; i < 5; i++) { var x = seq.getX(i) if (!(x === env.getMinX() || x === env.getMaxX())) { return false } var y = seq.getY(i) if (!(y === env.getMinY() || y === env.getMaxY())) { return false } } var prevX = seq.getX(0) var prevY = seq.getY(0) for (var i$1 = 1; i$1 <= 4; i$1++) { var x$1 = seq.getX(i$1) var y$1 = seq.getY(i$1) var xChanged = x$1 !== prevX var yChanged = y$1 !== prevY if (xChanged === yChanged) { return false } prevX = x$1 prevY = y$1 } return true } Polygon.prototype.equalsExact = function equalsExact () { var this$1$1 = this if (arguments.length === 2) { var other = arguments[0] var tolerance = arguments[1] if (!this.isEquivalentClass(other)) { return false } var otherPolygon = other var thisShell = this._shell var otherPolygonShell = otherPolygon._shell if (!thisShell.equalsExact(otherPolygonShell, tolerance)) { return false } if (this._holes.length !== otherPolygon._holes.length) { return false } for (var i = 0; i < this._holes.length; i++) { if (!this$1$1._holes[i].equalsExact(otherPolygon._holes[i], tolerance)) { return false } } return true } else { return Geometry$$1.prototype.equalsExact.apply(this, arguments) } } Polygon.prototype.normalize = function normalize () { var this$1$1 = this if (arguments.length === 0) { this.normalize(this._shell, true) for (var i = 0; i < this._holes.length; i++) { this$1$1.normalize(this$1$1._holes[i], false) } Arrays.sort(this._holes) } else if (arguments.length === 2) { var ring = arguments[0] var clockwise = arguments[1] if (ring.isEmpty()) { return null } var uniqueCoordinates = new Array(ring.getCoordinates().length - 1).fill(null) System.arraycopy(ring.getCoordinates(), 0, uniqueCoordinates, 0, uniqueCoordinates.length) var minCoordinate = CoordinateArrays.minCoordinate(ring.getCoordinates()) CoordinateArrays.scroll(uniqueCoordinates, minCoordinate) System.arraycopy(uniqueCoordinates, 0, ring.getCoordinates(), 0, uniqueCoordinates.length) ring.getCoordinates()[uniqueCoordinates.length] = uniqueCoordinates[0] if (CGAlgorithms.isCCW(ring.getCoordinates()) === clockwise) { CoordinateArrays.reverse(ring.getCoordinates()) } } } Polygon.prototype.getCoordinate = function getCoordinate () { return this._shell.getCoordinate() } Polygon.prototype.getNumInteriorRing = function getNumInteriorRing () { return this._holes.length } Polygon.prototype.getBoundaryDimension = function getBoundaryDimension () { return 1 } Polygon.prototype.getDimension = function getDimension () { return 2 } Polygon.prototype.getLength = function getLength () { var this$1$1 = this var len = 0.0 len += this._shell.getLength() for (var i = 0; i < this._holes.length; i++) { len += this$1$1._holes[i].getLength() } return len } Polygon.prototype.getNumPoints = function getNumPoints () { var this$1$1 = this var numPoints = this._shell.getNumPoints() for (var i = 0; i < this._holes.length; i++) { numPoints += this$1$1._holes[i].getNumPoints() } return numPoints } Polygon.prototype.reverse = function reverse () { var this$1$1 = this var poly = this.copy() poly._shell = this._shell.copy().reverse() poly._holes = new Array(this._holes.length).fill(null) for (var i = 0; i < this._holes.length; i++) { poly._holes[i] = this$1$1._holes[i].copy().reverse() } return poly } Polygon.prototype.convexHull = function convexHull () { return this.getExteriorRing().convexHull() } Polygon.prototype.compareToSameClass = function compareToSameClass () { var this$1$1 = this if (arguments.length === 1) { var o = arguments[0] var thisShell = this._shell var otherShell = o._shell return thisShell.compareToSameClass(otherShell) } else if (arguments.length === 2) { var o$1 = arguments[0] var comp = arguments[1] var poly = o$1 var thisShell$1 = this._shell var otherShell$1 = poly._shell var shellComp = thisShell$1.compareToSameClass(otherShell$1, comp) if (shellComp !== 0) { return shellComp } var nHole1 = this.getNumInteriorRing() var nHole2 = poly.getNumInteriorRing() var i = 0 while (i < nHole1 && i < nHole2) { var thisHole = this$1$1.getInteriorRingN(i) var otherHole = poly.getInteriorRingN(i) var holeComp = thisHole.compareToSameClass(otherHole, comp) if (holeComp !== 0) { return holeComp } i++ } if (i < nHole1) { return 1 } if (i < nHole2) { return -1 } return 0 } } Polygon.prototype.apply = function apply (filter) { var this$1$1 = this if (hasInterface(filter, CoordinateFilter)) { this._shell.apply(filter) for (var i$1 = 0; i$1 < this._holes.length; i$1++) { this$1$1._holes[i$1].apply(filter) } } else if (hasInterface(filter, CoordinateSequenceFilter)) { this._shell.apply(filter) if (!filter.isDone()) { for (var i$2 = 0; i$2 < this._holes.length; i$2++) { this$1$1._holes[i$2].apply(filter) if (filter.isDone()) { break } } } if (filter.isGeometryChanged()) { this.geometryChanged() } } else if (hasInterface(filter, GeometryFilter)) { filter.filter(this) } else if (hasInterface(filter, GeometryComponentFilter)) { filter.filter(this) this._shell.apply(filter) for (var i = 0; i < this._holes.length; i++) { this$1$1._holes[i].apply(filter) } } } Polygon.prototype.getBoundary = function getBoundary () { var this$1$1 = this if (this.isEmpty()) { return this.getFactory().createMultiLineString() } var rings = new Array(this._holes.length + 1).fill(null) rings[0] = this._shell for (var i = 0; i < this._holes.length; i++) { rings[i + 1] = this$1$1._holes[i] } if (rings.length <= 1) { return this.getFactory().createLinearRing(rings[0].getCoordinateSequence()) } return this.getFactory().createMultiLineString(rings) } Polygon.prototype.clone = function clone () { var this$1$1 = this var poly = Geometry$$1.prototype.clone.call(this) poly._shell = this._shell.clone() poly._holes = new Array(this._holes.length).fill(null) for (var i = 0; i < this._holes.length; i++) { poly._holes[i] = this$1$1._holes[i].clone() } return poly } Polygon.prototype.getGeometryType = function getGeometryType () { return 'Polygon' } Polygon.prototype.copy = function copy () { var this$1$1 = this var shell = this._shell.copy() var holes = new Array(this._holes.length).fill(null) for (var i = 0; i < holes.length; i++) { holes[i] = this$1$1._holes[i].copy() } return new Polygon(shell, holes, this._factory) } Polygon.prototype.getExteriorRing = function getExteriorRing () { return this._shell } Polygon.prototype.isEmpty = function isEmpty () { return this._shell.isEmpty() } Polygon.prototype.getInteriorRingN = function getInteriorRingN (n) { return this._holes[n] } Polygon.prototype.interfaces_ = function interfaces_ () { return [Polygonal] } Polygon.prototype.getClass = function getClass () { return Polygon } staticAccessors.serialVersionUID.get = function () { return -3494792200821764533 } Object.defineProperties(Polygon, staticAccessors) return Polygon }(Geometry$2)) var MultiPoint = (function (GeometryCollection$$1) { function MultiPoint () { GeometryCollection$$1.apply(this, arguments) } if (GeometryCollection$$1) MultiPoint.__proto__ = GeometryCollection$$1 MultiPoint.prototype = Object.create(GeometryCollection$$1 && GeometryCollection$$1.prototype) MultiPoint.prototype.constructor = MultiPoint var staticAccessors = { serialVersionUID: { configurable: true } } MultiPoint.prototype.getSortIndex = function getSortIndex () { return Geometry$2.SORTINDEX_MULTIPOINT } MultiPoint.prototype.isValid = function isValid () { return true } MultiPoint.prototype.equalsExact = function equalsExact () { if (arguments.length === 2) { var other = arguments[0] var tolerance = arguments[1] if (!this.isEquivalentClass(other)) { return false } return GeometryCollection$$1.prototype.equalsExact.call(this, other, tolerance) } else { return GeometryCollection$$1.prototype.equalsExact.apply(this, arguments) } } MultiPoint.prototype.getCoordinate = function getCoordinate () { if (arguments.length === 1) { var n = arguments[0] return this._geometries[n].getCoordinate() } else { return GeometryCollection$$1.prototype.getCoordinate.apply(this, arguments) } } MultiPoint.prototype.getBoundaryDimension = function getBoundaryDimension () { return Dimension.FALSE } MultiPoint.prototype.getDimension = function getDimension () { return 0 } MultiPoint.prototype.getBoundary = function getBoundary () { return this.getFactory().createGeometryCollection(null) } MultiPoint.prototype.getGeometryType = function getGeometryType () { return 'MultiPoint' } MultiPoint.prototype.copy = function copy () { var this$1$1 = this var points = new Array(this._geometries.length).fill(null) for (var i = 0; i < points.length; i++) { points[i] = this$1$1._geometries[i].copy() } return new MultiPoint(points, this._factory) } MultiPoint.prototype.interfaces_ = function interfaces_ () { return [Puntal] } MultiPoint.prototype.getClass = function getClass () { return MultiPoint } staticAccessors.serialVersionUID.get = function () { return -8048474874175355449 } Object.defineProperties(MultiPoint, staticAccessors) return MultiPoint }(GeometryCollection)) var LinearRing = (function (LineString$$1) { function LinearRing (points, factory) { if (points instanceof Coordinate && factory instanceof GeometryFactory) { points = factory.getCoordinateSequenceFactory().create(points) } LineString$$1.call(this, points, factory) this.validateConstruction() } if (LineString$$1) LinearRing.__proto__ = LineString$$1 LinearRing.prototype = Object.create(LineString$$1 && LineString$$1.prototype) LinearRing.prototype.constructor = LinearRing var staticAccessors = { MINIMUM_VALID_SIZE: { configurable: true }, serialVersionUID: { configurable: true } } LinearRing.prototype.getSortIndex = function getSortIndex () { return Geometry$2.SORTINDEX_LINEARRING } LinearRing.prototype.getBoundaryDimension = function getBoundaryDimension () { return Dimension.FALSE } LinearRing.prototype.isClosed = function isClosed () { if (this.isEmpty()) { return true } return LineString$$1.prototype.isClosed.call(this) } LinearRing.prototype.reverse = function reverse () { var seq = this._points.copy() CoordinateSequences.reverse(seq) var rev = this.getFactory().createLinearRing(seq) return rev } LinearRing.prototype.validateConstruction = function validateConstruction () { if (!this.isEmpty() && !LineString$$1.prototype.isClosed.call(this)) { throw new IllegalArgumentException('Points of LinearRing do not form a closed linestring') } if (this.getCoordinateSequence().size() >= 1 && this.getCoordinateSequence().size() < LinearRing.MINIMUM_VALID_SIZE) { throw new IllegalArgumentException('Invalid number of points in LinearRing (found ' + this.getCoordinateSequence().size() + ' - must be 0 or >= 4)') } } LinearRing.prototype.getGeometryType = function getGeometryType () { return 'LinearRing' } LinearRing.prototype.copy = function copy () { return new LinearRing(this._points.copy(), this._factory) } LinearRing.prototype.interfaces_ = function interfaces_ () { return [] } LinearRing.prototype.getClass = function getClass () { return LinearRing } staticAccessors.MINIMUM_VALID_SIZE.get = function () { return 4 } staticAccessors.serialVersionUID.get = function () { return -4261142084085851829 } Object.defineProperties(LinearRing, staticAccessors) return LinearRing }(LineString)) var MultiPolygon = (function (GeometryCollection$$1) { function MultiPolygon () { GeometryCollection$$1.apply(this, arguments) } if (GeometryCollection$$1) MultiPolygon.__proto__ = GeometryCollection$$1 MultiPolygon.prototype = Object.create(GeometryCollection$$1 && GeometryCollection$$1.prototype) MultiPolygon.prototype.constructor = MultiPolygon var staticAccessors = { serialVersionUID: { configurable: true } } MultiPolygon.prototype.getSortIndex = function getSortIndex () { return Geometry$2.SORTINDEX_MULTIPOLYGON } MultiPolygon.prototype.equalsExact = function equalsExact () { if (arguments.length === 2) { var other = arguments[0] var tolerance = arguments[1] if (!this.isEquivalentClass(other)) { return false } return GeometryCollection$$1.prototype.equalsExact.call(this, other, tolerance) } else { return GeometryCollection$$1.prototype.equalsExact.apply(this, arguments) } } MultiPolygon.prototype.getBoundaryDimension = function getBoundaryDimension () { return 1 } MultiPolygon.prototype.getDimension = function getDimension () { return 2 } MultiPolygon.prototype.reverse = function reverse () { var this$1$1 = this var n = this._geometries.length var revGeoms = new Array(n).fill(null) for (var i = 0; i < this._geometries.length; i++) { revGeoms[i] = this$1$1._geometries[i].reverse() } return this.getFactory().createMultiPolygon(revGeoms) } MultiPolygon.prototype.getBoundary = function getBoundary () { var this$1$1 = this if (this.isEmpty()) { return this.getFactory().createMultiLineString() } var allRings = new ArrayList() for (var i = 0; i < this._geometries.length; i++) { var polygon = this$1$1._geometries[i] var rings = polygon.getBoundary() for (var j = 0; j < rings.getNumGeometries(); j++) { allRings.add(rings.getGeometryN(j)) } } var allRingsArray = new Array(allRings.size()).fill(null) return this.getFactory().createMultiLineString(allRings.toArray(allRingsArray)) } MultiPolygon.prototype.getGeometryType = function getGeometryType () { return 'MultiPolygon' } MultiPolygon.prototype.copy = function copy () { var this$1$1 = this var polygons = new Array(this._geometries.length).fill(null) for (var i = 0; i < polygons.length; i++) { polygons[i] = this$1$1._geometries[i].copy() } return new MultiPolygon(polygons, this._factory) } MultiPolygon.prototype.interfaces_ = function interfaces_ () { return [Polygonal] } MultiPolygon.prototype.getClass = function getClass () { return MultiPolygon } staticAccessors.serialVersionUID.get = function () { return -551033529766975875 } Object.defineProperties(MultiPolygon, staticAccessors) return MultiPolygon }(GeometryCollection)) var GeometryEditor = function GeometryEditor (factory) { this._factory = factory || null this._isUserDataCopied = false } var staticAccessors$16 = { NoOpGeometryOperation: { configurable: true }, CoordinateOperation: { configurable: true }, CoordinateSequenceOperation: { configurable: true } } GeometryEditor.prototype.setCopyUserData = function setCopyUserData (isUserDataCopied) { this._isUserDataCopied = isUserDataCopied } GeometryEditor.prototype.edit = function edit (geometry, operation) { if (geometry === null) { return null } var result = this.editInternal(geometry, operation) if (this._isUserDataCopied) { result.setUserData(geometry.getUserData()) } return result } GeometryEditor.prototype.editInternal = function editInternal (geometry, operation) { if (this._factory === null) { this._factory = geometry.getFactory() } if (geometry instanceof GeometryCollection) { return this.editGeometryCollection(geometry, operation) } if (geometry instanceof Polygon) { return this.editPolygon(geometry, operation) } if (geometry instanceof Point) { return operation.edit(geometry, this._factory) } if (geometry instanceof LineString) { return operation.edit(geometry, this._factory) } Assert.shouldNeverReachHere('Unsupported Geometry class: ' + geometry.getClass().getName()) return null } GeometryEditor.prototype.editGeometryCollection = function editGeometryCollection (collection, operation) { var this$1$1 = this var collectionForType = operation.edit(collection, this._factory) var geometries = new ArrayList() for (var i = 0; i < collectionForType.getNumGeometries(); i++) { var geometry = this$1$1.edit(collectionForType.getGeometryN(i), operation) if (geometry === null || geometry.isEmpty()) { continue } geometries.add(geometry) } if (collectionForType.getClass() === MultiPoint) { return this._factory.createMultiPoint(geometries.toArray([])) } if (collectionForType.getClass() === MultiLineString) { return this._factory.createMultiLineString(geometries.toArray([])) } if (collectionForType.getClass() === MultiPolygon) { return this._factory.createMultiPolygon(geometries.toArray([])) } return this._factory.createGeometryCollection(geometries.toArray([])) } GeometryEditor.prototype.editPolygon = function editPolygon (polygon, operation) { var this$1$1 = this var newPolygon = operation.edit(polygon, this._factory) if (newPolygon === null) { newPolygon = this._factory.createPolygon(null) } if (newPolygon.isEmpty()) { return newPolygon } var shell = this.edit(newPolygon.getExteriorRing(), operation) if (shell === null || shell.isEmpty()) { return this._factory.createPolygon() } var holes = new ArrayList() for (var i = 0; i < newPolygon.getNumInteriorRing(); i++) { var hole = this$1$1.edit(newPolygon.getInteriorRingN(i), operation) if (hole === null || hole.isEmpty()) { continue } holes.add(hole) } return this._factory.createPolygon(shell, holes.toArray([])) } GeometryEditor.prototype.interfaces_ = function interfaces_ () { return [] } GeometryEditor.prototype.getClass = function getClass () { return GeometryEditor } GeometryEditor.GeometryEditorOperation = function GeometryEditorOperation () { } staticAccessors$16.NoOpGeometryOperation.get = function () { return NoOpGeometryOperation } staticAccessors$16.CoordinateOperation.get = function () { return CoordinateOperation } staticAccessors$16.CoordinateSequenceOperation.get = function () { return CoordinateSequenceOperation } Object.defineProperties(GeometryEditor, staticAccessors$16) var NoOpGeometryOperation = function NoOpGeometryOperation () { } NoOpGeometryOperation.prototype.edit = function edit (geometry, factory) { return geometry } NoOpGeometryOperation.prototype.interfaces_ = function interfaces_ () { return [GeometryEditor.GeometryEditorOperation] } NoOpGeometryOperation.prototype.getClass = function getClass () { return NoOpGeometryOperation } var CoordinateOperation = function CoordinateOperation () { } CoordinateOperation.prototype.edit = function edit (geometry, factory) { var coords = this.editCoordinates(geometry.getCoordinates(), geometry) if (coords === null) { return geometry } if (geometry instanceof LinearRing) { return factory.createLinearRing(coords) } if (geometry instanceof LineString) { return factory.createLineString(coords) } if (geometry instanceof Point) { if (coords.length > 0) { return factory.createPoint(coords[0]) } else { return factory.createPoint() } } return geometry } CoordinateOperation.prototype.interfaces_ = function interfaces_ () { return [GeometryEditor.GeometryEditorOperation] } CoordinateOperation.prototype.getClass = function getClass () { return CoordinateOperation } var CoordinateSequenceOperation = function CoordinateSequenceOperation () { } CoordinateSequenceOperation.prototype.edit = function edit (geometry, factory) { if (geometry instanceof LinearRing) { return factory.createLinearRing(this.edit(geometry.getCoordinateSequence(), geometry)) } if (geometry instanceof LineString) { return factory.createLineString(this.edit(geometry.getCoordinateSequence(), geometry)) } if (geometry instanceof Point) { return factory.createPoint(this.edit(geometry.getCoordinateSequence(), geometry)) } return geometry } CoordinateSequenceOperation.prototype.interfaces_ = function interfaces_ () { return [GeometryEditor.GeometryEditorOperation] } CoordinateSequenceOperation.prototype.getClass = function getClass () { return CoordinateSequenceOperation } var CoordinateArraySequence = function CoordinateArraySequence () { var this$1$1 = this this._dimension = 3 this._coordinates = null if (arguments.length === 1) { if (arguments[0] instanceof Array) { this._coordinates = arguments[0] this._dimension = 3 } else if (Number.isInteger(arguments[0])) { var size = arguments[0] this._coordinates = new Array(size).fill(null) for (var i = 0; i < size; i++) { this$1$1._coordinates[i] = new Coordinate() } } else if (hasInterface(arguments[0], CoordinateSequence)) { var coordSeq = arguments[0] if (coordSeq === null) { this._coordinates = new Array(0).fill(null) return null } this._dimension = coordSeq.getDimension() this._coordinates = new Array(coordSeq.size()).fill(null) for (var i$1 = 0; i$1 < this._coordinates.length; i$1++) { this$1$1._coordinates[i$1] = coordSeq.getCoordinateCopy(i$1) } } } else if (arguments.length === 2) { if (arguments[0] instanceof Array && Number.isInteger(arguments[1])) { var coordinates = arguments[0] var dimension = arguments[1] this._coordinates = coordinates this._dimension = dimension if (coordinates === null) { this._coordinates = new Array(0).fill(null) } } else if (Number.isInteger(arguments[0]) && Number.isInteger(arguments[1])) { var size$1 = arguments[0] var dimension$1 = arguments[1] this._coordinates = new Array(size$1).fill(null) this._dimension = dimension$1 for (var i$2 = 0; i$2 < size$1; i$2++) { this$1$1._coordinates[i$2] = new Coordinate() } } } } var staticAccessors$18 = { serialVersionUID: { configurable: true } } CoordinateArraySequence.prototype.setOrdinate = function setOrdinate (index, ordinateIndex, value) { switch (ordinateIndex) { case CoordinateSequence.X: this._coordinates[index].x = value break case CoordinateSequence.Y: this._coordinates[index].y = value break case CoordinateSequence.Z: this._coordinates[index].z = value break default: throw new IllegalArgumentException('invalid ordinateIndex') } } CoordinateArraySequence.prototype.size = function size () { return this._coordinates.length } CoordinateArraySequence.prototype.getOrdinate = function getOrdinate (index, ordinateIndex) { switch (ordinateIndex) { case CoordinateSequence.X: return this._coordinates[index].x case CoordinateSequence.Y: return this._coordinates[index].y case CoordinateSequence.Z: return this._coordinates[index].z } return Double.NaN } CoordinateArraySequence.prototype.getCoordinate = function getCoordinate () { if (arguments.length === 1) { var i = arguments[0] return this._coordinates[i] } else if (arguments.length === 2) { var index = arguments[0] var coord = arguments[1] coord.x = this._coordinates[index].x coord.y = this._coordinates[index].y coord.z = this._coordinates[index].z } } CoordinateArraySequence.prototype.getCoordinateCopy = function getCoordinateCopy (i) { return new Coordinate(this._coordinates[i]) } CoordinateArraySequence.prototype.getDimension = function getDimension () { return this._dimension } CoordinateArraySequence.prototype.getX = function getX (index) { return this._coordinates[index].x } CoordinateArraySequence.prototype.clone = function clone () { var this$1$1 = this var cloneCoordinates = new Array(this.size()).fill(null) for (var i = 0; i < this._coordinates.length; i++) { cloneCoordinates[i] = this$1$1._coordinates[i].clone() } return new CoordinateArraySequence(cloneCoordinates, this._dimension) } CoordinateArraySequence.prototype.expandEnvelope = function expandEnvelope (env) { var this$1$1 = this for (var i = 0; i < this._coordinates.length; i++) { env.expandToInclude(this$1$1._coordinates[i]) } return env } CoordinateArraySequence.prototype.copy = function copy () { var this$1$1 = this var cloneCoordinates = new Array(this.size()).fill(null) for (var i = 0; i < this._coordinates.length; i++) { cloneCoordinates[i] = this$1$1._coordinates[i].copy() } return new CoordinateArraySequence(cloneCoordinates, this._dimension) } CoordinateArraySequence.prototype.toString = function toString () { var this$1$1 = this if (this._coordinates.length > 0) { var strBuf = new StringBuffer(17 * this._coordinates.length) strBuf.append('(') strBuf.append(this._coordinates[0]) for (var i = 1; i < this._coordinates.length; i++) { strBuf.append(', ') strBuf.append(this$1$1._coordinates[i]) } strBuf.append(')') return strBuf.toString() } else { return '()' } } CoordinateArraySequence.prototype.getY = function getY (index) { return this._coordinates[index].y } CoordinateArraySequence.prototype.toCoordinateArray = function toCoordinateArray () { return this._coordinates } CoordinateArraySequence.prototype.interfaces_ = function interfaces_ () { return [CoordinateSequence, Serializable] } CoordinateArraySequence.prototype.getClass = function getClass () { return CoordinateArraySequence } staticAccessors$18.serialVersionUID.get = function () { return -915438501601840650 } Object.defineProperties(CoordinateArraySequence, staticAccessors$18) var CoordinateArraySequenceFactory = function CoordinateArraySequenceFactory () { } var staticAccessors$17 = { serialVersionUID: { configurable: true }, instanceObject: { configurable: true } } CoordinateArraySequenceFactory.prototype.readResolve = function readResolve () { return CoordinateArraySequenceFactory.instance() } CoordinateArraySequenceFactory.prototype.create = function create () { if (arguments.length === 1) { if (arguments[0] instanceof Array) { var coordinates = arguments[0] return new CoordinateArraySequence(coordinates) } else if (hasInterface(arguments[0], CoordinateSequence)) { var coordSeq = arguments[0] return new CoordinateArraySequence(coordSeq) } } else if (arguments.length === 2) { var size = arguments[0] var dimension = arguments[1] if (dimension > 3) { dimension = 3 } if (dimension < 2) { return new CoordinateArraySequence(size) } return new CoordinateArraySequence(size, dimension) } } CoordinateArraySequenceFactory.prototype.interfaces_ = function interfaces_ () { return [CoordinateSequenceFactory, Serializable] } CoordinateArraySequenceFactory.prototype.getClass = function getClass () { return CoordinateArraySequenceFactory } CoordinateArraySequenceFactory.instance = function instance () { return CoordinateArraySequenceFactory.instanceObject } staticAccessors$17.serialVersionUID.get = function () { return -4099577099607551657 } staticAccessors$17.instanceObject.get = function () { return new CoordinateArraySequenceFactory() } Object.defineProperties(CoordinateArraySequenceFactory, staticAccessors$17) /** * @see http://download.oracle.com/javase/6/docs/api/java/util/HashMap.html * * @extends {javascript.util.Map} * @constructor * @private */ var HashMap = (function (MapInterface) { function HashMap () { MapInterface.call(this) this.map_ = new Map() } if (MapInterface) HashMap.__proto__ = MapInterface HashMap.prototype = Object.create(MapInterface && MapInterface.prototype) HashMap.prototype.constructor = HashMap /** * @override */ HashMap.prototype.get = function get (key) { return this.map_.get(key) || null } /** * @override */ HashMap.prototype.put = function put (key, value) { this.map_.set(key, value) return value } /** * @override */ HashMap.prototype.values = function values () { var arrayList = new ArrayList() var it = this.map_.values() var o = it.next() while (!o.done) { arrayList.add(o.value) o = it.next() } return arrayList } /** * @override */ HashMap.prototype.entrySet = function entrySet () { var hashSet = new HashSet() this.map_.entries().forEach(function (entry) { return hashSet.add(entry) }) return hashSet } /** * @override */ HashMap.prototype.size = function size () { return this.map_.size() } return HashMap }(Map$1)) var PrecisionModel = function PrecisionModel () { this._modelType = null this._scale = null if (arguments.length === 0) { this._modelType = PrecisionModel.FLOATING } else if (arguments.length === 1) { if (arguments[0] instanceof Type) { var modelType = arguments[0] this._modelType = modelType if (modelType === PrecisionModel.FIXED) { this.setScale(1.0) } } else if (typeof arguments[0] === 'number') { var scale = arguments[0] this._modelType = PrecisionModel.FIXED this.setScale(scale) } else if (arguments[0] instanceof PrecisionModel) { var pm = arguments[0] this._modelType = pm._modelType this._scale = pm._scale } } } var staticAccessors$19 = { serialVersionUID: { configurable: true }, maximumPreciseValue: { configurable: true } } PrecisionModel.prototype.equals = function equals (other) { if (!(other instanceof PrecisionModel)) { return false } var otherPrecisionModel = other return this._modelType === otherPrecisionModel._modelType && this._scale === otherPrecisionModel._scale } PrecisionModel.prototype.compareTo = function compareTo (o) { var other = o var sigDigits = this.getMaximumSignificantDigits() var otherSigDigits = other.getMaximumSignificantDigits() return new Integer(sigDigits).compareTo(new Integer(otherSigDigits)) } PrecisionModel.prototype.getScale = function getScale () { return this._scale } PrecisionModel.prototype.isFloating = function isFloating () { return this._modelType === PrecisionModel.FLOATING || this._modelType === PrecisionModel.FLOATING_SINGLE } PrecisionModel.prototype.getType = function getType () { return this._modelType } PrecisionModel.prototype.toString = function toString () { var description = 'UNKNOWN' if (this._modelType === PrecisionModel.FLOATING) { description = 'Floating' } else if (this._modelType === PrecisionModel.FLOATING_SINGLE) { description = 'Floating-Single' } else if (this._modelType === PrecisionModel.FIXED) { description = 'Fixed (Scale=' + this.getScale() + ')' } return description } PrecisionModel.prototype.makePrecise = function makePrecise () { if (typeof arguments[0] === 'number') { var val = arguments[0] if (Double.isNaN(val)) { return val } if (this._modelType === PrecisionModel.FLOATING_SINGLE) { var floatSingleVal = val return floatSingleVal } if (this._modelType === PrecisionModel.FIXED) { return Math.round(val * this._scale) / this._scale } return val } else if (arguments[0] instanceof Coordinate) { var coord = arguments[0] if (this._modelType === PrecisionModel.FLOATING) { return null } coord.x = this.makePrecise(coord.x) coord.y = this.makePrecise(coord.y) } } PrecisionModel.prototype.getMaximumSignificantDigits = function getMaximumSignificantDigits () { var maxSigDigits = 16 if (this._modelType === PrecisionModel.FLOATING) { maxSigDigits = 16 } else if (this._modelType === PrecisionModel.FLOATING_SINGLE) { maxSigDigits = 6 } else if (this._modelType === PrecisionModel.FIXED) { maxSigDigits = 1 + Math.trunc(Math.ceil(Math.log(this.getScale()) / Math.log(10))) } return maxSigDigits } PrecisionModel.prototype.setScale = function setScale (scale) { this._scale = Math.abs(scale) } PrecisionModel.prototype.interfaces_ = function interfaces_ () { return [Serializable, Comparable] } PrecisionModel.prototype.getClass = function getClass () { return PrecisionModel } PrecisionModel.mostPrecise = function mostPrecise (pm1, pm2) { if (pm1.compareTo(pm2) >= 0) { return pm1 } return pm2 } staticAccessors$19.serialVersionUID.get = function () { return 7777263578777803835 } staticAccessors$19.maximumPreciseValue.get = function () { return 9007199254740992.0 } Object.defineProperties(PrecisionModel, staticAccessors$19) var Type = function Type (name) { this._name = name || null Type.nameToTypeMap.put(name, this) } var staticAccessors$1$1 = { serialVersionUID: { configurable: true }, nameToTypeMap: { configurable: true } } Type.prototype.readResolve = function readResolve () { return Type.nameToTypeMap.get(this._name) } Type.prototype.toString = function toString () { return this._name } Type.prototype.interfaces_ = function interfaces_ () { return [Serializable] } Type.prototype.getClass = function getClass () { return Type } staticAccessors$1$1.serialVersionUID.get = function () { return -5528602631731589822 } staticAccessors$1$1.nameToTypeMap.get = function () { return new HashMap() } Object.defineProperties(Type, staticAccessors$1$1) PrecisionModel.Type = Type PrecisionModel.FIXED = new Type('FIXED') PrecisionModel.FLOATING = new Type('FLOATING') PrecisionModel.FLOATING_SINGLE = new Type('FLOATING SINGLE') var GeometryFactory = function GeometryFactory () { this._precisionModel = new PrecisionModel() this._SRID = 0 this._coordinateSequenceFactory = GeometryFactory.getDefaultCoordinateSequenceFactory() if (arguments.length === 0); else if (arguments.length === 1) { if (hasInterface(arguments[0], CoordinateSequenceFactory)) { this._coordinateSequenceFactory = arguments[0] } else if (arguments[0] instanceof PrecisionModel) { this._precisionModel = arguments[0] } } else if (arguments.length === 2) { this._precisionModel = arguments[0] this._SRID = arguments[1] } else if (arguments.length === 3) { this._precisionModel = arguments[0] this._SRID = arguments[1] this._coordinateSequenceFactory = arguments[2] } } var staticAccessors$2 = { serialVersionUID: { configurable: true } } GeometryFactory.prototype.toGeometry = function toGeometry (envelope) { if (envelope.isNull()) { return this.createPoint(null) } if (envelope.getMinX() === envelope.getMaxX() && envelope.getMinY() === envelope.getMaxY()) { return this.createPoint(new Coordinate(envelope.getMinX(), envelope.getMinY())) } if (envelope.getMinX() === envelope.getMaxX() || envelope.getMinY() === envelope.getMaxY()) { return this.createLineString([new Coordinate(envelope.getMinX(), envelope.getMinY()), new Coordinate(envelope.getMaxX(), envelope.getMaxY())]) } return this.createPolygon(this.createLinearRing([new Coordinate(envelope.getMinX(), envelope.getMinY()), new Coordinate(envelope.getMinX(), envelope.getMaxY()), new Coordinate(envelope.getMaxX(), envelope.getMaxY()), new Coordinate(envelope.getMaxX(), envelope.getMinY()), new Coordinate(envelope.getMinX(), envelope.getMinY())]), null) } GeometryFactory.prototype.createLineString = function createLineString (coordinates) { if (!coordinates) { return new LineString(this.getCoordinateSequenceFactory().create([]), this) } else if (coordinates instanceof Array) { return new LineString(this.getCoordinateSequenceFactory().create(coordinates), this) } else if (hasInterface(coordinates, CoordinateSequence)) { return new LineString(coordinates, this) } } GeometryFactory.prototype.createMultiLineString = function createMultiLineString () { if (arguments.length === 0) { return new MultiLineString(null, this) } else if (arguments.length === 1) { var lineStrings = arguments[0] return new MultiLineString(lineStrings, this) } } GeometryFactory.prototype.buildGeometry = function buildGeometry (geomList) { var geomClass = null var isHeterogeneous = false var hasGeometryCollection = false for (var i = geomList.iterator(); i.hasNext();) { var geom = i.next() var partClass = geom.getClass() if (geomClass === null) { geomClass = partClass } if (partClass !== geomClass) { isHeterogeneous = true } if (geom.isGeometryCollectionOrDerived()) { hasGeometryCollection = true } } if (geomClass === null) { return this.createGeometryCollection() } if (isHeterogeneous || hasGeometryCollection) { return this.createGeometryCollection(GeometryFactory.toGeometryArray(geomList)) } var geom0 = geomList.iterator().next() var isCollection = geomList.size() > 1 if (isCollection) { if (geom0 instanceof Polygon) { return this.createMultiPolygon(GeometryFactory.toPolygonArray(geomList)) } else if (geom0 instanceof LineString) { return this.createMultiLineString(GeometryFactory.toLineStringArray(geomList)) } else if (geom0 instanceof Point) { return this.createMultiPoint(GeometryFactory.toPointArray(geomList)) } Assert.shouldNeverReachHere('Unhandled class: ' + geom0.getClass().getName()) } return geom0 } GeometryFactory.prototype.createMultiPointFromCoords = function createMultiPointFromCoords (coordinates) { return this.createMultiPoint(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null) } GeometryFactory.prototype.createPoint = function createPoint () { if (arguments.length === 0) { return this.createPoint(this.getCoordinateSequenceFactory().create([])) } else if (arguments.length === 1) { if (arguments[0] instanceof Coordinate) { var coordinate = arguments[0] return this.createPoint(coordinate !== null ? this.getCoordinateSequenceFactory().create([coordinate]) : null) } else if (hasInterface(arguments[0], CoordinateSequence)) { var coordinates = arguments[0] return new Point(coordinates, this) } } } GeometryFactory.prototype.getCoordinateSequenceFactory = function getCoordinateSequenceFactory () { return this._coordinateSequenceFactory } GeometryFactory.prototype.createPolygon = function createPolygon () { if (arguments.length === 0) { return new Polygon(null, null, this) } else if (arguments.length === 1) { if (hasInterface(arguments[0], CoordinateSequence)) { var coordinates = arguments[0] return this.createPolygon(this.createLinearRing(coordinates)) } else if (arguments[0] instanceof Array) { var coordinates$1 = arguments[0] return this.createPolygon(this.createLinearRing(coordinates$1)) } else if (arguments[0] instanceof LinearRing) { var shell = arguments[0] return this.createPolygon(shell, null) } } else if (arguments.length === 2) { var shell$1 = arguments[0] var holes = arguments[1] return new Polygon(shell$1, holes, this) } } GeometryFactory.prototype.getSRID = function getSRID () { return this._SRID } GeometryFactory.prototype.createGeometryCollection = function createGeometryCollection () { if (arguments.length === 0) { return new GeometryCollection(null, this) } else if (arguments.length === 1) { var geometries = arguments[0] return new GeometryCollection(geometries, this) } } GeometryFactory.prototype.createGeometry = function createGeometry (g) { var editor = new GeometryEditor(this) return editor.edit(g, { edit: function () { if (arguments.length === 2) { var coordSeq = arguments[0] // const geometry = arguments[1] return this._coordinateSequenceFactory.create(coordSeq) } } }) } GeometryFactory.prototype.getPrecisionModel = function getPrecisionModel () { return this._precisionModel } GeometryFactory.prototype.createLinearRing = function createLinearRing () { if (arguments.length === 0) { return this.createLinearRing(this.getCoordinateSequenceFactory().create([])) } else if (arguments.length === 1) { if (arguments[0] instanceof Array) { var coordinates = arguments[0] return this.createLinearRing(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null) } else if (hasInterface(arguments[0], CoordinateSequence)) { var coordinates$1 = arguments[0] return new LinearRing(coordinates$1, this) } } } GeometryFactory.prototype.createMultiPolygon = function createMultiPolygon () { if (arguments.length === 0) { return new MultiPolygon(null, this) } else if (arguments.length === 1) { var polygons = arguments[0] return new MultiPolygon(polygons, this) } } GeometryFactory.prototype.createMultiPoint = function createMultiPoint () { var this$1$1 = this if (arguments.length === 0) { return new MultiPoint(null, this) } else if (arguments.length === 1) { if (arguments[0] instanceof Array) { var point = arguments[0] return new MultiPoint(point, this) } else if (arguments[0] instanceof Array) { var coordinates = arguments[0] return this.createMultiPoint(coordinates !== null ? this.getCoordinateSequenceFactory().create(coordinates) : null) } else if (hasInterface(arguments[0], CoordinateSequence)) { var coordinates$1 = arguments[0] if (coordinates$1 === null) { return this.createMultiPoint(new Array(0).fill(null)) } var points = new Array(coordinates$1.size()).fill(null) for (var i = 0; i < coordinates$1.size(); i++) { var ptSeq = this$1$1.getCoordinateSequenceFactory().create(1, coordinates$1.getDimension()) CoordinateSequences.copy(coordinates$1, i, ptSeq, 0, 1) points[i] = this$1$1.createPoint(ptSeq) } return this.createMultiPoint(points) } } } GeometryFactory.prototype.interfaces_ = function interfaces_ () { return [Serializable] } GeometryFactory.prototype.getClass = function getClass () { return GeometryFactory } GeometryFactory.toMultiPolygonArray = function toMultiPolygonArray (multiPolygons) { var multiPolygonArray = new Array(multiPolygons.size()).fill(null) return multiPolygons.toArray(multiPolygonArray) } GeometryFactory.toGeometryArray = function toGeometryArray (geometries) { if (geometries === null) { return null } var geometryArray = new Array(geometries.size()).fill(null) return geometries.toArray(geometryArray) } GeometryFactory.getDefaultCoordinateSequenceFactory = function getDefaultCoordinateSequenceFactory () { return CoordinateArraySequenceFactory.instance() } GeometryFactory.toMultiLineStringArray = function toMultiLineStringArray (multiLineStrings) { var multiLineStringArray = new Array(multiLineStrings.size()).fill(null) return multiLineStrings.toArray(multiLineStringArray) } GeometryFactory.toLineStringArray = function toLineStringArray (lineStrings) { var lineStringArray = new Array(lineStrings.size()).fill(null) return lineStrings.toArray(lineStringArray) } GeometryFactory.toMultiPointArray = function toMultiPointArray (multiPoints) { var multiPointArray = new Array(multiPoints.size()).fill(null) return multiPoints.toArray(multiPointArray) } GeometryFactory.toLinearRingArray = function toLinearRingArray (linearRings) { var linearRingArray = new Array(linearRings.size()).fill(null) return linearRings.toArray(linearRingArray) } GeometryFactory.toPointArray = function toPointArray (points) { var pointArray = new Array(points.size()).fill(null) return points.toArray(pointArray) } GeometryFactory.toPolygonArray = function toPolygonArray (polygons) { var polygonArray = new Array(polygons.size()).fill(null) return polygons.toArray(polygonArray) } GeometryFactory.createPointFromInternalCoord = function createPointFromInternalCoord (coord, exemplar) { exemplar.getPrecisionModel().makePrecise(coord) return exemplar.getFactory().createPoint(coord) } staticAccessors$2.serialVersionUID.get = function () { return -6820524753094095635 } Object.defineProperties(GeometryFactory, staticAccessors$2) var geometryTypes$2 = ['Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon'] /** * Class for reading and writing Well-Known Text.Create a new parser for GeoJSON * NOTE: Adapted from OpenLayers 2.11 implementation. */ /** * Create a new parser for GeoJSON * * @param {GeometryFactory} geometryFactory * @return An instance of GeoJsonParser. * @constructor * @private */ var GeoJSONParser = function GeoJSONParser (geometryFactory) { this.geometryFactory = geometryFactory || new GeometryFactory() } /** * Deserialize a GeoJSON object and return the Geometry or Feature(Collection) with JSTS Geometries * * @param {} * A GeoJSON object. * @return {} A Geometry instance or object representing a Feature(Collection) with Geometry instances. * @private */ GeoJSONParser.prototype.read = function read (json) { var obj if (typeof json === 'string') { obj = JSON.parse(json) } else { obj = json } var type = obj.type if (!parse[type]) { throw new Error('Unknown GeoJSON type: ' + obj.type) } if (geometryTypes$2.indexOf(type) !== -1) { return parse[type].apply(this, [obj.coordinates]) } else if (type === 'GeometryCollection') { return parse[type].apply(this, [obj.geometries]) } // feature or feature collection return parse[type].apply(this, [obj]) } /** * Serialize a Geometry object into GeoJSON * * @param {Geometry} * geometry A Geometry or array of Geometries. * @return {Object} A GeoJSON object represting the input Geometry/Geometries. * @private */ GeoJSONParser.prototype.write = function write (geometry) { var type = geometry.getGeometryType() if (!extract[type]) { throw new Error('Geometry is not supported') } return extract[type].apply(this, [geometry]) } var parse = { /** * Parse a GeoJSON Feature object * * @param {Object} * obj Object to parse. * * @return {Object} Feature with geometry/bbox converted to JSTS Geometries. */ Feature: function (obj) { var feature = {} // copy features for (var key in obj) { feature[key] = obj[key] } // parse geometry if (obj.geometry) { var type = obj.geometry.type if (!parse[type]) { throw new Error('Unknown GeoJSON type: ' + obj.type) } feature.geometry = this.read(obj.geometry) } // bbox if (obj.bbox) { feature.bbox = parse.bbox.apply(this, [obj.bbox]) } return feature }, /** * Parse a GeoJSON FeatureCollection object * * @param {Object} * obj Object to parse. * * @return {Object} FeatureCollection with geometry/bbox converted to JSTS Geometries. */ FeatureCollection: function (obj) { var this$1$1 = this var featureCollection = {} if (obj.features) { featureCollection.features = [] for (var i = 0; i < obj.features.length; ++i) { featureCollection.features.push(this$1$1.read(obj.features[i])) } } if (obj.bbox) { featureCollection.bbox = this.parse.bbox.apply(this, [obj.bbox]) } return featureCollection }, /** * Convert the ordinates in an array to an array of Coordinates * * @param {Array} * array Array with {Number}s. * * @return {Array} Array with Coordinates. */ coordinates: function (array) { var coordinates = [] for (var i = 0; i < array.length; ++i) { var sub = array[i] coordinates.push(new Coordinate(sub[0], sub[1])) } return coordinates }, /** * Convert the bbox to a LinearRing * * @param {Array} * array Array with [xMin, yMin, xMax, yMax]. * * @return {Array} Array with Coordinates. */ bbox: function (array) { return this.geometryFactory.createLinearRing([ new Coordinate(array[0], array[1]), new Coordinate(array[2], array[1]), new Coordinate(array[2], array[3]), new Coordinate(array[0], array[3]), new Coordinate(array[0], array[1]) ]) }, /** * Convert an Array with ordinates to a Point * * @param {Array} * array Array with ordinates. * * @return {Point} Point. */ Point: function (array) { var coordinate = new Coordinate(array[0], array[1]) return this.geometryFactory.createPoint(coordinate) }, /** * Convert an Array with coordinates to a MultiPoint * * @param {Array} * array Array with coordinates. * * @return {MultiPoint} MultiPoint. */ MultiPoint: function (array) { var this$1$1 = this var points = [] for (var i = 0; i < array.length; ++i) { points.push(parse.Point.apply(this$1$1, [array[i]])) } return this.geometryFactory.createMultiPoint(points) }, /** * Convert an Array with coordinates to a LineString * * @param {Array} * array Array with coordinates. * * @return {LineString} LineString. */ LineString: function (array) { var coordinates = parse.coordinates.apply(this, [array]) return this.geometryFactory.createLineString(coordinates) }, /** * Convert an Array with coordinates to a MultiLineString * * @param {Array} * array Array with coordinates. * * @return {MultiLineString} MultiLineString. */ MultiLineString: function (array) { var this$1$1 = this var lineStrings = [] for (var i = 0; i < array.length; ++i) { lineStrings.push(parse.LineString.apply(this$1$1, [array[i]])) } return this.geometryFactory.createMultiLineString(lineStrings) }, /** * Convert an Array to a Polygon * * @param {Array} * array Array with shell and holes. * * @return {Polygon} Polygon. */ Polygon: function (array) { var this$1$1 = this var shellCoordinates = parse.coordinates.apply(this, [array[0]]) var shell = this.geometryFactory.createLinearRing(shellCoordinates) var holes = [] for (var i = 1; i < array.length; ++i) { var hole = array[i] var coordinates = parse.coordinates.apply(this$1$1, [hole]) var linearRing = this$1$1.geometryFactory.createLinearRing(coordinates) holes.push(linearRing) } return this.geometryFactory.createPolygon(shell, holes) }, /** * Convert an Array to a MultiPolygon * * @param {Array} * array Array of arrays with shell and rings. * * @return {MultiPolygon} MultiPolygon. */ MultiPolygon: function (array) { var this$1$1 = this var polygons = [] for (var i = 0; i < array.length; ++i) { var polygon = array[i] polygons.push(parse.Polygon.apply(this$1$1, [polygon])) } return this.geometryFactory.createMultiPolygon(polygons) }, /** * Convert an Array to a GeometryCollection * * @param {Array} * array Array of GeoJSON geometries. * * @return {GeometryCollection} GeometryCollection. */ GeometryCollection: function (array) { var this$1$1 = this var geometries = [] for (var i = 0; i < array.length; ++i) { var geometry = array[i] geometries.push(this$1$1.read(geometry)) } return this.geometryFactory.createGeometryCollection(geometries) } } var extract = { /** * Convert a Coordinate to an Array * * @param {Coordinate} * coordinate Coordinate to convert. * * @return {Array} Array of ordinates. */ coordinate: function (coordinate) { return [coordinate.x, coordinate.y] }, /** * Convert a Point to a GeoJSON object * * @param {Point} * point Point to convert. * * @return {Array} Array of 2 ordinates (paired to a coordinate). */ Point: function (point) { var array = extract.coordinate.apply(this, [point.getCoordinate()]) return { type: 'Point', coordinates: array } }, /** * Convert a MultiPoint to a GeoJSON object * * @param {MultiPoint} * multipoint MultiPoint to convert. * * @return {Array} Array of coordinates. */ MultiPoint: function (multipoint) { var this$1$1 = this var array = [] for (var i = 0; i < multipoint._geometries.length; ++i) { var point = multipoint._geometries[i] var geoJson = extract.Point.apply(this$1$1, [point]) array.push(geoJson.coordinates) } return { type: 'MultiPoint', coordinates: array } }, /** * Convert a LineString to a GeoJSON object * * @param {LineString} * linestring LineString to convert. * * @return {Array} Array of coordinates. */ LineString: function (linestring) { var this$1$1 = this var array = [] var coordinates = linestring.getCoordinates() for (var i = 0; i < coordinates.length; ++i) { var coordinate = coordinates[i] array.push(extract.coordinate.apply(this$1$1, [coordinate])) } return { type: 'LineString', coordinates: array } }, /** * Convert a MultiLineString to a GeoJSON object * * @param {MultiLineString} * multilinestring MultiLineString to convert. * * @return {Array} Array of Array of coordinates. */ MultiLineString: function (multilinestring) { var this$1$1 = this var array = [] for (var i = 0; i < multilinestring._geometries.length; ++i) { var linestring = multilinestring._geometries[i] var geoJson = extract.LineString.apply(this$1$1, [linestring]) array.push(geoJson.coordinates) } return { type: 'MultiLineString', coordinates: array } }, /** * Convert a Polygon to a GeoJSON object * * @param {Polygon} * polygon Polygon to convert. * * @return {Array} Array with shell, holes. */ Polygon: function (polygon) { var this$1$1 = this var array = [] var shellGeoJson = extract.LineString.apply(this, [polygon._shell]) array.push(shellGeoJson.coordinates) for (var i = 0; i < polygon._holes.length; ++i) { var hole = polygon._holes[i] var holeGeoJson = extract.LineString.apply(this$1$1, [hole]) array.push(holeGeoJson.coordinates) } return { type: 'Polygon', coordinates: array } }, /** * Convert a MultiPolygon to a GeoJSON object * * @param {MultiPolygon} * multipolygon MultiPolygon to convert. * * @return {Array} Array of polygons. */ MultiPolygon: function (multipolygon) { var this$1$1 = this var array = [] for (var i = 0; i < multipolygon._geometries.length; ++i) { var polygon = multipolygon._geometries[i] var geoJson = extract.Polygon.apply(this$1$1, [polygon]) array.push(geoJson.coordinates) } return { type: 'MultiPolygon', coordinates: array } }, /** * Convert a GeometryCollection to a GeoJSON object * * @param {GeometryCollection} * collection GeometryCollection to convert. * * @return {Array} Array of geometries. */ GeometryCollection: function (collection) { var this$1$1 = this var array = [] for (var i = 0; i < collection._geometries.length; ++i) { var geometry = collection._geometries[i] var type = geometry.getGeometryType() array.push(extract[type].apply(this$1$1, [geometry])) } return { type: 'GeometryCollection', geometries: array } } } /** * Converts a geometry in GeoJSON to a {@link Geometry}. */ /** * A GeoJSONReader is parameterized by a GeometryFactory, * to allow it to create Geometry objects of the appropriate * implementation. In particular, the GeometryFactory determines * the PrecisionModel and SRID that is used. * * @param {GeometryFactory} geometryFactory * @constructor */ var GeoJSONReader = function GeoJSONReader (geometryFactory) { this.geometryFactory = geometryFactory || new GeometryFactory() this.precisionModel = this.geometryFactory.getPrecisionModel() this.parser = new GeoJSONParser(this.geometryFactory) } /** * Reads a GeoJSON representation of a {@link Geometry} * * Will also parse GeoJSON Features/FeatureCollections as custom objects. * * @param {Object|String} geoJson a GeoJSON Object or String. * @return {Geometry|Object} a Geometry or Feature/FeatureCollection representation. * @memberof GeoJSONReader */ GeoJSONReader.prototype.read = function read (geoJson) { var geometry = this.parser.read(geoJson) if (this.precisionModel.getType() === PrecisionModel.FIXED) { this.reducePrecision(geometry) } return geometry } // NOTE: this is a hack GeoJSONReader.prototype.reducePrecision = function reducePrecision (geometry) { var this$1$1 = this var i, len if (geometry.coordinate) { this.precisionModel.makePrecise(geometry.coordinate) } else if (geometry.points) { for (i = 0, len = geometry.points.length; i < len; i++) { this$1$1.precisionModel.makePrecise(geometry.points[i]) } } else if (geometry.geometries) { for (i = 0, len = geometry.geometries.length; i < len; i++) { this$1$1.reducePrecision(geometry.geometries[i]) } } } /** * @module GeoJSONWriter */ /** * Writes the GeoJSON representation of a {@link Geometry}. The * The GeoJSON format is defined here. */ /** * The GeoJSONWriter outputs coordinates rounded to the precision * model. Only the maximum number of decimal places necessary to represent the * ordinates to the required precision will be output. * * @param {GeometryFactory} geometryFactory * @constructor */ var GeoJSONWriter = function GeoJSONWriter () { this.parser = new GeoJSONParser(this.geometryFactory) } /** * Converts a Geometry to its GeoJSON representation. * * @param {Geometry} * geometry a Geometry to process. * @return {Object} The GeoJSON representation of the Geometry. * @memberof GeoJSONWriter */ GeoJSONWriter.prototype.write = function write (geometry) { return this.parser.write(geometry) } /* eslint-disable no-undef */ // io var Position = function Position () { } var staticAccessors$20 = { ON: { configurable: true }, LEFT: { configurable: true }, RIGHT: { configurable: true } } Position.prototype.interfaces_ = function interfaces_ () { return [] } Position.prototype.getClass = function getClass () { return Position } Position.opposite = function opposite (position) { if (position === Position.LEFT) { return Position.RIGHT } if (position === Position.RIGHT) { return Position.LEFT } return position } staticAccessors$20.ON.get = function () { return 0 } staticAccessors$20.LEFT.get = function () { return 1 } staticAccessors$20.RIGHT.get = function () { return 2 } Object.defineProperties(Position, staticAccessors$20) /** * @param {string=} message Optional message * @extends {Error} * @constructor * @private */ function EmptyStackException (message) { this.message = message || '' } EmptyStackException.prototype = new Error() /** * @type {string} */ EmptyStackException.prototype.name = 'EmptyStackException' /** * @see http://download.oracle.com/javase/6/docs/api/java/util/Stack.html * * @extends {List} * @constructor * @private */ function Stack () { /** * @type {Array} * @private */ this.array_ = [] } Stack.prototype = new List() /** * @override */ Stack.prototype.add = function (e) { this.array_.push(e) return true } /** * @override */ Stack.prototype.get = function (index) { if (index < 0 || index >= this.size()) { throw new Error() } return this.array_[index] } /** * Pushes an item onto the top of this stack. * @param {Object} e * @return {Object} */ Stack.prototype.push = function (e) { this.array_.push(e) return e } /** * Pushes an item onto the top of this stack. * @param {Object} e * @return {Object} */ Stack.prototype.pop = function (e) { if (this.array_.length === 0) { throw new EmptyStackException() } return this.array_.pop() } /** * Looks at the object at the top of this stack without removing it from the * stack. * @return {Object} */ Stack.prototype.peek = function () { if (this.array_.length === 0) { throw new EmptyStackException() } return this.array_[this.array_.length - 1] } /** * Tests if this stack is empty. * @return {boolean} true if and only if this stack contains no items; false * otherwise. */ Stack.prototype.empty = function () { if (this.array_.length === 0) { return true } else { return false } } /** * @return {boolean} */ Stack.prototype.isEmpty = function () { return this.empty() } /** * Returns the 1-based position where an object is on this stack. If the object * o occurs as an item in this stack, this method returns the distance from the * top of the stack of the occurrence nearest the top of the stack; the topmost * item on the stack is considered to be at distance 1. The equals method is * used to compare o to the items in this stack. * * NOTE: does not currently actually use equals. (=== is used) * * @param {Object} o * @return {number} the 1-based position from the top of the stack where the * object is located; the return value -1 indicates that the object is * not on the stack. */ Stack.prototype.search = function (o) { return this.array_.indexOf(o) } /** * @return {number} * @export */ Stack.prototype.size = function () { return this.array_.length } /** * @return {Array} */ Stack.prototype.toArray = function () { var this$1$1 = this var array = [] for (var i = 0, len = this.array_.length; i < len; i++) { array.push(this$1$1.array_[i]) } return array } var RightmostEdgeFinder = function RightmostEdgeFinder () { this._minIndex = -1 this._minCoord = null this._minDe = null this._orientedDe = null } RightmostEdgeFinder.prototype.getCoordinate = function getCoordinate () { return this._minCoord } RightmostEdgeFinder.prototype.getRightmostSide = function getRightmostSide (de, index) { var side = this.getRightmostSideOfSegment(de, index) if (side < 0) { side = this.getRightmostSideOfSegment(de, index - 1) } if (side < 0) { this._minCoord = null this.checkForRightmostCoordinate(de) } return side } RightmostEdgeFinder.prototype.findRightmostEdgeAtVertex = function findRightmostEdgeAtVertex () { var pts = this._minDe.getEdge().getCoordinates() Assert.isTrue(this._minIndex > 0 && this._minIndex < pts.length, 'rightmost point expected to be interior vertex of edge') var pPrev = pts[this._minIndex - 1] var pNext = pts[this._minIndex + 1] var orientation = CGAlgorithms.computeOrientation(this._minCoord, pNext, pPrev) var usePrev = false if (pPrev.y < this._minCoord.y && pNext.y < this._minCoord.y && orientation === CGAlgorithms.COUNTERCLOCKWISE) { usePrev = true } else if (pPrev.y > this._minCoord.y && pNext.y > this._minCoord.y && orientation === CGAlgorithms.CLOCKWISE) { usePrev = true } if (usePrev) { this._minIndex = this._minIndex - 1 } } RightmostEdgeFinder.prototype.getRightmostSideOfSegment = function getRightmostSideOfSegment (de, i) { var e = de.getEdge() var coord = e.getCoordinates() if (i < 0 || i + 1 >= coord.length) { return -1 } if (coord[i].y === coord[i + 1].y) { return -1 } var pos = Position.LEFT if (coord[i].y < coord[i + 1].y) { pos = Position.RIGHT } return pos } RightmostEdgeFinder.prototype.getEdge = function getEdge () { return this._orientedDe } RightmostEdgeFinder.prototype.checkForRightmostCoordinate = function checkForRightmostCoordinate (de) { var this$1$1 = this var coord = de.getEdge().getCoordinates() for (var i = 0; i < coord.length - 1; i++) { if (this$1$1._minCoord === null || coord[i].x > this$1$1._minCoord.x) { this$1$1._minDe = de this$1$1._minIndex = i this$1$1._minCoord = coord[i] } } } RightmostEdgeFinder.prototype.findRightmostEdgeAtNode = function findRightmostEdgeAtNode () { var node = this._minDe.getNode() var star = node.getEdges() this._minDe = star.getRightmostEdge() if (!this._minDe.isForward()) { this._minDe = this._minDe.getSym() this._minIndex = this._minDe.getEdge().getCoordinates().length - 1 } } RightmostEdgeFinder.prototype.findEdge = function findEdge (dirEdgeList) { var this$1$1 = this for (var i = dirEdgeList.iterator(); i.hasNext();) { var de = i.next() if (!de.isForward()) { continue } this$1$1.checkForRightmostCoordinate(de) } Assert.isTrue(this._minIndex !== 0 || this._minCoord.equals(this._minDe.getCoordinate()), 'inconsistency in rightmost processing') if (this._minIndex === 0) { this.findRightmostEdgeAtNode() } else { this.findRightmostEdgeAtVertex() } this._orientedDe = this._minDe var rightmostSide = this.getRightmostSide(this._minDe, this._minIndex) if (rightmostSide === Position.LEFT) { this._orientedDe = this._minDe.getSym() } } RightmostEdgeFinder.prototype.interfaces_ = function interfaces_ () { return [] } RightmostEdgeFinder.prototype.getClass = function getClass () { return RightmostEdgeFinder } var TopologyException = (function (RuntimeException$$1) { function TopologyException (msg, pt) { RuntimeException$$1.call(this, TopologyException.msgWithCoord(msg, pt)) this.pt = pt ? new Coordinate(pt) : null this.name = 'TopologyException' } if (RuntimeException$$1) TopologyException.__proto__ = RuntimeException$$1 TopologyException.prototype = Object.create(RuntimeException$$1 && RuntimeException$$1.prototype) TopologyException.prototype.constructor = TopologyException TopologyException.prototype.getCoordinate = function getCoordinate () { return this.pt } TopologyException.prototype.interfaces_ = function interfaces_ () { return [] } TopologyException.prototype.getClass = function getClass () { return TopologyException } TopologyException.msgWithCoord = function msgWithCoord (msg, pt) { if (!pt) { return msg + ' [ ' + pt + ' ]' } return msg } return TopologyException }(RuntimeException)) var LinkedList = function LinkedList () { this.array_ = [] } LinkedList.prototype.addLast = function addLast (e) { this.array_.push(e) } LinkedList.prototype.removeFirst = function removeFirst () { return this.array_.shift() } LinkedList.prototype.isEmpty = function isEmpty () { return this.array_.length === 0 } var BufferSubgraph = function BufferSubgraph () { this._finder = null this._dirEdgeList = new ArrayList() this._nodes = new ArrayList() this._rightMostCoord = null this._env = null this._finder = new RightmostEdgeFinder() } BufferSubgraph.prototype.clearVisitedEdges = function clearVisitedEdges () { for (var it = this._dirEdgeList.iterator(); it.hasNext();) { var de = it.next() de.setVisited(false) } } BufferSubgraph.prototype.getRightmostCoordinate = function getRightmostCoordinate () { return this._rightMostCoord } BufferSubgraph.prototype.computeNodeDepth = function computeNodeDepth (n) { var this$1$1 = this var startEdge = null for (var i = n.getEdges().iterator(); i.hasNext();) { var de = i.next() if (de.isVisited() || de.getSym().isVisited()) { startEdge = de break } } if (startEdge === null) { throw new TopologyException('unable to find edge to compute depths at ' + n.getCoordinate()) } n.getEdges().computeDepths(startEdge) for (var i$1 = n.getEdges().iterator(); i$1.hasNext();) { var de$1 = i$1.next() de$1.setVisited(true) this$1$1.copySymDepths(de$1) } } BufferSubgraph.prototype.computeDepth = function computeDepth (outsideDepth) { this.clearVisitedEdges() var de = this._finder.getEdge() // const n = de.getNode() // const label = de.getLabel() de.setEdgeDepths(Position.RIGHT, outsideDepth) this.copySymDepths(de) this.computeDepths(de) } BufferSubgraph.prototype.create = function create (node) { this.addReachable(node) this._finder.findEdge(this._dirEdgeList) this._rightMostCoord = this._finder.getCoordinate() } BufferSubgraph.prototype.findResultEdges = function findResultEdges () { for (var it = this._dirEdgeList.iterator(); it.hasNext();) { var de = it.next() if (de.getDepth(Position.RIGHT) >= 1 && de.getDepth(Position.LEFT) <= 0 && !de.isInteriorAreaEdge()) { de.setInResult(true) } } } BufferSubgraph.prototype.computeDepths = function computeDepths (startEdge) { var this$1$1 = this var nodesVisited = new HashSet() var nodeQueue = new LinkedList() var startNode = startEdge.getNode() nodeQueue.addLast(startNode) nodesVisited.add(startNode) startEdge.setVisited(true) while (!nodeQueue.isEmpty()) { var n = nodeQueue.removeFirst() nodesVisited.add(n) this$1$1.computeNodeDepth(n) for (var i = n.getEdges().iterator(); i.hasNext();) { var de = i.next() var sym = de.getSym() if (sym.isVisited()) { continue } var adjNode = sym.getNode() if (!nodesVisited.contains(adjNode)) { nodeQueue.addLast(adjNode) nodesVisited.add(adjNode) } } } } BufferSubgraph.prototype.compareTo = function compareTo (o) { var graph = o if (this._rightMostCoord.x < graph._rightMostCoord.x) { return -1 } if (this._rightMostCoord.x > graph._rightMostCoord.x) { return 1 } return 0 } BufferSubgraph.prototype.getEnvelope = function getEnvelope () { if (this._env === null) { var edgeEnv = new Envelope() for (var it = this._dirEdgeList.iterator(); it.hasNext();) { var dirEdge = it.next() var pts = dirEdge.getEdge().getCoordinates() for (var i = 0; i < pts.length - 1; i++) { edgeEnv.expandToInclude(pts[i]) } } this._env = edgeEnv } return this._env } BufferSubgraph.prototype.addReachable = function addReachable (startNode) { var this$1$1 = this var nodeStack = new Stack() nodeStack.add(startNode) while (!nodeStack.empty()) { var node = nodeStack.pop() this$1$1.add(node, nodeStack) } } BufferSubgraph.prototype.copySymDepths = function copySymDepths (de) { var sym = de.getSym() sym.setDepth(Position.LEFT, de.getDepth(Position.RIGHT)) sym.setDepth(Position.RIGHT, de.getDepth(Position.LEFT)) } BufferSubgraph.prototype.add = function add (node, nodeStack) { var this$1$1 = this node.setVisited(true) this._nodes.add(node) for (var i = node.getEdges().iterator(); i.hasNext();) { var de = i.next() this$1$1._dirEdgeList.add(de) var sym = de.getSym() var symNode = sym.getNode() if (!symNode.isVisited()) { nodeStack.push(symNode) } } } BufferSubgraph.prototype.getNodes = function getNodes () { return this._nodes } BufferSubgraph.prototype.getDirectedEdges = function getDirectedEdges () { return this._dirEdgeList } BufferSubgraph.prototype.interfaces_ = function interfaces_ () { return [Comparable] } BufferSubgraph.prototype.getClass = function getClass () { return BufferSubgraph } var TopologyLocation = function TopologyLocation () { var this$1$1 = this this.location = null if (arguments.length === 1) { if (arguments[0] instanceof Array) { var location = arguments[0] this.init(location.length) } else if (Number.isInteger(arguments[0])) { var on = arguments[0] this.init(1) this.location[Position.ON] = on } else if (arguments[0] instanceof TopologyLocation) { var gl = arguments[0] this.init(gl.location.length) if (gl !== null) { for (var i = 0; i < this.location.length; i++) { this$1$1.location[i] = gl.location[i] } } } } else if (arguments.length === 3) { var on$1 = arguments[0] var left = arguments[1] var right = arguments[2] this.init(3) this.location[Position.ON] = on$1 this.location[Position.LEFT] = left this.location[Position.RIGHT] = right } } TopologyLocation.prototype.setAllLocations = function setAllLocations (locValue) { var this$1$1 = this for (var i = 0; i < this.location.length; i++) { this$1$1.location[i] = locValue } } TopologyLocation.prototype.isNull = function isNull () { var this$1$1 = this for (var i = 0; i < this.location.length; i++) { if (this$1$1.location[i] !== Location.NONE) { return false } } return true } TopologyLocation.prototype.setAllLocationsIfNull = function setAllLocationsIfNull (locValue) { var this$1$1 = this for (var i = 0; i < this.location.length; i++) { if (this$1$1.location[i] === Location.NONE) { this$1$1.location[i] = locValue } } } TopologyLocation.prototype.isLine = function isLine () { return this.location.length === 1 } TopologyLocation.prototype.merge = function merge (gl) { var this$1$1 = this if (gl.location.length > this.location.length) { var newLoc = new Array(3).fill(null) newLoc[Position.ON] = this.location[Position.ON] newLoc[Position.LEFT] = Location.NONE newLoc[Position.RIGHT] = Location.NONE this.location = newLoc } for (var i = 0; i < this.location.length; i++) { if (this$1$1.location[i] === Location.NONE && i < gl.location.length) { this$1$1.location[i] = gl.location[i] } } } TopologyLocation.prototype.getLocations = function getLocations () { return this.location } TopologyLocation.prototype.flip = function flip () { if (this.location.length <= 1) { return null } var temp = this.location[Position.LEFT] this.location[Position.LEFT] = this.location[Position.RIGHT] this.location[Position.RIGHT] = temp } TopologyLocation.prototype.toString = function toString () { var buf = new StringBuffer() if (this.location.length > 1) { buf.append(Location.toLocationSymbol(this.location[Position.LEFT])) } buf.append(Location.toLocationSymbol(this.location[Position.ON])) if (this.location.length > 1) { buf.append(Location.toLocationSymbol(this.location[Position.RIGHT])) } return buf.toString() } TopologyLocation.prototype.setLocations = function setLocations (on, left, right) { this.location[Position.ON] = on this.location[Position.LEFT] = left this.location[Position.RIGHT] = right } TopologyLocation.prototype.get = function get (posIndex) { if (posIndex < this.location.length) { return this.location[posIndex] } return Location.NONE } TopologyLocation.prototype.isArea = function isArea () { return this.location.length > 1 } TopologyLocation.prototype.isAnyNull = function isAnyNull () { var this$1$1 = this for (var i = 0; i < this.location.length; i++) { if (this$1$1.location[i] === Location.NONE) { return true } } return false } TopologyLocation.prototype.setLocation = function setLocation () { if (arguments.length === 1) { var locValue = arguments[0] this.setLocation(Position.ON, locValue) } else if (arguments.length === 2) { var locIndex = arguments[0] var locValue$1 = arguments[1] this.location[locIndex] = locValue$1 } } TopologyLocation.prototype.init = function init (size) { this.location = new Array(size).fill(null) this.setAllLocations(Location.NONE) } TopologyLocation.prototype.isEqualOnSide = function isEqualOnSide (le, locIndex) { return this.location[locIndex] === le.location[locIndex] } TopologyLocation.prototype.allPositionsEqual = function allPositionsEqual (loc) { var this$1$1 = this for (var i = 0; i < this.location.length; i++) { if (this$1$1.location[i] !== loc) { return false } } return true } TopologyLocation.prototype.interfaces_ = function interfaces_ () { return [] } TopologyLocation.prototype.getClass = function getClass () { return TopologyLocation } var Label = function Label () { this.elt = new Array(2).fill(null) if (arguments.length === 1) { if (Number.isInteger(arguments[0])) { var onLoc = arguments[0] this.elt[0] = new TopologyLocation(onLoc) this.elt[1] = new TopologyLocation(onLoc) } else if (arguments[0] instanceof Label) { var lbl = arguments[0] this.elt[0] = new TopologyLocation(lbl.elt[0]) this.elt[1] = new TopologyLocation(lbl.elt[1]) } } else if (arguments.length === 2) { var geomIndex = arguments[0] var onLoc$1 = arguments[1] this.elt[0] = new TopologyLocation(Location.NONE) this.elt[1] = new TopologyLocation(Location.NONE) this.elt[geomIndex].setLocation(onLoc$1) } else if (arguments.length === 3) { var onLoc$2 = arguments[0] var leftLoc = arguments[1] var rightLoc = arguments[2] this.elt[0] = new TopologyLocation(onLoc$2, leftLoc, rightLoc) this.elt[1] = new TopologyLocation(onLoc$2, leftLoc, rightLoc) } else if (arguments.length === 4) { var geomIndex$1 = arguments[0] var onLoc$3 = arguments[1] var leftLoc$1 = arguments[2] var rightLoc$1 = arguments[3] this.elt[0] = new TopologyLocation(Location.NONE, Location.NONE, Location.NONE) this.elt[1] = new TopologyLocation(Location.NONE, Location.NONE, Location.NONE) this.elt[geomIndex$1].setLocations(onLoc$3, leftLoc$1, rightLoc$1) } } Label.prototype.getGeometryCount = function getGeometryCount () { var count = 0 if (!this.elt[0].isNull()) { count++ } if (!this.elt[1].isNull()) { count++ } return count } Label.prototype.setAllLocations = function setAllLocations (geomIndex, location) { this.elt[geomIndex].setAllLocations(location) } Label.prototype.isNull = function isNull (geomIndex) { return this.elt[geomIndex].isNull() } Label.prototype.setAllLocationsIfNull = function setAllLocationsIfNull () { if (arguments.length === 1) { var location = arguments[0] this.setAllLocationsIfNull(0, location) this.setAllLocationsIfNull(1, location) } else if (arguments.length === 2) { var geomIndex = arguments[0] var location$1 = arguments[1] this.elt[geomIndex].setAllLocationsIfNull(location$1) } } Label.prototype.isLine = function isLine (geomIndex) { return this.elt[geomIndex].isLine() } Label.prototype.merge = function merge (lbl) { var this$1$1 = this for (var i = 0; i < 2; i++) { if (this$1$1.elt[i] === null && lbl.elt[i] !== null) { this$1$1.elt[i] = new TopologyLocation(lbl.elt[i]) } else { this$1$1.elt[i].merge(lbl.elt[i]) } } } Label.prototype.flip = function flip () { this.elt[0].flip() this.elt[1].flip() } Label.prototype.getLocation = function getLocation () { if (arguments.length === 1) { var geomIndex = arguments[0] return this.elt[geomIndex].get(Position.ON) } else if (arguments.length === 2) { var geomIndex$1 = arguments[0] var posIndex = arguments[1] return this.elt[geomIndex$1].get(posIndex) } } Label.prototype.toString = function toString () { var buf = new StringBuffer() if (this.elt[0] !== null) { buf.append('A:') buf.append(this.elt[0].toString()) } if (this.elt[1] !== null) { buf.append(' B:') buf.append(this.elt[1].toString()) } return buf.toString() } Label.prototype.isArea = function isArea () { if (arguments.length === 0) { return this.elt[0].isArea() || this.elt[1].isArea() } else if (arguments.length === 1) { var geomIndex = arguments[0] return this.elt[geomIndex].isArea() } } Label.prototype.isAnyNull = function isAnyNull (geomIndex) { return this.elt[geomIndex].isAnyNull() } Label.prototype.setLocation = function setLocation () { if (arguments.length === 2) { var geomIndex = arguments[0] var location = arguments[1] this.elt[geomIndex].setLocation(Position.ON, location) } else if (arguments.length === 3) { var geomIndex$1 = arguments[0] var posIndex = arguments[1] var location$1 = arguments[2] this.elt[geomIndex$1].setLocation(posIndex, location$1) } } Label.prototype.isEqualOnSide = function isEqualOnSide (lbl, side) { return this.elt[0].isEqualOnSide(lbl.elt[0], side) && this.elt[1].isEqualOnSide(lbl.elt[1], side) } Label.prototype.allPositionsEqual = function allPositionsEqual (geomIndex, loc) { return this.elt[geomIndex].allPositionsEqual(loc) } Label.prototype.toLine = function toLine (geomIndex) { if (this.elt[geomIndex].isArea()) { this.elt[geomIndex] = new TopologyLocation(this.elt[geomIndex].location[0]) } } Label.prototype.interfaces_ = function interfaces_ () { return [] } Label.prototype.getClass = function getClass () { return Label } Label.toLineLabel = function toLineLabel (label) { var lineLabel = new Label(Location.NONE) for (var i = 0; i < 2; i++) { lineLabel.setLocation(i, label.getLocation(i)) } return lineLabel } var EdgeRing = function EdgeRing () { this._startDe = null this._maxNodeDegree = -1 this._edges = new ArrayList() this._pts = new ArrayList() this._label = new Label(Location.NONE) this._ring = null this._isHole = null this._shell = null this._holes = new ArrayList() this._geometryFactory = null var start = arguments[0] var geometryFactory = arguments[1] this._geometryFactory = geometryFactory this.computePoints(start) this.computeRing() } EdgeRing.prototype.computeRing = function computeRing () { var this$1$1 = this if (this._ring !== null) { return null } var coord = new Array(this._pts.size()).fill(null) for (var i = 0; i < this._pts.size(); i++) { coord[i] = this$1$1._pts.get(i) } this._ring = this._geometryFactory.createLinearRing(coord) this._isHole = CGAlgorithms.isCCW(this._ring.getCoordinates()) } EdgeRing.prototype.isIsolated = function isIsolated () { return this._label.getGeometryCount() === 1 } EdgeRing.prototype.computePoints = function computePoints (start) { var this$1$1 = this this._startDe = start var de = start var isFirstEdge = true do { if (de === null) { throw new TopologyException('Found null DirectedEdge') } if (de.getEdgeRing() === this$1$1) { throw new TopologyException('Directed Edge visited twice during ring-building at ' + de.getCoordinate()) } this$1$1._edges.add(de) var label = de.getLabel() Assert.isTrue(label.isArea()) this$1$1.mergeLabel(label) this$1$1.addPoints(de.getEdge(), de.isForward(), isFirstEdge) isFirstEdge = false this$1$1.setEdgeRing(de, this$1$1) de = this$1$1.getNext(de) } while (de !== this._startDe) } EdgeRing.prototype.getLinearRing = function getLinearRing () { return this._ring } EdgeRing.prototype.getCoordinate = function getCoordinate (i) { return this._pts.get(i) } EdgeRing.prototype.computeMaxNodeDegree = function computeMaxNodeDegree () { var this$1$1 = this this._maxNodeDegree = 0 var de = this._startDe do { var node = de.getNode() var degree = node.getEdges().getOutgoingDegree(this$1$1) if (degree > this$1$1._maxNodeDegree) { this$1$1._maxNodeDegree = degree } de = this$1$1.getNext(de) } while (de !== this._startDe) this._maxNodeDegree *= 2 } EdgeRing.prototype.addPoints = function addPoints (edge, isForward, isFirstEdge) { var this$1$1 = this var edgePts = edge.getCoordinates() if (isForward) { var startIndex = 1 if (isFirstEdge) { startIndex = 0 } for (var i = startIndex; i < edgePts.length; i++) { this$1$1._pts.add(edgePts[i]) } } else { var startIndex$1 = edgePts.length - 2 if (isFirstEdge) { startIndex$1 = edgePts.length - 1 } for (var i$1 = startIndex$1; i$1 >= 0; i$1--) { this$1$1._pts.add(edgePts[i$1]) } } } EdgeRing.prototype.isHole = function isHole () { return this._isHole } EdgeRing.prototype.setInResult = function setInResult () { var de = this._startDe do { de.getEdge().setInResult(true) de = de.getNext() } while (de !== this._startDe) } EdgeRing.prototype.containsPoint = function containsPoint (p) { var shell = this.getLinearRing() var env = shell.getEnvelopeInternal() if (!env.contains(p)) { return false } if (!CGAlgorithms.isPointInRing(p, shell.getCoordinates())) { return false } for (var i = this._holes.iterator(); i.hasNext();) { var hole = i.next() if (hole.containsPoint(p)) { return false } } return true } EdgeRing.prototype.addHole = function addHole (ring) { this._holes.add(ring) } EdgeRing.prototype.isShell = function isShell () { return this._shell === null } EdgeRing.prototype.getLabel = function getLabel () { return this._label } EdgeRing.prototype.getEdges = function getEdges () { return this._edges } EdgeRing.prototype.getMaxNodeDegree = function getMaxNodeDegree () { if (this._maxNodeDegree < 0) { this.computeMaxNodeDegree() } return this._maxNodeDegree } EdgeRing.prototype.getShell = function getShell () { return this._shell } EdgeRing.prototype.mergeLabel = function mergeLabel () { if (arguments.length === 1) { var deLabel = arguments[0] this.mergeLabel(deLabel, 0) this.mergeLabel(deLabel, 1) } else if (arguments.length === 2) { var deLabel$1 = arguments[0] var geomIndex = arguments[1] var loc = deLabel$1.getLocation(geomIndex, Position.RIGHT) if (loc === Location.NONE) { return null } if (this._label.getLocation(geomIndex) === Location.NONE) { this._label.setLocation(geomIndex, loc) return null } } } EdgeRing.prototype.setShell = function setShell (shell) { this._shell = shell if (shell !== null) { shell.addHole(this) } } EdgeRing.prototype.toPolygon = function toPolygon (geometryFactory) { var this$1$1 = this var holeLR = new Array(this._holes.size()).fill(null) for (var i = 0; i < this._holes.size(); i++) { holeLR[i] = this$1$1._holes.get(i).getLinearRing() } var poly = geometryFactory.createPolygon(this.getLinearRing(), holeLR) return poly } EdgeRing.prototype.interfaces_ = function interfaces_ () { return [] } EdgeRing.prototype.getClass = function getClass () { return EdgeRing } var MinimalEdgeRing = (function (EdgeRing$$1) { function MinimalEdgeRing () { var start = arguments[0] var geometryFactory = arguments[1] EdgeRing$$1.call(this, start, geometryFactory) } if (EdgeRing$$1) MinimalEdgeRing.__proto__ = EdgeRing$$1 MinimalEdgeRing.prototype = Object.create(EdgeRing$$1 && EdgeRing$$1.prototype) MinimalEdgeRing.prototype.constructor = MinimalEdgeRing MinimalEdgeRing.prototype.setEdgeRing = function setEdgeRing (de, er) { de.setMinEdgeRing(er) } MinimalEdgeRing.prototype.getNext = function getNext (de) { return de.getNextMin() } MinimalEdgeRing.prototype.interfaces_ = function interfaces_ () { return [] } MinimalEdgeRing.prototype.getClass = function getClass () { return MinimalEdgeRing } return MinimalEdgeRing }(EdgeRing)) var MaximalEdgeRing = (function (EdgeRing$$1) { function MaximalEdgeRing () { var start = arguments[0] var geometryFactory = arguments[1] EdgeRing$$1.call(this, start, geometryFactory) } if (EdgeRing$$1) MaximalEdgeRing.__proto__ = EdgeRing$$1 MaximalEdgeRing.prototype = Object.create(EdgeRing$$1 && EdgeRing$$1.prototype) MaximalEdgeRing.prototype.constructor = MaximalEdgeRing MaximalEdgeRing.prototype.buildMinimalRings = function buildMinimalRings () { var this$1$1 = this var minEdgeRings = new ArrayList() var de = this._startDe do { if (de.getMinEdgeRing() === null) { var minEr = new MinimalEdgeRing(de, this$1$1._geometryFactory) minEdgeRings.add(minEr) } de = de.getNext() } while (de !== this._startDe) return minEdgeRings } MaximalEdgeRing.prototype.setEdgeRing = function setEdgeRing (de, er) { de.setEdgeRing(er) } MaximalEdgeRing.prototype.linkDirectedEdgesForMinimalEdgeRings = function linkDirectedEdgesForMinimalEdgeRings () { var this$1$1 = this var de = this._startDe do { var node = de.getNode() node.getEdges().linkMinimalDirectedEdges(this$1$1) de = de.getNext() } while (de !== this._startDe) } MaximalEdgeRing.prototype.getNext = function getNext (de) { return de.getNext() } MaximalEdgeRing.prototype.interfaces_ = function interfaces_ () { return [] } MaximalEdgeRing.prototype.getClass = function getClass () { return MaximalEdgeRing } return MaximalEdgeRing }(EdgeRing)) var GraphComponent = function GraphComponent () { this._label = null this._isInResult = false this._isCovered = false this._isCoveredSet = false this._isVisited = false if (arguments.length === 0); else if (arguments.length === 1) { var label = arguments[0] this._label = label } } GraphComponent.prototype.setVisited = function setVisited (isVisited) { this._isVisited = isVisited } GraphComponent.prototype.setInResult = function setInResult (isInResult) { this._isInResult = isInResult } GraphComponent.prototype.isCovered = function isCovered () { return this._isCovered } GraphComponent.prototype.isCoveredSet = function isCoveredSet () { return this._isCoveredSet } GraphComponent.prototype.setLabel = function setLabel (label) { this._label = label } GraphComponent.prototype.getLabel = function getLabel () { return this._label } GraphComponent.prototype.setCovered = function setCovered (isCovered) { this._isCovered = isCovered this._isCoveredSet = true } GraphComponent.prototype.updateIM = function updateIM (im) { Assert.isTrue(this._label.getGeometryCount() >= 2, 'found partial label') this.computeIM(im) } GraphComponent.prototype.isInResult = function isInResult () { return this._isInResult } GraphComponent.prototype.isVisited = function isVisited () { return this._isVisited } GraphComponent.prototype.interfaces_ = function interfaces_ () { return [] } GraphComponent.prototype.getClass = function getClass () { return GraphComponent } var Node = (function (GraphComponent$$1) { function Node () { GraphComponent$$1.call(this) this._coord = null this._edges = null var coord = arguments[0] var edges = arguments[1] this._coord = coord this._edges = edges this._label = new Label(0, Location.NONE) } if (GraphComponent$$1) Node.__proto__ = GraphComponent$$1 Node.prototype = Object.create(GraphComponent$$1 && GraphComponent$$1.prototype) Node.prototype.constructor = Node Node.prototype.isIncidentEdgeInResult = function isIncidentEdgeInResult () { for (var it = this.getEdges().getEdges().iterator(); it.hasNext();) { var de = it.next() if (de.getEdge().isInResult()) { return true } } return false } Node.prototype.isIsolated = function isIsolated () { return this._label.getGeometryCount() === 1 } Node.prototype.getCoordinate = function getCoordinate () { return this._coord } Node.prototype.print = function print (out) { out.println('node ' + this._coord + ' lbl: ' + this._label) } Node.prototype.computeIM = function computeIM (im) { } Node.prototype.computeMergedLocation = function computeMergedLocation (label2, eltIndex) { var loc = Location.NONE loc = this._label.getLocation(eltIndex) if (!label2.isNull(eltIndex)) { var nLoc = label2.getLocation(eltIndex) if (loc !== Location.BOUNDARY) { loc = nLoc } } return loc } Node.prototype.setLabel = function setLabel () { if (arguments.length === 2) { var argIndex = arguments[0] var onLocation = arguments[1] if (this._label === null) { this._label = new Label(argIndex, onLocation) } else { this._label.setLocation(argIndex, onLocation) } } else { return GraphComponent$$1.prototype.setLabel.apply(this, arguments) } } Node.prototype.getEdges = function getEdges () { return this._edges } Node.prototype.mergeLabel = function mergeLabel () { var this$1$1 = this if (arguments[0] instanceof Node) { var n = arguments[0] this.mergeLabel(n._label) } else if (arguments[0] instanceof Label) { var label2 = arguments[0] for (var i = 0; i < 2; i++) { var loc = this$1$1.computeMergedLocation(label2, i) var thisLoc = this$1$1._label.getLocation(i) if (thisLoc === Location.NONE) { this$1$1._label.setLocation(i, loc) } } } } Node.prototype.add = function add (e) { this._edges.insert(e) e.setNode(this) } Node.prototype.setLabelBoundary = function setLabelBoundary (argIndex) { if (this._label === null) { return null } var loc = Location.NONE if (this._label !== null) { loc = this._label.getLocation(argIndex) } var newLoc = null switch (loc) { case Location.BOUNDARY: newLoc = Location.INTERIOR break case Location.INTERIOR: newLoc = Location.BOUNDARY break default: newLoc = Location.BOUNDARY break } this._label.setLocation(argIndex, newLoc) } Node.prototype.interfaces_ = function interfaces_ () { return [] } Node.prototype.getClass = function getClass () { return Node } return Node }(GraphComponent)) var NodeMap = function NodeMap () { this.nodeMap = new TreeMap() this.nodeFact = null var nodeFact = arguments[0] this.nodeFact = nodeFact } NodeMap.prototype.find = function find (coord) { return this.nodeMap.get(coord) } NodeMap.prototype.addNode = function addNode () { if (arguments[0] instanceof Coordinate) { var coord = arguments[0] var node = this.nodeMap.get(coord) if (node === null) { node = this.nodeFact.createNode(coord) this.nodeMap.put(coord, node) } return node } else if (arguments[0] instanceof Node) { var n = arguments[0] var node$1 = this.nodeMap.get(n.getCoordinate()) if (node$1 === null) { this.nodeMap.put(n.getCoordinate(), n) return n } node$1.mergeLabel(n) return node$1 } } NodeMap.prototype.print = function print (out) { for (var it = this.iterator(); it.hasNext();) { var n = it.next() n.print(out) } } NodeMap.prototype.iterator = function iterator () { return this.nodeMap.values().iterator() } NodeMap.prototype.values = function values () { return this.nodeMap.values() } NodeMap.prototype.getBoundaryNodes = function getBoundaryNodes (geomIndex) { var bdyNodes = new ArrayList() for (var i = this.iterator(); i.hasNext();) { var node = i.next() if (node.getLabel().getLocation(geomIndex) === Location.BOUNDARY) { bdyNodes.add(node) } } return bdyNodes } NodeMap.prototype.add = function add (e) { var p = e.getCoordinate() var n = this.addNode(p) n.add(e) } NodeMap.prototype.interfaces_ = function interfaces_ () { return [] } NodeMap.prototype.getClass = function getClass () { return NodeMap } var Quadrant = function Quadrant () { } var staticAccessors$21 = { NE: { configurable: true }, NW: { configurable: true }, SW: { configurable: true }, SE: { configurable: true } } Quadrant.prototype.interfaces_ = function interfaces_ () { return [] } Quadrant.prototype.getClass = function getClass () { return Quadrant } Quadrant.isNorthern = function isNorthern (quad) { return quad === Quadrant.NE || quad === Quadrant.NW } Quadrant.isOpposite = function isOpposite (quad1, quad2) { if (quad1 === quad2) { return false } var diff = (quad1 - quad2 + 4) % 4 if (diff === 2) { return true } return false } Quadrant.commonHalfPlane = function commonHalfPlane (quad1, quad2) { if (quad1 === quad2) { return quad1 } var diff = (quad1 - quad2 + 4) % 4 if (diff === 2) { return -1 } var min = quad1 < quad2 ? quad1 : quad2 var max = quad1 > quad2 ? quad1 : quad2 if (min === 0 && max === 3) { return 3 } return min } Quadrant.isInHalfPlane = function isInHalfPlane (quad, halfPlane) { if (halfPlane === Quadrant.SE) { return quad === Quadrant.SE || quad === Quadrant.SW } return quad === halfPlane || quad === halfPlane + 1 } Quadrant.quadrant = function quadrant () { if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') { var dx = arguments[0] var dy = arguments[1] if (dx === 0.0 && dy === 0.0) { throw new IllegalArgumentException('Cannot compute the quadrant for point ( ' + dx + ', ' + dy + ' )') } if (dx >= 0.0) { if (dy >= 0.0) { return Quadrant.NE } else { return Quadrant.SE } } else { if (dy >= 0.0) { return Quadrant.NW } else { return Quadrant.SW } } } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) { var p0 = arguments[0] var p1 = arguments[1] if (p1.x === p0.x && p1.y === p0.y) { throw new IllegalArgumentException('Cannot compute the quadrant for two identical points ' + p0) } if (p1.x >= p0.x) { if (p1.y >= p0.y) { return Quadrant.NE } else { return Quadrant.SE } } else { if (p1.y >= p0.y) { return Quadrant.NW } else { return Quadrant.SW } } } } staticAccessors$21.NE.get = function () { return 0 } staticAccessors$21.NW.get = function () { return 1 } staticAccessors$21.SW.get = function () { return 2 } staticAccessors$21.SE.get = function () { return 3 } Object.defineProperties(Quadrant, staticAccessors$21) var EdgeEnd = function EdgeEnd () { this._edge = null this._label = null this._node = null this._p0 = null this._p1 = null this._dx = null this._dy = null this._quadrant = null if (arguments.length === 1) { var edge = arguments[0] this._edge = edge } else if (arguments.length === 3) { var edge$1 = arguments[0] var p0 = arguments[1] var p1 = arguments[2] var label = null this._edge = edge$1 this.init(p0, p1) this._label = label } else if (arguments.length === 4) { var edge$2 = arguments[0] var p0$1 = arguments[1] var p1$1 = arguments[2] var label$1 = arguments[3] this._edge = edge$2 this.init(p0$1, p1$1) this._label = label$1 } } EdgeEnd.prototype.compareDirection = function compareDirection (e) { if (this._dx === e._dx && this._dy === e._dy) { return 0 } if (this._quadrant > e._quadrant) { return 1 } if (this._quadrant < e._quadrant) { return -1 } return CGAlgorithms.computeOrientation(e._p0, e._p1, this._p1) } EdgeEnd.prototype.getDy = function getDy () { return this._dy } EdgeEnd.prototype.getCoordinate = function getCoordinate () { return this._p0 } EdgeEnd.prototype.setNode = function setNode (node) { this._node = node } EdgeEnd.prototype.print = function print (out) { var angle = Math.atan2(this._dy, this._dx) var className = this.getClass().getName() var lastDotPos = className.lastIndexOf('.') var name = className.substring(lastDotPos + 1) out.print(' ' + name + ': ' + this._p0 + ' - ' + this._p1 + ' ' + this._quadrant + ':' + angle + ' ' + this._label) } EdgeEnd.prototype.compareTo = function compareTo (obj) { var e = obj return this.compareDirection(e) } EdgeEnd.prototype.getDirectedCoordinate = function getDirectedCoordinate () { return this._p1 } EdgeEnd.prototype.getDx = function getDx () { return this._dx } EdgeEnd.prototype.getLabel = function getLabel () { return this._label } EdgeEnd.prototype.getEdge = function getEdge () { return this._edge } EdgeEnd.prototype.getQuadrant = function getQuadrant () { return this._quadrant } EdgeEnd.prototype.getNode = function getNode () { return this._node } EdgeEnd.prototype.toString = function toString () { var angle = Math.atan2(this._dy, this._dx) var className = this.getClass().getName() var lastDotPos = className.lastIndexOf('.') var name = className.substring(lastDotPos + 1) return ' ' + name + ': ' + this._p0 + ' - ' + this._p1 + ' ' + this._quadrant + ':' + angle + ' ' + this._label } EdgeEnd.prototype.computeLabel = function computeLabel (boundaryNodeRule) { } EdgeEnd.prototype.init = function init (p0, p1) { this._p0 = p0 this._p1 = p1 this._dx = p1.x - p0.x this._dy = p1.y - p0.y this._quadrant = Quadrant.quadrant(this._dx, this._dy) Assert.isTrue(!(this._dx === 0 && this._dy === 0), 'EdgeEnd with identical endpoints found') } EdgeEnd.prototype.interfaces_ = function interfaces_ () { return [Comparable] } EdgeEnd.prototype.getClass = function getClass () { return EdgeEnd } var DirectedEdge = (function (EdgeEnd$$1) { function DirectedEdge () { var edge = arguments[0] var isForward = arguments[1] EdgeEnd$$1.call(this, edge) this._isForward = null this._isInResult = false this._isVisited = false this._sym = null this._next = null this._nextMin = null this._edgeRing = null this._minEdgeRing = null this._depth = [0, -999, -999] this._isForward = isForward if (isForward) { this.init(edge.getCoordinate(0), edge.getCoordinate(1)) } else { var n = edge.getNumPoints() - 1 this.init(edge.getCoordinate(n), edge.getCoordinate(n - 1)) } this.computeDirectedLabel() } if (EdgeEnd$$1) DirectedEdge.__proto__ = EdgeEnd$$1 DirectedEdge.prototype = Object.create(EdgeEnd$$1 && EdgeEnd$$1.prototype) DirectedEdge.prototype.constructor = DirectedEdge DirectedEdge.prototype.getNextMin = function getNextMin () { return this._nextMin } DirectedEdge.prototype.getDepth = function getDepth (position) { return this._depth[position] } DirectedEdge.prototype.setVisited = function setVisited (isVisited) { this._isVisited = isVisited } DirectedEdge.prototype.computeDirectedLabel = function computeDirectedLabel () { this._label = new Label(this._edge.getLabel()) if (!this._isForward) { this._label.flip() } } DirectedEdge.prototype.getNext = function getNext () { return this._next } DirectedEdge.prototype.setDepth = function setDepth (position, depthVal) { if (this._depth[position] !== -999) { if (this._depth[position] !== depthVal) { throw new TopologyException('assigned depths do not match', this.getCoordinate()) } } this._depth[position] = depthVal } DirectedEdge.prototype.isInteriorAreaEdge = function isInteriorAreaEdge () { var this$1$1 = this var isInteriorAreaEdge = true for (var i = 0; i < 2; i++) { if (!(this$1$1._label.isArea(i) && this$1$1._label.getLocation(i, Position.LEFT) === Location.INTERIOR && this$1$1._label.getLocation(i, Position.RIGHT) === Location.INTERIOR)) { isInteriorAreaEdge = false } } return isInteriorAreaEdge } DirectedEdge.prototype.setNextMin = function setNextMin (nextMin) { this._nextMin = nextMin } DirectedEdge.prototype.print = function print (out) { EdgeEnd$$1.prototype.print.call(this, out) out.print(' ' + this._depth[Position.LEFT] + '/' + this._depth[Position.RIGHT]) out.print(' (' + this.getDepthDelta() + ')') if (this._isInResult) { out.print(' inResult') } } DirectedEdge.prototype.setMinEdgeRing = function setMinEdgeRing (minEdgeRing) { this._minEdgeRing = minEdgeRing } DirectedEdge.prototype.isLineEdge = function isLineEdge () { var isLine = this._label.isLine(0) || this._label.isLine(1) var isExteriorIfArea0 = !this._label.isArea(0) || this._label.allPositionsEqual(0, Location.EXTERIOR) var isExteriorIfArea1 = !this._label.isArea(1) || this._label.allPositionsEqual(1, Location.EXTERIOR) return isLine && isExteriorIfArea0 && isExteriorIfArea1 } DirectedEdge.prototype.setEdgeRing = function setEdgeRing (edgeRing) { this._edgeRing = edgeRing } DirectedEdge.prototype.getMinEdgeRing = function getMinEdgeRing () { return this._minEdgeRing } DirectedEdge.prototype.getDepthDelta = function getDepthDelta () { var depthDelta = this._edge.getDepthDelta() if (!this._isForward) { depthDelta = -depthDelta } return depthDelta } DirectedEdge.prototype.setInResult = function setInResult (isInResult) { this._isInResult = isInResult } DirectedEdge.prototype.getSym = function getSym () { return this._sym } DirectedEdge.prototype.isForward = function isForward () { return this._isForward } DirectedEdge.prototype.getEdge = function getEdge () { return this._edge } DirectedEdge.prototype.printEdge = function printEdge (out) { this.print(out) out.print(' ') if (this._isForward) { this._edge.print(out) } else { this._edge.printReverse(out) } } DirectedEdge.prototype.setSym = function setSym (de) { this._sym = de } DirectedEdge.prototype.setVisitedEdge = function setVisitedEdge (isVisited) { this.setVisited(isVisited) this._sym.setVisited(isVisited) } DirectedEdge.prototype.setEdgeDepths = function setEdgeDepths (position, depth) { var depthDelta = this.getEdge().getDepthDelta() if (!this._isForward) { depthDelta = -depthDelta } var directionFactor = 1 if (position === Position.LEFT) { directionFactor = -1 } var oppositePos = Position.opposite(position) var delta = depthDelta * directionFactor var oppositeDepth = depth + delta this.setDepth(position, depth) this.setDepth(oppositePos, oppositeDepth) } DirectedEdge.prototype.getEdgeRing = function getEdgeRing () { return this._edgeRing } DirectedEdge.prototype.isInResult = function isInResult () { return this._isInResult } DirectedEdge.prototype.setNext = function setNext (next) { this._next = next } DirectedEdge.prototype.isVisited = function isVisited () { return this._isVisited } DirectedEdge.prototype.interfaces_ = function interfaces_ () { return [] } DirectedEdge.prototype.getClass = function getClass () { return DirectedEdge } DirectedEdge.depthFactor = function depthFactor (currLocation, nextLocation) { if (currLocation === Location.EXTERIOR && nextLocation === Location.INTERIOR) { return 1 } else if (currLocation === Location.INTERIOR && nextLocation === Location.EXTERIOR) { return -1 } return 0 } return DirectedEdge }(EdgeEnd)) var NodeFactory = function NodeFactory () { } NodeFactory.prototype.createNode = function createNode (coord) { return new Node(coord, null) } NodeFactory.prototype.interfaces_ = function interfaces_ () { return [] } NodeFactory.prototype.getClass = function getClass () { return NodeFactory } var PlanarGraph = function PlanarGraph () { this._edges = new ArrayList() this._nodes = null this._edgeEndList = new ArrayList() if (arguments.length === 0) { this._nodes = new NodeMap(new NodeFactory()) } else if (arguments.length === 1) { var nodeFact = arguments[0] this._nodes = new NodeMap(nodeFact) } } PlanarGraph.prototype.printEdges = function printEdges (out) { var this$1$1 = this out.println('Edges:') for (var i = 0; i < this._edges.size(); i++) { out.println('edge ' + i + ':') var e = this$1$1._edges.get(i) e.print(out) e.eiList.print(out) } } PlanarGraph.prototype.find = function find (coord) { return this._nodes.find(coord) } PlanarGraph.prototype.addNode = function addNode () { if (arguments[0] instanceof Node) { var node = arguments[0] return this._nodes.addNode(node) } else if (arguments[0] instanceof Coordinate) { var coord = arguments[0] return this._nodes.addNode(coord) } } PlanarGraph.prototype.getNodeIterator = function getNodeIterator () { return this._nodes.iterator() } PlanarGraph.prototype.linkResultDirectedEdges = function linkResultDirectedEdges () { for (var nodeit = this._nodes.iterator(); nodeit.hasNext();) { var node = nodeit.next() node.getEdges().linkResultDirectedEdges() } } PlanarGraph.prototype.debugPrintln = function debugPrintln (o) { System.out.println(o) } PlanarGraph.prototype.isBoundaryNode = function isBoundaryNode (geomIndex, coord) { var node = this._nodes.find(coord) if (node === null) { return false } var label = node.getLabel() if (label !== null && label.getLocation(geomIndex) === Location.BOUNDARY) { return true } return false } PlanarGraph.prototype.linkAllDirectedEdges = function linkAllDirectedEdges () { for (var nodeit = this._nodes.iterator(); nodeit.hasNext();) { var node = nodeit.next() node.getEdges().linkAllDirectedEdges() } } PlanarGraph.prototype.matchInSameDirection = function matchInSameDirection (p0, p1, ep0, ep1) { if (!p0.equals(ep0)) { return false } if (CGAlgorithms.computeOrientation(p0, p1, ep1) === CGAlgorithms.COLLINEAR && Quadrant.quadrant(p0, p1) === Quadrant.quadrant(ep0, ep1)) { return true } return false } PlanarGraph.prototype.getEdgeEnds = function getEdgeEnds () { return this._edgeEndList } PlanarGraph.prototype.debugPrint = function debugPrint (o) { System.out.print(o) } PlanarGraph.prototype.getEdgeIterator = function getEdgeIterator () { return this._edges.iterator() } PlanarGraph.prototype.findEdgeInSameDirection = function findEdgeInSameDirection (p0, p1) { var this$1$1 = this for (var i = 0; i < this._edges.size(); i++) { var e = this$1$1._edges.get(i) var eCoord = e.getCoordinates() if (this$1$1.matchInSameDirection(p0, p1, eCoord[0], eCoord[1])) { return e } if (this$1$1.matchInSameDirection(p0, p1, eCoord[eCoord.length - 1], eCoord[eCoord.length - 2])) { return e } } return null } PlanarGraph.prototype.insertEdge = function insertEdge (e) { this._edges.add(e) } PlanarGraph.prototype.findEdgeEnd = function findEdgeEnd (e) { for (var i = this.getEdgeEnds().iterator(); i.hasNext();) { var ee = i.next() if (ee.getEdge() === e) { return ee } } return null } PlanarGraph.prototype.addEdges = function addEdges (edgesToAdd) { var this$1$1 = this for (var it = edgesToAdd.iterator(); it.hasNext();) { var e = it.next() this$1$1._edges.add(e) var de1 = new DirectedEdge(e, true) var de2 = new DirectedEdge(e, false) de1.setSym(de2) de2.setSym(de1) this$1$1.add(de1) this$1$1.add(de2) } } PlanarGraph.prototype.add = function add (e) { this._nodes.add(e) this._edgeEndList.add(e) } PlanarGraph.prototype.getNodes = function getNodes () { return this._nodes.values() } PlanarGraph.prototype.findEdge = function findEdge (p0, p1) { var this$1$1 = this for (var i = 0; i < this._edges.size(); i++) { var e = this$1$1._edges.get(i) var eCoord = e.getCoordinates() if (p0.equals(eCoord[0]) && p1.equals(eCoord[1])) { return e } } return null } PlanarGraph.prototype.interfaces_ = function interfaces_ () { return [] } PlanarGraph.prototype.getClass = function getClass () { return PlanarGraph } PlanarGraph.linkResultDirectedEdges = function linkResultDirectedEdges (nodes) { for (var nodeit = nodes.iterator(); nodeit.hasNext();) { var node = nodeit.next() node.getEdges().linkResultDirectedEdges() } } var PolygonBuilder = function PolygonBuilder () { this._geometryFactory = null this._shellList = new ArrayList() var geometryFactory = arguments[0] this._geometryFactory = geometryFactory } PolygonBuilder.prototype.sortShellsAndHoles = function sortShellsAndHoles (edgeRings, shellList, freeHoleList) { for (var it = edgeRings.iterator(); it.hasNext();) { var er = it.next() if (er.isHole()) { freeHoleList.add(er) } else { shellList.add(er) } } } PolygonBuilder.prototype.computePolygons = function computePolygons (shellList) { var this$1$1 = this var resultPolyList = new ArrayList() for (var it = shellList.iterator(); it.hasNext();) { var er = it.next() var poly = er.toPolygon(this$1$1._geometryFactory) resultPolyList.add(poly) } return resultPolyList } PolygonBuilder.prototype.placeFreeHoles = function placeFreeHoles (shellList, freeHoleList) { var this$1$1 = this for (var it = freeHoleList.iterator(); it.hasNext();) { var hole = it.next() if (hole.getShell() === null) { var shell = this$1$1.findEdgeRingContaining(hole, shellList) if (shell === null) { throw new TopologyException('unable to assign hole to a shell', hole.getCoordinate(0)) } hole.setShell(shell) } } } PolygonBuilder.prototype.buildMinimalEdgeRings = function buildMinimalEdgeRings (maxEdgeRings, shellList, freeHoleList) { var this$1$1 = this var edgeRings = new ArrayList() for (var it = maxEdgeRings.iterator(); it.hasNext();) { var er = it.next() if (er.getMaxNodeDegree() > 2) { er.linkDirectedEdgesForMinimalEdgeRings() var minEdgeRings = er.buildMinimalRings() var shell = this$1$1.findShell(minEdgeRings) if (shell !== null) { this$1$1.placePolygonHoles(shell, minEdgeRings) shellList.add(shell) } else { freeHoleList.addAll(minEdgeRings) } } else { edgeRings.add(er) } } return edgeRings } PolygonBuilder.prototype.containsPoint = function containsPoint (p) { for (var it = this._shellList.iterator(); it.hasNext();) { var er = it.next() if (er.containsPoint(p)) { return true } } return false } PolygonBuilder.prototype.buildMaximalEdgeRings = function buildMaximalEdgeRings (dirEdges) { var this$1$1 = this var maxEdgeRings = new ArrayList() for (var it = dirEdges.iterator(); it.hasNext();) { var de = it.next() if (de.isInResult() && de.getLabel().isArea()) { if (de.getEdgeRing() === null) { var er = new MaximalEdgeRing(de, this$1$1._geometryFactory) maxEdgeRings.add(er) er.setInResult() } } } return maxEdgeRings } PolygonBuilder.prototype.placePolygonHoles = function placePolygonHoles (shell, minEdgeRings) { for (var it = minEdgeRings.iterator(); it.hasNext();) { var er = it.next() if (er.isHole()) { er.setShell(shell) } } } PolygonBuilder.prototype.getPolygons = function getPolygons () { var resultPolyList = this.computePolygons(this._shellList) return resultPolyList } PolygonBuilder.prototype.findEdgeRingContaining = function findEdgeRingContaining (testEr, shellList) { var testRing = testEr.getLinearRing() var testEnv = testRing.getEnvelopeInternal() var testPt = testRing.getCoordinateN(0) var minShell = null var minEnv = null for (var it = shellList.iterator(); it.hasNext();) { var tryShell = it.next() var tryRing = tryShell.getLinearRing() var tryEnv = tryRing.getEnvelopeInternal() if (minShell !== null) { minEnv = minShell.getLinearRing().getEnvelopeInternal() } var isContained = false if (tryEnv.contains(testEnv) && CGAlgorithms.isPointInRing(testPt, tryRing.getCoordinates())) { isContained = true } if (isContained) { if (minShell === null || minEnv.contains(tryEnv)) { minShell = tryShell } } } return minShell } PolygonBuilder.prototype.findShell = function findShell (minEdgeRings) { var shellCount = 0 var shell = null for (var it = minEdgeRings.iterator(); it.hasNext();) { var er = it.next() if (!er.isHole()) { shell = er shellCount++ } } Assert.isTrue(shellCount <= 1, 'found two shells in MinimalEdgeRing list') return shell } PolygonBuilder.prototype.add = function add () { if (arguments.length === 1) { var graph = arguments[0] this.add(graph.getEdgeEnds(), graph.getNodes()) } else if (arguments.length === 2) { var dirEdges = arguments[0] var nodes = arguments[1] PlanarGraph.linkResultDirectedEdges(nodes) var maxEdgeRings = this.buildMaximalEdgeRings(dirEdges) var freeHoleList = new ArrayList() var edgeRings = this.buildMinimalEdgeRings(maxEdgeRings, this._shellList, freeHoleList) this.sortShellsAndHoles(edgeRings, this._shellList, freeHoleList) this.placeFreeHoles(this._shellList, freeHoleList) } } PolygonBuilder.prototype.interfaces_ = function interfaces_ () { return [] } PolygonBuilder.prototype.getClass = function getClass () { return PolygonBuilder } var Boundable = function Boundable () { } Boundable.prototype.getBounds = function getBounds () { } Boundable.prototype.interfaces_ = function interfaces_ () { return [] } Boundable.prototype.getClass = function getClass () { return Boundable } var ItemBoundable = function ItemBoundable () { this._bounds = null this._item = null var bounds = arguments[0] var item = arguments[1] this._bounds = bounds this._item = item } ItemBoundable.prototype.getItem = function getItem () { return this._item } ItemBoundable.prototype.getBounds = function getBounds () { return this._bounds } ItemBoundable.prototype.interfaces_ = function interfaces_ () { return [Boundable, Serializable] } ItemBoundable.prototype.getClass = function getClass () { return ItemBoundable } var PriorityQueue = function PriorityQueue () { this._size = null this._items = null this._size = 0 this._items = new ArrayList() this._items.add(null) } PriorityQueue.prototype.poll = function poll () { if (this.isEmpty()) { return null } var minItem = this._items.get(1) this._items.set(1, this._items.get(this._size)) this._size -= 1 this.reorder(1) return minItem } PriorityQueue.prototype.size = function size () { return this._size } PriorityQueue.prototype.reorder = function reorder (hole) { var this$1$1 = this var child = null var tmp = this._items.get(hole) for (; hole * 2 <= this._size; hole = child) { child = hole * 2 if (child !== this$1$1._size && this$1$1._items.get(child + 1).compareTo(this$1$1._items.get(child)) < 0) { child++ } if (this$1$1._items.get(child).compareTo(tmp) < 0) { this$1$1._items.set(hole, this$1$1._items.get(child)) } else { break } } this._items.set(hole, tmp) } PriorityQueue.prototype.clear = function clear () { this._size = 0 this._items.clear() } PriorityQueue.prototype.isEmpty = function isEmpty () { return this._size === 0 } PriorityQueue.prototype.add = function add (x) { var this$1$1 = this this._items.add(null) this._size += 1 var hole = this._size this._items.set(0, x) for (; x.compareTo(this._items.get(Math.trunc(hole / 2))) < 0; hole /= 2) { this$1$1._items.set(hole, this$1$1._items.get(Math.trunc(hole / 2))) } this._items.set(hole, x) } PriorityQueue.prototype.interfaces_ = function interfaces_ () { return [] } PriorityQueue.prototype.getClass = function getClass () { return PriorityQueue } var ItemVisitor = function ItemVisitor () { } ItemVisitor.prototype.visitItem = function visitItem (item) { } ItemVisitor.prototype.interfaces_ = function interfaces_ () { return [] } ItemVisitor.prototype.getClass = function getClass () { return ItemVisitor } var SpatialIndex = function SpatialIndex () { } SpatialIndex.prototype.insert = function insert (itemEnv, item) { } SpatialIndex.prototype.remove = function remove (itemEnv, item) { } SpatialIndex.prototype.query = function query () { // if (arguments.length === 1) { // const searchEnv = arguments[0] // } else if (arguments.length === 2) { // const searchEnv = arguments[0] // const visitor = arguments[1] // } } SpatialIndex.prototype.interfaces_ = function interfaces_ () { return [] } SpatialIndex.prototype.getClass = function getClass () { return SpatialIndex } var AbstractNode = function AbstractNode () { this._childBoundables = new ArrayList() this._bounds = null this._level = null if (arguments.length === 0); else if (arguments.length === 1) { var level = arguments[0] this._level = level } } var staticAccessors$22 = { serialVersionUID: { configurable: true } } AbstractNode.prototype.getLevel = function getLevel () { return this._level } AbstractNode.prototype.size = function size () { return this._childBoundables.size() } AbstractNode.prototype.getChildBoundables = function getChildBoundables () { return this._childBoundables } AbstractNode.prototype.addChildBoundable = function addChildBoundable (childBoundable) { Assert.isTrue(this._bounds === null) this._childBoundables.add(childBoundable) } AbstractNode.prototype.isEmpty = function isEmpty () { return this._childBoundables.isEmpty() } AbstractNode.prototype.getBounds = function getBounds () { if (this._bounds === null) { this._bounds = this.computeBounds() } return this._bounds } AbstractNode.prototype.interfaces_ = function interfaces_ () { return [Boundable, Serializable] } AbstractNode.prototype.getClass = function getClass () { return AbstractNode } staticAccessors$22.serialVersionUID.get = function () { return 6493722185909573708 } Object.defineProperties(AbstractNode, staticAccessors$22) var Collections = function Collections () { } Collections.reverseOrder = function reverseOrder () { return { compare: function compare (a, b) { return b.compareTo(a) } } } Collections.min = function min (l) { Collections.sort(l) return l.get(0) } Collections.sort = function sort (l, c) { var a = l.toArray() if (c) { Arrays.sort(a, c) } else { Arrays.sort(a) } var i = l.iterator() for (var pos = 0, alen = a.length; pos < alen; pos++) { i.next() i.set(a[pos]) } } Collections.singletonList = function singletonList (o) { var arrayList = new ArrayList() arrayList.add(o) return arrayList } var BoundablePair = function BoundablePair () { this._boundable1 = null this._boundable2 = null this._distance = null this._itemDistance = null var boundable1 = arguments[0] var boundable2 = arguments[1] var itemDistance = arguments[2] this._boundable1 = boundable1 this._boundable2 = boundable2 this._itemDistance = itemDistance this._distance = this.distance() } BoundablePair.prototype.expandToQueue = function expandToQueue (priQ, minDistance) { var isComp1 = BoundablePair.isComposite(this._boundable1) var isComp2 = BoundablePair.isComposite(this._boundable2) if (isComp1 && isComp2) { if (BoundablePair.area(this._boundable1) > BoundablePair.area(this._boundable2)) { this.expand(this._boundable1, this._boundable2, priQ, minDistance) return null } else { this.expand(this._boundable2, this._boundable1, priQ, minDistance) return null } } else if (isComp1) { this.expand(this._boundable1, this._boundable2, priQ, minDistance) return null } else if (isComp2) { this.expand(this._boundable2, this._boundable1, priQ, minDistance) return null } throw new IllegalArgumentException('neither boundable is composite') } BoundablePair.prototype.isLeaves = function isLeaves () { return !(BoundablePair.isComposite(this._boundable1) || BoundablePair.isComposite(this._boundable2)) } BoundablePair.prototype.compareTo = function compareTo (o) { var nd = o if (this._distance < nd._distance) { return -1 } if (this._distance > nd._distance) { return 1 } return 0 } BoundablePair.prototype.expand = function expand (bndComposite, bndOther, priQ, minDistance) { var this$1$1 = this var children = bndComposite.getChildBoundables() for (var i = children.iterator(); i.hasNext();) { var child = i.next() var bp = new BoundablePair(child, bndOther, this$1$1._itemDistance) if (bp.getDistance() < minDistance) { priQ.add(bp) } } } BoundablePair.prototype.getBoundable = function getBoundable (i) { if (i === 0) { return this._boundable1 } return this._boundable2 } BoundablePair.prototype.getDistance = function getDistance () { return this._distance } BoundablePair.prototype.distance = function distance () { if (this.isLeaves()) { return this._itemDistance.distance(this._boundable1, this._boundable2) } return this._boundable1.getBounds().distance(this._boundable2.getBounds()) } BoundablePair.prototype.interfaces_ = function interfaces_ () { return [Comparable] } BoundablePair.prototype.getClass = function getClass () { return BoundablePair } BoundablePair.area = function area (b) { return b.getBounds().getArea() } BoundablePair.isComposite = function isComposite (item) { return item instanceof AbstractNode } var AbstractSTRtree = function AbstractSTRtree () { this._root = null this._built = false this._itemBoundables = new ArrayList() this._nodeCapacity = null if (arguments.length === 0) { var nodeCapacity = AbstractSTRtree.DEFAULT_NODE_CAPACITY this._nodeCapacity = nodeCapacity } else if (arguments.length === 1) { var nodeCapacity$1 = arguments[0] Assert.isTrue(nodeCapacity$1 > 1, 'Node capacity must be greater than 1') this._nodeCapacity = nodeCapacity$1 } } var staticAccessors$23 = { IntersectsOp: { configurable: true }, serialVersionUID: { configurable: true }, DEFAULT_NODE_CAPACITY: { configurable: true } } AbstractSTRtree.prototype.getNodeCapacity = function getNodeCapacity () { return this._nodeCapacity } AbstractSTRtree.prototype.lastNode = function lastNode (nodes) { return nodes.get(nodes.size() - 1) } AbstractSTRtree.prototype.size = function size () { var this$1$1 = this if (arguments.length === 0) { if (this.isEmpty()) { return 0 } this.build() return this.size(this._root) } else if (arguments.length === 1) { var node = arguments[0] var size = 0 for (var i = node.getChildBoundables().iterator(); i.hasNext();) { var childBoundable = i.next() if (childBoundable instanceof AbstractNode) { size += this$1$1.size(childBoundable) } else if (childBoundable instanceof ItemBoundable) { size += 1 } } return size } } AbstractSTRtree.prototype.removeItem = function removeItem (node, item) { var childToRemove = null for (var i = node.getChildBoundables().iterator(); i.hasNext();) { var childBoundable = i.next() if (childBoundable instanceof ItemBoundable) { if (childBoundable.getItem() === item) { childToRemove = childBoundable } } } if (childToRemove !== null) { node.getChildBoundables().remove(childToRemove) return true } return false } AbstractSTRtree.prototype.itemsTree = function itemsTree () { var this$1$1 = this if (arguments.length === 0) { this.build() var valuesTree = this.itemsTree(this._root) if (valuesTree === null) { return new ArrayList() } return valuesTree } else if (arguments.length === 1) { var node = arguments[0] var valuesTreeForNode = new ArrayList() for (var i = node.getChildBoundables().iterator(); i.hasNext();) { var childBoundable = i.next() if (childBoundable instanceof AbstractNode) { var valuesTreeForChild = this$1$1.itemsTree(childBoundable) if (valuesTreeForChild !== null) { valuesTreeForNode.add(valuesTreeForChild) } } else if (childBoundable instanceof ItemBoundable) { valuesTreeForNode.add(childBoundable.getItem()) } else { Assert.shouldNeverReachHere() } } if (valuesTreeForNode.size() <= 0) { return null } return valuesTreeForNode } } AbstractSTRtree.prototype.insert = function insert (bounds, item) { Assert.isTrue(!this._built, 'Cannot insert items into an STR packed R-tree after it has been built.') this._itemBoundables.add(new ItemBoundable(bounds, item)) } AbstractSTRtree.prototype.boundablesAtLevel = function boundablesAtLevel () { var this$1$1 = this if (arguments.length === 1) { var level = arguments[0] var boundables = new ArrayList() this.boundablesAtLevel(level, this._root, boundables) return boundables } else if (arguments.length === 3) { var level$1 = arguments[0] var top = arguments[1] var boundables$1 = arguments[2] Assert.isTrue(level$1 > -2) if (top.getLevel() === level$1) { boundables$1.add(top) return null } for (var i = top.getChildBoundables().iterator(); i.hasNext();) { var boundable = i.next() if (boundable instanceof AbstractNode) { this$1$1.boundablesAtLevel(level$1, boundable, boundables$1) } else { Assert.isTrue(boundable instanceof ItemBoundable) if (level$1 === -1) { boundables$1.add(boundable) } } } return null } } AbstractSTRtree.prototype.query = function query () { var this$1$1 = this if (arguments.length === 1) { var searchBounds = arguments[0] this.build() var matches = new ArrayList() if (this.isEmpty()) { return matches } if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds)) { this.query(searchBounds, this._root, matches) } return matches } else if (arguments.length === 2) { var searchBounds$1 = arguments[0] var visitor = arguments[1] this.build() if (this.isEmpty()) { return null } if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds$1)) { this.query(searchBounds$1, this._root, visitor) } } else if (arguments.length === 3) { if (hasInterface(arguments[2], ItemVisitor) && (arguments[0] instanceof Object && arguments[1] instanceof AbstractNode)) { var searchBounds$2 = arguments[0] var node = arguments[1] var visitor$1 = arguments[2] var childBoundables = node.getChildBoundables() for (var i = 0; i < childBoundables.size(); i++) { var childBoundable = childBoundables.get(i) if (!this$1$1.getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds$2)) { continue } if (childBoundable instanceof AbstractNode) { this$1$1.query(searchBounds$2, childBoundable, visitor$1) } else if (childBoundable instanceof ItemBoundable) { visitor$1.visitItem(childBoundable.getItem()) } else { Assert.shouldNeverReachHere() } } } else if (hasInterface(arguments[2], List) && (arguments[0] instanceof Object && arguments[1] instanceof AbstractNode)) { var searchBounds$3 = arguments[0] var node$1 = arguments[1] var matches$1 = arguments[2] var childBoundables$1 = node$1.getChildBoundables() for (var i$1 = 0; i$1 < childBoundables$1.size(); i$1++) { var childBoundable$1 = childBoundables$1.get(i$1) if (!this$1$1.getIntersectsOp().intersects(childBoundable$1.getBounds(), searchBounds$3)) { continue } if (childBoundable$1 instanceof AbstractNode) { this$1$1.query(searchBounds$3, childBoundable$1, matches$1) } else if (childBoundable$1 instanceof ItemBoundable) { matches$1.add(childBoundable$1.getItem()) } else { Assert.shouldNeverReachHere() } } } } } AbstractSTRtree.prototype.build = function build () { if (this._built) { return null } this._root = this._itemBoundables.isEmpty() ? this.createNode(0) : this.createHigherLevels(this._itemBoundables, -1) this._itemBoundables = null this._built = true } AbstractSTRtree.prototype.getRoot = function getRoot () { this.build() return this._root } AbstractSTRtree.prototype.remove = function remove () { var this$1$1 = this if (arguments.length === 2) { var searchBounds = arguments[0] var item = arguments[1] this.build() if (this.getIntersectsOp().intersects(this._root.getBounds(), searchBounds)) { return this.remove(searchBounds, this._root, item) } return false } else if (arguments.length === 3) { var searchBounds$1 = arguments[0] var node = arguments[1] var item$1 = arguments[2] var found = this.removeItem(node, item$1) if (found) { return true } var childToPrune = null for (var i = node.getChildBoundables().iterator(); i.hasNext();) { var childBoundable = i.next() if (!this$1$1.getIntersectsOp().intersects(childBoundable.getBounds(), searchBounds$1)) { continue } if (childBoundable instanceof AbstractNode) { found = this$1$1.remove(searchBounds$1, childBoundable, item$1) if (found) { childToPrune = childBoundable break } } } if (childToPrune !== null) { if (childToPrune.getChildBoundables().isEmpty()) { node.getChildBoundables().remove(childToPrune) } } return found } } AbstractSTRtree.prototype.createHigherLevels = function createHigherLevels (boundablesOfALevel, level) { Assert.isTrue(!boundablesOfALevel.isEmpty()) var parentBoundables = this.createParentBoundables(boundablesOfALevel, level + 1) if (parentBoundables.size() === 1) { return parentBoundables.get(0) } return this.createHigherLevels(parentBoundables, level + 1) } AbstractSTRtree.prototype.depth = function depth () { var this$1$1 = this if (arguments.length === 0) { if (this.isEmpty()) { return 0 } this.build() return this.depth(this._root) } else if (arguments.length === 1) { var node = arguments[0] var maxChildDepth = 0 for (var i = node.getChildBoundables().iterator(); i.hasNext();) { var childBoundable = i.next() if (childBoundable instanceof AbstractNode) { var childDepth = this$1$1.depth(childBoundable) if (childDepth > maxChildDepth) { maxChildDepth = childDepth } } } return maxChildDepth + 1 } } AbstractSTRtree.prototype.createParentBoundables = function createParentBoundables (childBoundables, newLevel) { var this$1$1 = this Assert.isTrue(!childBoundables.isEmpty()) var parentBoundables = new ArrayList() parentBoundables.add(this.createNode(newLevel)) var sortedChildBoundables = new ArrayList(childBoundables) Collections.sort(sortedChildBoundables, this.getComparator()) for (var i = sortedChildBoundables.iterator(); i.hasNext();) { var childBoundable = i.next() if (this$1$1.lastNode(parentBoundables).getChildBoundables().size() === this$1$1.getNodeCapacity()) { parentBoundables.add(this$1$1.createNode(newLevel)) } this$1$1.lastNode(parentBoundables).addChildBoundable(childBoundable) } return parentBoundables } AbstractSTRtree.prototype.isEmpty = function isEmpty () { if (!this._built) { return this._itemBoundables.isEmpty() } return this._root.isEmpty() } AbstractSTRtree.prototype.interfaces_ = function interfaces_ () { return [Serializable] } AbstractSTRtree.prototype.getClass = function getClass () { return AbstractSTRtree } AbstractSTRtree.compareDoubles = function compareDoubles (a, b) { return a > b ? 1 : a < b ? -1 : 0 } staticAccessors$23.IntersectsOp.get = function () { return IntersectsOp } staticAccessors$23.serialVersionUID.get = function () { return -3886435814360241337 } staticAccessors$23.DEFAULT_NODE_CAPACITY.get = function () { return 10 } Object.defineProperties(AbstractSTRtree, staticAccessors$23) var IntersectsOp = function IntersectsOp () { } var ItemDistance = function ItemDistance () { } ItemDistance.prototype.distance = function distance (item1, item2) { } ItemDistance.prototype.interfaces_ = function interfaces_ () { return [] } ItemDistance.prototype.getClass = function getClass () { return ItemDistance } var STRtree = (function (AbstractSTRtree$$1) { function STRtree (nodeCapacity) { nodeCapacity = nodeCapacity || STRtree.DEFAULT_NODE_CAPACITY AbstractSTRtree$$1.call(this, nodeCapacity) } if (AbstractSTRtree$$1) STRtree.__proto__ = AbstractSTRtree$$1 STRtree.prototype = Object.create(AbstractSTRtree$$1 && AbstractSTRtree$$1.prototype) STRtree.prototype.constructor = STRtree var staticAccessors = { STRtreeNode: { configurable: true }, serialVersionUID: { configurable: true }, xComparator: { configurable: true }, yComparator: { configurable: true }, intersectsOp: { configurable: true }, DEFAULT_NODE_CAPACITY: { configurable: true } } STRtree.prototype.createParentBoundablesFromVerticalSlices = function createParentBoundablesFromVerticalSlices (verticalSlices, newLevel) { var this$1$1 = this Assert.isTrue(verticalSlices.length > 0) var parentBoundables = new ArrayList() for (var i = 0; i < verticalSlices.length; i++) { parentBoundables.addAll(this$1$1.createParentBoundablesFromVerticalSlice(verticalSlices[i], newLevel)) } return parentBoundables } STRtree.prototype.createNode = function createNode (level) { return new STRtreeNode(level) } STRtree.prototype.size = function size () { if (arguments.length === 0) { return AbstractSTRtree$$1.prototype.size.call(this) } else { return AbstractSTRtree$$1.prototype.size.apply(this, arguments) } } STRtree.prototype.insert = function insert () { if (arguments.length === 2) { var itemEnv = arguments[0] var item = arguments[1] if (itemEnv.isNull()) { return null } AbstractSTRtree$$1.prototype.insert.call(this, itemEnv, item) } else { return AbstractSTRtree$$1.prototype.insert.apply(this, arguments) } } STRtree.prototype.getIntersectsOp = function getIntersectsOp () { return STRtree.intersectsOp } STRtree.prototype.verticalSlices = function verticalSlices (childBoundables, sliceCount) { var sliceCapacity = Math.trunc(Math.ceil(childBoundables.size() / sliceCount)) var slices = new Array(sliceCount).fill(null) var i = childBoundables.iterator() for (var j = 0; j < sliceCount; j++) { slices[j] = new ArrayList() var boundablesAddedToSlice = 0 while (i.hasNext() && boundablesAddedToSlice < sliceCapacity) { var childBoundable = i.next() slices[j].add(childBoundable) boundablesAddedToSlice++ } } return slices } STRtree.prototype.query = function query () { if (arguments.length === 1) { var searchEnv = arguments[0] return AbstractSTRtree$$1.prototype.query.call(this, searchEnv) } else if (arguments.length === 2) { var searchEnv$1 = arguments[0] var visitor = arguments[1] AbstractSTRtree$$1.prototype.query.call(this, searchEnv$1, visitor) } else if (arguments.length === 3) { if (hasInterface(arguments[2], ItemVisitor) && (arguments[0] instanceof Object && arguments[1] instanceof AbstractNode)) { var searchBounds = arguments[0] var node = arguments[1] var visitor$1 = arguments[2] AbstractSTRtree$$1.prototype.query.call(this, searchBounds, node, visitor$1) } else if (hasInterface(arguments[2], List) && (arguments[0] instanceof Object && arguments[1] instanceof AbstractNode)) { var searchBounds$1 = arguments[0] var node$1 = arguments[1] var matches = arguments[2] AbstractSTRtree$$1.prototype.query.call(this, searchBounds$1, node$1, matches) } } } STRtree.prototype.getComparator = function getComparator () { return STRtree.yComparator } STRtree.prototype.createParentBoundablesFromVerticalSlice = function createParentBoundablesFromVerticalSlice (childBoundables, newLevel) { return AbstractSTRtree$$1.prototype.createParentBoundables.call(this, childBoundables, newLevel) } STRtree.prototype.remove = function remove () { if (arguments.length === 2) { var itemEnv = arguments[0] var item = arguments[1] return AbstractSTRtree$$1.prototype.remove.call(this, itemEnv, item) } else { return AbstractSTRtree$$1.prototype.remove.apply(this, arguments) } } STRtree.prototype.depth = function depth () { if (arguments.length === 0) { return AbstractSTRtree$$1.prototype.depth.call(this) } else { return AbstractSTRtree$$1.prototype.depth.apply(this, arguments) } } STRtree.prototype.createParentBoundables = function createParentBoundables (childBoundables, newLevel) { Assert.isTrue(!childBoundables.isEmpty()) var minLeafCount = Math.trunc(Math.ceil(childBoundables.size() / this.getNodeCapacity())) var sortedChildBoundables = new ArrayList(childBoundables) Collections.sort(sortedChildBoundables, STRtree.xComparator) var verticalSlices = this.verticalSlices(sortedChildBoundables, Math.trunc(Math.ceil(Math.sqrt(minLeafCount)))) return this.createParentBoundablesFromVerticalSlices(verticalSlices, newLevel) } STRtree.prototype.nearestNeighbour = function nearestNeighbour () { if (arguments.length === 1) { if (hasInterface(arguments[0], ItemDistance)) { var itemDist = arguments[0] var bp = new BoundablePair(this.getRoot(), this.getRoot(), itemDist) return this.nearestNeighbour(bp) } else if (arguments[0] instanceof BoundablePair) { var initBndPair = arguments[0] return this.nearestNeighbour(initBndPair, Double.POSITIVE_INFINITY) } } else if (arguments.length === 2) { if (arguments[0] instanceof STRtree && hasInterface(arguments[1], ItemDistance)) { var tree = arguments[0] var itemDist$1 = arguments[1] var bp$1 = new BoundablePair(this.getRoot(), tree.getRoot(), itemDist$1) return this.nearestNeighbour(bp$1) } else if (arguments[0] instanceof BoundablePair && typeof arguments[1] === 'number') { var initBndPair$1 = arguments[0] var maxDistance = arguments[1] var distanceLowerBound = maxDistance var minPair = null var priQ = new PriorityQueue() priQ.add(initBndPair$1) while (!priQ.isEmpty() && distanceLowerBound > 0.0) { var bndPair = priQ.poll() var currentDistance = bndPair.getDistance() if (currentDistance >= distanceLowerBound) { break } if (bndPair.isLeaves()) { distanceLowerBound = currentDistance minPair = bndPair } else { bndPair.expandToQueue(priQ, distanceLowerBound) } } return [minPair.getBoundable(0).getItem(), minPair.getBoundable(1).getItem()] } } else if (arguments.length === 3) { var env = arguments[0] var item = arguments[1] var itemDist$2 = arguments[2] var bnd = new ItemBoundable(env, item) var bp$2 = new BoundablePair(this.getRoot(), bnd, itemDist$2) return this.nearestNeighbour(bp$2)[0] } } STRtree.prototype.interfaces_ = function interfaces_ () { return [SpatialIndex, Serializable] } STRtree.prototype.getClass = function getClass () { return STRtree } STRtree.centreX = function centreX (e) { return STRtree.avg(e.getMinX(), e.getMaxX()) } STRtree.avg = function avg (a, b) { return (a + b) / 2 } STRtree.centreY = function centreY (e) { return STRtree.avg(e.getMinY(), e.getMaxY()) } staticAccessors.STRtreeNode.get = function () { return STRtreeNode } staticAccessors.serialVersionUID.get = function () { return 259274702368956900 } staticAccessors.xComparator.get = function () { return { interfaces_: function () { return [Comparator] }, compare: function (o1, o2) { return AbstractSTRtree$$1.compareDoubles(STRtree.centreX(o1.getBounds()), STRtree.centreX(o2.getBounds())) } } } staticAccessors.yComparator.get = function () { return { interfaces_: function () { return [Comparator] }, compare: function (o1, o2) { return AbstractSTRtree$$1.compareDoubles(STRtree.centreY(o1.getBounds()), STRtree.centreY(o2.getBounds())) } } } staticAccessors.intersectsOp.get = function () { return { interfaces_: function () { return [AbstractSTRtree$$1.IntersectsOp] }, intersects: function (aBounds, bBounds) { return aBounds.intersects(bBounds) } } } staticAccessors.DEFAULT_NODE_CAPACITY.get = function () { return 10 } Object.defineProperties(STRtree, staticAccessors) return STRtree }(AbstractSTRtree)) var STRtreeNode = (function (AbstractNode$$1) { function STRtreeNode () { var level = arguments[0] AbstractNode$$1.call(this, level) } if (AbstractNode$$1) STRtreeNode.__proto__ = AbstractNode$$1 STRtreeNode.prototype = Object.create(AbstractNode$$1 && AbstractNode$$1.prototype) STRtreeNode.prototype.constructor = STRtreeNode STRtreeNode.prototype.computeBounds = function computeBounds () { var bounds = null for (var i = this.getChildBoundables().iterator(); i.hasNext();) { var childBoundable = i.next() if (bounds === null) { bounds = new Envelope(childBoundable.getBounds()) } else { bounds.expandToInclude(childBoundable.getBounds()) } } return bounds } STRtreeNode.prototype.interfaces_ = function interfaces_ () { return [] } STRtreeNode.prototype.getClass = function getClass () { return STRtreeNode } return STRtreeNode }(AbstractNode)) var SegmentPointComparator = function SegmentPointComparator () { } SegmentPointComparator.prototype.interfaces_ = function interfaces_ () { return [] } SegmentPointComparator.prototype.getClass = function getClass () { return SegmentPointComparator } SegmentPointComparator.relativeSign = function relativeSign (x0, x1) { if (x0 < x1) { return -1 } if (x0 > x1) { return 1 } return 0 } SegmentPointComparator.compare = function compare (octant, p0, p1) { if (p0.equals2D(p1)) { return 0 } var xSign = SegmentPointComparator.relativeSign(p0.x, p1.x) var ySign = SegmentPointComparator.relativeSign(p0.y, p1.y) switch (octant) { case 0: return SegmentPointComparator.compareValue(xSign, ySign) case 1: return SegmentPointComparator.compareValue(ySign, xSign) case 2: return SegmentPointComparator.compareValue(ySign, -xSign) case 3: return SegmentPointComparator.compareValue(-xSign, ySign) case 4: return SegmentPointComparator.compareValue(-xSign, -ySign) case 5: return SegmentPointComparator.compareValue(-ySign, -xSign) case 6: return SegmentPointComparator.compareValue(-ySign, xSign) case 7: return SegmentPointComparator.compareValue(xSign, -ySign) } Assert.shouldNeverReachHere('invalid octant value') return 0 } SegmentPointComparator.compareValue = function compareValue (compareSign0, compareSign1) { if (compareSign0 < 0) { return -1 } if (compareSign0 > 0) { return 1 } if (compareSign1 < 0) { return -1 } if (compareSign1 > 0) { return 1 } return 0 } var SegmentNode = function SegmentNode () { this._segString = null this.coord = null this.segmentIndex = null this._segmentOctant = null this._isInterior = null var segString = arguments[0] var coord = arguments[1] var segmentIndex = arguments[2] var segmentOctant = arguments[3] this._segString = segString this.coord = new Coordinate(coord) this.segmentIndex = segmentIndex this._segmentOctant = segmentOctant this._isInterior = !coord.equals2D(segString.getCoordinate(segmentIndex)) } SegmentNode.prototype.getCoordinate = function getCoordinate () { return this.coord } SegmentNode.prototype.print = function print (out) { out.print(this.coord) out.print(' seg # = ' + this.segmentIndex) } SegmentNode.prototype.compareTo = function compareTo (obj) { var other = obj if (this.segmentIndex < other.segmentIndex) { return -1 } if (this.segmentIndex > other.segmentIndex) { return 1 } if (this.coord.equals2D(other.coord)) { return 0 } return SegmentPointComparator.compare(this._segmentOctant, this.coord, other.coord) } SegmentNode.prototype.isEndPoint = function isEndPoint (maxSegmentIndex) { if (this.segmentIndex === 0 && !this._isInterior) { return true } if (this.segmentIndex === maxSegmentIndex) { return true } return false } SegmentNode.prototype.isInterior = function isInterior () { return this._isInterior } SegmentNode.prototype.interfaces_ = function interfaces_ () { return [Comparable] } SegmentNode.prototype.getClass = function getClass () { return SegmentNode } // import Iterator from '../../../../java/util/Iterator' var SegmentNodeList = function SegmentNodeList () { this._nodeMap = new TreeMap() this._edge = null var edge = arguments[0] this._edge = edge } SegmentNodeList.prototype.getSplitCoordinates = function getSplitCoordinates () { var this$1$1 = this var coordList = new CoordinateList() this.addEndpoints() var it = this.iterator() var eiPrev = it.next() while (it.hasNext()) { var ei = it.next() this$1$1.addEdgeCoordinates(eiPrev, ei, coordList) eiPrev = ei } return coordList.toCoordinateArray() } SegmentNodeList.prototype.addCollapsedNodes = function addCollapsedNodes () { var this$1$1 = this var collapsedVertexIndexes = new ArrayList() this.findCollapsesFromInsertedNodes(collapsedVertexIndexes) this.findCollapsesFromExistingVertices(collapsedVertexIndexes) for (var it = collapsedVertexIndexes.iterator(); it.hasNext();) { var vertexIndex = it.next().intValue() this$1$1.add(this$1$1._edge.getCoordinate(vertexIndex), vertexIndex) } } SegmentNodeList.prototype.print = function print (out) { out.println('Intersections:') for (var it = this.iterator(); it.hasNext();) { var ei = it.next() ei.print(out) } } SegmentNodeList.prototype.findCollapsesFromExistingVertices = function findCollapsesFromExistingVertices (collapsedVertexIndexes) { var this$1$1 = this for (var i = 0; i < this._edge.size() - 2; i++) { var p0 = this$1$1._edge.getCoordinate(i) // const p1 = this._edge.getCoordinate(i + 1) var p2 = this$1$1._edge.getCoordinate(i + 2) if (p0.equals2D(p2)) { collapsedVertexIndexes.add(new Integer(i + 1)) } } } SegmentNodeList.prototype.addEdgeCoordinates = function addEdgeCoordinates (ei0, ei1, coordList) { var this$1$1 = this // let npts = ei1.segmentIndex - ei0.segmentIndex + 2 var lastSegStartPt = this._edge.getCoordinate(ei1.segmentIndex) var useIntPt1 = ei1.isInterior() || !ei1.coord.equals2D(lastSegStartPt) // if (!useIntPt1) { // npts-- // } // const ipt = 0 coordList.add(new Coordinate(ei0.coord), false) for (var i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) { coordList.add(this$1$1._edge.getCoordinate(i)) } if (useIntPt1) { coordList.add(new Coordinate(ei1.coord)) } } SegmentNodeList.prototype.iterator = function iterator () { return this._nodeMap.values().iterator() } SegmentNodeList.prototype.addSplitEdges = function addSplitEdges (edgeList) { var this$1$1 = this this.addEndpoints() this.addCollapsedNodes() var it = this.iterator() var eiPrev = it.next() while (it.hasNext()) { var ei = it.next() var newEdge = this$1$1.createSplitEdge(eiPrev, ei) edgeList.add(newEdge) eiPrev = ei } } SegmentNodeList.prototype.findCollapseIndex = function findCollapseIndex (ei0, ei1, collapsedVertexIndex) { if (!ei0.coord.equals2D(ei1.coord)) { return false } var numVerticesBetween = ei1.segmentIndex - ei0.segmentIndex if (!ei1.isInterior()) { numVerticesBetween-- } if (numVerticesBetween === 1) { collapsedVertexIndex[0] = ei0.segmentIndex + 1 return true } return false } SegmentNodeList.prototype.findCollapsesFromInsertedNodes = function findCollapsesFromInsertedNodes (collapsedVertexIndexes) { var this$1$1 = this var collapsedVertexIndex = new Array(1).fill(null) var it = this.iterator() var eiPrev = it.next() while (it.hasNext()) { var ei = it.next() var isCollapsed = this$1$1.findCollapseIndex(eiPrev, ei, collapsedVertexIndex) if (isCollapsed) { collapsedVertexIndexes.add(new Integer(collapsedVertexIndex[0])) } eiPrev = ei } } SegmentNodeList.prototype.getEdge = function getEdge () { return this._edge } SegmentNodeList.prototype.addEndpoints = function addEndpoints () { var maxSegIndex = this._edge.size() - 1 this.add(this._edge.getCoordinate(0), 0) this.add(this._edge.getCoordinate(maxSegIndex), maxSegIndex) } SegmentNodeList.prototype.createSplitEdge = function createSplitEdge (ei0, ei1) { var this$1$1 = this var npts = ei1.segmentIndex - ei0.segmentIndex + 2 var lastSegStartPt = this._edge.getCoordinate(ei1.segmentIndex) var useIntPt1 = ei1.isInterior() || !ei1.coord.equals2D(lastSegStartPt) if (!useIntPt1) { npts-- } var pts = new Array(npts).fill(null) var ipt = 0 pts[ipt++] = new Coordinate(ei0.coord) for (var i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) { pts[ipt++] = this$1$1._edge.getCoordinate(i) } if (useIntPt1) { pts[ipt] = new Coordinate(ei1.coord) } return new NodedSegmentString(pts, this._edge.getData()) } SegmentNodeList.prototype.add = function add (intPt, segmentIndex) { var eiNew = new SegmentNode(this._edge, intPt, segmentIndex, this._edge.getSegmentOctant(segmentIndex)) var ei = this._nodeMap.get(eiNew) if (ei !== null) { Assert.isTrue(ei.coord.equals2D(intPt), 'Found equal nodes with different coordinates') return ei } this._nodeMap.put(eiNew, eiNew) return eiNew } SegmentNodeList.prototype.checkSplitEdgesCorrectness = function checkSplitEdgesCorrectness (splitEdges) { var edgePts = this._edge.getCoordinates() var split0 = splitEdges.get(0) var pt0 = split0.getCoordinate(0) if (!pt0.equals2D(edgePts[0])) { throw new RuntimeException('bad split edge start point at ' + pt0) } var splitn = splitEdges.get(splitEdges.size() - 1) var splitnPts = splitn.getCoordinates() var ptn = splitnPts[splitnPts.length - 1] if (!ptn.equals2D(edgePts[edgePts.length - 1])) { throw new RuntimeException('bad split edge end point at ' + ptn) } } SegmentNodeList.prototype.interfaces_ = function interfaces_ () { return [] } SegmentNodeList.prototype.getClass = function getClass () { return SegmentNodeList } // class NodeVertexIterator { // constructor () { // this._nodeList = null // this._edge = null // this._nodeIt = null // this._currNode = null // this._nextNode = null // this._currSegIndex = 0 // let nodeList = arguments[0] // this._nodeList = nodeList // this._edge = nodeList.getEdge() // this._nodeIt = nodeList.iterator() // this.readNextNode() // } // next () { // if (this._currNode === null) { // this._currNode = this._nextNode // this._currSegIndex = this._currNode.segmentIndex // this.readNextNode() // return this._currNode // } // if (this._nextNode === null) return null // if (this._nextNode.segmentIndex === this._currNode.segmentIndex) { // this._currNode = this._nextNode // this._currSegIndex = this._currNode.segmentIndex // this.readNextNode() // return this._currNode // } // if (this._nextNode.segmentIndex > this._currNode.segmentIndex) {} // return null // } // remove () { // // throw new UnsupportedOperationException(this.getClass().getName()) // } // hasNext () { // if (this._nextNode === null) return false // return true // } // readNextNode () { // if (this._nodeIt.hasNext()) this._nextNode = this._nodeIt.next(); else this._nextNode = null // } // interfaces_ () { // return [Iterator] // } // getClass () { // return NodeVertexIterator // } // } var Octant = function Octant () { } Octant.prototype.interfaces_ = function interfaces_ () { return [] } Octant.prototype.getClass = function getClass () { return Octant } Octant.octant = function octant () { if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') { var dx = arguments[0] var dy = arguments[1] if (dx === 0.0 && dy === 0.0) { throw new IllegalArgumentException('Cannot compute the octant for point ( ' + dx + ', ' + dy + ' )') } var adx = Math.abs(dx) var ady = Math.abs(dy) if (dx >= 0) { if (dy >= 0) { if (adx >= ady) { return 0 } else { return 1 } } else { if (adx >= ady) { return 7 } else { return 6 } } } else { if (dy >= 0) { if (adx >= ady) { return 3 } else { return 2 } } else { if (adx >= ady) { return 4 } else { return 5 } } } } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) { var p0 = arguments[0] var p1 = arguments[1] var dx$1 = p1.x - p0.x var dy$1 = p1.y - p0.y if (dx$1 === 0.0 && dy$1 === 0.0) { throw new IllegalArgumentException('Cannot compute the octant for two identical points ' + p0) } return Octant.octant(dx$1, dy$1) } } var SegmentString = function SegmentString () { } SegmentString.prototype.getCoordinates = function getCoordinates () { } SegmentString.prototype.size = function size () { } SegmentString.prototype.getCoordinate = function getCoordinate (i) { } SegmentString.prototype.isClosed = function isClosed () { } SegmentString.prototype.setData = function setData (data) { } SegmentString.prototype.getData = function getData () { } SegmentString.prototype.interfaces_ = function interfaces_ () { return [] } SegmentString.prototype.getClass = function getClass () { return SegmentString } var NodableSegmentString = function NodableSegmentString () { } NodableSegmentString.prototype.addIntersection = function addIntersection (intPt, segmentIndex) { } NodableSegmentString.prototype.interfaces_ = function interfaces_ () { return [SegmentString] } NodableSegmentString.prototype.getClass = function getClass () { return NodableSegmentString } var NodedSegmentString = function NodedSegmentString () { this._nodeList = new SegmentNodeList(this) this._pts = null this._data = null var pts = arguments[0] var data = arguments[1] this._pts = pts this._data = data } NodedSegmentString.prototype.getCoordinates = function getCoordinates () { return this._pts } NodedSegmentString.prototype.size = function size () { return this._pts.length } NodedSegmentString.prototype.getCoordinate = function getCoordinate (i) { return this._pts[i] } NodedSegmentString.prototype.isClosed = function isClosed () { return this._pts[0].equals(this._pts[this._pts.length - 1]) } NodedSegmentString.prototype.getSegmentOctant = function getSegmentOctant (index) { if (index === this._pts.length - 1) { return -1 } return this.safeOctant(this.getCoordinate(index), this.getCoordinate(index + 1)) } NodedSegmentString.prototype.setData = function setData (data) { this._data = data } NodedSegmentString.prototype.safeOctant = function safeOctant (p0, p1) { if (p0.equals2D(p1)) { return 0 } return Octant.octant(p0, p1) } NodedSegmentString.prototype.getData = function getData () { return this._data } NodedSegmentString.prototype.addIntersection = function addIntersection () { if (arguments.length === 2) { var intPt$1 = arguments[0] var segmentIndex = arguments[1] this.addIntersectionNode(intPt$1, segmentIndex) } else if (arguments.length === 4) { var li = arguments[0] var segmentIndex$1 = arguments[1] // const geomIndex = arguments[2] var intIndex = arguments[3] var intPt = new Coordinate(li.getIntersection(intIndex)) this.addIntersection(intPt, segmentIndex$1) } } NodedSegmentString.prototype.toString = function toString () { return WKTWriter.toLineString(new CoordinateArraySequence(this._pts)) } NodedSegmentString.prototype.getNodeList = function getNodeList () { return this._nodeList } NodedSegmentString.prototype.addIntersectionNode = function addIntersectionNode (intPt, segmentIndex) { var normalizedSegmentIndex = segmentIndex var nextSegIndex = normalizedSegmentIndex + 1 if (nextSegIndex < this._pts.length) { var nextPt = this._pts[nextSegIndex] if (intPt.equals2D(nextPt)) { normalizedSegmentIndex = nextSegIndex } } var ei = this._nodeList.add(intPt, normalizedSegmentIndex) return ei } NodedSegmentString.prototype.addIntersections = function addIntersections (li, segmentIndex, geomIndex) { var this$1$1 = this for (var i = 0; i < li.getIntersectionNum(); i++) { this$1$1.addIntersection(li, segmentIndex, geomIndex, i) } } NodedSegmentString.prototype.interfaces_ = function interfaces_ () { return [NodableSegmentString] } NodedSegmentString.prototype.getClass = function getClass () { return NodedSegmentString } NodedSegmentString.getNodedSubstrings = function getNodedSubstrings () { if (arguments.length === 1) { var segStrings = arguments[0] var resultEdgelist = new ArrayList() NodedSegmentString.getNodedSubstrings(segStrings, resultEdgelist) return resultEdgelist } else if (arguments.length === 2) { var segStrings$1 = arguments[0] var resultEdgelist$1 = arguments[1] for (var i = segStrings$1.iterator(); i.hasNext();) { var ss = i.next() ss.getNodeList().addSplitEdges(resultEdgelist$1) } } } var LineSegment = function LineSegment () { this.p0 = null this.p1 = null if (arguments.length === 0) { this.p0 = new Coordinate() this.p1 = new Coordinate() } else if (arguments.length === 1) { var ls = arguments[0] this.p0 = new Coordinate(ls.p0) this.p1 = new Coordinate(ls.p1) } else if (arguments.length === 2) { this.p0 = arguments[0] this.p1 = arguments[1] } else if (arguments.length === 4) { var x0 = arguments[0] var y0 = arguments[1] var x1 = arguments[2] var y1 = arguments[3] this.p0 = new Coordinate(x0, y0) this.p1 = new Coordinate(x1, y1) } } var staticAccessors$24 = { serialVersionUID: { configurable: true } } LineSegment.prototype.minX = function minX () { return Math.min(this.p0.x, this.p1.x) } LineSegment.prototype.orientationIndex = function orientationIndex () { if (arguments[0] instanceof LineSegment) { var seg = arguments[0] var orient0 = CGAlgorithms.orientationIndex(this.p0, this.p1, seg.p0) var orient1 = CGAlgorithms.orientationIndex(this.p0, this.p1, seg.p1) if (orient0 >= 0 && orient1 >= 0) { return Math.max(orient0, orient1) } if (orient0 <= 0 && orient1 <= 0) { return Math.max(orient0, orient1) } return 0 } else if (arguments[0] instanceof Coordinate) { var p = arguments[0] return CGAlgorithms.orientationIndex(this.p0, this.p1, p) } } LineSegment.prototype.toGeometry = function toGeometry (geomFactory) { return geomFactory.createLineString([this.p0, this.p1]) } LineSegment.prototype.isVertical = function isVertical () { return this.p0.x === this.p1.x } LineSegment.prototype.equals = function equals (o) { if (!(o instanceof LineSegment)) { return false } var other = o return this.p0.equals(other.p0) && this.p1.equals(other.p1) } LineSegment.prototype.intersection = function intersection (line) { var li = new RobustLineIntersector() li.computeIntersection(this.p0, this.p1, line.p0, line.p1) if (li.hasIntersection()) { return li.getIntersection(0) } return null } LineSegment.prototype.project = function project () { if (arguments[0] instanceof Coordinate) { var p = arguments[0] if (p.equals(this.p0) || p.equals(this.p1)) { return new Coordinate(p) } var r = this.projectionFactor(p) var coord = new Coordinate() coord.x = this.p0.x + r * (this.p1.x - this.p0.x) coord.y = this.p0.y + r * (this.p1.y - this.p0.y) return coord } else if (arguments[0] instanceof LineSegment) { var seg = arguments[0] var pf0 = this.projectionFactor(seg.p0) var pf1 = this.projectionFactor(seg.p1) if (pf0 >= 1.0 && pf1 >= 1.0) { return null } if (pf0 <= 0.0 && pf1 <= 0.0) { return null } var newp0 = this.project(seg.p0) if (pf0 < 0.0) { newp0 = this.p0 } if (pf0 > 1.0) { newp0 = this.p1 } var newp1 = this.project(seg.p1) if (pf1 < 0.0) { newp1 = this.p0 } if (pf1 > 1.0) { newp1 = this.p1 } return new LineSegment(newp0, newp1) } } LineSegment.prototype.normalize = function normalize () { if (this.p1.compareTo(this.p0) < 0) { this.reverse() } } LineSegment.prototype.angle = function angle () { return Math.atan2(this.p1.y - this.p0.y, this.p1.x - this.p0.x) } LineSegment.prototype.getCoordinate = function getCoordinate (i) { if (i === 0) { return this.p0 } return this.p1 } LineSegment.prototype.distancePerpendicular = function distancePerpendicular (p) { return CGAlgorithms.distancePointLinePerpendicular(p, this.p0, this.p1) } LineSegment.prototype.minY = function minY () { return Math.min(this.p0.y, this.p1.y) } LineSegment.prototype.midPoint = function midPoint () { return LineSegment.midPoint(this.p0, this.p1) } LineSegment.prototype.projectionFactor = function projectionFactor (p) { if (p.equals(this.p0)) { return 0.0 } if (p.equals(this.p1)) { return 1.0 } var dx = this.p1.x - this.p0.x var dy = this.p1.y - this.p0.y var len = dx * dx + dy * dy if (len <= 0.0) { return Double.NaN } var r = ((p.x - this.p0.x) * dx + (p.y - this.p0.y) * dy) / len return r } LineSegment.prototype.closestPoints = function closestPoints (line) { var intPt = this.intersection(line) if (intPt !== null) { return [intPt, intPt] } var closestPt = new Array(2).fill(null) var minDistance = Double.MAX_VALUE var dist = null var close00 = this.closestPoint(line.p0) minDistance = close00.distance(line.p0) closestPt[0] = close00 closestPt[1] = line.p0 var close01 = this.closestPoint(line.p1) dist = close01.distance(line.p1) if (dist < minDistance) { minDistance = dist closestPt[0] = close01 closestPt[1] = line.p1 } var close10 = line.closestPoint(this.p0) dist = close10.distance(this.p0) if (dist < minDistance) { minDistance = dist closestPt[0] = this.p0 closestPt[1] = close10 } var close11 = line.closestPoint(this.p1) dist = close11.distance(this.p1) if (dist < minDistance) { minDistance = dist closestPt[0] = this.p1 closestPt[1] = close11 } return closestPt } LineSegment.prototype.closestPoint = function closestPoint (p) { var factor = this.projectionFactor(p) if (factor > 0 && factor < 1) { return this.project(p) } var dist0 = this.p0.distance(p) var dist1 = this.p1.distance(p) if (dist0 < dist1) { return this.p0 } return this.p1 } LineSegment.prototype.maxX = function maxX () { return Math.max(this.p0.x, this.p1.x) } LineSegment.prototype.getLength = function getLength () { return this.p0.distance(this.p1) } LineSegment.prototype.compareTo = function compareTo (o) { var other = o var comp0 = this.p0.compareTo(other.p0) if (comp0 !== 0) { return comp0 } return this.p1.compareTo(other.p1) } LineSegment.prototype.reverse = function reverse () { var temp = this.p0 this.p0 = this.p1 this.p1 = temp } LineSegment.prototype.equalsTopo = function equalsTopo (other) { return this.p0.equals(other.p0) && (this.p1.equals(other.p1) || this.p0.equals(other.p1)) && this.p1.equals(other.p0) } LineSegment.prototype.lineIntersection = function lineIntersection (line) { try { var intPt = HCoordinate.intersection(this.p0, this.p1, line.p0, line.p1) return intPt } catch (ex) { if (ex instanceof NotRepresentableException); else { throw ex } } finally { } return null } LineSegment.prototype.maxY = function maxY () { return Math.max(this.p0.y, this.p1.y) } LineSegment.prototype.pointAlongOffset = function pointAlongOffset (segmentLengthFraction, offsetDistance) { var segx = this.p0.x + segmentLengthFraction * (this.p1.x - this.p0.x) var segy = this.p0.y + segmentLengthFraction * (this.p1.y - this.p0.y) var dx = this.p1.x - this.p0.x var dy = this.p1.y - this.p0.y var len = Math.sqrt(dx * dx + dy * dy) var ux = 0.0 var uy = 0.0 if (offsetDistance !== 0.0) { if (len <= 0.0) { throw new Error('Cannot compute offset from zero-length line segment') } ux = offsetDistance * dx / len uy = offsetDistance * dy / len } var offsetx = segx - uy var offsety = segy + ux var coord = new Coordinate(offsetx, offsety) return coord } LineSegment.prototype.setCoordinates = function setCoordinates () { if (arguments.length === 1) { var ls = arguments[0] this.setCoordinates(ls.p0, ls.p1) } else if (arguments.length === 2) { var p0 = arguments[0] var p1 = arguments[1] this.p0.x = p0.x this.p0.y = p0.y this.p1.x = p1.x this.p1.y = p1.y } } LineSegment.prototype.segmentFraction = function segmentFraction (inputPt) { var segFrac = this.projectionFactor(inputPt) if (segFrac < 0.0) { segFrac = 0.0 } else if (segFrac > 1.0 || Double.isNaN(segFrac)) { segFrac = 1.0 } return segFrac } LineSegment.prototype.toString = function toString () { return 'LINESTRING( ' + this.p0.x + ' ' + this.p0.y + ', ' + this.p1.x + ' ' + this.p1.y + ')' } LineSegment.prototype.isHorizontal = function isHorizontal () { return this.p0.y === this.p1.y } LineSegment.prototype.distance = function distance () { if (arguments[0] instanceof LineSegment) { var ls = arguments[0] return CGAlgorithms.distanceLineLine(this.p0, this.p1, ls.p0, ls.p1) } else if (arguments[0] instanceof Coordinate) { var p = arguments[0] return CGAlgorithms.distancePointLine(p, this.p0, this.p1) } } LineSegment.prototype.pointAlong = function pointAlong (segmentLengthFraction) { var coord = new Coordinate() coord.x = this.p0.x + segmentLengthFraction * (this.p1.x - this.p0.x) coord.y = this.p0.y + segmentLengthFraction * (this.p1.y - this.p0.y) return coord } LineSegment.prototype.hashCode = function hashCode () { var bits0 = Double.doubleToLongBits(this.p0.x) bits0 ^= Double.doubleToLongBits(this.p0.y) * 31 var hash0 = Math.trunc(bits0) ^ Math.trunc(bits0 >> 32) var bits1 = Double.doubleToLongBits(this.p1.x) bits1 ^= Double.doubleToLongBits(this.p1.y) * 31 var hash1 = Math.trunc(bits1) ^ Math.trunc(bits1 >> 32) return hash0 ^ hash1 } LineSegment.prototype.interfaces_ = function interfaces_ () { return [Comparable, Serializable] } LineSegment.prototype.getClass = function getClass () { return LineSegment } LineSegment.midPoint = function midPoint (p0, p1) { return new Coordinate((p0.x + p1.x) / 2, (p0.y + p1.y) / 2) } staticAccessors$24.serialVersionUID.get = function () { return 3252005833466256227 } Object.defineProperties(LineSegment, staticAccessors$24) var MonotoneChainOverlapAction = function MonotoneChainOverlapAction () { this.tempEnv1 = new Envelope() this.tempEnv2 = new Envelope() this._overlapSeg1 = new LineSegment() this._overlapSeg2 = new LineSegment() } MonotoneChainOverlapAction.prototype.overlap = function overlap () { if (arguments.length === 2); else if (arguments.length === 4) { var mc1 = arguments[0] var start1 = arguments[1] var mc2 = arguments[2] var start2 = arguments[3] mc1.getLineSegment(start1, this._overlapSeg1) mc2.getLineSegment(start2, this._overlapSeg2) this.overlap(this._overlapSeg1, this._overlapSeg2) } } MonotoneChainOverlapAction.prototype.interfaces_ = function interfaces_ () { return [] } MonotoneChainOverlapAction.prototype.getClass = function getClass () { return MonotoneChainOverlapAction } var MonotoneChain = function MonotoneChain () { this._pts = null this._start = null this._end = null this._env = null this._context = null this._id = null var pts = arguments[0] var start = arguments[1] var end = arguments[2] var context = arguments[3] this._pts = pts this._start = start this._end = end this._context = context } MonotoneChain.prototype.getLineSegment = function getLineSegment (index, ls) { ls.p0 = this._pts[index] ls.p1 = this._pts[index + 1] } MonotoneChain.prototype.computeSelect = function computeSelect (searchEnv, start0, end0, mcs) { var p0 = this._pts[start0] var p1 = this._pts[end0] mcs.tempEnv1.init(p0, p1) if (end0 - start0 === 1) { mcs.select(this, start0) return null } if (!searchEnv.intersects(mcs.tempEnv1)) { return null } var mid = Math.trunc((start0 + end0) / 2) if (start0 < mid) { this.computeSelect(searchEnv, start0, mid, mcs) } if (mid < end0) { this.computeSelect(searchEnv, mid, end0, mcs) } } MonotoneChain.prototype.getCoordinates = function getCoordinates () { var this$1$1 = this var coord = new Array(this._end - this._start + 1).fill(null) var index = 0 for (var i = this._start; i <= this._end; i++) { coord[index++] = this$1$1._pts[i] } return coord } MonotoneChain.prototype.computeOverlaps = function computeOverlaps (mc, mco) { this.computeOverlapsInternal(this._start, this._end, mc, mc._start, mc._end, mco) } MonotoneChain.prototype.setId = function setId (id) { this._id = id } MonotoneChain.prototype.select = function select (searchEnv, mcs) { this.computeSelect(searchEnv, this._start, this._end, mcs) } MonotoneChain.prototype.getEnvelope = function getEnvelope () { if (this._env === null) { var p0 = this._pts[this._start] var p1 = this._pts[this._end] this._env = new Envelope(p0, p1) } return this._env } MonotoneChain.prototype.getEndIndex = function getEndIndex () { return this._end } MonotoneChain.prototype.getStartIndex = function getStartIndex () { return this._start } MonotoneChain.prototype.getContext = function getContext () { return this._context } MonotoneChain.prototype.getId = function getId () { return this._id } MonotoneChain.prototype.computeOverlapsInternal = function computeOverlapsInternal (start0, end0, mc, start1, end1, mco) { var p00 = this._pts[start0] var p01 = this._pts[end0] var p10 = mc._pts[start1] var p11 = mc._pts[end1] if (end0 - start0 === 1 && end1 - start1 === 1) { mco.overlap(this, start0, mc, start1) return null } mco.tempEnv1.init(p00, p01) mco.tempEnv2.init(p10, p11) if (!mco.tempEnv1.intersects(mco.tempEnv2)) { return null } var mid0 = Math.trunc((start0 + end0) / 2) var mid1 = Math.trunc((start1 + end1) / 2) if (start0 < mid0) { if (start1 < mid1) { this.computeOverlapsInternal(start0, mid0, mc, start1, mid1, mco) } if (mid1 < end1) { this.computeOverlapsInternal(start0, mid0, mc, mid1, end1, mco) } } if (mid0 < end0) { if (start1 < mid1) { this.computeOverlapsInternal(mid0, end0, mc, start1, mid1, mco) } if (mid1 < end1) { this.computeOverlapsInternal(mid0, end0, mc, mid1, end1, mco) } } } MonotoneChain.prototype.interfaces_ = function interfaces_ () { return [] } MonotoneChain.prototype.getClass = function getClass () { return MonotoneChain } var MonotoneChainBuilder = function MonotoneChainBuilder () { } MonotoneChainBuilder.prototype.interfaces_ = function interfaces_ () { return [] } MonotoneChainBuilder.prototype.getClass = function getClass () { return MonotoneChainBuilder } MonotoneChainBuilder.getChainStartIndices = function getChainStartIndices (pts) { var start = 0 var startIndexList = new ArrayList() startIndexList.add(new Integer(start)) do { var last = MonotoneChainBuilder.findChainEnd(pts, start) startIndexList.add(new Integer(last)) start = last } while (start < pts.length - 1) var startIndex = MonotoneChainBuilder.toIntArray(startIndexList) return startIndex } MonotoneChainBuilder.findChainEnd = function findChainEnd (pts, start) { var safeStart = start while (safeStart < pts.length - 1 && pts[safeStart].equals2D(pts[safeStart + 1])) { safeStart++ } if (safeStart >= pts.length - 1) { return pts.length - 1 } var chainQuad = Quadrant.quadrant(pts[safeStart], pts[safeStart + 1]) var last = start + 1 while (last < pts.length) { if (!pts[last - 1].equals2D(pts[last])) { var quad = Quadrant.quadrant(pts[last - 1], pts[last]) if (quad !== chainQuad) { break } } last++ } return last - 1 } MonotoneChainBuilder.getChains = function getChains () { if (arguments.length === 1) { var pts = arguments[0] return MonotoneChainBuilder.getChains(pts, null) } else if (arguments.length === 2) { var pts$1 = arguments[0] var context = arguments[1] var mcList = new ArrayList() var startIndex = MonotoneChainBuilder.getChainStartIndices(pts$1) for (var i = 0; i < startIndex.length - 1; i++) { var mc = new MonotoneChain(pts$1, startIndex[i], startIndex[i + 1], context) mcList.add(mc) } return mcList } } MonotoneChainBuilder.toIntArray = function toIntArray (list) { var array = new Array(list.size()).fill(null) for (var i = 0; i < array.length; i++) { array[i] = list.get(i).intValue() } return array } var Noder = function Noder () { } Noder.prototype.computeNodes = function computeNodes (segStrings) { } Noder.prototype.getNodedSubstrings = function getNodedSubstrings () { } Noder.prototype.interfaces_ = function interfaces_ () { return [] } Noder.prototype.getClass = function getClass () { return Noder } var SinglePassNoder = function SinglePassNoder () { this._segInt = null if (arguments.length === 0); else if (arguments.length === 1) { var segInt = arguments[0] this.setSegmentIntersector(segInt) } } SinglePassNoder.prototype.setSegmentIntersector = function setSegmentIntersector (segInt) { this._segInt = segInt } SinglePassNoder.prototype.interfaces_ = function interfaces_ () { return [Noder] } SinglePassNoder.prototype.getClass = function getClass () { return SinglePassNoder } var MCIndexNoder = (function (SinglePassNoder$$1) { function MCIndexNoder (si) { if (si) { SinglePassNoder$$1.call(this, si) } else { SinglePassNoder$$1.call(this) } this._monoChains = new ArrayList() this._index = new STRtree() this._idCounter = 0 this._nodedSegStrings = null this._nOverlaps = 0 } if (SinglePassNoder$$1) MCIndexNoder.__proto__ = SinglePassNoder$$1 MCIndexNoder.prototype = Object.create(SinglePassNoder$$1 && SinglePassNoder$$1.prototype) MCIndexNoder.prototype.constructor = MCIndexNoder var staticAccessors = { SegmentOverlapAction: { configurable: true } } MCIndexNoder.prototype.getMonotoneChains = function getMonotoneChains () { return this._monoChains } MCIndexNoder.prototype.getNodedSubstrings = function getNodedSubstrings () { return NodedSegmentString.getNodedSubstrings(this._nodedSegStrings) } MCIndexNoder.prototype.getIndex = function getIndex () { return this._index } MCIndexNoder.prototype.add = function add (segStr) { var this$1$1 = this var segChains = MonotoneChainBuilder.getChains(segStr.getCoordinates(), segStr) for (var i = segChains.iterator(); i.hasNext();) { var mc = i.next() mc.setId(this$1$1._idCounter++) this$1$1._index.insert(mc.getEnvelope(), mc) this$1$1._monoChains.add(mc) } } MCIndexNoder.prototype.computeNodes = function computeNodes (inputSegStrings) { var this$1$1 = this this._nodedSegStrings = inputSegStrings for (var i = inputSegStrings.iterator(); i.hasNext();) { this$1$1.add(i.next()) } this.intersectChains() } MCIndexNoder.prototype.intersectChains = function intersectChains () { var this$1$1 = this var overlapAction = new SegmentOverlapAction(this._segInt) for (var i = this._monoChains.iterator(); i.hasNext();) { var queryChain = i.next() var overlapChains = this$1$1._index.query(queryChain.getEnvelope()) for (var j = overlapChains.iterator(); j.hasNext();) { var testChain = j.next() if (testChain.getId() > queryChain.getId()) { queryChain.computeOverlaps(testChain, overlapAction) this$1$1._nOverlaps++ } if (this$1$1._segInt.isDone()) { return null } } } } MCIndexNoder.prototype.interfaces_ = function interfaces_ () { return [] } MCIndexNoder.prototype.getClass = function getClass () { return MCIndexNoder } staticAccessors.SegmentOverlapAction.get = function () { return SegmentOverlapAction } Object.defineProperties(MCIndexNoder, staticAccessors) return MCIndexNoder }(SinglePassNoder)) var SegmentOverlapAction = (function (MonotoneChainOverlapAction$$1) { function SegmentOverlapAction () { MonotoneChainOverlapAction$$1.call(this) this._si = null var si = arguments[0] this._si = si } if (MonotoneChainOverlapAction$$1) SegmentOverlapAction.__proto__ = MonotoneChainOverlapAction$$1 SegmentOverlapAction.prototype = Object.create(MonotoneChainOverlapAction$$1 && MonotoneChainOverlapAction$$1.prototype) SegmentOverlapAction.prototype.constructor = SegmentOverlapAction SegmentOverlapAction.prototype.overlap = function overlap () { if (arguments.length === 4) { var mc1 = arguments[0] var start1 = arguments[1] var mc2 = arguments[2] var start2 = arguments[3] var ss1 = mc1.getContext() var ss2 = mc2.getContext() this._si.processIntersections(ss1, start1, ss2, start2) } else { return MonotoneChainOverlapAction$$1.prototype.overlap.apply(this, arguments) } } SegmentOverlapAction.prototype.interfaces_ = function interfaces_ () { return [] } SegmentOverlapAction.prototype.getClass = function getClass () { return SegmentOverlapAction } return SegmentOverlapAction }(MonotoneChainOverlapAction)) var BufferParameters = function BufferParameters () { this._quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS this._endCapStyle = BufferParameters.CAP_ROUND this._joinStyle = BufferParameters.JOIN_ROUND this._mitreLimit = BufferParameters.DEFAULT_MITRE_LIMIT this._isSingleSided = false this._simplifyFactor = BufferParameters.DEFAULT_SIMPLIFY_FACTOR if (arguments.length === 0); else if (arguments.length === 1) { var quadrantSegments = arguments[0] this.setQuadrantSegments(quadrantSegments) } else if (arguments.length === 2) { var quadrantSegments$1 = arguments[0] var endCapStyle = arguments[1] this.setQuadrantSegments(quadrantSegments$1) this.setEndCapStyle(endCapStyle) } else if (arguments.length === 4) { var quadrantSegments$2 = arguments[0] var endCapStyle$1 = arguments[1] var joinStyle = arguments[2] var mitreLimit = arguments[3] this.setQuadrantSegments(quadrantSegments$2) this.setEndCapStyle(endCapStyle$1) this.setJoinStyle(joinStyle) this.setMitreLimit(mitreLimit) } } var staticAccessors$25 = { CAP_ROUND: { configurable: true }, CAP_FLAT: { configurable: true }, CAP_SQUARE: { configurable: true }, JOIN_ROUND: { configurable: true }, JOIN_MITRE: { configurable: true }, JOIN_BEVEL: { configurable: true }, DEFAULT_QUADRANT_SEGMENTS: { configurable: true }, DEFAULT_MITRE_LIMIT: { configurable: true }, DEFAULT_SIMPLIFY_FACTOR: { configurable: true } } BufferParameters.prototype.getEndCapStyle = function getEndCapStyle () { return this._endCapStyle } BufferParameters.prototype.isSingleSided = function isSingleSided () { return this._isSingleSided } BufferParameters.prototype.setQuadrantSegments = function setQuadrantSegments (quadSegs) { this._quadrantSegments = quadSegs if (this._quadrantSegments === 0) { this._joinStyle = BufferParameters.JOIN_BEVEL } if (this._quadrantSegments < 0) { this._joinStyle = BufferParameters.JOIN_MITRE this._mitreLimit = Math.abs(this._quadrantSegments) } if (quadSegs <= 0) { this._quadrantSegments = 1 } if (this._joinStyle !== BufferParameters.JOIN_ROUND) { this._quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS } } BufferParameters.prototype.getJoinStyle = function getJoinStyle () { return this._joinStyle } BufferParameters.prototype.setJoinStyle = function setJoinStyle (joinStyle) { this._joinStyle = joinStyle } BufferParameters.prototype.setSimplifyFactor = function setSimplifyFactor (simplifyFactor) { this._simplifyFactor = simplifyFactor < 0 ? 0 : simplifyFactor } BufferParameters.prototype.getSimplifyFactor = function getSimplifyFactor () { return this._simplifyFactor } BufferParameters.prototype.getQuadrantSegments = function getQuadrantSegments () { return this._quadrantSegments } BufferParameters.prototype.setEndCapStyle = function setEndCapStyle (endCapStyle) { this._endCapStyle = endCapStyle } BufferParameters.prototype.getMitreLimit = function getMitreLimit () { return this._mitreLimit } BufferParameters.prototype.setMitreLimit = function setMitreLimit (mitreLimit) { this._mitreLimit = mitreLimit } BufferParameters.prototype.setSingleSided = function setSingleSided (isSingleSided) { this._isSingleSided = isSingleSided } BufferParameters.prototype.interfaces_ = function interfaces_ () { return [] } BufferParameters.prototype.getClass = function getClass () { return BufferParameters } BufferParameters.bufferDistanceError = function bufferDistanceError (quadSegs) { var alpha = Math.PI / 2.0 / quadSegs return 1 - Math.cos(alpha / 2.0) } staticAccessors$25.CAP_ROUND.get = function () { return 1 } staticAccessors$25.CAP_FLAT.get = function () { return 2 } staticAccessors$25.CAP_SQUARE.get = function () { return 3 } staticAccessors$25.JOIN_ROUND.get = function () { return 1 } staticAccessors$25.JOIN_MITRE.get = function () { return 2 } staticAccessors$25.JOIN_BEVEL.get = function () { return 3 } staticAccessors$25.DEFAULT_QUADRANT_SEGMENTS.get = function () { return 8 } staticAccessors$25.DEFAULT_MITRE_LIMIT.get = function () { return 5.0 } staticAccessors$25.DEFAULT_SIMPLIFY_FACTOR.get = function () { return 0.01 } Object.defineProperties(BufferParameters, staticAccessors$25) var BufferInputLineSimplifier = function BufferInputLineSimplifier (inputLine) { this._distanceTol = null this._isDeleted = null this._angleOrientation = CGAlgorithms.COUNTERCLOCKWISE this._inputLine = inputLine || null } var staticAccessors$26 = { INIT: { configurable: true }, DELETE: { configurable: true }, KEEP: { configurable: true }, NUM_PTS_TO_CHECK: { configurable: true } } BufferInputLineSimplifier.prototype.isDeletable = function isDeletable (i0, i1, i2, distanceTol) { var p0 = this._inputLine[i0] var p1 = this._inputLine[i1] var p2 = this._inputLine[i2] if (!this.isConcave(p0, p1, p2)) { return false } if (!this.isShallow(p0, p1, p2, distanceTol)) { return false } return this.isShallowSampled(p0, p1, i0, i2, distanceTol) } BufferInputLineSimplifier.prototype.deleteShallowConcavities = function deleteShallowConcavities () { var this$1$1 = this var index = 1 // const maxIndex = this._inputLine.length - 1 var midIndex = this.findNextNonDeletedIndex(index) var lastIndex = this.findNextNonDeletedIndex(midIndex) var isChanged = false while (lastIndex < this._inputLine.length) { var isMiddleVertexDeleted = false if (this$1$1.isDeletable(index, midIndex, lastIndex, this$1$1._distanceTol)) { this$1$1._isDeleted[midIndex] = BufferInputLineSimplifier.DELETE isMiddleVertexDeleted = true isChanged = true } if (isMiddleVertexDeleted) { index = lastIndex } else { index = midIndex } midIndex = this$1$1.findNextNonDeletedIndex(index) lastIndex = this$1$1.findNextNonDeletedIndex(midIndex) } return isChanged } BufferInputLineSimplifier.prototype.isShallowConcavity = function isShallowConcavity (p0, p1, p2, distanceTol) { var orientation = CGAlgorithms.computeOrientation(p0, p1, p2) var isAngleToSimplify = orientation === this._angleOrientation if (!isAngleToSimplify) { return false } var dist = CGAlgorithms.distancePointLine(p1, p0, p2) return dist < distanceTol } BufferInputLineSimplifier.prototype.isShallowSampled = function isShallowSampled (p0, p2, i0, i2, distanceTol) { var this$1$1 = this var inc = Math.trunc((i2 - i0) / BufferInputLineSimplifier.NUM_PTS_TO_CHECK) if (inc <= 0) { inc = 1 } for (var i = i0; i < i2; i += inc) { if (!this$1$1.isShallow(p0, p2, this$1$1._inputLine[i], distanceTol)) { return false } } return true } BufferInputLineSimplifier.prototype.isConcave = function isConcave (p0, p1, p2) { var orientation = CGAlgorithms.computeOrientation(p0, p1, p2) var isConcave = orientation === this._angleOrientation return isConcave } BufferInputLineSimplifier.prototype.simplify = function simplify (distanceTol) { var this$1$1 = this this._distanceTol = Math.abs(distanceTol) if (distanceTol < 0) { this._angleOrientation = CGAlgorithms.CLOCKWISE } this._isDeleted = new Array(this._inputLine.length).fill(null) var isChanged = false do { isChanged = this$1$1.deleteShallowConcavities() } while (isChanged) return this.collapseLine() } BufferInputLineSimplifier.prototype.findNextNonDeletedIndex = function findNextNonDeletedIndex (index) { var next = index + 1 while (next < this._inputLine.length && this._isDeleted[next] === BufferInputLineSimplifier.DELETE) { next++ } return next } BufferInputLineSimplifier.prototype.isShallow = function isShallow (p0, p1, p2, distanceTol) { var dist = CGAlgorithms.distancePointLine(p1, p0, p2) return dist < distanceTol } BufferInputLineSimplifier.prototype.collapseLine = function collapseLine () { var this$1$1 = this var coordList = new CoordinateList() for (var i = 0; i < this._inputLine.length; i++) { if (this$1$1._isDeleted[i] !== BufferInputLineSimplifier.DELETE) { coordList.add(this$1$1._inputLine[i]) } } return coordList.toCoordinateArray() } BufferInputLineSimplifier.prototype.interfaces_ = function interfaces_ () { return [] } BufferInputLineSimplifier.prototype.getClass = function getClass () { return BufferInputLineSimplifier } BufferInputLineSimplifier.simplify = function simplify (inputLine, distanceTol) { var simp = new BufferInputLineSimplifier(inputLine) return simp.simplify(distanceTol) } staticAccessors$26.INIT.get = function () { return 0 } staticAccessors$26.DELETE.get = function () { return 1 } staticAccessors$26.KEEP.get = function () { return 1 } staticAccessors$26.NUM_PTS_TO_CHECK.get = function () { return 10 } Object.defineProperties(BufferInputLineSimplifier, staticAccessors$26) var OffsetSegmentString = function OffsetSegmentString () { this._ptList = null this._precisionModel = null this._minimimVertexDistance = 0.0 this._ptList = new ArrayList() } var staticAccessors$28 = { COORDINATE_ARRAY_TYPE: { configurable: true } } OffsetSegmentString.prototype.getCoordinates = function getCoordinates () { var coord = this._ptList.toArray(OffsetSegmentString.COORDINATE_ARRAY_TYPE) return coord } OffsetSegmentString.prototype.setPrecisionModel = function setPrecisionModel (precisionModel) { this._precisionModel = precisionModel } OffsetSegmentString.prototype.addPt = function addPt (pt) { var bufPt = new Coordinate(pt) this._precisionModel.makePrecise(bufPt) if (this.isRedundant(bufPt)) { return null } this._ptList.add(bufPt) } OffsetSegmentString.prototype.revere = function revere () { } OffsetSegmentString.prototype.addPts = function addPts (pt, isForward) { var this$1$1 = this if (isForward) { for (var i = 0; i < pt.length; i++) { this$1$1.addPt(pt[i]) } } else { for (var i$1 = pt.length - 1; i$1 >= 0; i$1--) { this$1$1.addPt(pt[i$1]) } } } OffsetSegmentString.prototype.isRedundant = function isRedundant (pt) { if (this._ptList.size() < 1) { return false } var lastPt = this._ptList.get(this._ptList.size() - 1) var ptDist = pt.distance(lastPt) if (ptDist < this._minimimVertexDistance) { return true } return false } OffsetSegmentString.prototype.toString = function toString () { var fact = new GeometryFactory() var line = fact.createLineString(this.getCoordinates()) return line.toString() } OffsetSegmentString.prototype.closeRing = function closeRing () { if (this._ptList.size() < 1) { return null } var startPt = new Coordinate(this._ptList.get(0)) var lastPt = this._ptList.get(this._ptList.size() - 1) // const last2Pt = null // if (this._ptList.size() >= 2) last2Pt = this._ptList.get(this._ptList.size() - 2) if (startPt.equals(lastPt)) { return null } this._ptList.add(startPt) } OffsetSegmentString.prototype.setMinimumVertexDistance = function setMinimumVertexDistance (minimimVertexDistance) { this._minimimVertexDistance = minimimVertexDistance } OffsetSegmentString.prototype.interfaces_ = function interfaces_ () { return [] } OffsetSegmentString.prototype.getClass = function getClass () { return OffsetSegmentString } staticAccessors$28.COORDINATE_ARRAY_TYPE.get = function () { return new Array(0).fill(null) } Object.defineProperties(OffsetSegmentString, staticAccessors$28) var Angle = function Angle () { } var staticAccessors$29 = { PI_TIMES_2: { configurable: true }, PI_OVER_2: { configurable: true }, PI_OVER_4: { configurable: true }, COUNTERCLOCKWISE: { configurable: true }, CLOCKWISE: { configurable: true }, NONE: { configurable: true } } Angle.prototype.interfaces_ = function interfaces_ () { return [] } Angle.prototype.getClass = function getClass () { return Angle } Angle.toDegrees = function toDegrees (radians) { return radians * 180 / Math.PI } Angle.normalize = function normalize (angle) { while (angle > Math.PI) { angle -= Angle.PI_TIMES_2 } while (angle <= -Math.PI) { angle += Angle.PI_TIMES_2 } return angle } Angle.angle = function angle () { if (arguments.length === 1) { var p = arguments[0] return Math.atan2(p.y, p.x) } else if (arguments.length === 2) { var p0 = arguments[0] var p1 = arguments[1] var dx = p1.x - p0.x var dy = p1.y - p0.y return Math.atan2(dy, dx) } } Angle.isAcute = function isAcute (p0, p1, p2) { var dx0 = p0.x - p1.x var dy0 = p0.y - p1.y var dx1 = p2.x - p1.x var dy1 = p2.y - p1.y var dotprod = dx0 * dx1 + dy0 * dy1 return dotprod > 0 } Angle.isObtuse = function isObtuse (p0, p1, p2) { var dx0 = p0.x - p1.x var dy0 = p0.y - p1.y var dx1 = p2.x - p1.x var dy1 = p2.y - p1.y var dotprod = dx0 * dx1 + dy0 * dy1 return dotprod < 0 } Angle.interiorAngle = function interiorAngle (p0, p1, p2) { var anglePrev = Angle.angle(p1, p0) var angleNext = Angle.angle(p1, p2) return Math.abs(angleNext - anglePrev) } Angle.normalizePositive = function normalizePositive (angle) { if (angle < 0.0) { while (angle < 0.0) { angle += Angle.PI_TIMES_2 } if (angle >= Angle.PI_TIMES_2) { angle = 0.0 } } else { while (angle >= Angle.PI_TIMES_2) { angle -= Angle.PI_TIMES_2 } if (angle < 0.0) { angle = 0.0 } } return angle } Angle.angleBetween = function angleBetween (tip1, tail, tip2) { var a1 = Angle.angle(tail, tip1) var a2 = Angle.angle(tail, tip2) return Angle.diff(a1, a2) } Angle.diff = function diff (ang1, ang2) { var delAngle = null if (ang1 < ang2) { delAngle = ang2 - ang1 } else { delAngle = ang1 - ang2 } if (delAngle > Math.PI) { delAngle = 2 * Math.PI - delAngle } return delAngle } Angle.toRadians = function toRadians (angleDegrees) { return angleDegrees * Math.PI / 180.0 } Angle.getTurn = function getTurn (ang1, ang2) { var crossproduct = Math.sin(ang2 - ang1) if (crossproduct > 0) { return Angle.COUNTERCLOCKWISE } if (crossproduct < 0) { return Angle.CLOCKWISE } return Angle.NONE } Angle.angleBetweenOriented = function angleBetweenOriented (tip1, tail, tip2) { var a1 = Angle.angle(tail, tip1) var a2 = Angle.angle(tail, tip2) var angDel = a2 - a1 if (angDel <= -Math.PI) { return angDel + Angle.PI_TIMES_2 } if (angDel > Math.PI) { return angDel - Angle.PI_TIMES_2 } return angDel } staticAccessors$29.PI_TIMES_2.get = function () { return 2.0 * Math.PI } staticAccessors$29.PI_OVER_2.get = function () { return Math.PI / 2.0 } staticAccessors$29.PI_OVER_4.get = function () { return Math.PI / 4.0 } staticAccessors$29.COUNTERCLOCKWISE.get = function () { return CGAlgorithms.COUNTERCLOCKWISE } staticAccessors$29.CLOCKWISE.get = function () { return CGAlgorithms.CLOCKWISE } staticAccessors$29.NONE.get = function () { return CGAlgorithms.COLLINEAR } Object.defineProperties(Angle, staticAccessors$29) var OffsetSegmentGenerator = function OffsetSegmentGenerator () { this._maxCurveSegmentError = 0.0 this._filletAngleQuantum = null this._closingSegLengthFactor = 1 this._segList = null this._distance = 0.0 this._precisionModel = null this._bufParams = null this._li = null this._s0 = null this._s1 = null this._s2 = null this._seg0 = new LineSegment() this._seg1 = new LineSegment() this._offset0 = new LineSegment() this._offset1 = new LineSegment() this._side = 0 this._hasNarrowConcaveAngle = false var precisionModel = arguments[0] var bufParams = arguments[1] var distance = arguments[2] this._precisionModel = precisionModel this._bufParams = bufParams this._li = new RobustLineIntersector() this._filletAngleQuantum = Math.PI / 2.0 / bufParams.getQuadrantSegments() if (bufParams.getQuadrantSegments() >= 8 && bufParams.getJoinStyle() === BufferParameters.JOIN_ROUND) { this._closingSegLengthFactor = OffsetSegmentGenerator.MAX_CLOSING_SEG_LEN_FACTOR } this.init(distance) } var staticAccessors$27 = { OFFSET_SEGMENT_SEPARATION_FACTOR: { configurable: true }, INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR: { configurable: true }, CURVE_VERTEX_SNAP_DISTANCE_FACTOR: { configurable: true }, MAX_CLOSING_SEG_LEN_FACTOR: { configurable: true } } OffsetSegmentGenerator.prototype.addNextSegment = function addNextSegment (p, addStartPoint) { this._s0 = this._s1 this._s1 = this._s2 this._s2 = p this._seg0.setCoordinates(this._s0, this._s1) this.computeOffsetSegment(this._seg0, this._side, this._distance, this._offset0) this._seg1.setCoordinates(this._s1, this._s2) this.computeOffsetSegment(this._seg1, this._side, this._distance, this._offset1) if (this._s1.equals(this._s2)) { return null } var orientation = CGAlgorithms.computeOrientation(this._s0, this._s1, this._s2) var outsideTurn = (orientation === CGAlgorithms.CLOCKWISE && this._side === Position.LEFT) || (orientation === CGAlgorithms.COUNTERCLOCKWISE && this._side === Position.RIGHT) if (orientation === 0) { this.addCollinear(addStartPoint) } else if (outsideTurn) { this.addOutsideTurn(orientation, addStartPoint) } else { this.addInsideTurn(orientation, addStartPoint) } } OffsetSegmentGenerator.prototype.addLineEndCap = function addLineEndCap (p0, p1) { var seg = new LineSegment(p0, p1) var offsetL = new LineSegment() this.computeOffsetSegment(seg, Position.LEFT, this._distance, offsetL) var offsetR = new LineSegment() this.computeOffsetSegment(seg, Position.RIGHT, this._distance, offsetR) var dx = p1.x - p0.x var dy = p1.y - p0.y var angle = Math.atan2(dy, dx) switch (this._bufParams.getEndCapStyle()) { case BufferParameters.CAP_ROUND: this._segList.addPt(offsetL.p1) this.addFilletArc(p1, angle + Math.PI / 2, angle - Math.PI / 2, CGAlgorithms.CLOCKWISE, this._distance) this._segList.addPt(offsetR.p1) break case BufferParameters.CAP_FLAT: this._segList.addPt(offsetL.p1) this._segList.addPt(offsetR.p1) break case BufferParameters.CAP_SQUARE: var squareCapSideOffset = new Coordinate() squareCapSideOffset.x = Math.abs(this._distance) * Math.cos(angle) squareCapSideOffset.y = Math.abs(this._distance) * Math.sin(angle) var squareCapLOffset = new Coordinate(offsetL.p1.x + squareCapSideOffset.x, offsetL.p1.y + squareCapSideOffset.y) var squareCapROffset = new Coordinate(offsetR.p1.x + squareCapSideOffset.x, offsetR.p1.y + squareCapSideOffset.y) this._segList.addPt(squareCapLOffset) this._segList.addPt(squareCapROffset) break } } OffsetSegmentGenerator.prototype.getCoordinates = function getCoordinates () { var pts = this._segList.getCoordinates() return pts } OffsetSegmentGenerator.prototype.addMitreJoin = function addMitreJoin (p, offset0, offset1, distance) { var isMitreWithinLimit = true var intPt = null try { intPt = HCoordinate.intersection(offset0.p0, offset0.p1, offset1.p0, offset1.p1) var mitreRatio = distance <= 0.0 ? 1.0 : intPt.distance(p) / Math.abs(distance) if (mitreRatio > this._bufParams.getMitreLimit()) { isMitreWithinLimit = false } } catch (ex) { if (ex instanceof NotRepresentableException) { intPt = new Coordinate(0, 0) isMitreWithinLimit = false } else { throw ex } } finally { } if (isMitreWithinLimit) { this._segList.addPt(intPt) } else { this.addLimitedMitreJoin(offset0, offset1, distance, this._bufParams.getMitreLimit()) } } OffsetSegmentGenerator.prototype.addFilletCorner = function addFilletCorner (p, p0, p1, direction, radius) { var dx0 = p0.x - p.x var dy0 = p0.y - p.y var startAngle = Math.atan2(dy0, dx0) var dx1 = p1.x - p.x var dy1 = p1.y - p.y var endAngle = Math.atan2(dy1, dx1) if (direction === CGAlgorithms.CLOCKWISE) { if (startAngle <= endAngle) { startAngle += 2.0 * Math.PI } } else { if (startAngle >= endAngle) { startAngle -= 2.0 * Math.PI } } this._segList.addPt(p0) this.addFilletArc(p, startAngle, endAngle, direction, radius) this._segList.addPt(p1) } OffsetSegmentGenerator.prototype.addOutsideTurn = function addOutsideTurn (orientation, addStartPoint) { if (this._offset0.p1.distance(this._offset1.p0) < this._distance * OffsetSegmentGenerator.OFFSET_SEGMENT_SEPARATION_FACTOR) { this._segList.addPt(this._offset0.p1) return null } if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_MITRE) { this.addMitreJoin(this._s1, this._offset0, this._offset1, this._distance) } else if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_BEVEL) { this.addBevelJoin(this._offset0, this._offset1) } else { if (addStartPoint) { this._segList.addPt(this._offset0.p1) } this.addFilletCorner(this._s1, this._offset0.p1, this._offset1.p0, orientation, this._distance) this._segList.addPt(this._offset1.p0) } } OffsetSegmentGenerator.prototype.createSquare = function createSquare (p) { this._segList.addPt(new Coordinate(p.x + this._distance, p.y + this._distance)) this._segList.addPt(new Coordinate(p.x + this._distance, p.y - this._distance)) this._segList.addPt(new Coordinate(p.x - this._distance, p.y - this._distance)) this._segList.addPt(new Coordinate(p.x - this._distance, p.y + this._distance)) this._segList.closeRing() } OffsetSegmentGenerator.prototype.addSegments = function addSegments (pt, isForward) { this._segList.addPts(pt, isForward) } OffsetSegmentGenerator.prototype.addFirstSegment = function addFirstSegment () { this._segList.addPt(this._offset1.p0) } OffsetSegmentGenerator.prototype.addLastSegment = function addLastSegment () { this._segList.addPt(this._offset1.p1) } OffsetSegmentGenerator.prototype.initSideSegments = function initSideSegments (s1, s2, side) { this._s1 = s1 this._s2 = s2 this._side = side this._seg1.setCoordinates(s1, s2) this.computeOffsetSegment(this._seg1, side, this._distance, this._offset1) } OffsetSegmentGenerator.prototype.addLimitedMitreJoin = function addLimitedMitreJoin (offset0, offset1, distance, mitreLimit) { var basePt = this._seg0.p1 var ang0 = Angle.angle(basePt, this._seg0.p0) // const ang1 = Angle.angle(basePt, this._seg1.p1) var angDiff = Angle.angleBetweenOriented(this._seg0.p0, basePt, this._seg1.p1) var angDiffHalf = angDiff / 2 var midAng = Angle.normalize(ang0 + angDiffHalf) var mitreMidAng = Angle.normalize(midAng + Math.PI) var mitreDist = mitreLimit * distance var bevelDelta = mitreDist * Math.abs(Math.sin(angDiffHalf)) var bevelHalfLen = distance - bevelDelta var bevelMidX = basePt.x + mitreDist * Math.cos(mitreMidAng) var bevelMidY = basePt.y + mitreDist * Math.sin(mitreMidAng) var bevelMidPt = new Coordinate(bevelMidX, bevelMidY) var mitreMidLine = new LineSegment(basePt, bevelMidPt) var bevelEndLeft = mitreMidLine.pointAlongOffset(1.0, bevelHalfLen) var bevelEndRight = mitreMidLine.pointAlongOffset(1.0, -bevelHalfLen) if (this._side === Position.LEFT) { this._segList.addPt(bevelEndLeft) this._segList.addPt(bevelEndRight) } else { this._segList.addPt(bevelEndRight) this._segList.addPt(bevelEndLeft) } } OffsetSegmentGenerator.prototype.computeOffsetSegment = function computeOffsetSegment (seg, side, distance, offset) { var sideSign = side === Position.LEFT ? 1 : -1 var dx = seg.p1.x - seg.p0.x var dy = seg.p1.y - seg.p0.y var len = Math.sqrt(dx * dx + dy * dy) var ux = sideSign * distance * dx / len var uy = sideSign * distance * dy / len offset.p0.x = seg.p0.x - uy offset.p0.y = seg.p0.y + ux offset.p1.x = seg.p1.x - uy offset.p1.y = seg.p1.y + ux } OffsetSegmentGenerator.prototype.addFilletArc = function addFilletArc (p, startAngle, endAngle, direction, radius) { var this$1$1 = this var directionFactor = direction === CGAlgorithms.CLOCKWISE ? -1 : 1 var totalAngle = Math.abs(startAngle - endAngle) var nSegs = Math.trunc(totalAngle / this._filletAngleQuantum + 0.5) if (nSegs < 1) { return null } var initAngle = 0.0 var currAngleInc = totalAngle / nSegs var currAngle = initAngle var pt = new Coordinate() while (currAngle < totalAngle) { var angle = startAngle + directionFactor * currAngle pt.x = p.x + radius * Math.cos(angle) pt.y = p.y + radius * Math.sin(angle) this$1$1._segList.addPt(pt) currAngle += currAngleInc } } OffsetSegmentGenerator.prototype.addInsideTurn = function addInsideTurn (orientation, addStartPoint) { this._li.computeIntersection(this._offset0.p0, this._offset0.p1, this._offset1.p0, this._offset1.p1) if (this._li.hasIntersection()) { this._segList.addPt(this._li.getIntersection(0)) } else { this._hasNarrowConcaveAngle = true if (this._offset0.p1.distance(this._offset1.p0) < this._distance * OffsetSegmentGenerator.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR) { this._segList.addPt(this._offset0.p1) } else { this._segList.addPt(this._offset0.p1) if (this._closingSegLengthFactor > 0) { var mid0 = new Coordinate((this._closingSegLengthFactor * this._offset0.p1.x + this._s1.x) / (this._closingSegLengthFactor + 1), (this._closingSegLengthFactor * this._offset0.p1.y + this._s1.y) / (this._closingSegLengthFactor + 1)) this._segList.addPt(mid0) var mid1 = new Coordinate((this._closingSegLengthFactor * this._offset1.p0.x + this._s1.x) / (this._closingSegLengthFactor + 1), (this._closingSegLengthFactor * this._offset1.p0.y + this._s1.y) / (this._closingSegLengthFactor + 1)) this._segList.addPt(mid1) } else { this._segList.addPt(this._s1) } this._segList.addPt(this._offset1.p0) } } } OffsetSegmentGenerator.prototype.createCircle = function createCircle (p) { var pt = new Coordinate(p.x + this._distance, p.y) this._segList.addPt(pt) this.addFilletArc(p, 0.0, 2.0 * Math.PI, -1, this._distance) this._segList.closeRing() } OffsetSegmentGenerator.prototype.addBevelJoin = function addBevelJoin (offset0, offset1) { this._segList.addPt(offset0.p1) this._segList.addPt(offset1.p0) } OffsetSegmentGenerator.prototype.init = function init (distance) { this._distance = distance this._maxCurveSegmentError = distance * (1 - Math.cos(this._filletAngleQuantum / 2.0)) this._segList = new OffsetSegmentString() this._segList.setPrecisionModel(this._precisionModel) this._segList.setMinimumVertexDistance(distance * OffsetSegmentGenerator.CURVE_VERTEX_SNAP_DISTANCE_FACTOR) } OffsetSegmentGenerator.prototype.addCollinear = function addCollinear (addStartPoint) { this._li.computeIntersection(this._s0, this._s1, this._s1, this._s2) var numInt = this._li.getIntersectionNum() if (numInt >= 2) { if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_BEVEL || this._bufParams.getJoinStyle() === BufferParameters.JOIN_MITRE) { if (addStartPoint) { this._segList.addPt(this._offset0.p1) } this._segList.addPt(this._offset1.p0) } else { this.addFilletCorner(this._s1, this._offset0.p1, this._offset1.p0, CGAlgorithms.CLOCKWISE, this._distance) } } } OffsetSegmentGenerator.prototype.closeRing = function closeRing () { this._segList.closeRing() } OffsetSegmentGenerator.prototype.hasNarrowConcaveAngle = function hasNarrowConcaveAngle () { return this._hasNarrowConcaveAngle } OffsetSegmentGenerator.prototype.interfaces_ = function interfaces_ () { return [] } OffsetSegmentGenerator.prototype.getClass = function getClass () { return OffsetSegmentGenerator } staticAccessors$27.OFFSET_SEGMENT_SEPARATION_FACTOR.get = function () { return 1.0E-3 } staticAccessors$27.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR.get = function () { return 1.0E-3 } staticAccessors$27.CURVE_VERTEX_SNAP_DISTANCE_FACTOR.get = function () { return 1.0E-6 } staticAccessors$27.MAX_CLOSING_SEG_LEN_FACTOR.get = function () { return 80 } Object.defineProperties(OffsetSegmentGenerator, staticAccessors$27) var OffsetCurveBuilder = function OffsetCurveBuilder () { this._distance = 0.0 this._precisionModel = null this._bufParams = null var precisionModel = arguments[0] var bufParams = arguments[1] this._precisionModel = precisionModel this._bufParams = bufParams } OffsetCurveBuilder.prototype.getOffsetCurve = function getOffsetCurve (inputPts, distance) { this._distance = distance if (distance === 0.0) { return null } var isRightSide = distance < 0.0 var posDistance = Math.abs(distance) var segGen = this.getSegGen(posDistance) if (inputPts.length <= 1) { this.computePointCurve(inputPts[0], segGen) } else { this.computeOffsetCurve(inputPts, isRightSide, segGen) } var curvePts = segGen.getCoordinates() if (isRightSide) { CoordinateArrays.reverse(curvePts) } return curvePts } OffsetCurveBuilder.prototype.computeSingleSidedBufferCurve = function computeSingleSidedBufferCurve (inputPts, isRightSide, segGen) { var distTol = this.simplifyTolerance(this._distance) if (isRightSide) { segGen.addSegments(inputPts, true) var simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol) var n2 = simp2.length - 1 segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT) segGen.addFirstSegment() for (var i = n2 - 2; i >= 0; i--) { segGen.addNextSegment(simp2[i], true) } } else { segGen.addSegments(inputPts, false) var simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol) var n1 = simp1.length - 1 segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT) segGen.addFirstSegment() for (var i$1 = 2; i$1 <= n1; i$1++) { segGen.addNextSegment(simp1[i$1], true) } } segGen.addLastSegment() segGen.closeRing() } OffsetCurveBuilder.prototype.computeRingBufferCurve = function computeRingBufferCurve (inputPts, side, segGen) { var distTol = this.simplifyTolerance(this._distance) if (side === Position.RIGHT) { distTol = -distTol } var simp = BufferInputLineSimplifier.simplify(inputPts, distTol) var n = simp.length - 1 segGen.initSideSegments(simp[n - 1], simp[0], side) for (var i = 1; i <= n; i++) { var addStartPoint = i !== 1 segGen.addNextSegment(simp[i], addStartPoint) } segGen.closeRing() } OffsetCurveBuilder.prototype.computeLineBufferCurve = function computeLineBufferCurve (inputPts, segGen) { var distTol = this.simplifyTolerance(this._distance) var simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol) var n1 = simp1.length - 1 segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT) for (var i = 2; i <= n1; i++) { segGen.addNextSegment(simp1[i], true) } segGen.addLastSegment() segGen.addLineEndCap(simp1[n1 - 1], simp1[n1]) var simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol) var n2 = simp2.length - 1 segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT) for (var i$1 = n2 - 2; i$1 >= 0; i$1--) { segGen.addNextSegment(simp2[i$1], true) } segGen.addLastSegment() segGen.addLineEndCap(simp2[1], simp2[0]) segGen.closeRing() } OffsetCurveBuilder.prototype.computePointCurve = function computePointCurve (pt, segGen) { switch (this._bufParams.getEndCapStyle()) { case BufferParameters.CAP_ROUND: segGen.createCircle(pt) break case BufferParameters.CAP_SQUARE: segGen.createSquare(pt) break } } OffsetCurveBuilder.prototype.getLineCurve = function getLineCurve (inputPts, distance) { this._distance = distance if (distance < 0.0 && !this._bufParams.isSingleSided()) { return null } if (distance === 0.0) { return null } var posDistance = Math.abs(distance) var segGen = this.getSegGen(posDistance) if (inputPts.length <= 1) { this.computePointCurve(inputPts[0], segGen) } else { if (this._bufParams.isSingleSided()) { var isRightSide = distance < 0.0 this.computeSingleSidedBufferCurve(inputPts, isRightSide, segGen) } else { this.computeLineBufferCurve(inputPts, segGen) } } var lineCoord = segGen.getCoordinates() return lineCoord } OffsetCurveBuilder.prototype.getBufferParameters = function getBufferParameters () { return this._bufParams } OffsetCurveBuilder.prototype.simplifyTolerance = function simplifyTolerance (bufDistance) { return bufDistance * this._bufParams.getSimplifyFactor() } OffsetCurveBuilder.prototype.getRingCurve = function getRingCurve (inputPts, side, distance) { this._distance = distance if (inputPts.length <= 2) { return this.getLineCurve(inputPts, distance) } if (distance === 0.0) { return OffsetCurveBuilder.copyCoordinates(inputPts) } var segGen = this.getSegGen(distance) this.computeRingBufferCurve(inputPts, side, segGen) return segGen.getCoordinates() } OffsetCurveBuilder.prototype.computeOffsetCurve = function computeOffsetCurve (inputPts, isRightSide, segGen) { var distTol = this.simplifyTolerance(this._distance) if (isRightSide) { var simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol) var n2 = simp2.length - 1 segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT) segGen.addFirstSegment() for (var i = n2 - 2; i >= 0; i--) { segGen.addNextSegment(simp2[i], true) } } else { var simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol) var n1 = simp1.length - 1 segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT) segGen.addFirstSegment() for (var i$1 = 2; i$1 <= n1; i$1++) { segGen.addNextSegment(simp1[i$1], true) } } segGen.addLastSegment() } OffsetCurveBuilder.prototype.getSegGen = function getSegGen (distance) { return new OffsetSegmentGenerator(this._precisionModel, this._bufParams, distance) } OffsetCurveBuilder.prototype.interfaces_ = function interfaces_ () { return [] } OffsetCurveBuilder.prototype.getClass = function getClass () { return OffsetCurveBuilder } OffsetCurveBuilder.copyCoordinates = function copyCoordinates (pts) { var copy = new Array(pts.length).fill(null) for (var i = 0; i < copy.length; i++) { copy[i] = new Coordinate(pts[i]) } return copy } var SubgraphDepthLocater = function SubgraphDepthLocater () { this._subgraphs = null this._seg = new LineSegment() this._cga = new CGAlgorithms() var subgraphs = arguments[0] this._subgraphs = subgraphs } var staticAccessors$30 = { DepthSegment: { configurable: true } } SubgraphDepthLocater.prototype.findStabbedSegments = function findStabbedSegments () { var this$1$1 = this if (arguments.length === 1) { var stabbingRayLeftPt = arguments[0] var stabbedSegments = new ArrayList() for (var i = this._subgraphs.iterator(); i.hasNext();) { var bsg = i.next() var env = bsg.getEnvelope() if (stabbingRayLeftPt.y < env.getMinY() || stabbingRayLeftPt.y > env.getMaxY()) { continue } this$1$1.findStabbedSegments(stabbingRayLeftPt, bsg.getDirectedEdges(), stabbedSegments) } return stabbedSegments } else if (arguments.length === 3) { if (hasInterface(arguments[2], List) && (arguments[0] instanceof Coordinate && arguments[1] instanceof DirectedEdge)) { var stabbingRayLeftPt$1 = arguments[0] var dirEdge = arguments[1] var stabbedSegments$1 = arguments[2] var pts = dirEdge.getEdge().getCoordinates() for (var i$1 = 0; i$1 < pts.length - 1; i$1++) { this$1$1._seg.p0 = pts[i$1] this$1$1._seg.p1 = pts[i$1 + 1] if (this$1$1._seg.p0.y > this$1$1._seg.p1.y) { this$1$1._seg.reverse() } var maxx = Math.max(this$1$1._seg.p0.x, this$1$1._seg.p1.x) if (maxx < stabbingRayLeftPt$1.x) { continue } if (this$1$1._seg.isHorizontal()) { continue } if (stabbingRayLeftPt$1.y < this$1$1._seg.p0.y || stabbingRayLeftPt$1.y > this$1$1._seg.p1.y) { continue } if (CGAlgorithms.computeOrientation(this$1$1._seg.p0, this$1$1._seg.p1, stabbingRayLeftPt$1) === CGAlgorithms.RIGHT) { continue } var depth = dirEdge.getDepth(Position.LEFT) if (!this$1$1._seg.p0.equals(pts[i$1])) { depth = dirEdge.getDepth(Position.RIGHT) } var ds = new DepthSegment(this$1$1._seg, depth) stabbedSegments$1.add(ds) } } else if (hasInterface(arguments[2], List) && (arguments[0] instanceof Coordinate && hasInterface(arguments[1], List))) { var stabbingRayLeftPt$2 = arguments[0] var dirEdges = arguments[1] var stabbedSegments$2 = arguments[2] for (var i$2 = dirEdges.iterator(); i$2.hasNext();) { var de = i$2.next() if (!de.isForward()) { continue } this$1$1.findStabbedSegments(stabbingRayLeftPt$2, de, stabbedSegments$2) } } } } SubgraphDepthLocater.prototype.getDepth = function getDepth (p) { var stabbedSegments = this.findStabbedSegments(p) if (stabbedSegments.size() === 0) { return 0 } var ds = Collections.min(stabbedSegments) return ds._leftDepth } SubgraphDepthLocater.prototype.interfaces_ = function interfaces_ () { return [] } SubgraphDepthLocater.prototype.getClass = function getClass () { return SubgraphDepthLocater } staticAccessors$30.DepthSegment.get = function () { return DepthSegment } Object.defineProperties(SubgraphDepthLocater, staticAccessors$30) var DepthSegment = function DepthSegment () { this._upwardSeg = null this._leftDepth = null var seg = arguments[0] var depth = arguments[1] this._upwardSeg = new LineSegment(seg) this._leftDepth = depth } DepthSegment.prototype.compareTo = function compareTo (obj) { var other = obj if (this._upwardSeg.minX() >= other._upwardSeg.maxX()) { return 1 } if (this._upwardSeg.maxX() <= other._upwardSeg.minX()) { return -1 } var orientIndex = this._upwardSeg.orientationIndex(other._upwardSeg) if (orientIndex !== 0) { return orientIndex } orientIndex = -1 * other._upwardSeg.orientationIndex(this._upwardSeg) if (orientIndex !== 0) { return orientIndex } return this._upwardSeg.compareTo(other._upwardSeg) } DepthSegment.prototype.compareX = function compareX (seg0, seg1) { var compare0 = seg0.p0.compareTo(seg1.p0) if (compare0 !== 0) { return compare0 } return seg0.p1.compareTo(seg1.p1) } DepthSegment.prototype.toString = function toString () { return this._upwardSeg.toString() } DepthSegment.prototype.interfaces_ = function interfaces_ () { return [Comparable] } DepthSegment.prototype.getClass = function getClass () { return DepthSegment } var Triangle = function Triangle (p0, p1, p2) { this.p0 = p0 || null this.p1 = p1 || null this.p2 = p2 || null } Triangle.prototype.area = function area () { return Triangle.area(this.p0, this.p1, this.p2) } Triangle.prototype.signedArea = function signedArea () { return Triangle.signedArea(this.p0, this.p1, this.p2) } Triangle.prototype.interpolateZ = function interpolateZ (p) { if (p === null) { throw new IllegalArgumentException('Supplied point is null.') } return Triangle.interpolateZ(p, this.p0, this.p1, this.p2) } Triangle.prototype.longestSideLength = function longestSideLength () { return Triangle.longestSideLength(this.p0, this.p1, this.p2) } Triangle.prototype.isAcute = function isAcute () { return Triangle.isAcute(this.p0, this.p1, this.p2) } Triangle.prototype.circumcentre = function circumcentre () { return Triangle.circumcentre(this.p0, this.p1, this.p2) } Triangle.prototype.area3D = function area3D () { return Triangle.area3D(this.p0, this.p1, this.p2) } Triangle.prototype.centroid = function centroid () { return Triangle.centroid(this.p0, this.p1, this.p2) } Triangle.prototype.inCentre = function inCentre () { return Triangle.inCentre(this.p0, this.p1, this.p2) } Triangle.prototype.interfaces_ = function interfaces_ () { return [] } Triangle.prototype.getClass = function getClass () { return Triangle } Triangle.area = function area (a, b, c) { return Math.abs(((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2) } Triangle.signedArea = function signedArea (a, b, c) { return ((c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y)) / 2 } Triangle.det = function det (m00, m01, m10, m11) { return m00 * m11 - m01 * m10 } Triangle.interpolateZ = function interpolateZ (p, v0, v1, v2) { var x0 = v0.x var y0 = v0.y var a = v1.x - x0 var b = v2.x - x0 var c = v1.y - y0 var d = v2.y - y0 var det = a * d - b * c var dx = p.x - x0 var dy = p.y - y0 var t = (d * dx - b * dy) / det var u = (-c * dx + a * dy) / det var z = v0.z + t * (v1.z - v0.z) + u * (v2.z - v0.z) return z } Triangle.longestSideLength = function longestSideLength (a, b, c) { var lenAB = a.distance(b) var lenBC = b.distance(c) var lenCA = c.distance(a) var maxLen = lenAB if (lenBC > maxLen) { maxLen = lenBC } if (lenCA > maxLen) { maxLen = lenCA } return maxLen } Triangle.isAcute = function isAcute (a, b, c) { if (!Angle.isAcute(a, b, c)) { return false } if (!Angle.isAcute(b, c, a)) { return false } if (!Angle.isAcute(c, a, b)) { return false } return true } Triangle.circumcentre = function circumcentre (a, b, c) { var cx = c.x var cy = c.y var ax = a.x - cx var ay = a.y - cy var bx = b.x - cx var by = b.y - cy var denom = 2 * Triangle.det(ax, ay, bx, by) var numx = Triangle.det(ay, ax * ax + ay * ay, by, bx * bx + by * by) var numy = Triangle.det(ax, ax * ax + ay * ay, bx, bx * bx + by * by) var ccx = cx - numx / denom var ccy = cy + numy / denom return new Coordinate(ccx, ccy) } Triangle.perpendicularBisector = function perpendicularBisector (a, b) { var dx = b.x - a.x var dy = b.y - a.y var l1 = new HCoordinate(a.x + dx / 2.0, a.y + dy / 2.0, 1.0) var l2 = new HCoordinate(a.x - dy + dx / 2.0, a.y + dx + dy / 2.0, 1.0) return new HCoordinate(l1, l2) } Triangle.angleBisector = function angleBisector (a, b, c) { var len0 = b.distance(a) var len2 = b.distance(c) var frac = len0 / (len0 + len2) var dx = c.x - a.x var dy = c.y - a.y var splitPt = new Coordinate(a.x + frac * dx, a.y + frac * dy) return splitPt } Triangle.area3D = function area3D (a, b, c) { var ux = b.x - a.x var uy = b.y - a.y var uz = b.z - a.z var vx = c.x - a.x var vy = c.y - a.y var vz = c.z - a.z var crossx = uy * vz - uz * vy var crossy = uz * vx - ux * vz var crossz = ux * vy - uy * vx var absSq = crossx * crossx + crossy * crossy + crossz * crossz var area3D = Math.sqrt(absSq) / 2 return area3D } Triangle.centroid = function centroid (a, b, c) { var x = (a.x + b.x + c.x) / 3 var y = (a.y + b.y + c.y) / 3 return new Coordinate(x, y) } Triangle.inCentre = function inCentre (a, b, c) { var len0 = b.distance(c) var len1 = a.distance(c) var len2 = a.distance(b) var circum = len0 + len1 + len2 var inCentreX = (len0 * a.x + len1 * b.x + len2 * c.x) / circum var inCentreY = (len0 * a.y + len1 * b.y + len2 * c.y) / circum return new Coordinate(inCentreX, inCentreY) } var OffsetCurveSetBuilder = function OffsetCurveSetBuilder () { this._inputGeom = null this._distance = null this._curveBuilder = null this._curveList = new ArrayList() var inputGeom = arguments[0] var distance = arguments[1] var curveBuilder = arguments[2] this._inputGeom = inputGeom this._distance = distance this._curveBuilder = curveBuilder } OffsetCurveSetBuilder.prototype.addPoint = function addPoint (p) { if (this._distance <= 0.0) { return null } var coord = p.getCoordinates() var curve = this._curveBuilder.getLineCurve(coord, this._distance) this.addCurve(curve, Location.EXTERIOR, Location.INTERIOR) } OffsetCurveSetBuilder.prototype.addPolygon = function addPolygon (p) { var this$1$1 = this var offsetDistance = this._distance var offsetSide = Position.LEFT if (this._distance < 0.0) { offsetDistance = -this._distance offsetSide = Position.RIGHT } var shell = p.getExteriorRing() var shellCoord = CoordinateArrays.removeRepeatedPoints(shell.getCoordinates()) if (this._distance < 0.0 && this.isErodedCompletely(shell, this._distance)) { return null } if (this._distance <= 0.0 && shellCoord.length < 3) { return null } this.addPolygonRing(shellCoord, offsetDistance, offsetSide, Location.EXTERIOR, Location.INTERIOR) for (var i = 0; i < p.getNumInteriorRing(); i++) { var hole = p.getInteriorRingN(i) var holeCoord = CoordinateArrays.removeRepeatedPoints(hole.getCoordinates()) if (this$1$1._distance > 0.0 && this$1$1.isErodedCompletely(hole, -this$1$1._distance)) { continue } this$1$1.addPolygonRing(holeCoord, offsetDistance, Position.opposite(offsetSide), Location.INTERIOR, Location.EXTERIOR) } } OffsetCurveSetBuilder.prototype.isTriangleErodedCompletely = function isTriangleErodedCompletely (triangleCoord, bufferDistance) { var tri = new Triangle(triangleCoord[0], triangleCoord[1], triangleCoord[2]) var inCentre = tri.inCentre() var distToCentre = CGAlgorithms.distancePointLine(inCentre, tri.p0, tri.p1) return distToCentre < Math.abs(bufferDistance) } OffsetCurveSetBuilder.prototype.addLineString = function addLineString (line) { if (this._distance <= 0.0 && !this._curveBuilder.getBufferParameters().isSingleSided()) { return null } var coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates()) var curve = this._curveBuilder.getLineCurve(coord, this._distance) this.addCurve(curve, Location.EXTERIOR, Location.INTERIOR) } OffsetCurveSetBuilder.prototype.addCurve = function addCurve (coord, leftLoc, rightLoc) { if (coord === null || coord.length < 2) { return null } var e = new NodedSegmentString(coord, new Label(0, Location.BOUNDARY, leftLoc, rightLoc)) this._curveList.add(e) } OffsetCurveSetBuilder.prototype.getCurves = function getCurves () { this.add(this._inputGeom) return this._curveList } OffsetCurveSetBuilder.prototype.addPolygonRing = function addPolygonRing (coord, offsetDistance, side, cwLeftLoc, cwRightLoc) { if (offsetDistance === 0.0 && coord.length < LinearRing.MINIMUM_VALID_SIZE) { return null } var leftLoc = cwLeftLoc var rightLoc = cwRightLoc if (coord.length >= LinearRing.MINIMUM_VALID_SIZE && CGAlgorithms.isCCW(coord)) { leftLoc = cwRightLoc rightLoc = cwLeftLoc side = Position.opposite(side) } var curve = this._curveBuilder.getRingCurve(coord, side, offsetDistance) this.addCurve(curve, leftLoc, rightLoc) } OffsetCurveSetBuilder.prototype.add = function add (g) { if (g.isEmpty()) { return null } if (g instanceof Polygon) { this.addPolygon(g) } else if (g instanceof LineString) { this.addLineString(g) } else if (g instanceof Point) { this.addPoint(g) } else if (g instanceof MultiPoint) { this.addCollection(g) } else if (g instanceof MultiLineString) { this.addCollection(g) } else if (g instanceof MultiPolygon) { this.addCollection(g) } else if (g instanceof GeometryCollection) { this.addCollection(g) } // else throw new UnsupportedOperationException(g.getClass().getName()) } OffsetCurveSetBuilder.prototype.isErodedCompletely = function isErodedCompletely (ring, bufferDistance) { var ringCoord = ring.getCoordinates() // const minDiam = 0.0 if (ringCoord.length < 4) { return bufferDistance < 0 } if (ringCoord.length === 4) { return this.isTriangleErodedCompletely(ringCoord, bufferDistance) } var env = ring.getEnvelopeInternal() var envMinDimension = Math.min(env.getHeight(), env.getWidth()) if (bufferDistance < 0.0 && 2 * Math.abs(bufferDistance) > envMinDimension) { return true } return false } OffsetCurveSetBuilder.prototype.addCollection = function addCollection (gc) { var this$1$1 = this for (var i = 0; i < gc.getNumGeometries(); i++) { var g = gc.getGeometryN(i) this$1$1.add(g) } } OffsetCurveSetBuilder.prototype.interfaces_ = function interfaces_ () { return [] } OffsetCurveSetBuilder.prototype.getClass = function getClass () { return OffsetCurveSetBuilder } var PointOnGeometryLocator = function PointOnGeometryLocator () { } PointOnGeometryLocator.prototype.locate = function locate (p) { } PointOnGeometryLocator.prototype.interfaces_ = function interfaces_ () { return [] } PointOnGeometryLocator.prototype.getClass = function getClass () { return PointOnGeometryLocator } var GeometryCollectionIterator = function GeometryCollectionIterator () { this._parent = null this._atStart = null this._max = null this._index = null this._subcollectionIterator = null var parent = arguments[0] this._parent = parent this._atStart = true this._index = 0 this._max = parent.getNumGeometries() } GeometryCollectionIterator.prototype.next = function next () { if (this._atStart) { this._atStart = false if (GeometryCollectionIterator.isAtomic(this._parent)) { this._index++ } return this._parent } if (this._subcollectionIterator !== null) { if (this._subcollectionIterator.hasNext()) { return this._subcollectionIterator.next() } else { this._subcollectionIterator = null } } if (this._index >= this._max) { throw new NoSuchElementException() } var obj = this._parent.getGeometryN(this._index++) if (obj instanceof GeometryCollection) { this._subcollectionIterator = new GeometryCollectionIterator(obj) return this._subcollectionIterator.next() } return obj } GeometryCollectionIterator.prototype.remove = function remove () { throw new Error(this.getClass().getName()) } GeometryCollectionIterator.prototype.hasNext = function hasNext () { if (this._atStart) { return true } if (this._subcollectionIterator !== null) { if (this._subcollectionIterator.hasNext()) { return true } this._subcollectionIterator = null } if (this._index >= this._max) { return false } return true } GeometryCollectionIterator.prototype.interfaces_ = function interfaces_ () { return [Iterator] } GeometryCollectionIterator.prototype.getClass = function getClass () { return GeometryCollectionIterator } GeometryCollectionIterator.isAtomic = function isAtomic (geom) { return !(geom instanceof GeometryCollection) } var SimplePointInAreaLocator = function SimplePointInAreaLocator () { this._geom = null var geom = arguments[0] this._geom = geom } SimplePointInAreaLocator.prototype.locate = function locate (p) { return SimplePointInAreaLocator.locate(p, this._geom) } SimplePointInAreaLocator.prototype.interfaces_ = function interfaces_ () { return [PointOnGeometryLocator] } SimplePointInAreaLocator.prototype.getClass = function getClass () { return SimplePointInAreaLocator } SimplePointInAreaLocator.isPointInRing = function isPointInRing (p, ring) { if (!ring.getEnvelopeInternal().intersects(p)) { return false } return CGAlgorithms.isPointInRing(p, ring.getCoordinates()) } SimplePointInAreaLocator.containsPointInPolygon = function containsPointInPolygon (p, poly) { if (poly.isEmpty()) { return false } var shell = poly.getExteriorRing() if (!SimplePointInAreaLocator.isPointInRing(p, shell)) { return false } for (var i = 0; i < poly.getNumInteriorRing(); i++) { var hole = poly.getInteriorRingN(i) if (SimplePointInAreaLocator.isPointInRing(p, hole)) { return false } } return true } SimplePointInAreaLocator.containsPoint = function containsPoint (p, geom) { if (geom instanceof Polygon) { return SimplePointInAreaLocator.containsPointInPolygon(p, geom) } else if (geom instanceof GeometryCollection) { var geomi = new GeometryCollectionIterator(geom) while (geomi.hasNext()) { var g2 = geomi.next() if (g2 !== geom) { if (SimplePointInAreaLocator.containsPoint(p, g2)) { return true } } } } return false } SimplePointInAreaLocator.locate = function locate (p, geom) { if (geom.isEmpty()) { return Location.EXTERIOR } if (SimplePointInAreaLocator.containsPoint(p, geom)) { return Location.INTERIOR } return Location.EXTERIOR } var EdgeEndStar = function EdgeEndStar () { this._edgeMap = new TreeMap() this._edgeList = null this._ptInAreaLocation = [Location.NONE, Location.NONE] } EdgeEndStar.prototype.getNextCW = function getNextCW (ee) { this.getEdges() var i = this._edgeList.indexOf(ee) var iNextCW = i - 1 if (i === 0) { iNextCW = this._edgeList.size() - 1 } return this._edgeList.get(iNextCW) } EdgeEndStar.prototype.propagateSideLabels = function propagateSideLabels (geomIndex) { var startLoc = Location.NONE for (var it = this.iterator(); it.hasNext();) { var e = it.next() var label = e.getLabel() if (label.isArea(geomIndex) && label.getLocation(geomIndex, Position.LEFT) !== Location.NONE) { startLoc = label.getLocation(geomIndex, Position.LEFT) } } if (startLoc === Location.NONE) { return null } var currLoc = startLoc for (var it$1 = this.iterator(); it$1.hasNext();) { var e$1 = it$1.next() var label$1 = e$1.getLabel() if (label$1.getLocation(geomIndex, Position.ON) === Location.NONE) { label$1.setLocation(geomIndex, Position.ON, currLoc) } if (label$1.isArea(geomIndex)) { var leftLoc = label$1.getLocation(geomIndex, Position.LEFT) var rightLoc = label$1.getLocation(geomIndex, Position.RIGHT) if (rightLoc !== Location.NONE) { if (rightLoc !== currLoc) { throw new TopologyException('side location conflict', e$1.getCoordinate()) } if (leftLoc === Location.NONE) { Assert.shouldNeverReachHere('found single null side (at ' + e$1.getCoordinate() + ')') } currLoc = leftLoc } else { Assert.isTrue(label$1.getLocation(geomIndex, Position.LEFT) === Location.NONE, 'found single null side') label$1.setLocation(geomIndex, Position.RIGHT, currLoc) label$1.setLocation(geomIndex, Position.LEFT, currLoc) } } } } EdgeEndStar.prototype.getCoordinate = function getCoordinate () { var it = this.iterator() if (!it.hasNext()) { return null } var e = it.next() return e.getCoordinate() } EdgeEndStar.prototype.print = function print (out) { System.out.println('EdgeEndStar: ' + this.getCoordinate()) for (var it = this.iterator(); it.hasNext();) { var e = it.next() e.print(out) } } EdgeEndStar.prototype.isAreaLabelsConsistent = function isAreaLabelsConsistent (geomGraph) { this.computeEdgeEndLabels(geomGraph.getBoundaryNodeRule()) return this.checkAreaLabelsConsistent(0) } EdgeEndStar.prototype.checkAreaLabelsConsistent = function checkAreaLabelsConsistent (geomIndex) { var edges = this.getEdges() if (edges.size() <= 0) { return true } var lastEdgeIndex = edges.size() - 1 var startLabel = edges.get(lastEdgeIndex).getLabel() var startLoc = startLabel.getLocation(geomIndex, Position.LEFT) Assert.isTrue(startLoc !== Location.NONE, 'Found unlabelled area edge') var currLoc = startLoc for (var it = this.iterator(); it.hasNext();) { var e = it.next() var label = e.getLabel() Assert.isTrue(label.isArea(geomIndex), 'Found non-area edge') var leftLoc = label.getLocation(geomIndex, Position.LEFT) var rightLoc = label.getLocation(geomIndex, Position.RIGHT) if (leftLoc === rightLoc) { return false } if (rightLoc !== currLoc) { return false } currLoc = leftLoc } return true } EdgeEndStar.prototype.findIndex = function findIndex (eSearch) { var this$1$1 = this this.iterator() for (var i = 0; i < this._edgeList.size(); i++) { var e = this$1$1._edgeList.get(i) if (e === eSearch) { return i } } return -1 } EdgeEndStar.prototype.iterator = function iterator () { return this.getEdges().iterator() } EdgeEndStar.prototype.getEdges = function getEdges () { if (this._edgeList === null) { this._edgeList = new ArrayList(this._edgeMap.values()) } return this._edgeList } EdgeEndStar.prototype.getLocation = function getLocation (geomIndex, p, geom) { if (this._ptInAreaLocation[geomIndex] === Location.NONE) { this._ptInAreaLocation[geomIndex] = SimplePointInAreaLocator.locate(p, geom[geomIndex].getGeometry()) } return this._ptInAreaLocation[geomIndex] } EdgeEndStar.prototype.toString = function toString () { var buf = new StringBuffer() buf.append('EdgeEndStar: ' + this.getCoordinate()) buf.append('\n') for (var it = this.iterator(); it.hasNext();) { var e = it.next() buf.append(e) buf.append('\n') } return buf.toString() } EdgeEndStar.prototype.computeEdgeEndLabels = function computeEdgeEndLabels (boundaryNodeRule) { for (var it = this.iterator(); it.hasNext();) { var ee = it.next() ee.computeLabel(boundaryNodeRule) } } EdgeEndStar.prototype.computeLabelling = function computeLabelling (geomGraph) { var this$1$1 = this this.computeEdgeEndLabels(geomGraph[0].getBoundaryNodeRule()) this.propagateSideLabels(0) this.propagateSideLabels(1) var hasDimensionalCollapseEdge = [false, false] for (var it = this.iterator(); it.hasNext();) { var e = it.next() var label = e.getLabel() for (var geomi = 0; geomi < 2; geomi++) { if (label.isLine(geomi) && label.getLocation(geomi) === Location.BOUNDARY) { hasDimensionalCollapseEdge[geomi] = true } } } for (var it$1 = this.iterator(); it$1.hasNext();) { var e$1 = it$1.next() var label$1 = e$1.getLabel() for (var geomi$1 = 0; geomi$1 < 2; geomi$1++) { if (label$1.isAnyNull(geomi$1)) { var loc = Location.NONE if (hasDimensionalCollapseEdge[geomi$1]) { loc = Location.EXTERIOR } else { var p = e$1.getCoordinate() loc = this$1$1.getLocation(geomi$1, p, geomGraph) } label$1.setAllLocationsIfNull(geomi$1, loc) } } } } EdgeEndStar.prototype.getDegree = function getDegree () { return this._edgeMap.size() } EdgeEndStar.prototype.insertEdgeEnd = function insertEdgeEnd (e, obj) { this._edgeMap.put(e, obj) this._edgeList = null } EdgeEndStar.prototype.interfaces_ = function interfaces_ () { return [] } EdgeEndStar.prototype.getClass = function getClass () { return EdgeEndStar } var DirectedEdgeStar = (function (EdgeEndStar$$1) { function DirectedEdgeStar () { EdgeEndStar$$1.call(this) this._resultAreaEdgeList = null this._label = null this._SCANNING_FOR_INCOMING = 1 this._LINKING_TO_OUTGOING = 2 } if (EdgeEndStar$$1) DirectedEdgeStar.__proto__ = EdgeEndStar$$1 DirectedEdgeStar.prototype = Object.create(EdgeEndStar$$1 && EdgeEndStar$$1.prototype) DirectedEdgeStar.prototype.constructor = DirectedEdgeStar DirectedEdgeStar.prototype.linkResultDirectedEdges = function linkResultDirectedEdges () { var this$1$1 = this this.getResultAreaEdges() var firstOut = null var incoming = null var state = this._SCANNING_FOR_INCOMING for (var i = 0; i < this._resultAreaEdgeList.size(); i++) { var nextOut = this$1$1._resultAreaEdgeList.get(i) var nextIn = nextOut.getSym() if (!nextOut.getLabel().isArea()) { continue } if (firstOut === null && nextOut.isInResult()) { firstOut = nextOut } switch (state) { case this$1$1._SCANNING_FOR_INCOMING: if (!nextIn.isInResult()) { continue } incoming = nextIn state = this$1$1._LINKING_TO_OUTGOING break case this$1$1._LINKING_TO_OUTGOING: if (!nextOut.isInResult()) { continue } incoming.setNext(nextOut) state = this$1$1._SCANNING_FOR_INCOMING break } } if (state === this._LINKING_TO_OUTGOING) { if (firstOut === null) { throw new TopologyException('no outgoing dirEdge found', this.getCoordinate()) } Assert.isTrue(firstOut.isInResult(), 'unable to link last incoming dirEdge') incoming.setNext(firstOut) } } DirectedEdgeStar.prototype.insert = function insert (ee) { var de = ee this.insertEdgeEnd(de, de) } DirectedEdgeStar.prototype.getRightmostEdge = function getRightmostEdge () { var edges = this.getEdges() var size = edges.size() if (size < 1) { return null } var de0 = edges.get(0) if (size === 1) { return de0 } var deLast = edges.get(size - 1) var quad0 = de0.getQuadrant() var quad1 = deLast.getQuadrant() if (Quadrant.isNorthern(quad0) && Quadrant.isNorthern(quad1)) { return de0 } else if (!Quadrant.isNorthern(quad0) && !Quadrant.isNorthern(quad1)) { return deLast } else { // const nonHorizontalEdge = null if (de0.getDy() !== 0) { return de0 } else if (deLast.getDy() !== 0) { return deLast } } Assert.shouldNeverReachHere('found two horizontal edges incident on node') return null } DirectedEdgeStar.prototype.print = function print (out) { System.out.println('DirectedEdgeStar: ' + this.getCoordinate()) for (var it = this.iterator(); it.hasNext();) { var de = it.next() out.print('out ') de.print(out) out.println() out.print('in ') de.getSym().print(out) out.println() } } DirectedEdgeStar.prototype.getResultAreaEdges = function getResultAreaEdges () { var this$1$1 = this if (this._resultAreaEdgeList !== null) { return this._resultAreaEdgeList } this._resultAreaEdgeList = new ArrayList() for (var it = this.iterator(); it.hasNext();) { var de = it.next() if (de.isInResult() || de.getSym().isInResult()) { this$1$1._resultAreaEdgeList.add(de) } } return this._resultAreaEdgeList } DirectedEdgeStar.prototype.updateLabelling = function updateLabelling (nodeLabel) { for (var it = this.iterator(); it.hasNext();) { var de = it.next() var label = de.getLabel() label.setAllLocationsIfNull(0, nodeLabel.getLocation(0)) label.setAllLocationsIfNull(1, nodeLabel.getLocation(1)) } } DirectedEdgeStar.prototype.linkAllDirectedEdges = function linkAllDirectedEdges () { var this$1$1 = this this.getEdges() var prevOut = null var firstIn = null for (var i = this._edgeList.size() - 1; i >= 0; i--) { var nextOut = this$1$1._edgeList.get(i) var nextIn = nextOut.getSym() if (firstIn === null) { firstIn = nextIn } if (prevOut !== null) { nextIn.setNext(prevOut) } prevOut = nextOut } firstIn.setNext(prevOut) } DirectedEdgeStar.prototype.computeDepths = function computeDepths () { var this$1$1 = this if (arguments.length === 1) { var de = arguments[0] var edgeIndex = this.findIndex(de) // const label = de.getLabel() var startDepth = de.getDepth(Position.LEFT) var targetLastDepth = de.getDepth(Position.RIGHT) var nextDepth = this.computeDepths(edgeIndex + 1, this._edgeList.size(), startDepth) var lastDepth = this.computeDepths(0, edgeIndex, nextDepth) if (lastDepth !== targetLastDepth) { throw new TopologyException('depth mismatch at ' + de.getCoordinate()) } } else if (arguments.length === 3) { var startIndex = arguments[0] var endIndex = arguments[1] var startDepth$1 = arguments[2] var currDepth = startDepth$1 for (var i = startIndex; i < endIndex; i++) { var nextDe = this$1$1._edgeList.get(i) // const label = nextDe.getLabel() nextDe.setEdgeDepths(Position.RIGHT, currDepth) currDepth = nextDe.getDepth(Position.LEFT) } return currDepth } } DirectedEdgeStar.prototype.mergeSymLabels = function mergeSymLabels () { for (var it = this.iterator(); it.hasNext();) { var de = it.next() var label = de.getLabel() label.merge(de.getSym().getLabel()) } } DirectedEdgeStar.prototype.linkMinimalDirectedEdges = function linkMinimalDirectedEdges (er) { var this$1$1 = this var firstOut = null var incoming = null var state = this._SCANNING_FOR_INCOMING for (var i = this._resultAreaEdgeList.size() - 1; i >= 0; i--) { var nextOut = this$1$1._resultAreaEdgeList.get(i) var nextIn = nextOut.getSym() if (firstOut === null && nextOut.getEdgeRing() === er) { firstOut = nextOut } switch (state) { case this$1$1._SCANNING_FOR_INCOMING: if (nextIn.getEdgeRing() !== er) { continue } incoming = nextIn state = this$1$1._LINKING_TO_OUTGOING break case this$1$1._LINKING_TO_OUTGOING: if (nextOut.getEdgeRing() !== er) { continue } incoming.setNextMin(nextOut) state = this$1$1._SCANNING_FOR_INCOMING break } } if (state === this._LINKING_TO_OUTGOING) { Assert.isTrue(firstOut !== null, 'found null for first outgoing dirEdge') Assert.isTrue(firstOut.getEdgeRing() === er, 'unable to link last incoming dirEdge') incoming.setNextMin(firstOut) } } DirectedEdgeStar.prototype.getOutgoingDegree = function getOutgoingDegree () { if (arguments.length === 0) { var degree = 0 for (var it = this.iterator(); it.hasNext();) { var de = it.next() if (de.isInResult()) { degree++ } } return degree } else if (arguments.length === 1) { var er = arguments[0] var degree$1 = 0 for (var it$1 = this.iterator(); it$1.hasNext();) { var de$1 = it$1.next() if (de$1.getEdgeRing() === er) { degree$1++ } } return degree$1 } } DirectedEdgeStar.prototype.getLabel = function getLabel () { return this._label } DirectedEdgeStar.prototype.findCoveredLineEdges = function findCoveredLineEdges () { var startLoc = Location.NONE for (var it = this.iterator(); it.hasNext();) { var nextOut = it.next() var nextIn = nextOut.getSym() if (!nextOut.isLineEdge()) { if (nextOut.isInResult()) { startLoc = Location.INTERIOR break } if (nextIn.isInResult()) { startLoc = Location.EXTERIOR break } } } if (startLoc === Location.NONE) { return null } var currLoc = startLoc for (var it$1 = this.iterator(); it$1.hasNext();) { var nextOut$1 = it$1.next() var nextIn$1 = nextOut$1.getSym() if (nextOut$1.isLineEdge()) { nextOut$1.getEdge().setCovered(currLoc === Location.INTERIOR) } else { if (nextOut$1.isInResult()) { currLoc = Location.EXTERIOR } if (nextIn$1.isInResult()) { currLoc = Location.INTERIOR } } } } DirectedEdgeStar.prototype.computeLabelling = function computeLabelling (geom) { var this$1$1 = this EdgeEndStar$$1.prototype.computeLabelling.call(this, geom) this._label = new Label(Location.NONE) for (var it = this.iterator(); it.hasNext();) { var ee = it.next() var e = ee.getEdge() var eLabel = e.getLabel() for (var i = 0; i < 2; i++) { var eLoc = eLabel.getLocation(i) if (eLoc === Location.INTERIOR || eLoc === Location.BOUNDARY) { this$1$1._label.setLocation(i, Location.INTERIOR) } } } } DirectedEdgeStar.prototype.interfaces_ = function interfaces_ () { return [] } DirectedEdgeStar.prototype.getClass = function getClass () { return DirectedEdgeStar } return DirectedEdgeStar }(EdgeEndStar)) var OverlayNodeFactory = (function (NodeFactory$$1) { function OverlayNodeFactory () { NodeFactory$$1.apply(this, arguments) } if (NodeFactory$$1) OverlayNodeFactory.__proto__ = NodeFactory$$1 OverlayNodeFactory.prototype = Object.create(NodeFactory$$1 && NodeFactory$$1.prototype) OverlayNodeFactory.prototype.constructor = OverlayNodeFactory OverlayNodeFactory.prototype.createNode = function createNode (coord) { return new Node(coord, new DirectedEdgeStar()) } OverlayNodeFactory.prototype.interfaces_ = function interfaces_ () { return [] } OverlayNodeFactory.prototype.getClass = function getClass () { return OverlayNodeFactory } return OverlayNodeFactory }(NodeFactory)) var OrientedCoordinateArray = function OrientedCoordinateArray () { this._pts = null this._orientation = null var pts = arguments[0] this._pts = pts this._orientation = OrientedCoordinateArray.orientation(pts) } OrientedCoordinateArray.prototype.compareTo = function compareTo (o1) { var oca = o1 var comp = OrientedCoordinateArray.compareOriented(this._pts, this._orientation, oca._pts, oca._orientation) return comp } OrientedCoordinateArray.prototype.interfaces_ = function interfaces_ () { return [Comparable] } OrientedCoordinateArray.prototype.getClass = function getClass () { return OrientedCoordinateArray } OrientedCoordinateArray.orientation = function orientation (pts) { return CoordinateArrays.increasingDirection(pts) === 1 } OrientedCoordinateArray.compareOriented = function compareOriented (pts1, orientation1, pts2, orientation2) { var dir1 = orientation1 ? 1 : -1 var dir2 = orientation2 ? 1 : -1 var limit1 = orientation1 ? pts1.length : -1 var limit2 = orientation2 ? pts2.length : -1 var i1 = orientation1 ? 0 : pts1.length - 1 var i2 = orientation2 ? 0 : pts2.length - 1 // const comp = 0 while (true) { var compPt = pts1[i1].compareTo(pts2[i2]) if (compPt !== 0) { return compPt } i1 += dir1 i2 += dir2 var done1 = i1 === limit1 var done2 = i2 === limit2 if (done1 && !done2) { return -1 } if (!done1 && done2) { return 1 } if (done1 && done2) { return 0 } } } var EdgeList = function EdgeList () { this._edges = new ArrayList() this._ocaMap = new TreeMap() } EdgeList.prototype.print = function print (out) { var this$1$1 = this out.print('MULTILINESTRING ( ') for (var j = 0; j < this._edges.size(); j++) { var e = this$1$1._edges.get(j) if (j > 0) { out.print(',') } out.print('(') var pts = e.getCoordinates() for (var i = 0; i < pts.length; i++) { if (i > 0) { out.print(',') } out.print(pts[i].x + ' ' + pts[i].y) } out.println(')') } out.print(') ') } EdgeList.prototype.addAll = function addAll (edgeColl) { var this$1$1 = this for (var i = edgeColl.iterator(); i.hasNext();) { this$1$1.add(i.next()) } } EdgeList.prototype.findEdgeIndex = function findEdgeIndex (e) { var this$1$1 = this for (var i = 0; i < this._edges.size(); i++) { if (this$1$1._edges.get(i).equals(e)) { return i } } return -1 } EdgeList.prototype.iterator = function iterator () { return this._edges.iterator() } EdgeList.prototype.getEdges = function getEdges () { return this._edges } EdgeList.prototype.get = function get (i) { return this._edges.get(i) } EdgeList.prototype.findEqualEdge = function findEqualEdge (e) { var oca = new OrientedCoordinateArray(e.getCoordinates()) var matchEdge = this._ocaMap.get(oca) return matchEdge } EdgeList.prototype.add = function add (e) { this._edges.add(e) var oca = new OrientedCoordinateArray(e.getCoordinates()) this._ocaMap.put(oca, e) } EdgeList.prototype.interfaces_ = function interfaces_ () { return [] } EdgeList.prototype.getClass = function getClass () { return EdgeList } var SegmentIntersector = function SegmentIntersector () { } SegmentIntersector.prototype.processIntersections = function processIntersections (e0, segIndex0, e1, segIndex1) { } SegmentIntersector.prototype.isDone = function isDone () { } SegmentIntersector.prototype.interfaces_ = function interfaces_ () { return [] } SegmentIntersector.prototype.getClass = function getClass () { return SegmentIntersector } var IntersectionAdder = function IntersectionAdder () { this._hasIntersection = false this._hasProper = false this._hasProperInterior = false this._hasInterior = false this._properIntersectionPoint = null this._li = null this._isSelfIntersection = null this.numIntersections = 0 this.numInteriorIntersections = 0 this.numProperIntersections = 0 this.numTests = 0 var li = arguments[0] this._li = li } IntersectionAdder.prototype.isTrivialIntersection = function isTrivialIntersection (e0, segIndex0, e1, segIndex1) { if (e0 === e1) { if (this._li.getIntersectionNum() === 1) { if (IntersectionAdder.isAdjacentSegments(segIndex0, segIndex1)) { return true } if (e0.isClosed()) { var maxSegIndex = e0.size() - 1 if ((segIndex0 === 0 && segIndex1 === maxSegIndex) || (segIndex1 === 0 && segIndex0 === maxSegIndex)) { return true } } } } return false } IntersectionAdder.prototype.getProperIntersectionPoint = function getProperIntersectionPoint () { return this._properIntersectionPoint } IntersectionAdder.prototype.hasProperInteriorIntersection = function hasProperInteriorIntersection () { return this._hasProperInterior } IntersectionAdder.prototype.getLineIntersector = function getLineIntersector () { return this._li } IntersectionAdder.prototype.hasProperIntersection = function hasProperIntersection () { return this._hasProper } IntersectionAdder.prototype.processIntersections = function processIntersections (e0, segIndex0, e1, segIndex1) { if (e0 === e1 && segIndex0 === segIndex1) { return null } this.numTests++ var p00 = e0.getCoordinates()[segIndex0] var p01 = e0.getCoordinates()[segIndex0 + 1] var p10 = e1.getCoordinates()[segIndex1] var p11 = e1.getCoordinates()[segIndex1 + 1] this._li.computeIntersection(p00, p01, p10, p11) if (this._li.hasIntersection()) { this.numIntersections++ if (this._li.isInteriorIntersection()) { this.numInteriorIntersections++ this._hasInterior = true } if (!this.isTrivialIntersection(e0, segIndex0, e1, segIndex1)) { this._hasIntersection = true e0.addIntersections(this._li, segIndex0, 0) e1.addIntersections(this._li, segIndex1, 1) if (this._li.isProper()) { this.numProperIntersections++ this._hasProper = true this._hasProperInterior = true } } } } IntersectionAdder.prototype.hasIntersection = function hasIntersection () { return this._hasIntersection } IntersectionAdder.prototype.isDone = function isDone () { return false } IntersectionAdder.prototype.hasInteriorIntersection = function hasInteriorIntersection () { return this._hasInterior } IntersectionAdder.prototype.interfaces_ = function interfaces_ () { return [SegmentIntersector] } IntersectionAdder.prototype.getClass = function getClass () { return IntersectionAdder } IntersectionAdder.isAdjacentSegments = function isAdjacentSegments (i1, i2) { return Math.abs(i1 - i2) === 1 } var EdgeIntersection = function EdgeIntersection () { this.coord = null this.segmentIndex = null this.dist = null var coord = arguments[0] var segmentIndex = arguments[1] var dist = arguments[2] this.coord = new Coordinate(coord) this.segmentIndex = segmentIndex this.dist = dist } EdgeIntersection.prototype.getSegmentIndex = function getSegmentIndex () { return this.segmentIndex } EdgeIntersection.prototype.getCoordinate = function getCoordinate () { return this.coord } EdgeIntersection.prototype.print = function print (out) { out.print(this.coord) out.print(' seg # = ' + this.segmentIndex) out.println(' dist = ' + this.dist) } EdgeIntersection.prototype.compareTo = function compareTo (obj) { var other = obj return this.compare(other.segmentIndex, other.dist) } EdgeIntersection.prototype.isEndPoint = function isEndPoint (maxSegmentIndex) { if (this.segmentIndex === 0 && this.dist === 0.0) { return true } if (this.segmentIndex === maxSegmentIndex) { return true } return false } EdgeIntersection.prototype.toString = function toString () { return this.coord + ' seg # = ' + this.segmentIndex + ' dist = ' + this.dist } EdgeIntersection.prototype.getDistance = function getDistance () { return this.dist } EdgeIntersection.prototype.compare = function compare (segmentIndex, dist) { if (this.segmentIndex < segmentIndex) { return -1 } if (this.segmentIndex > segmentIndex) { return 1 } if (this.dist < dist) { return -1 } if (this.dist > dist) { return 1 } return 0 } EdgeIntersection.prototype.interfaces_ = function interfaces_ () { return [Comparable] } EdgeIntersection.prototype.getClass = function getClass () { return EdgeIntersection } var EdgeIntersectionList = function EdgeIntersectionList () { this._nodeMap = new TreeMap() this.edge = null var edge = arguments[0] this.edge = edge } EdgeIntersectionList.prototype.print = function print (out) { out.println('Intersections:') for (var it = this.iterator(); it.hasNext();) { var ei = it.next() ei.print(out) } } EdgeIntersectionList.prototype.iterator = function iterator () { return this._nodeMap.values().iterator() } EdgeIntersectionList.prototype.addSplitEdges = function addSplitEdges (edgeList) { var this$1$1 = this this.addEndpoints() var it = this.iterator() var eiPrev = it.next() while (it.hasNext()) { var ei = it.next() var newEdge = this$1$1.createSplitEdge(eiPrev, ei) edgeList.add(newEdge) eiPrev = ei } } EdgeIntersectionList.prototype.addEndpoints = function addEndpoints () { var maxSegIndex = this.edge.pts.length - 1 this.add(this.edge.pts[0], 0, 0.0) this.add(this.edge.pts[maxSegIndex], maxSegIndex, 0.0) } EdgeIntersectionList.prototype.createSplitEdge = function createSplitEdge (ei0, ei1) { var this$1$1 = this var npts = ei1.segmentIndex - ei0.segmentIndex + 2 var lastSegStartPt = this.edge.pts[ei1.segmentIndex] var useIntPt1 = ei1.dist > 0.0 || !ei1.coord.equals2D(lastSegStartPt) if (!useIntPt1) { npts-- } var pts = new Array(npts).fill(null) var ipt = 0 pts[ipt++] = new Coordinate(ei0.coord) for (var i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) { pts[ipt++] = this$1$1.edge.pts[i] } if (useIntPt1) { pts[ipt] = ei1.coord } return new Edge(pts, new Label(this.edge._label)) } EdgeIntersectionList.prototype.add = function add (intPt, segmentIndex, dist) { var eiNew = new EdgeIntersection(intPt, segmentIndex, dist) var ei = this._nodeMap.get(eiNew) if (ei !== null) { return ei } this._nodeMap.put(eiNew, eiNew) return eiNew } EdgeIntersectionList.prototype.isIntersection = function isIntersection (pt) { for (var it = this.iterator(); it.hasNext();) { var ei = it.next() if (ei.coord.equals(pt)) { return true } } return false } EdgeIntersectionList.prototype.interfaces_ = function interfaces_ () { return [] } EdgeIntersectionList.prototype.getClass = function getClass () { return EdgeIntersectionList } var MonotoneChainIndexer = function MonotoneChainIndexer () { } MonotoneChainIndexer.prototype.getChainStartIndices = function getChainStartIndices (pts) { var this$1$1 = this var start = 0 var startIndexList = new ArrayList() startIndexList.add(new Integer(start)) do { var last = this$1$1.findChainEnd(pts, start) startIndexList.add(new Integer(last)) start = last } while (start < pts.length - 1) var startIndex = MonotoneChainIndexer.toIntArray(startIndexList) return startIndex } MonotoneChainIndexer.prototype.findChainEnd = function findChainEnd (pts, start) { var chainQuad = Quadrant.quadrant(pts[start], pts[start + 1]) var last = start + 1 while (last < pts.length) { var quad = Quadrant.quadrant(pts[last - 1], pts[last]) if (quad !== chainQuad) { break } last++ } return last - 1 } MonotoneChainIndexer.prototype.interfaces_ = function interfaces_ () { return [] } MonotoneChainIndexer.prototype.getClass = function getClass () { return MonotoneChainIndexer } MonotoneChainIndexer.toIntArray = function toIntArray (list) { var array = new Array(list.size()).fill(null) for (var i = 0; i < array.length; i++) { array[i] = list.get(i).intValue() } return array } var MonotoneChainEdge = function MonotoneChainEdge () { this.e = null this.pts = null this.startIndex = null this.env1 = new Envelope() this.env2 = new Envelope() var e = arguments[0] this.e = e this.pts = e.getCoordinates() var mcb = new MonotoneChainIndexer() this.startIndex = mcb.getChainStartIndices(this.pts) } MonotoneChainEdge.prototype.getCoordinates = function getCoordinates () { return this.pts } MonotoneChainEdge.prototype.getMaxX = function getMaxX (chainIndex) { var x1 = this.pts[this.startIndex[chainIndex]].x var x2 = this.pts[this.startIndex[chainIndex + 1]].x return x1 > x2 ? x1 : x2 } MonotoneChainEdge.prototype.getMinX = function getMinX (chainIndex) { var x1 = this.pts[this.startIndex[chainIndex]].x var x2 = this.pts[this.startIndex[chainIndex + 1]].x return x1 < x2 ? x1 : x2 } MonotoneChainEdge.prototype.computeIntersectsForChain = function computeIntersectsForChain () { if (arguments.length === 4) { var chainIndex0 = arguments[0] var mce = arguments[1] var chainIndex1 = arguments[2] var si = arguments[3] this.computeIntersectsForChain(this.startIndex[chainIndex0], this.startIndex[chainIndex0 + 1], mce, mce.startIndex[chainIndex1], mce.startIndex[chainIndex1 + 1], si) } else if (arguments.length === 6) { var start0 = arguments[0] var end0 = arguments[1] var mce$1 = arguments[2] var start1 = arguments[3] var end1 = arguments[4] var ei = arguments[5] var p00 = this.pts[start0] var p01 = this.pts[end0] var p10 = mce$1.pts[start1] var p11 = mce$1.pts[end1] if (end0 - start0 === 1 && end1 - start1 === 1) { ei.addIntersections(this.e, start0, mce$1.e, start1) return null } this.env1.init(p00, p01) this.env2.init(p10, p11) if (!this.env1.intersects(this.env2)) { return null } var mid0 = Math.trunc((start0 + end0) / 2) var mid1 = Math.trunc((start1 + end1) / 2) if (start0 < mid0) { if (start1 < mid1) { this.computeIntersectsForChain(start0, mid0, mce$1, start1, mid1, ei) } if (mid1 < end1) { this.computeIntersectsForChain(start0, mid0, mce$1, mid1, end1, ei) } } if (mid0 < end0) { if (start1 < mid1) { this.computeIntersectsForChain(mid0, end0, mce$1, start1, mid1, ei) } if (mid1 < end1) { this.computeIntersectsForChain(mid0, end0, mce$1, mid1, end1, ei) } } } } MonotoneChainEdge.prototype.getStartIndexes = function getStartIndexes () { return this.startIndex } MonotoneChainEdge.prototype.computeIntersects = function computeIntersects (mce, si) { var this$1$1 = this for (var i = 0; i < this.startIndex.length - 1; i++) { for (var j = 0; j < mce.startIndex.length - 1; j++) { this$1$1.computeIntersectsForChain(i, mce, j, si) } } } MonotoneChainEdge.prototype.interfaces_ = function interfaces_ () { return [] } MonotoneChainEdge.prototype.getClass = function getClass () { return MonotoneChainEdge } var Depth = function Depth () { var this$1$1 = this this._depth = Array(2).fill().map(function () { return Array(3) }) for (var i = 0; i < 2; i++) { for (var j = 0; j < 3; j++) { this$1$1._depth[i][j] = Depth.NULL_VALUE } } } var staticAccessors$31 = { NULL_VALUE: { configurable: true } } Depth.prototype.getDepth = function getDepth (geomIndex, posIndex) { return this._depth[geomIndex][posIndex] } Depth.prototype.setDepth = function setDepth (geomIndex, posIndex, depthValue) { this._depth[geomIndex][posIndex] = depthValue } Depth.prototype.isNull = function isNull () { var this$1$1 = this if (arguments.length === 0) { for (var i = 0; i < 2; i++) { for (var j = 0; j < 3; j++) { if (this$1$1._depth[i][j] !== Depth.NULL_VALUE) { return false } } } return true } else if (arguments.length === 1) { var geomIndex = arguments[0] return this._depth[geomIndex][1] === Depth.NULL_VALUE } else if (arguments.length === 2) { var geomIndex$1 = arguments[0] var posIndex = arguments[1] return this._depth[geomIndex$1][posIndex] === Depth.NULL_VALUE } } Depth.prototype.normalize = function normalize () { var this$1$1 = this for (var i = 0; i < 2; i++) { if (!this$1$1.isNull(i)) { var minDepth = this$1$1._depth[i][1] if (this$1$1._depth[i][2] < minDepth) { minDepth = this$1$1._depth[i][2] } if (minDepth < 0) { minDepth = 0 } for (var j = 1; j < 3; j++) { var newValue = 0 if (this$1$1._depth[i][j] > minDepth) { newValue = 1 } this$1$1._depth[i][j] = newValue } } } } Depth.prototype.getDelta = function getDelta (geomIndex) { return this._depth[geomIndex][Position.RIGHT] - this._depth[geomIndex][Position.LEFT] } Depth.prototype.getLocation = function getLocation (geomIndex, posIndex) { if (this._depth[geomIndex][posIndex] <= 0) { return Location.EXTERIOR } return Location.INTERIOR } Depth.prototype.toString = function toString () { return 'A: ' + this._depth[0][1] + ',' + this._depth[0][2] + ' B: ' + this._depth[1][1] + ',' + this._depth[1][2] } Depth.prototype.add = function add () { var this$1$1 = this if (arguments.length === 1) { var lbl = arguments[0] for (var i = 0; i < 2; i++) { for (var j = 1; j < 3; j++) { var loc = lbl.getLocation(i, j) if (loc === Location.EXTERIOR || loc === Location.INTERIOR) { if (this$1$1.isNull(i, j)) { this$1$1._depth[i][j] = Depth.depthAtLocation(loc) } else { this$1$1._depth[i][j] += Depth.depthAtLocation(loc) } } } } } else if (arguments.length === 3) { var geomIndex = arguments[0] var posIndex = arguments[1] var location = arguments[2] if (location === Location.INTERIOR) { this._depth[geomIndex][posIndex]++ } } } Depth.prototype.interfaces_ = function interfaces_ () { return [] } Depth.prototype.getClass = function getClass () { return Depth } Depth.depthAtLocation = function depthAtLocation (location) { if (location === Location.EXTERIOR) { return 0 } if (location === Location.INTERIOR) { return 1 } return Depth.NULL_VALUE } staticAccessors$31.NULL_VALUE.get = function () { return -1 } Object.defineProperties(Depth, staticAccessors$31) var Edge = (function (GraphComponent$$1) { function Edge () { GraphComponent$$1.call(this) this.pts = null this._env = null this.eiList = new EdgeIntersectionList(this) this._name = null this._mce = null this._isIsolated = true this._depth = new Depth() this._depthDelta = 0 if (arguments.length === 1) { var pts = arguments[0] Edge.call(this, pts, null) } else if (arguments.length === 2) { var pts$1 = arguments[0] var label = arguments[1] this.pts = pts$1 this._label = label } } if (GraphComponent$$1) Edge.__proto__ = GraphComponent$$1 Edge.prototype = Object.create(GraphComponent$$1 && GraphComponent$$1.prototype) Edge.prototype.constructor = Edge Edge.prototype.getDepth = function getDepth () { return this._depth } Edge.prototype.getCollapsedEdge = function getCollapsedEdge () { var newPts = new Array(2).fill(null) newPts[0] = this.pts[0] newPts[1] = this.pts[1] var newe = new Edge(newPts, Label.toLineLabel(this._label)) return newe } Edge.prototype.isIsolated = function isIsolated () { return this._isIsolated } Edge.prototype.getCoordinates = function getCoordinates () { return this.pts } Edge.prototype.setIsolated = function setIsolated (isIsolated) { this._isIsolated = isIsolated } Edge.prototype.setName = function setName (name) { this._name = name } Edge.prototype.equals = function equals (o) { var this$1$1 = this if (!(o instanceof Edge)) { return false } var e = o if (this.pts.length !== e.pts.length) { return false } var isEqualForward = true var isEqualReverse = true var iRev = this.pts.length for (var i = 0; i < this.pts.length; i++) { if (!this$1$1.pts[i].equals2D(e.pts[i])) { isEqualForward = false } if (!this$1$1.pts[i].equals2D(e.pts[--iRev])) { isEqualReverse = false } if (!isEqualForward && !isEqualReverse) { return false } } return true } Edge.prototype.getCoordinate = function getCoordinate () { if (arguments.length === 0) { if (this.pts.length > 0) { return this.pts[0] } return null } else if (arguments.length === 1) { var i = arguments[0] return this.pts[i] } } Edge.prototype.print = function print (out) { var this$1$1 = this out.print('edge ' + this._name + ': ') out.print('LINESTRING (') for (var i = 0; i < this.pts.length; i++) { if (i > 0) { out.print(',') } out.print(this$1$1.pts[i].x + ' ' + this$1$1.pts[i].y) } out.print(') ' + this._label + ' ' + this._depthDelta) } Edge.prototype.computeIM = function computeIM (im) { Edge.updateIM(this._label, im) } Edge.prototype.isCollapsed = function isCollapsed () { if (!this._label.isArea()) { return false } if (this.pts.length !== 3) { return false } if (this.pts[0].equals(this.pts[2])) { return true } return false } Edge.prototype.isClosed = function isClosed () { return this.pts[0].equals(this.pts[this.pts.length - 1]) } Edge.prototype.getMaximumSegmentIndex = function getMaximumSegmentIndex () { return this.pts.length - 1 } Edge.prototype.getDepthDelta = function getDepthDelta () { return this._depthDelta } Edge.prototype.getNumPoints = function getNumPoints () { return this.pts.length } Edge.prototype.printReverse = function printReverse (out) { var this$1$1 = this out.print('edge ' + this._name + ': ') for (var i = this.pts.length - 1; i >= 0; i--) { out.print(this$1$1.pts[i] + ' ') } out.println('') } Edge.prototype.getMonotoneChainEdge = function getMonotoneChainEdge () { if (this._mce === null) { this._mce = new MonotoneChainEdge(this) } return this._mce } Edge.prototype.getEnvelope = function getEnvelope () { var this$1$1 = this if (this._env === null) { this._env = new Envelope() for (var i = 0; i < this.pts.length; i++) { this$1$1._env.expandToInclude(this$1$1.pts[i]) } } return this._env } Edge.prototype.addIntersection = function addIntersection (li, segmentIndex, geomIndex, intIndex) { var intPt = new Coordinate(li.getIntersection(intIndex)) var normalizedSegmentIndex = segmentIndex var dist = li.getEdgeDistance(geomIndex, intIndex) var nextSegIndex = normalizedSegmentIndex + 1 if (nextSegIndex < this.pts.length) { var nextPt = this.pts[nextSegIndex] if (intPt.equals2D(nextPt)) { normalizedSegmentIndex = nextSegIndex dist = 0.0 } } this.eiList.add(intPt, normalizedSegmentIndex, dist) } Edge.prototype.toString = function toString () { var this$1$1 = this var buf = new StringBuffer() buf.append('edge ' + this._name + ': ') buf.append('LINESTRING (') for (var i = 0; i < this.pts.length; i++) { if (i > 0) { buf.append(',') } buf.append(this$1$1.pts[i].x + ' ' + this$1$1.pts[i].y) } buf.append(') ' + this._label + ' ' + this._depthDelta) return buf.toString() } Edge.prototype.isPointwiseEqual = function isPointwiseEqual (e) { var this$1$1 = this if (this.pts.length !== e.pts.length) { return false } for (var i = 0; i < this.pts.length; i++) { if (!this$1$1.pts[i].equals2D(e.pts[i])) { return false } } return true } Edge.prototype.setDepthDelta = function setDepthDelta (depthDelta) { this._depthDelta = depthDelta } Edge.prototype.getEdgeIntersectionList = function getEdgeIntersectionList () { return this.eiList } Edge.prototype.addIntersections = function addIntersections (li, segmentIndex, geomIndex) { var this$1$1 = this for (var i = 0; i < li.getIntersectionNum(); i++) { this$1$1.addIntersection(li, segmentIndex, geomIndex, i) } } Edge.prototype.interfaces_ = function interfaces_ () { return [] } Edge.prototype.getClass = function getClass () { return Edge } Edge.updateIM = function updateIM () { if (arguments.length === 2) { var label = arguments[0] var im = arguments[1] im.setAtLeastIfValid(label.getLocation(0, Position.ON), label.getLocation(1, Position.ON), 1) if (label.isArea()) { im.setAtLeastIfValid(label.getLocation(0, Position.LEFT), label.getLocation(1, Position.LEFT), 2) im.setAtLeastIfValid(label.getLocation(0, Position.RIGHT), label.getLocation(1, Position.RIGHT), 2) } } else { return GraphComponent$$1.prototype.updateIM.apply(this, arguments) } } return Edge }(GraphComponent)) var BufferBuilder = function BufferBuilder (bufParams) { this._workingPrecisionModel = null this._workingNoder = null this._geomFact = null this._graph = null this._edgeList = new EdgeList() this._bufParams = bufParams || null } BufferBuilder.prototype.setWorkingPrecisionModel = function setWorkingPrecisionModel (pm) { this._workingPrecisionModel = pm } BufferBuilder.prototype.insertUniqueEdge = function insertUniqueEdge (e) { var existingEdge = this._edgeList.findEqualEdge(e) if (existingEdge !== null) { var existingLabel = existingEdge.getLabel() var labelToMerge = e.getLabel() if (!existingEdge.isPointwiseEqual(e)) { labelToMerge = new Label(e.getLabel()) labelToMerge.flip() } existingLabel.merge(labelToMerge) var mergeDelta = BufferBuilder.depthDelta(labelToMerge) var existingDelta = existingEdge.getDepthDelta() var newDelta = existingDelta + mergeDelta existingEdge.setDepthDelta(newDelta) } else { this._edgeList.add(e) e.setDepthDelta(BufferBuilder.depthDelta(e.getLabel())) } } BufferBuilder.prototype.buildSubgraphs = function buildSubgraphs (subgraphList, polyBuilder) { var processedGraphs = new ArrayList() for (var i = subgraphList.iterator(); i.hasNext();) { var subgraph = i.next() var p = subgraph.getRightmostCoordinate() var locater = new SubgraphDepthLocater(processedGraphs) var outsideDepth = locater.getDepth(p) subgraph.computeDepth(outsideDepth) subgraph.findResultEdges() processedGraphs.add(subgraph) polyBuilder.add(subgraph.getDirectedEdges(), subgraph.getNodes()) } } BufferBuilder.prototype.createSubgraphs = function createSubgraphs (graph) { var subgraphList = new ArrayList() for (var i = graph.getNodes().iterator(); i.hasNext();) { var node = i.next() if (!node.isVisited()) { var subgraph = new BufferSubgraph() subgraph.create(node) subgraphList.add(subgraph) } } Collections.sort(subgraphList, Collections.reverseOrder()) return subgraphList } BufferBuilder.prototype.createEmptyResultGeometry = function createEmptyResultGeometry () { var emptyGeom = this._geomFact.createPolygon() return emptyGeom } BufferBuilder.prototype.getNoder = function getNoder (precisionModel) { if (this._workingNoder !== null) { return this._workingNoder } var noder = new MCIndexNoder() var li = new RobustLineIntersector() li.setPrecisionModel(precisionModel) noder.setSegmentIntersector(new IntersectionAdder(li)) return noder } BufferBuilder.prototype.buffer = function buffer (g, distance) { var precisionModel = this._workingPrecisionModel if (precisionModel === null) { precisionModel = g.getPrecisionModel() } this._geomFact = g.getFactory() var curveBuilder = new OffsetCurveBuilder(precisionModel, this._bufParams) var curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder) var bufferSegStrList = curveSetBuilder.getCurves() if (bufferSegStrList.size() <= 0) { return this.createEmptyResultGeometry() } this.computeNodedEdges(bufferSegStrList, precisionModel) this._graph = new PlanarGraph(new OverlayNodeFactory()) this._graph.addEdges(this._edgeList.getEdges()) var subgraphList = this.createSubgraphs(this._graph) var polyBuilder = new PolygonBuilder(this._geomFact) this.buildSubgraphs(subgraphList, polyBuilder) var resultPolyList = polyBuilder.getPolygons() if (resultPolyList.size() <= 0) { return this.createEmptyResultGeometry() } var resultGeom = this._geomFact.buildGeometry(resultPolyList) return resultGeom } BufferBuilder.prototype.computeNodedEdges = function computeNodedEdges (bufferSegStrList, precisionModel) { var this$1$1 = this var noder = this.getNoder(precisionModel) noder.computeNodes(bufferSegStrList) var nodedSegStrings = noder.getNodedSubstrings() for (var i = nodedSegStrings.iterator(); i.hasNext();) { var segStr = i.next() var pts = segStr.getCoordinates() if (pts.length === 2 && pts[0].equals2D(pts[1])) { continue } var oldLabel = segStr.getData() var edge = new Edge(segStr.getCoordinates(), new Label(oldLabel)) this$1$1.insertUniqueEdge(edge) } } BufferBuilder.prototype.setNoder = function setNoder (noder) { this._workingNoder = noder } BufferBuilder.prototype.interfaces_ = function interfaces_ () { return [] } BufferBuilder.prototype.getClass = function getClass () { return BufferBuilder } BufferBuilder.depthDelta = function depthDelta (label) { var lLoc = label.getLocation(0, Position.LEFT) var rLoc = label.getLocation(0, Position.RIGHT) if (lLoc === Location.INTERIOR && rLoc === Location.EXTERIOR) { return 1 } else if (lLoc === Location.EXTERIOR && rLoc === Location.INTERIOR) { return -1 } return 0 } BufferBuilder.convertSegStrings = function convertSegStrings (it) { var fact = new GeometryFactory() var lines = new ArrayList() while (it.hasNext()) { var ss = it.next() var line = fact.createLineString(ss.getCoordinates()) lines.add(line) } return fact.buildGeometry(lines) } var ScaledNoder = function ScaledNoder () { this._noder = null this._scaleFactor = null this._offsetX = null this._offsetY = null this._isScaled = false if (arguments.length === 2) { var noder = arguments[0] var scaleFactor = arguments[1] this._noder = noder this._scaleFactor = scaleFactor this._offsetX = 0.0 this._offsetY = 0.0 this._isScaled = !this.isIntegerPrecision() } else if (arguments.length === 4) { var noder$1 = arguments[0] var scaleFactor$1 = arguments[1] var offsetX = arguments[2] var offsetY = arguments[3] this._noder = noder$1 this._scaleFactor = scaleFactor$1 this._offsetX = offsetX this._offsetY = offsetY this._isScaled = !this.isIntegerPrecision() } } ScaledNoder.prototype.rescale = function rescale () { var this$1$1 = this if (hasInterface(arguments[0], Collection)) { var segStrings = arguments[0] for (var i = segStrings.iterator(); i.hasNext();) { var ss = i.next() this$1$1.rescale(ss.getCoordinates()) } } else if (arguments[0] instanceof Array) { var pts = arguments[0] // let p0 = null // let p1 = null // if (pts.length === 2) { // p0 = new Coordinate(pts[0]) // p1 = new Coordinate(pts[1]) // } for (var i$1 = 0; i$1 < pts.length; i$1++) { pts[i$1].x = pts[i$1].x / this$1$1._scaleFactor + this$1$1._offsetX pts[i$1].y = pts[i$1].y / this$1$1._scaleFactor + this$1$1._offsetY } if (pts.length === 2 && pts[0].equals2D(pts[1])) { System.out.println(pts) } } } ScaledNoder.prototype.scale = function scale () { var this$1$1 = this if (hasInterface(arguments[0], Collection)) { var segStrings = arguments[0] var nodedSegmentStrings = new ArrayList() for (var i = segStrings.iterator(); i.hasNext();) { var ss = i.next() nodedSegmentStrings.add(new NodedSegmentString(this$1$1.scale(ss.getCoordinates()), ss.getData())) } return nodedSegmentStrings } else if (arguments[0] instanceof Array) { var pts = arguments[0] var roundPts = new Array(pts.length).fill(null) for (var i$1 = 0; i$1 < pts.length; i$1++) { roundPts[i$1] = new Coordinate(Math.round((pts[i$1].x - this$1$1._offsetX) * this$1$1._scaleFactor), Math.round((pts[i$1].y - this$1$1._offsetY) * this$1$1._scaleFactor), pts[i$1].z) } var roundPtsNoDup = CoordinateArrays.removeRepeatedPoints(roundPts) return roundPtsNoDup } } ScaledNoder.prototype.isIntegerPrecision = function isIntegerPrecision () { return this._scaleFactor === 1.0 } ScaledNoder.prototype.getNodedSubstrings = function getNodedSubstrings () { var splitSS = this._noder.getNodedSubstrings() if (this._isScaled) { this.rescale(splitSS) } return splitSS } ScaledNoder.prototype.computeNodes = function computeNodes (inputSegStrings) { var intSegStrings = inputSegStrings if (this._isScaled) { intSegStrings = this.scale(inputSegStrings) } this._noder.computeNodes(intSegStrings) } ScaledNoder.prototype.interfaces_ = function interfaces_ () { return [Noder] } ScaledNoder.prototype.getClass = function getClass () { return ScaledNoder } var NodingValidator = function NodingValidator () { this._li = new RobustLineIntersector() this._segStrings = null var segStrings = arguments[0] this._segStrings = segStrings } var staticAccessors$33 = { fact: { configurable: true } } NodingValidator.prototype.checkEndPtVertexIntersections = function checkEndPtVertexIntersections () { var this$1$1 = this if (arguments.length === 0) { for (var i = this._segStrings.iterator(); i.hasNext();) { var ss = i.next() var pts = ss.getCoordinates() this$1$1.checkEndPtVertexIntersections(pts[0], this$1$1._segStrings) this$1$1.checkEndPtVertexIntersections(pts[pts.length - 1], this$1$1._segStrings) } } else if (arguments.length === 2) { var testPt = arguments[0] var segStrings = arguments[1] for (var i$1 = segStrings.iterator(); i$1.hasNext();) { var ss$1 = i$1.next() var pts$1 = ss$1.getCoordinates() for (var j = 1; j < pts$1.length - 1; j++) { if (pts$1[j].equals(testPt)) { throw new RuntimeException('found endpt/interior pt intersection at index ' + j + ' :pt ' + testPt) } } } } } NodingValidator.prototype.checkInteriorIntersections = function checkInteriorIntersections () { var this$1$1 = this if (arguments.length === 0) { for (var i = this._segStrings.iterator(); i.hasNext();) { var ss0 = i.next() for (var j = this._segStrings.iterator(); j.hasNext();) { var ss1 = j.next() this$1$1.checkInteriorIntersections(ss0, ss1) } } } else if (arguments.length === 2) { var ss0$1 = arguments[0] var ss1$1 = arguments[1] var pts0 = ss0$1.getCoordinates() var pts1 = ss1$1.getCoordinates() for (var i0 = 0; i0 < pts0.length - 1; i0++) { for (var i1 = 0; i1 < pts1.length - 1; i1++) { this$1$1.checkInteriorIntersections(ss0$1, i0, ss1$1, i1) } } } else if (arguments.length === 4) { var e0 = arguments[0] var segIndex0 = arguments[1] var e1 = arguments[2] var segIndex1 = arguments[3] if (e0 === e1 && segIndex0 === segIndex1) { return null } var p00 = e0.getCoordinates()[segIndex0] var p01 = e0.getCoordinates()[segIndex0 + 1] var p10 = e1.getCoordinates()[segIndex1] var p11 = e1.getCoordinates()[segIndex1 + 1] this._li.computeIntersection(p00, p01, p10, p11) if (this._li.hasIntersection()) { if (this._li.isProper() || this.hasInteriorIntersection(this._li, p00, p01) || this.hasInteriorIntersection(this._li, p10, p11)) { throw new RuntimeException('found non-noded intersection at ' + p00 + '-' + p01 + ' and ' + p10 + '-' + p11) } } } } NodingValidator.prototype.checkValid = function checkValid () { this.checkEndPtVertexIntersections() this.checkInteriorIntersections() this.checkCollapses() } NodingValidator.prototype.checkCollapses = function checkCollapses () { var this$1$1 = this if (arguments.length === 0) { for (var i = this._segStrings.iterator(); i.hasNext();) { var ss = i.next() this$1$1.checkCollapses(ss) } } else if (arguments.length === 1) { var ss$1 = arguments[0] var pts = ss$1.getCoordinates() for (var i$1 = 0; i$1 < pts.length - 2; i$1++) { this$1$1.checkCollapse(pts[i$1], pts[i$1 + 1], pts[i$1 + 2]) } } } NodingValidator.prototype.hasInteriorIntersection = function hasInteriorIntersection (li, p0, p1) { for (var i = 0; i < li.getIntersectionNum(); i++) { var intPt = li.getIntersection(i) if (!(intPt.equals(p0) || intPt.equals(p1))) { return true } } return false } NodingValidator.prototype.checkCollapse = function checkCollapse (p0, p1, p2) { if (p0.equals(p2)) { throw new RuntimeException('found non-noded collapse at ' + NodingValidator.fact.createLineString([p0, p1, p2])) } } NodingValidator.prototype.interfaces_ = function interfaces_ () { return [] } NodingValidator.prototype.getClass = function getClass () { return NodingValidator } staticAccessors$33.fact.get = function () { return new GeometryFactory() } Object.defineProperties(NodingValidator, staticAccessors$33) var HotPixel = function HotPixel () { this._li = null this._pt = null this._originalPt = null this._ptScaled = null this._p0Scaled = null this._p1Scaled = null this._scaleFactor = null this._minx = null this._maxx = null this._miny = null this._maxy = null this._corner = new Array(4).fill(null) this._safeEnv = null var pt = arguments[0] var scaleFactor = arguments[1] var li = arguments[2] this._originalPt = pt this._pt = pt this._scaleFactor = scaleFactor this._li = li if (scaleFactor <= 0) { throw new IllegalArgumentException('Scale factor must be non-zero') } if (scaleFactor !== 1.0) { this._pt = new Coordinate(this.scale(pt.x), this.scale(pt.y)) this._p0Scaled = new Coordinate() this._p1Scaled = new Coordinate() } this.initCorners(this._pt) } var staticAccessors$34 = { SAFE_ENV_EXPANSION_FACTOR: { configurable: true } } HotPixel.prototype.intersectsScaled = function intersectsScaled (p0, p1) { var segMinx = Math.min(p0.x, p1.x) var segMaxx = Math.max(p0.x, p1.x) var segMiny = Math.min(p0.y, p1.y) var segMaxy = Math.max(p0.y, p1.y) var isOutsidePixelEnv = this._maxx < segMinx || this._minx > segMaxx || this._maxy < segMiny || this._miny > segMaxy if (isOutsidePixelEnv) { return false } var intersects = this.intersectsToleranceSquare(p0, p1) Assert.isTrue(!(isOutsidePixelEnv && intersects), 'Found bad envelope test') return intersects } HotPixel.prototype.initCorners = function initCorners (pt) { var tolerance = 0.5 this._minx = pt.x - tolerance this._maxx = pt.x + tolerance this._miny = pt.y - tolerance this._maxy = pt.y + tolerance this._corner[0] = new Coordinate(this._maxx, this._maxy) this._corner[1] = new Coordinate(this._minx, this._maxy) this._corner[2] = new Coordinate(this._minx, this._miny) this._corner[3] = new Coordinate(this._maxx, this._miny) } HotPixel.prototype.intersects = function intersects (p0, p1) { if (this._scaleFactor === 1.0) { return this.intersectsScaled(p0, p1) } this.copyScaled(p0, this._p0Scaled) this.copyScaled(p1, this._p1Scaled) return this.intersectsScaled(this._p0Scaled, this._p1Scaled) } HotPixel.prototype.scale = function scale (val) { return Math.round(val * this._scaleFactor) } HotPixel.prototype.getCoordinate = function getCoordinate () { return this._originalPt } HotPixel.prototype.copyScaled = function copyScaled (p, pScaled) { pScaled.x = this.scale(p.x) pScaled.y = this.scale(p.y) } HotPixel.prototype.getSafeEnvelope = function getSafeEnvelope () { if (this._safeEnv === null) { var safeTolerance = HotPixel.SAFE_ENV_EXPANSION_FACTOR / this._scaleFactor this._safeEnv = new Envelope(this._originalPt.x - safeTolerance, this._originalPt.x + safeTolerance, this._originalPt.y - safeTolerance, this._originalPt.y + safeTolerance) } return this._safeEnv } HotPixel.prototype.intersectsPixelClosure = function intersectsPixelClosure (p0, p1) { this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1]) if (this._li.hasIntersection()) { return true } this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2]) if (this._li.hasIntersection()) { return true } this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3]) if (this._li.hasIntersection()) { return true } this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0]) if (this._li.hasIntersection()) { return true } return false } HotPixel.prototype.intersectsToleranceSquare = function intersectsToleranceSquare (p0, p1) { var intersectsLeft = false var intersectsBottom = false this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1]) if (this._li.isProper()) { return true } this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2]) if (this._li.isProper()) { return true } if (this._li.hasIntersection()) { intersectsLeft = true } this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3]) if (this._li.isProper()) { return true } if (this._li.hasIntersection()) { intersectsBottom = true } this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0]) if (this._li.isProper()) { return true } if (intersectsLeft && intersectsBottom) { return true } if (p0.equals(this._pt)) { return true } if (p1.equals(this._pt)) { return true } return false } HotPixel.prototype.addSnappedNode = function addSnappedNode (segStr, segIndex) { var p0 = segStr.getCoordinate(segIndex) var p1 = segStr.getCoordinate(segIndex + 1) if (this.intersects(p0, p1)) { segStr.addIntersection(this.getCoordinate(), segIndex) return true } return false } HotPixel.prototype.interfaces_ = function interfaces_ () { return [] } HotPixel.prototype.getClass = function getClass () { return HotPixel } staticAccessors$34.SAFE_ENV_EXPANSION_FACTOR.get = function () { return 0.75 } Object.defineProperties(HotPixel, staticAccessors$34) var MonotoneChainSelectAction = function MonotoneChainSelectAction () { this.tempEnv1 = new Envelope() this.selectedSegment = new LineSegment() } MonotoneChainSelectAction.prototype.select = function select () { if (arguments.length === 1); else if (arguments.length === 2) { var mc = arguments[0] var startIndex = arguments[1] mc.getLineSegment(startIndex, this.selectedSegment) this.select(this.selectedSegment) } } MonotoneChainSelectAction.prototype.interfaces_ = function interfaces_ () { return [] } MonotoneChainSelectAction.prototype.getClass = function getClass () { return MonotoneChainSelectAction } var MCIndexPointSnapper = function MCIndexPointSnapper () { this._index = null var index = arguments[0] this._index = index } var staticAccessors$35 = { HotPixelSnapAction: { configurable: true } } MCIndexPointSnapper.prototype.snap = function snap () { if (arguments.length === 1) { var hotPixel = arguments[0] return this.snap(hotPixel, null, -1) } else if (arguments.length === 3) { var hotPixel$1 = arguments[0] var parentEdge = arguments[1] var hotPixelVertexIndex = arguments[2] var pixelEnv = hotPixel$1.getSafeEnvelope() var hotPixelSnapAction = new HotPixelSnapAction(hotPixel$1, parentEdge, hotPixelVertexIndex) this._index.query(pixelEnv, { interfaces_: function () { return [ItemVisitor] }, visitItem: function (item) { var testChain = item testChain.select(pixelEnv, hotPixelSnapAction) } }) return hotPixelSnapAction.isNodeAdded() } } MCIndexPointSnapper.prototype.interfaces_ = function interfaces_ () { return [] } MCIndexPointSnapper.prototype.getClass = function getClass () { return MCIndexPointSnapper } staticAccessors$35.HotPixelSnapAction.get = function () { return HotPixelSnapAction } Object.defineProperties(MCIndexPointSnapper, staticAccessors$35) var HotPixelSnapAction = (function (MonotoneChainSelectAction$$1) { function HotPixelSnapAction () { MonotoneChainSelectAction$$1.call(this) this._hotPixel = null this._parentEdge = null this._hotPixelVertexIndex = null this._isNodeAdded = false var hotPixel = arguments[0] var parentEdge = arguments[1] var hotPixelVertexIndex = arguments[2] this._hotPixel = hotPixel this._parentEdge = parentEdge this._hotPixelVertexIndex = hotPixelVertexIndex } if (MonotoneChainSelectAction$$1) HotPixelSnapAction.__proto__ = MonotoneChainSelectAction$$1 HotPixelSnapAction.prototype = Object.create(MonotoneChainSelectAction$$1 && MonotoneChainSelectAction$$1.prototype) HotPixelSnapAction.prototype.constructor = HotPixelSnapAction HotPixelSnapAction.prototype.isNodeAdded = function isNodeAdded () { return this._isNodeAdded } HotPixelSnapAction.prototype.select = function select () { if (arguments.length === 2) { var mc = arguments[0] var startIndex = arguments[1] var ss = mc.getContext() if (this._parentEdge !== null) { if (ss === this._parentEdge && startIndex === this._hotPixelVertexIndex) { return null } } this._isNodeAdded = this._hotPixel.addSnappedNode(ss, startIndex) } else { return MonotoneChainSelectAction$$1.prototype.select.apply(this, arguments) } } HotPixelSnapAction.prototype.interfaces_ = function interfaces_ () { return [] } HotPixelSnapAction.prototype.getClass = function getClass () { return HotPixelSnapAction } return HotPixelSnapAction }(MonotoneChainSelectAction)) var InteriorIntersectionFinderAdder = function InteriorIntersectionFinderAdder () { this._li = null this._interiorIntersections = null var li = arguments[0] this._li = li this._interiorIntersections = new ArrayList() } InteriorIntersectionFinderAdder.prototype.processIntersections = function processIntersections (e0, segIndex0, e1, segIndex1) { var this$1$1 = this if (e0 === e1 && segIndex0 === segIndex1) { return null } var p00 = e0.getCoordinates()[segIndex0] var p01 = e0.getCoordinates()[segIndex0 + 1] var p10 = e1.getCoordinates()[segIndex1] var p11 = e1.getCoordinates()[segIndex1 + 1] this._li.computeIntersection(p00, p01, p10, p11) if (this._li.hasIntersection()) { if (this._li.isInteriorIntersection()) { for (var intIndex = 0; intIndex < this._li.getIntersectionNum(); intIndex++) { this$1$1._interiorIntersections.add(this$1$1._li.getIntersection(intIndex)) } e0.addIntersections(this._li, segIndex0, 0) e1.addIntersections(this._li, segIndex1, 1) } } } InteriorIntersectionFinderAdder.prototype.isDone = function isDone () { return false } InteriorIntersectionFinderAdder.prototype.getInteriorIntersections = function getInteriorIntersections () { return this._interiorIntersections } InteriorIntersectionFinderAdder.prototype.interfaces_ = function interfaces_ () { return [SegmentIntersector] } InteriorIntersectionFinderAdder.prototype.getClass = function getClass () { return InteriorIntersectionFinderAdder } var MCIndexSnapRounder = function MCIndexSnapRounder () { this._pm = null this._li = null this._scaleFactor = null this._noder = null this._pointSnapper = null this._nodedSegStrings = null var pm = arguments[0] this._pm = pm this._li = new RobustLineIntersector() this._li.setPrecisionModel(pm) this._scaleFactor = pm.getScale() } MCIndexSnapRounder.prototype.checkCorrectness = function checkCorrectness (inputSegmentStrings) { var resultSegStrings = NodedSegmentString.getNodedSubstrings(inputSegmentStrings) var nv = new NodingValidator(resultSegStrings) try { nv.checkValid() } catch (ex) { if (ex instanceof Exception) { ex.printStackTrace() } else { throw ex } } finally { } } MCIndexSnapRounder.prototype.getNodedSubstrings = function getNodedSubstrings () { return NodedSegmentString.getNodedSubstrings(this._nodedSegStrings) } MCIndexSnapRounder.prototype.snapRound = function snapRound (segStrings, li) { var intersections = this.findInteriorIntersections(segStrings, li) this.computeIntersectionSnaps(intersections) this.computeVertexSnaps(segStrings) } MCIndexSnapRounder.prototype.findInteriorIntersections = function findInteriorIntersections (segStrings, li) { var intFinderAdder = new InteriorIntersectionFinderAdder(li) this._noder.setSegmentIntersector(intFinderAdder) this._noder.computeNodes(segStrings) return intFinderAdder.getInteriorIntersections() } MCIndexSnapRounder.prototype.computeVertexSnaps = function computeVertexSnaps () { var this$1$1 = this if (hasInterface(arguments[0], Collection)) { var edges = arguments[0] for (var i0 = edges.iterator(); i0.hasNext();) { var edge0 = i0.next() this$1$1.computeVertexSnaps(edge0) } } else if (arguments[0] instanceof NodedSegmentString) { var e = arguments[0] var pts0 = e.getCoordinates() for (var i = 0; i < pts0.length; i++) { var hotPixel = new HotPixel(pts0[i], this$1$1._scaleFactor, this$1$1._li) var isNodeAdded = this$1$1._pointSnapper.snap(hotPixel, e, i) if (isNodeAdded) { e.addIntersection(pts0[i], i) } } } } MCIndexSnapRounder.prototype.computeNodes = function computeNodes (inputSegmentStrings) { this._nodedSegStrings = inputSegmentStrings this._noder = new MCIndexNoder() this._pointSnapper = new MCIndexPointSnapper(this._noder.getIndex()) this.snapRound(inputSegmentStrings, this._li) } MCIndexSnapRounder.prototype.computeIntersectionSnaps = function computeIntersectionSnaps (snapPts) { var this$1$1 = this for (var it = snapPts.iterator(); it.hasNext();) { var snapPt = it.next() var hotPixel = new HotPixel(snapPt, this$1$1._scaleFactor, this$1$1._li) this$1$1._pointSnapper.snap(hotPixel) } } MCIndexSnapRounder.prototype.interfaces_ = function interfaces_ () { return [Noder] } MCIndexSnapRounder.prototype.getClass = function getClass () { return MCIndexSnapRounder } var BufferOp = function BufferOp () { this._argGeom = null this._distance = null this._bufParams = new BufferParameters() this._resultGeometry = null this._saveException = null if (arguments.length === 1) { var g = arguments[0] this._argGeom = g } else if (arguments.length === 2) { var g$1 = arguments[0] var bufParams = arguments[1] this._argGeom = g$1 this._bufParams = bufParams } } var staticAccessors$32 = { CAP_ROUND: { configurable: true }, CAP_BUTT: { configurable: true }, CAP_FLAT: { configurable: true }, CAP_SQUARE: { configurable: true }, MAX_PRECISION_DIGITS: { configurable: true } } BufferOp.prototype.bufferFixedPrecision = function bufferFixedPrecision (fixedPM) { var noder = new ScaledNoder(new MCIndexSnapRounder(new PrecisionModel(1.0)), fixedPM.getScale()) var bufBuilder = new BufferBuilder(this._bufParams) bufBuilder.setWorkingPrecisionModel(fixedPM) bufBuilder.setNoder(noder) this._resultGeometry = bufBuilder.buffer(this._argGeom, this._distance) } BufferOp.prototype.bufferReducedPrecision = function bufferReducedPrecision () { var this$1$1 = this if (arguments.length === 0) { for (var precDigits = BufferOp.MAX_PRECISION_DIGITS; precDigits >= 0; precDigits--) { try { this$1$1.bufferReducedPrecision(precDigits) } catch (ex) { if (ex instanceof TopologyException) { this$1$1._saveException = ex } else { throw ex } } finally { } if (this$1$1._resultGeometry !== null) { return null } } throw this._saveException } else if (arguments.length === 1) { var precisionDigits = arguments[0] var sizeBasedScaleFactor = BufferOp.precisionScaleFactor(this._argGeom, this._distance, precisionDigits) var fixedPM = new PrecisionModel(sizeBasedScaleFactor) this.bufferFixedPrecision(fixedPM) } } BufferOp.prototype.computeGeometry = function computeGeometry () { this.bufferOriginalPrecision() if (this._resultGeometry !== null) { return null } var argPM = this._argGeom.getFactory().getPrecisionModel() if (argPM.getType() === PrecisionModel.FIXED) { this.bufferFixedPrecision(argPM) } else { this.bufferReducedPrecision() } } BufferOp.prototype.setQuadrantSegments = function setQuadrantSegments (quadrantSegments) { this._bufParams.setQuadrantSegments(quadrantSegments) } BufferOp.prototype.bufferOriginalPrecision = function bufferOriginalPrecision () { try { var bufBuilder = new BufferBuilder(this._bufParams) this._resultGeometry = bufBuilder.buffer(this._argGeom, this._distance) } catch (ex) { if (ex instanceof RuntimeException) { this._saveException = ex } else { throw ex } } finally { } } BufferOp.prototype.getResultGeometry = function getResultGeometry (distance) { this._distance = distance this.computeGeometry() return this._resultGeometry } BufferOp.prototype.setEndCapStyle = function setEndCapStyle (endCapStyle) { this._bufParams.setEndCapStyle(endCapStyle) } BufferOp.prototype.interfaces_ = function interfaces_ () { return [] } BufferOp.prototype.getClass = function getClass () { return BufferOp } BufferOp.bufferOp = function bufferOp () { if (arguments.length === 2) { var g = arguments[0] var distance = arguments[1] var gBuf = new BufferOp(g) var geomBuf = gBuf.getResultGeometry(distance) return geomBuf } else if (arguments.length === 3) { if (Number.isInteger(arguments[2]) && (arguments[0] instanceof Geometry$2 && typeof arguments[1] === 'number')) { var g$1 = arguments[0] var distance$1 = arguments[1] var quadrantSegments = arguments[2] var bufOp = new BufferOp(g$1) bufOp.setQuadrantSegments(quadrantSegments) var geomBuf$1 = bufOp.getResultGeometry(distance$1) return geomBuf$1 } else if (arguments[2] instanceof BufferParameters && (arguments[0] instanceof Geometry$2 && typeof arguments[1] === 'number')) { var g$2 = arguments[0] var distance$2 = arguments[1] var params = arguments[2] var bufOp$1 = new BufferOp(g$2, params) var geomBuf$2 = bufOp$1.getResultGeometry(distance$2) return geomBuf$2 } } else if (arguments.length === 4) { var g$3 = arguments[0] var distance$3 = arguments[1] var quadrantSegments$1 = arguments[2] var endCapStyle = arguments[3] var bufOp$2 = new BufferOp(g$3) bufOp$2.setQuadrantSegments(quadrantSegments$1) bufOp$2.setEndCapStyle(endCapStyle) var geomBuf$3 = bufOp$2.getResultGeometry(distance$3) return geomBuf$3 } } BufferOp.precisionScaleFactor = function precisionScaleFactor (g, distance, maxPrecisionDigits) { var env = g.getEnvelopeInternal() var envMax = MathUtil.max(Math.abs(env.getMaxX()), Math.abs(env.getMaxY()), Math.abs(env.getMinX()), Math.abs(env.getMinY())) var expandByDistance = distance > 0.0 ? distance : 0.0 var bufEnvMax = envMax + 2 * expandByDistance var bufEnvPrecisionDigits = Math.trunc(Math.log(bufEnvMax) / Math.log(10) + 1.0) var minUnitLog10 = maxPrecisionDigits - bufEnvPrecisionDigits var scaleFactor = Math.pow(10.0, minUnitLog10) return scaleFactor } staticAccessors$32.CAP_ROUND.get = function () { return BufferParameters.CAP_ROUND } staticAccessors$32.CAP_BUTT.get = function () { return BufferParameters.CAP_FLAT } staticAccessors$32.CAP_FLAT.get = function () { return BufferParameters.CAP_FLAT } staticAccessors$32.CAP_SQUARE.get = function () { return BufferParameters.CAP_SQUARE } staticAccessors$32.MAX_PRECISION_DIGITS.get = function () { return 12 } Object.defineProperties(BufferOp, staticAccessors$32) var PointPairDistance = function PointPairDistance () { this._pt = [new Coordinate(), new Coordinate()] this._distance = Double.NaN this._isNull = true } PointPairDistance.prototype.getCoordinates = function getCoordinates () { return this._pt } PointPairDistance.prototype.getCoordinate = function getCoordinate (i) { return this._pt[i] } PointPairDistance.prototype.setMinimum = function setMinimum () { if (arguments.length === 1) { var ptDist = arguments[0] this.setMinimum(ptDist._pt[0], ptDist._pt[1]) } else if (arguments.length === 2) { var p0 = arguments[0] var p1 = arguments[1] if (this._isNull) { this.initialize(p0, p1) return null } var dist = p0.distance(p1) if (dist < this._distance) { this.initialize(p0, p1, dist) } } } PointPairDistance.prototype.initialize = function initialize () { if (arguments.length === 0) { this._isNull = true } else if (arguments.length === 2) { var p0 = arguments[0] var p1 = arguments[1] this._pt[0].setCoordinate(p0) this._pt[1].setCoordinate(p1) this._distance = p0.distance(p1) this._isNull = false } else if (arguments.length === 3) { var p0$1 = arguments[0] var p1$1 = arguments[1] var distance = arguments[2] this._pt[0].setCoordinate(p0$1) this._pt[1].setCoordinate(p1$1) this._distance = distance this._isNull = false } } PointPairDistance.prototype.getDistance = function getDistance () { return this._distance } PointPairDistance.prototype.setMaximum = function setMaximum () { if (arguments.length === 1) { var ptDist = arguments[0] this.setMaximum(ptDist._pt[0], ptDist._pt[1]) } else if (arguments.length === 2) { var p0 = arguments[0] var p1 = arguments[1] if (this._isNull) { this.initialize(p0, p1) return null } var dist = p0.distance(p1) if (dist > this._distance) { this.initialize(p0, p1, dist) } } } PointPairDistance.prototype.interfaces_ = function interfaces_ () { return [] } PointPairDistance.prototype.getClass = function getClass () { return PointPairDistance } var DistanceToPointFinder = function DistanceToPointFinder () { } DistanceToPointFinder.prototype.interfaces_ = function interfaces_ () { return [] } DistanceToPointFinder.prototype.getClass = function getClass () { return DistanceToPointFinder } DistanceToPointFinder.computeDistance = function computeDistance () { if (arguments[2] instanceof PointPairDistance && (arguments[0] instanceof LineString && arguments[1] instanceof Coordinate)) { var line = arguments[0] var pt = arguments[1] var ptDist = arguments[2] var coords = line.getCoordinates() var tempSegment = new LineSegment() for (var i = 0; i < coords.length - 1; i++) { tempSegment.setCoordinates(coords[i], coords[i + 1]) var closestPt = tempSegment.closestPoint(pt) ptDist.setMinimum(closestPt, pt) } } else if (arguments[2] instanceof PointPairDistance && (arguments[0] instanceof Polygon && arguments[1] instanceof Coordinate)) { var poly = arguments[0] var pt$1 = arguments[1] var ptDist$1 = arguments[2] DistanceToPointFinder.computeDistance(poly.getExteriorRing(), pt$1, ptDist$1) for (var i$1 = 0; i$1 < poly.getNumInteriorRing(); i$1++) { DistanceToPointFinder.computeDistance(poly.getInteriorRingN(i$1), pt$1, ptDist$1) } } else if (arguments[2] instanceof PointPairDistance && (arguments[0] instanceof Geometry$2 && arguments[1] instanceof Coordinate)) { var geom = arguments[0] var pt$2 = arguments[1] var ptDist$2 = arguments[2] if (geom instanceof LineString) { DistanceToPointFinder.computeDistance(geom, pt$2, ptDist$2) } else if (geom instanceof Polygon) { DistanceToPointFinder.computeDistance(geom, pt$2, ptDist$2) } else if (geom instanceof GeometryCollection) { var gc = geom for (var i$2 = 0; i$2 < gc.getNumGeometries(); i$2++) { var g = gc.getGeometryN(i$2) DistanceToPointFinder.computeDistance(g, pt$2, ptDist$2) } } else { ptDist$2.setMinimum(geom.getCoordinate(), pt$2) } } else if (arguments[2] instanceof PointPairDistance && (arguments[0] instanceof LineSegment && arguments[1] instanceof Coordinate)) { var segment = arguments[0] var pt$3 = arguments[1] var ptDist$3 = arguments[2] var closestPt$1 = segment.closestPoint(pt$3) ptDist$3.setMinimum(closestPt$1, pt$3) } } var BufferCurveMaximumDistanceFinder = function BufferCurveMaximumDistanceFinder (inputGeom) { this._maxPtDist = new PointPairDistance() this._inputGeom = inputGeom || null } var staticAccessors$36 = { MaxPointDistanceFilter: { configurable: true }, MaxMidpointDistanceFilter: { configurable: true } } BufferCurveMaximumDistanceFinder.prototype.computeMaxMidpointDistance = function computeMaxMidpointDistance (curve) { var distFilter = new MaxMidpointDistanceFilter(this._inputGeom) curve.apply(distFilter) this._maxPtDist.setMaximum(distFilter.getMaxPointDistance()) } BufferCurveMaximumDistanceFinder.prototype.computeMaxVertexDistance = function computeMaxVertexDistance (curve) { var distFilter = new MaxPointDistanceFilter(this._inputGeom) curve.apply(distFilter) this._maxPtDist.setMaximum(distFilter.getMaxPointDistance()) } BufferCurveMaximumDistanceFinder.prototype.findDistance = function findDistance (bufferCurve) { this.computeMaxVertexDistance(bufferCurve) this.computeMaxMidpointDistance(bufferCurve) return this._maxPtDist.getDistance() } BufferCurveMaximumDistanceFinder.prototype.getDistancePoints = function getDistancePoints () { return this._maxPtDist } BufferCurveMaximumDistanceFinder.prototype.interfaces_ = function interfaces_ () { return [] } BufferCurveMaximumDistanceFinder.prototype.getClass = function getClass () { return BufferCurveMaximumDistanceFinder } staticAccessors$36.MaxPointDistanceFilter.get = function () { return MaxPointDistanceFilter } staticAccessors$36.MaxMidpointDistanceFilter.get = function () { return MaxMidpointDistanceFilter } Object.defineProperties(BufferCurveMaximumDistanceFinder, staticAccessors$36) var MaxPointDistanceFilter = function MaxPointDistanceFilter (geom) { this._maxPtDist = new PointPairDistance() this._minPtDist = new PointPairDistance() this._geom = geom || null } MaxPointDistanceFilter.prototype.filter = function filter (pt) { this._minPtDist.initialize() DistanceToPointFinder.computeDistance(this._geom, pt, this._minPtDist) this._maxPtDist.setMaximum(this._minPtDist) } MaxPointDistanceFilter.prototype.getMaxPointDistance = function getMaxPointDistance () { return this._maxPtDist } MaxPointDistanceFilter.prototype.interfaces_ = function interfaces_ () { return [CoordinateFilter] } MaxPointDistanceFilter.prototype.getClass = function getClass () { return MaxPointDistanceFilter } var MaxMidpointDistanceFilter = function MaxMidpointDistanceFilter (geom) { this._maxPtDist = new PointPairDistance() this._minPtDist = new PointPairDistance() this._geom = geom || null } MaxMidpointDistanceFilter.prototype.filter = function filter (seq, index) { if (index === 0) { return null } var p0 = seq.getCoordinate(index - 1) var p1 = seq.getCoordinate(index) var midPt = new Coordinate((p0.x + p1.x) / 2, (p0.y + p1.y) / 2) this._minPtDist.initialize() DistanceToPointFinder.computeDistance(this._geom, midPt, this._minPtDist) this._maxPtDist.setMaximum(this._minPtDist) } MaxMidpointDistanceFilter.prototype.isDone = function isDone () { return false } MaxMidpointDistanceFilter.prototype.isGeometryChanged = function isGeometryChanged () { return false } MaxMidpointDistanceFilter.prototype.getMaxPointDistance = function getMaxPointDistance () { return this._maxPtDist } MaxMidpointDistanceFilter.prototype.interfaces_ = function interfaces_ () { return [CoordinateSequenceFilter] } MaxMidpointDistanceFilter.prototype.getClass = function getClass () { return MaxMidpointDistanceFilter } var PolygonExtracter = function PolygonExtracter (comps) { this._comps = comps || null } PolygonExtracter.prototype.filter = function filter (geom) { if (geom instanceof Polygon) { this._comps.add(geom) } } PolygonExtracter.prototype.interfaces_ = function interfaces_ () { return [GeometryFilter] } PolygonExtracter.prototype.getClass = function getClass () { return PolygonExtracter } PolygonExtracter.getPolygons = function getPolygons () { if (arguments.length === 1) { var geom = arguments[0] return PolygonExtracter.getPolygons(geom, new ArrayList()) } else if (arguments.length === 2) { var geom$1 = arguments[0] var list = arguments[1] if (geom$1 instanceof Polygon) { list.add(geom$1) } else if (geom$1 instanceof GeometryCollection) { geom$1.apply(new PolygonExtracter(list)) } return list } } var LinearComponentExtracter = function LinearComponentExtracter () { this._lines = null this._isForcedToLineString = false if (arguments.length === 1) { var lines = arguments[0] this._lines = lines } else if (arguments.length === 2) { var lines$1 = arguments[0] var isForcedToLineString = arguments[1] this._lines = lines$1 this._isForcedToLineString = isForcedToLineString } } LinearComponentExtracter.prototype.filter = function filter (geom) { if (this._isForcedToLineString && geom instanceof LinearRing) { var line = geom.getFactory().createLineString(geom.getCoordinateSequence()) this._lines.add(line) return null } if (geom instanceof LineString) { this._lines.add(geom) } } LinearComponentExtracter.prototype.setForceToLineString = function setForceToLineString (isForcedToLineString) { this._isForcedToLineString = isForcedToLineString } LinearComponentExtracter.prototype.interfaces_ = function interfaces_ () { return [GeometryComponentFilter] } LinearComponentExtracter.prototype.getClass = function getClass () { return LinearComponentExtracter } LinearComponentExtracter.getGeometry = function getGeometry () { if (arguments.length === 1) { var geom = arguments[0] return geom.getFactory().buildGeometry(LinearComponentExtracter.getLines(geom)) } else if (arguments.length === 2) { var geom$1 = arguments[0] var forceToLineString = arguments[1] return geom$1.getFactory().buildGeometry(LinearComponentExtracter.getLines(geom$1, forceToLineString)) } } LinearComponentExtracter.getLines = function getLines () { if (arguments.length === 1) { var geom = arguments[0] return LinearComponentExtracter.getLines(geom, false) } else if (arguments.length === 2) { if (hasInterface(arguments[0], Collection) && hasInterface(arguments[1], Collection)) { var geoms = arguments[0] var lines$1 = arguments[1] for (var i = geoms.iterator(); i.hasNext();) { var g = i.next() LinearComponentExtracter.getLines(g, lines$1) } return lines$1 } else if (arguments[0] instanceof Geometry$2 && typeof arguments[1] === 'boolean') { var geom$1 = arguments[0] var forceToLineString = arguments[1] var lines = new ArrayList() geom$1.apply(new LinearComponentExtracter(lines, forceToLineString)) return lines } else if (arguments[0] instanceof Geometry$2 && hasInterface(arguments[1], Collection)) { var geom$2 = arguments[0] var lines$2 = arguments[1] if (geom$2 instanceof LineString) { lines$2.add(geom$2) } else { geom$2.apply(new LinearComponentExtracter(lines$2)) } return lines$2 } } else if (arguments.length === 3) { if (typeof arguments[2] === 'boolean' && (hasInterface(arguments[0], Collection) && hasInterface(arguments[1], Collection))) { var geoms$1 = arguments[0] var lines$3 = arguments[1] var forceToLineString$1 = arguments[2] for (var i$1 = geoms$1.iterator(); i$1.hasNext();) { var g$1 = i$1.next() LinearComponentExtracter.getLines(g$1, lines$3, forceToLineString$1) } return lines$3 } else if (typeof arguments[2] === 'boolean' && (arguments[0] instanceof Geometry$2 && hasInterface(arguments[1], Collection))) { var geom$3 = arguments[0] var lines$4 = arguments[1] var forceToLineString$2 = arguments[2] geom$3.apply(new LinearComponentExtracter(lines$4, forceToLineString$2)) return lines$4 } } } var PointLocator = function PointLocator () { this._boundaryRule = BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE this._isIn = null this._numBoundaries = null if (arguments.length === 0); else if (arguments.length === 1) { var boundaryRule = arguments[0] if (boundaryRule === null) { throw new IllegalArgumentException('Rule must be non-null') } this._boundaryRule = boundaryRule } } PointLocator.prototype.locateInternal = function locateInternal () { var this$1$1 = this if (arguments[0] instanceof Coordinate && arguments[1] instanceof Polygon) { var p = arguments[0] var poly = arguments[1] if (poly.isEmpty()) { return Location.EXTERIOR } var shell = poly.getExteriorRing() var shellLoc = this.locateInPolygonRing(p, shell) if (shellLoc === Location.EXTERIOR) { return Location.EXTERIOR } if (shellLoc === Location.BOUNDARY) { return Location.BOUNDARY } for (var i = 0; i < poly.getNumInteriorRing(); i++) { var hole = poly.getInteriorRingN(i) var holeLoc = this$1$1.locateInPolygonRing(p, hole) if (holeLoc === Location.INTERIOR) { return Location.EXTERIOR } if (holeLoc === Location.BOUNDARY) { return Location.BOUNDARY } } return Location.INTERIOR } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof LineString) { var p$1 = arguments[0] var l = arguments[1] if (!l.getEnvelopeInternal().intersects(p$1)) { return Location.EXTERIOR } var pt = l.getCoordinates() if (!l.isClosed()) { if (p$1.equals(pt[0]) || p$1.equals(pt[pt.length - 1])) { return Location.BOUNDARY } } if (CGAlgorithms.isOnLine(p$1, pt)) { return Location.INTERIOR } return Location.EXTERIOR } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Point) { var p$2 = arguments[0] var pt$1 = arguments[1] var ptCoord = pt$1.getCoordinate() if (ptCoord.equals2D(p$2)) { return Location.INTERIOR } return Location.EXTERIOR } } PointLocator.prototype.locateInPolygonRing = function locateInPolygonRing (p, ring) { if (!ring.getEnvelopeInternal().intersects(p)) { return Location.EXTERIOR } return CGAlgorithms.locatePointInRing(p, ring.getCoordinates()) } PointLocator.prototype.intersects = function intersects (p, geom) { return this.locate(p, geom) !== Location.EXTERIOR } PointLocator.prototype.updateLocationInfo = function updateLocationInfo (loc) { if (loc === Location.INTERIOR) { this._isIn = true } if (loc === Location.BOUNDARY) { this._numBoundaries++ } } PointLocator.prototype.computeLocation = function computeLocation (p, geom) { var this$1$1 = this if (geom instanceof Point) { this.updateLocationInfo(this.locateInternal(p, geom)) } if (geom instanceof LineString) { this.updateLocationInfo(this.locateInternal(p, geom)) } else if (geom instanceof Polygon) { this.updateLocationInfo(this.locateInternal(p, geom)) } else if (geom instanceof MultiLineString) { var ml = geom for (var i = 0; i < ml.getNumGeometries(); i++) { var l = ml.getGeometryN(i) this$1$1.updateLocationInfo(this$1$1.locateInternal(p, l)) } } else if (geom instanceof MultiPolygon) { var mpoly = geom for (var i$1 = 0; i$1 < mpoly.getNumGeometries(); i$1++) { var poly = mpoly.getGeometryN(i$1) this$1$1.updateLocationInfo(this$1$1.locateInternal(p, poly)) } } else if (geom instanceof GeometryCollection) { var geomi = new GeometryCollectionIterator(geom) while (geomi.hasNext()) { var g2 = geomi.next() if (g2 !== geom) { this$1$1.computeLocation(p, g2) } } } } PointLocator.prototype.locate = function locate (p, geom) { if (geom.isEmpty()) { return Location.EXTERIOR } if (geom instanceof LineString) { return this.locateInternal(p, geom) } else if (geom instanceof Polygon) { return this.locateInternal(p, geom) } this._isIn = false this._numBoundaries = 0 this.computeLocation(p, geom) if (this._boundaryRule.isInBoundary(this._numBoundaries)) { return Location.BOUNDARY } if (this._numBoundaries > 0 || this._isIn) { return Location.INTERIOR } return Location.EXTERIOR } PointLocator.prototype.interfaces_ = function interfaces_ () { return [] } PointLocator.prototype.getClass = function getClass () { return PointLocator } var GeometryLocation = function GeometryLocation () { this._component = null this._segIndex = null this._pt = null if (arguments.length === 2) { var component = arguments[0] var pt = arguments[1] GeometryLocation.call(this, component, GeometryLocation.INSIDE_AREA, pt) } else if (arguments.length === 3) { var component$1 = arguments[0] var segIndex = arguments[1] var pt$1 = arguments[2] this._component = component$1 this._segIndex = segIndex this._pt = pt$1 } } var staticAccessors$38 = { INSIDE_AREA: { configurable: true } } GeometryLocation.prototype.isInsideArea = function isInsideArea () { return this._segIndex === GeometryLocation.INSIDE_AREA } GeometryLocation.prototype.getCoordinate = function getCoordinate () { return this._pt } GeometryLocation.prototype.getGeometryComponent = function getGeometryComponent () { return this._component } GeometryLocation.prototype.getSegmentIndex = function getSegmentIndex () { return this._segIndex } GeometryLocation.prototype.interfaces_ = function interfaces_ () { return [] } GeometryLocation.prototype.getClass = function getClass () { return GeometryLocation } staticAccessors$38.INSIDE_AREA.get = function () { return -1 } Object.defineProperties(GeometryLocation, staticAccessors$38) var PointExtracter = function PointExtracter (pts) { this._pts = pts || null } PointExtracter.prototype.filter = function filter (geom) { if (geom instanceof Point) { this._pts.add(geom) } } PointExtracter.prototype.interfaces_ = function interfaces_ () { return [GeometryFilter] } PointExtracter.prototype.getClass = function getClass () { return PointExtracter } PointExtracter.getPoints = function getPoints () { if (arguments.length === 1) { var geom = arguments[0] if (geom instanceof Point) { return Collections.singletonList(geom) } return PointExtracter.getPoints(geom, new ArrayList()) } else if (arguments.length === 2) { var geom$1 = arguments[0] var list = arguments[1] if (geom$1 instanceof Point) { list.add(geom$1) } else if (geom$1 instanceof GeometryCollection) { geom$1.apply(new PointExtracter(list)) } return list } } var ConnectedElementLocationFilter = function ConnectedElementLocationFilter () { this._locations = null var locations = arguments[0] this._locations = locations } ConnectedElementLocationFilter.prototype.filter = function filter (geom) { if (geom instanceof Point || geom instanceof LineString || geom instanceof Polygon) { this._locations.add(new GeometryLocation(geom, 0, geom.getCoordinate())) } } ConnectedElementLocationFilter.prototype.interfaces_ = function interfaces_ () { return [GeometryFilter] } ConnectedElementLocationFilter.prototype.getClass = function getClass () { return ConnectedElementLocationFilter } ConnectedElementLocationFilter.getLocations = function getLocations (geom) { var locations = new ArrayList() geom.apply(new ConnectedElementLocationFilter(locations)) return locations } var DistanceOp = function DistanceOp () { this._geom = null this._terminateDistance = 0.0 this._ptLocator = new PointLocator() this._minDistanceLocation = null this._minDistance = Double.MAX_VALUE if (arguments.length === 2) { var g0 = arguments[0] var g1 = arguments[1] this._geom = [g0, g1] this._terminateDistance = 0.0 } else if (arguments.length === 3) { var g0$1 = arguments[0] var g1$1 = arguments[1] var terminateDistance = arguments[2] this._geom = new Array(2).fill(null) this._geom[0] = g0$1 this._geom[1] = g1$1 this._terminateDistance = terminateDistance } } DistanceOp.prototype.computeContainmentDistance = function computeContainmentDistance () { var this$1$1 = this if (arguments.length === 0) { var locPtPoly = new Array(2).fill(null) this.computeContainmentDistance(0, locPtPoly) if (this._minDistance <= this._terminateDistance) { return null } this.computeContainmentDistance(1, locPtPoly) } else if (arguments.length === 2) { var polyGeomIndex = arguments[0] var locPtPoly$1 = arguments[1] var locationsIndex = 1 - polyGeomIndex var polys = PolygonExtracter.getPolygons(this._geom[polyGeomIndex]) if (polys.size() > 0) { var insideLocs = ConnectedElementLocationFilter.getLocations(this._geom[locationsIndex]) this.computeContainmentDistance(insideLocs, polys, locPtPoly$1) if (this._minDistance <= this._terminateDistance) { this._minDistanceLocation[locationsIndex] = locPtPoly$1[0] this._minDistanceLocation[polyGeomIndex] = locPtPoly$1[1] return null } } } else if (arguments.length === 3) { if (arguments[2] instanceof Array && (hasInterface(arguments[0], List) && hasInterface(arguments[1], List))) { var locs = arguments[0] var polys$1 = arguments[1] var locPtPoly$2 = arguments[2] for (var i = 0; i < locs.size(); i++) { var loc = locs.get(i) for (var j = 0; j < polys$1.size(); j++) { this$1$1.computeContainmentDistance(loc, polys$1.get(j), locPtPoly$2) if (this$1$1._minDistance <= this$1$1._terminateDistance) { return null } } } } else if (arguments[2] instanceof Array && (arguments[0] instanceof GeometryLocation && arguments[1] instanceof Polygon)) { var ptLoc = arguments[0] var poly = arguments[1] var locPtPoly$3 = arguments[2] var pt = ptLoc.getCoordinate() if (Location.EXTERIOR !== this._ptLocator.locate(pt, poly)) { this._minDistance = 0.0 locPtPoly$3[0] = ptLoc locPtPoly$3[1] = new GeometryLocation(poly, pt) return null } } } } DistanceOp.prototype.computeMinDistanceLinesPoints = function computeMinDistanceLinesPoints (lines, points, locGeom) { var this$1$1 = this for (var i = 0; i < lines.size(); i++) { var line = lines.get(i) for (var j = 0; j < points.size(); j++) { var pt = points.get(j) this$1$1.computeMinDistance(line, pt, locGeom) if (this$1$1._minDistance <= this$1$1._terminateDistance) { return null } } } } DistanceOp.prototype.computeFacetDistance = function computeFacetDistance () { var locGeom = new Array(2).fill(null) var lines0 = LinearComponentExtracter.getLines(this._geom[0]) var lines1 = LinearComponentExtracter.getLines(this._geom[1]) var pts0 = PointExtracter.getPoints(this._geom[0]) var pts1 = PointExtracter.getPoints(this._geom[1]) this.computeMinDistanceLines(lines0, lines1, locGeom) this.updateMinDistance(locGeom, false) if (this._minDistance <= this._terminateDistance) { return null } locGeom[0] = null locGeom[1] = null this.computeMinDistanceLinesPoints(lines0, pts1, locGeom) this.updateMinDistance(locGeom, false) if (this._minDistance <= this._terminateDistance) { return null } locGeom[0] = null locGeom[1] = null this.computeMinDistanceLinesPoints(lines1, pts0, locGeom) this.updateMinDistance(locGeom, true) if (this._minDistance <= this._terminateDistance) { return null } locGeom[0] = null locGeom[1] = null this.computeMinDistancePoints(pts0, pts1, locGeom) this.updateMinDistance(locGeom, false) } DistanceOp.prototype.nearestLocations = function nearestLocations () { this.computeMinDistance() return this._minDistanceLocation } DistanceOp.prototype.updateMinDistance = function updateMinDistance (locGeom, flip) { if (locGeom[0] === null) { return null } if (flip) { this._minDistanceLocation[0] = locGeom[1] this._minDistanceLocation[1] = locGeom[0] } else { this._minDistanceLocation[0] = locGeom[0] this._minDistanceLocation[1] = locGeom[1] } } DistanceOp.prototype.nearestPoints = function nearestPoints () { this.computeMinDistance() var nearestPts = [this._minDistanceLocation[0].getCoordinate(), this._minDistanceLocation[1].getCoordinate()] return nearestPts } DistanceOp.prototype.computeMinDistance = function computeMinDistance () { var this$1$1 = this if (arguments.length === 0) { if (this._minDistanceLocation !== null) { return null } this._minDistanceLocation = new Array(2).fill(null) this.computeContainmentDistance() if (this._minDistance <= this._terminateDistance) { return null } this.computeFacetDistance() } else if (arguments.length === 3) { if (arguments[2] instanceof Array && (arguments[0] instanceof LineString && arguments[1] instanceof Point)) { var line = arguments[0] var pt = arguments[1] var locGeom = arguments[2] if (line.getEnvelopeInternal().distance(pt.getEnvelopeInternal()) > this._minDistance) { return null } var coord0 = line.getCoordinates() var coord = pt.getCoordinate() for (var i = 0; i < coord0.length - 1; i++) { var dist = CGAlgorithms.distancePointLine(coord, coord0[i], coord0[i + 1]) if (dist < this$1$1._minDistance) { this$1$1._minDistance = dist var seg = new LineSegment(coord0[i], coord0[i + 1]) var segClosestPoint = seg.closestPoint(coord) locGeom[0] = new GeometryLocation(line, i, segClosestPoint) locGeom[1] = new GeometryLocation(pt, 0, coord) } if (this$1$1._minDistance <= this$1$1._terminateDistance) { return null } } } else if (arguments[2] instanceof Array && (arguments[0] instanceof LineString && arguments[1] instanceof LineString)) { var line0 = arguments[0] var line1 = arguments[1] var locGeom$1 = arguments[2] if (line0.getEnvelopeInternal().distance(line1.getEnvelopeInternal()) > this._minDistance) { return null } var coord0$1 = line0.getCoordinates() var coord1 = line1.getCoordinates() for (var i$1 = 0; i$1 < coord0$1.length - 1; i$1++) { for (var j = 0; j < coord1.length - 1; j++) { var dist$1 = CGAlgorithms.distanceLineLine(coord0$1[i$1], coord0$1[i$1 + 1], coord1[j], coord1[j + 1]) if (dist$1 < this$1$1._minDistance) { this$1$1._minDistance = dist$1 var seg0 = new LineSegment(coord0$1[i$1], coord0$1[i$1 + 1]) var seg1 = new LineSegment(coord1[j], coord1[j + 1]) var closestPt = seg0.closestPoints(seg1) locGeom$1[0] = new GeometryLocation(line0, i$1, closestPt[0]) locGeom$1[1] = new GeometryLocation(line1, j, closestPt[1]) } if (this$1$1._minDistance <= this$1$1._terminateDistance) { return null } } } } } } DistanceOp.prototype.computeMinDistancePoints = function computeMinDistancePoints (points0, points1, locGeom) { var this$1$1 = this for (var i = 0; i < points0.size(); i++) { var pt0 = points0.get(i) for (var j = 0; j < points1.size(); j++) { var pt1 = points1.get(j) var dist = pt0.getCoordinate().distance(pt1.getCoordinate()) if (dist < this$1$1._minDistance) { this$1$1._minDistance = dist locGeom[0] = new GeometryLocation(pt0, 0, pt0.getCoordinate()) locGeom[1] = new GeometryLocation(pt1, 0, pt1.getCoordinate()) } if (this$1$1._minDistance <= this$1$1._terminateDistance) { return null } } } } DistanceOp.prototype.distance = function distance () { if (this._geom[0] === null || this._geom[1] === null) { throw new IllegalArgumentException('null geometries are not supported') } if (this._geom[0].isEmpty() || this._geom[1].isEmpty()) { return 0.0 } this.computeMinDistance() return this._minDistance } DistanceOp.prototype.computeMinDistanceLines = function computeMinDistanceLines (lines0, lines1, locGeom) { var this$1$1 = this for (var i = 0; i < lines0.size(); i++) { var line0 = lines0.get(i) for (var j = 0; j < lines1.size(); j++) { var line1 = lines1.get(j) this$1$1.computeMinDistance(line0, line1, locGeom) if (this$1$1._minDistance <= this$1$1._terminateDistance) { return null } } } } DistanceOp.prototype.interfaces_ = function interfaces_ () { return [] } DistanceOp.prototype.getClass = function getClass () { return DistanceOp } DistanceOp.distance = function distance (g0, g1) { var distOp = new DistanceOp(g0, g1) return distOp.distance() } DistanceOp.isWithinDistance = function isWithinDistance (g0, g1, distance) { var distOp = new DistanceOp(g0, g1, distance) return distOp.distance() <= distance } DistanceOp.nearestPoints = function nearestPoints (g0, g1) { var distOp = new DistanceOp(g0, g1) return distOp.nearestPoints() } var PointPairDistance$2 = function PointPairDistance () { this._pt = [new Coordinate(), new Coordinate()] this._distance = Double.NaN this._isNull = true } PointPairDistance$2.prototype.getCoordinates = function getCoordinates () { return this._pt } PointPairDistance$2.prototype.getCoordinate = function getCoordinate (i) { return this._pt[i] } PointPairDistance$2.prototype.setMinimum = function setMinimum () { if (arguments.length === 1) { var ptDist = arguments[0] this.setMinimum(ptDist._pt[0], ptDist._pt[1]) } else if (arguments.length === 2) { var p0 = arguments[0] var p1 = arguments[1] if (this._isNull) { this.initialize(p0, p1) return null } var dist = p0.distance(p1) if (dist < this._distance) { this.initialize(p0, p1, dist) } } } PointPairDistance$2.prototype.initialize = function initialize () { if (arguments.length === 0) { this._isNull = true } else if (arguments.length === 2) { var p0 = arguments[0] var p1 = arguments[1] this._pt[0].setCoordinate(p0) this._pt[1].setCoordinate(p1) this._distance = p0.distance(p1) this._isNull = false } else if (arguments.length === 3) { var p0$1 = arguments[0] var p1$1 = arguments[1] var distance = arguments[2] this._pt[0].setCoordinate(p0$1) this._pt[1].setCoordinate(p1$1) this._distance = distance this._isNull = false } } PointPairDistance$2.prototype.toString = function toString () { return WKTWriter.toLineString(this._pt[0], this._pt[1]) } PointPairDistance$2.prototype.getDistance = function getDistance () { return this._distance } PointPairDistance$2.prototype.setMaximum = function setMaximum () { if (arguments.length === 1) { var ptDist = arguments[0] this.setMaximum(ptDist._pt[0], ptDist._pt[1]) } else if (arguments.length === 2) { var p0 = arguments[0] var p1 = arguments[1] if (this._isNull) { this.initialize(p0, p1) return null } var dist = p0.distance(p1) if (dist > this._distance) { this.initialize(p0, p1, dist) } } } PointPairDistance$2.prototype.interfaces_ = function interfaces_ () { return [] } PointPairDistance$2.prototype.getClass = function getClass () { return PointPairDistance$2 } var DistanceToPoint = function DistanceToPoint () { } DistanceToPoint.prototype.interfaces_ = function interfaces_ () { return [] } DistanceToPoint.prototype.getClass = function getClass () { return DistanceToPoint } DistanceToPoint.computeDistance = function computeDistance () { if (arguments[2] instanceof PointPairDistance$2 && (arguments[0] instanceof LineString && arguments[1] instanceof Coordinate)) { var line = arguments[0] var pt = arguments[1] var ptDist = arguments[2] var tempSegment = new LineSegment() var coords = line.getCoordinates() for (var i = 0; i < coords.length - 1; i++) { tempSegment.setCoordinates(coords[i], coords[i + 1]) var closestPt = tempSegment.closestPoint(pt) ptDist.setMinimum(closestPt, pt) } } else if (arguments[2] instanceof PointPairDistance$2 && (arguments[0] instanceof Polygon && arguments[1] instanceof Coordinate)) { var poly = arguments[0] var pt$1 = arguments[1] var ptDist$1 = arguments[2] DistanceToPoint.computeDistance(poly.getExteriorRing(), pt$1, ptDist$1) for (var i$1 = 0; i$1 < poly.getNumInteriorRing(); i$1++) { DistanceToPoint.computeDistance(poly.getInteriorRingN(i$1), pt$1, ptDist$1) } } else if (arguments[2] instanceof PointPairDistance$2 && (arguments[0] instanceof Geometry$2 && arguments[1] instanceof Coordinate)) { var geom = arguments[0] var pt$2 = arguments[1] var ptDist$2 = arguments[2] if (geom instanceof LineString) { DistanceToPoint.computeDistance(geom, pt$2, ptDist$2) } else if (geom instanceof Polygon) { DistanceToPoint.computeDistance(geom, pt$2, ptDist$2) } else if (geom instanceof GeometryCollection) { var gc = geom for (var i$2 = 0; i$2 < gc.getNumGeometries(); i$2++) { var g = gc.getGeometryN(i$2) DistanceToPoint.computeDistance(g, pt$2, ptDist$2) } } else { ptDist$2.setMinimum(geom.getCoordinate(), pt$2) } } else if (arguments[2] instanceof PointPairDistance$2 && (arguments[0] instanceof LineSegment && arguments[1] instanceof Coordinate)) { var segment = arguments[0] var pt$3 = arguments[1] var ptDist$3 = arguments[2] var closestPt$1 = segment.closestPoint(pt$3) ptDist$3.setMinimum(closestPt$1, pt$3) } } var DiscreteHausdorffDistance = function DiscreteHausdorffDistance () { this._g0 = null this._g1 = null this._ptDist = new PointPairDistance$2() this._densifyFrac = 0.0 var g0 = arguments[0] var g1 = arguments[1] this._g0 = g0 this._g1 = g1 } var staticAccessors$39 = { MaxPointDistanceFilter: { configurable: true }, MaxDensifiedByFractionDistanceFilter: { configurable: true } } DiscreteHausdorffDistance.prototype.getCoordinates = function getCoordinates () { return this._ptDist.getCoordinates() } DiscreteHausdorffDistance.prototype.setDensifyFraction = function setDensifyFraction (densifyFrac) { if (densifyFrac > 1.0 || densifyFrac <= 0.0) { throw new IllegalArgumentException('Fraction is not in range (0.0 - 1.0]') } this._densifyFrac = densifyFrac } DiscreteHausdorffDistance.prototype.compute = function compute (g0, g1) { this.computeOrientedDistance(g0, g1, this._ptDist) this.computeOrientedDistance(g1, g0, this._ptDist) } DiscreteHausdorffDistance.prototype.distance = function distance () { this.compute(this._g0, this._g1) return this._ptDist.getDistance() } DiscreteHausdorffDistance.prototype.computeOrientedDistance = function computeOrientedDistance (discreteGeom, geom, ptDist) { var distFilter = new MaxPointDistanceFilter$1(geom) discreteGeom.apply(distFilter) ptDist.setMaximum(distFilter.getMaxPointDistance()) if (this._densifyFrac > 0) { var fracFilter = new MaxDensifiedByFractionDistanceFilter(geom, this._densifyFrac) discreteGeom.apply(fracFilter) ptDist.setMaximum(fracFilter.getMaxPointDistance()) } } DiscreteHausdorffDistance.prototype.orientedDistance = function orientedDistance () { this.computeOrientedDistance(this._g0, this._g1, this._ptDist) return this._ptDist.getDistance() } DiscreteHausdorffDistance.prototype.interfaces_ = function interfaces_ () { return [] } DiscreteHausdorffDistance.prototype.getClass = function getClass () { return DiscreteHausdorffDistance } DiscreteHausdorffDistance.distance = function distance () { if (arguments.length === 2) { var g0 = arguments[0] var g1 = arguments[1] var dist = new DiscreteHausdorffDistance(g0, g1) return dist.distance() } else if (arguments.length === 3) { var g0$1 = arguments[0] var g1$1 = arguments[1] var densifyFrac = arguments[2] var dist$1 = new DiscreteHausdorffDistance(g0$1, g1$1) dist$1.setDensifyFraction(densifyFrac) return dist$1.distance() } } staticAccessors$39.MaxPointDistanceFilter.get = function () { return MaxPointDistanceFilter$1 } staticAccessors$39.MaxDensifiedByFractionDistanceFilter.get = function () { return MaxDensifiedByFractionDistanceFilter } Object.defineProperties(DiscreteHausdorffDistance, staticAccessors$39) var MaxPointDistanceFilter$1 = function MaxPointDistanceFilter () { this._maxPtDist = new PointPairDistance$2() this._minPtDist = new PointPairDistance$2() this._euclideanDist = new DistanceToPoint() this._geom = null var geom = arguments[0] this._geom = geom } MaxPointDistanceFilter$1.prototype.filter = function filter (pt) { this._minPtDist.initialize() DistanceToPoint.computeDistance(this._geom, pt, this._minPtDist) this._maxPtDist.setMaximum(this._minPtDist) } MaxPointDistanceFilter$1.prototype.getMaxPointDistance = function getMaxPointDistance () { return this._maxPtDist } MaxPointDistanceFilter$1.prototype.interfaces_ = function interfaces_ () { return [CoordinateFilter] } MaxPointDistanceFilter$1.prototype.getClass = function getClass () { return MaxPointDistanceFilter$1 } var MaxDensifiedByFractionDistanceFilter = function MaxDensifiedByFractionDistanceFilter () { this._maxPtDist = new PointPairDistance$2() this._minPtDist = new PointPairDistance$2() this._geom = null this._numSubSegs = 0 var geom = arguments[0] var fraction = arguments[1] this._geom = geom this._numSubSegs = Math.trunc(Math.round(1.0 / fraction)) } MaxDensifiedByFractionDistanceFilter.prototype.filter = function filter (seq, index) { var this$1$1 = this if (index === 0) { return null } var p0 = seq.getCoordinate(index - 1) var p1 = seq.getCoordinate(index) var delx = (p1.x - p0.x) / this._numSubSegs var dely = (p1.y - p0.y) / this._numSubSegs for (var i = 0; i < this._numSubSegs; i++) { var x = p0.x + i * delx var y = p0.y + i * dely var pt = new Coordinate(x, y) this$1$1._minPtDist.initialize() DistanceToPoint.computeDistance(this$1$1._geom, pt, this$1$1._minPtDist) this$1$1._maxPtDist.setMaximum(this$1$1._minPtDist) } } MaxDensifiedByFractionDistanceFilter.prototype.isDone = function isDone () { return false } MaxDensifiedByFractionDistanceFilter.prototype.isGeometryChanged = function isGeometryChanged () { return false } MaxDensifiedByFractionDistanceFilter.prototype.getMaxPointDistance = function getMaxPointDistance () { return this._maxPtDist } MaxDensifiedByFractionDistanceFilter.prototype.interfaces_ = function interfaces_ () { return [CoordinateSequenceFilter] } MaxDensifiedByFractionDistanceFilter.prototype.getClass = function getClass () { return MaxDensifiedByFractionDistanceFilter } var BufferDistanceValidator = function BufferDistanceValidator (input, bufDistance, result) { this._minValidDistance = null this._maxValidDistance = null this._minDistanceFound = null this._maxDistanceFound = null this._isValid = true this._errMsg = null this._errorLocation = null this._errorIndicator = null this._input = input || null this._bufDistance = bufDistance || null this._result = result || null } var staticAccessors$37 = { VERBOSE: { configurable: true }, MAX_DISTANCE_DIFF_FRAC: { configurable: true } } BufferDistanceValidator.prototype.checkMaximumDistance = function checkMaximumDistance (input, bufCurve, maxDist) { var haus = new DiscreteHausdorffDistance(bufCurve, input) haus.setDensifyFraction(0.25) this._maxDistanceFound = haus.orientedDistance() if (this._maxDistanceFound > maxDist) { this._isValid = false var pts = haus.getCoordinates() this._errorLocation = pts[1] this._errorIndicator = input.getFactory().createLineString(pts) this._errMsg = 'Distance between buffer curve and input is too large (' + this._maxDistanceFound + ' at ' + WKTWriter.toLineString(pts[0], pts[1]) + ')' } } BufferDistanceValidator.prototype.isValid = function isValid () { var posDistance = Math.abs(this._bufDistance) var distDelta = BufferDistanceValidator.MAX_DISTANCE_DIFF_FRAC * posDistance this._minValidDistance = posDistance - distDelta this._maxValidDistance = posDistance + distDelta if (this._input.isEmpty() || this._result.isEmpty()) { return true } if (this._bufDistance > 0.0) { this.checkPositiveValid() } else { this.checkNegativeValid() } if (BufferDistanceValidator.VERBOSE) { System.out.println('Min Dist= ' + this._minDistanceFound + ' err= ' + (1.0 - this._minDistanceFound / this._bufDistance) + ' Max Dist= ' + this._maxDistanceFound + ' err= ' + (this._maxDistanceFound / this._bufDistance - 1.0)) } return this._isValid } BufferDistanceValidator.prototype.checkNegativeValid = function checkNegativeValid () { if (!(this._input instanceof Polygon || this._input instanceof MultiPolygon || this._input instanceof GeometryCollection)) { return null } var inputCurve = this.getPolygonLines(this._input) this.checkMinimumDistance(inputCurve, this._result, this._minValidDistance) if (!this._isValid) { return null } this.checkMaximumDistance(inputCurve, this._result, this._maxValidDistance) } BufferDistanceValidator.prototype.getErrorIndicator = function getErrorIndicator () { return this._errorIndicator } BufferDistanceValidator.prototype.checkMinimumDistance = function checkMinimumDistance (g1, g2, minDist) { var distOp = new DistanceOp(g1, g2, minDist) this._minDistanceFound = distOp.distance() if (this._minDistanceFound < minDist) { this._isValid = false var pts = distOp.nearestPoints() this._errorLocation = distOp.nearestPoints()[1] this._errorIndicator = g1.getFactory().createLineString(pts) this._errMsg = 'Distance between buffer curve and input is too small (' + this._minDistanceFound + ' at ' + WKTWriter.toLineString(pts[0], pts[1]) + ' )' } } BufferDistanceValidator.prototype.checkPositiveValid = function checkPositiveValid () { var bufCurve = this._result.getBoundary() this.checkMinimumDistance(this._input, bufCurve, this._minValidDistance) if (!this._isValid) { return null } this.checkMaximumDistance(this._input, bufCurve, this._maxValidDistance) } BufferDistanceValidator.prototype.getErrorLocation = function getErrorLocation () { return this._errorLocation } BufferDistanceValidator.prototype.getPolygonLines = function getPolygonLines (g) { var lines = new ArrayList() var lineExtracter = new LinearComponentExtracter(lines) var polys = PolygonExtracter.getPolygons(g) for (var i = polys.iterator(); i.hasNext();) { var poly = i.next() poly.apply(lineExtracter) } return g.getFactory().buildGeometry(lines) } BufferDistanceValidator.prototype.getErrorMessage = function getErrorMessage () { return this._errMsg } BufferDistanceValidator.prototype.interfaces_ = function interfaces_ () { return [] } BufferDistanceValidator.prototype.getClass = function getClass () { return BufferDistanceValidator } staticAccessors$37.VERBOSE.get = function () { return false } staticAccessors$37.MAX_DISTANCE_DIFF_FRAC.get = function () { return 0.012 } Object.defineProperties(BufferDistanceValidator, staticAccessors$37) var BufferResultValidator = function BufferResultValidator (input, distance, result) { this._isValid = true this._errorMsg = null this._errorLocation = null this._errorIndicator = null this._input = input || null this._distance = distance || null this._result = result || null } var staticAccessors$40 = { VERBOSE: { configurable: true }, MAX_ENV_DIFF_FRAC: { configurable: true } } BufferResultValidator.prototype.isValid = function isValid () { this.checkPolygonal() if (!this._isValid) { return this._isValid } this.checkExpectedEmpty() if (!this._isValid) { return this._isValid } this.checkEnvelope() if (!this._isValid) { return this._isValid } this.checkArea() if (!this._isValid) { return this._isValid } this.checkDistance() return this._isValid } BufferResultValidator.prototype.checkEnvelope = function checkEnvelope () { if (this._distance < 0.0) { return null } var padding = this._distance * BufferResultValidator.MAX_ENV_DIFF_FRAC if (padding === 0.0) { padding = 0.001 } var expectedEnv = new Envelope(this._input.getEnvelopeInternal()) expectedEnv.expandBy(this._distance) var bufEnv = new Envelope(this._result.getEnvelopeInternal()) bufEnv.expandBy(padding) if (!bufEnv.contains(expectedEnv)) { this._isValid = false this._errorMsg = 'Buffer envelope is incorrect' this._errorIndicator = this._input.getFactory().toGeometry(bufEnv) } this.report('Envelope') } BufferResultValidator.prototype.checkDistance = function checkDistance () { var distValid = new BufferDistanceValidator(this._input, this._distance, this._result) if (!distValid.isValid()) { this._isValid = false this._errorMsg = distValid.getErrorMessage() this._errorLocation = distValid.getErrorLocation() this._errorIndicator = distValid.getErrorIndicator() } this.report('Distance') } BufferResultValidator.prototype.checkArea = function checkArea () { var inputArea = this._input.getArea() var resultArea = this._result.getArea() if (this._distance > 0.0 && inputArea > resultArea) { this._isValid = false this._errorMsg = 'Area of positive buffer is smaller than input' this._errorIndicator = this._result } if (this._distance < 0.0 && inputArea < resultArea) { this._isValid = false this._errorMsg = 'Area of negative buffer is larger than input' this._errorIndicator = this._result } this.report('Area') } BufferResultValidator.prototype.checkPolygonal = function checkPolygonal () { if (!(this._result instanceof Polygon || this._result instanceof MultiPolygon)) { this._isValid = false } this._errorMsg = 'Result is not polygonal' this._errorIndicator = this._result this.report('Polygonal') } BufferResultValidator.prototype.getErrorIndicator = function getErrorIndicator () { return this._errorIndicator } BufferResultValidator.prototype.getErrorLocation = function getErrorLocation () { return this._errorLocation } BufferResultValidator.prototype.checkExpectedEmpty = function checkExpectedEmpty () { if (this._input.getDimension() >= 2) { return null } if (this._distance > 0.0) { return null } if (!this._result.isEmpty()) { this._isValid = false this._errorMsg = 'Result is non-empty' this._errorIndicator = this._result } this.report('ExpectedEmpty') } BufferResultValidator.prototype.report = function report (checkName) { if (!BufferResultValidator.VERBOSE) { return null } System.out.println('Check ' + checkName + ': ' + (this._isValid ? 'passed' : 'FAILED')) } BufferResultValidator.prototype.getErrorMessage = function getErrorMessage () { return this._errorMsg } BufferResultValidator.prototype.interfaces_ = function interfaces_ () { return [] } BufferResultValidator.prototype.getClass = function getClass () { return BufferResultValidator } BufferResultValidator.isValidMsg = function isValidMsg (g, distance, result) { var validator = new BufferResultValidator(g, distance, result) if (!validator.isValid()) { return validator.getErrorMessage() } return null } BufferResultValidator.isValid = function isValid (g, distance, result) { var validator = new BufferResultValidator(g, distance, result) if (validator.isValid()) { return true } return false } staticAccessors$40.VERBOSE.get = function () { return false } staticAccessors$40.MAX_ENV_DIFF_FRAC.get = function () { return 0.012 } Object.defineProperties(BufferResultValidator, staticAccessors$40) // operation.buffer var BasicSegmentString = function BasicSegmentString () { this._pts = null this._data = null var pts = arguments[0] var data = arguments[1] this._pts = pts this._data = data } BasicSegmentString.prototype.getCoordinates = function getCoordinates () { return this._pts } BasicSegmentString.prototype.size = function size () { return this._pts.length } BasicSegmentString.prototype.getCoordinate = function getCoordinate (i) { return this._pts[i] } BasicSegmentString.prototype.isClosed = function isClosed () { return this._pts[0].equals(this._pts[this._pts.length - 1]) } BasicSegmentString.prototype.getSegmentOctant = function getSegmentOctant (index) { if (index === this._pts.length - 1) { return -1 } return Octant.octant(this.getCoordinate(index), this.getCoordinate(index + 1)) } BasicSegmentString.prototype.setData = function setData (data) { this._data = data } BasicSegmentString.prototype.getData = function getData () { return this._data } BasicSegmentString.prototype.toString = function toString () { return WKTWriter.toLineString(new CoordinateArraySequence(this._pts)) } BasicSegmentString.prototype.interfaces_ = function interfaces_ () { return [SegmentString] } BasicSegmentString.prototype.getClass = function getClass () { return BasicSegmentString } var InteriorIntersectionFinder = function InteriorIntersectionFinder () { this._findAllIntersections = false this._isCheckEndSegmentsOnly = false this._li = null this._interiorIntersection = null this._intSegments = null this._intersections = new ArrayList() this._intersectionCount = 0 this._keepIntersections = true var li = arguments[0] this._li = li this._interiorIntersection = null } InteriorIntersectionFinder.prototype.getInteriorIntersection = function getInteriorIntersection () { return this._interiorIntersection } InteriorIntersectionFinder.prototype.setCheckEndSegmentsOnly = function setCheckEndSegmentsOnly (isCheckEndSegmentsOnly) { this._isCheckEndSegmentsOnly = isCheckEndSegmentsOnly } InteriorIntersectionFinder.prototype.getIntersectionSegments = function getIntersectionSegments () { return this._intSegments } InteriorIntersectionFinder.prototype.count = function count () { return this._intersectionCount } InteriorIntersectionFinder.prototype.getIntersections = function getIntersections () { return this._intersections } InteriorIntersectionFinder.prototype.setFindAllIntersections = function setFindAllIntersections (findAllIntersections) { this._findAllIntersections = findAllIntersections } InteriorIntersectionFinder.prototype.setKeepIntersections = function setKeepIntersections (keepIntersections) { this._keepIntersections = keepIntersections } InteriorIntersectionFinder.prototype.processIntersections = function processIntersections (e0, segIndex0, e1, segIndex1) { if (!this._findAllIntersections && this.hasIntersection()) { return null } if (e0 === e1 && segIndex0 === segIndex1) { return null } if (this._isCheckEndSegmentsOnly) { var isEndSegPresent = this.isEndSegment(e0, segIndex0) || this.isEndSegment(e1, segIndex1) if (!isEndSegPresent) { return null } } var p00 = e0.getCoordinates()[segIndex0] var p01 = e0.getCoordinates()[segIndex0 + 1] var p10 = e1.getCoordinates()[segIndex1] var p11 = e1.getCoordinates()[segIndex1 + 1] this._li.computeIntersection(p00, p01, p10, p11) if (this._li.hasIntersection()) { if (this._li.isInteriorIntersection()) { this._intSegments = new Array(4).fill(null) this._intSegments[0] = p00 this._intSegments[1] = p01 this._intSegments[2] = p10 this._intSegments[3] = p11 this._interiorIntersection = this._li.getIntersection(0) if (this._keepIntersections) { this._intersections.add(this._interiorIntersection) } this._intersectionCount++ } } } InteriorIntersectionFinder.prototype.isEndSegment = function isEndSegment (segStr, index) { if (index === 0) { return true } if (index >= segStr.size() - 2) { return true } return false } InteriorIntersectionFinder.prototype.hasIntersection = function hasIntersection () { return this._interiorIntersection !== null } InteriorIntersectionFinder.prototype.isDone = function isDone () { if (this._findAllIntersections) { return false } return this._interiorIntersection !== null } InteriorIntersectionFinder.prototype.interfaces_ = function interfaces_ () { return [SegmentIntersector] } InteriorIntersectionFinder.prototype.getClass = function getClass () { return InteriorIntersectionFinder } InteriorIntersectionFinder.createAllIntersectionsFinder = function createAllIntersectionsFinder (li) { var finder = new InteriorIntersectionFinder(li) finder.setFindAllIntersections(true) return finder } InteriorIntersectionFinder.createAnyIntersectionFinder = function createAnyIntersectionFinder (li) { return new InteriorIntersectionFinder(li) } InteriorIntersectionFinder.createIntersectionCounter = function createIntersectionCounter (li) { var finder = new InteriorIntersectionFinder(li) finder.setFindAllIntersections(true) finder.setKeepIntersections(false) return finder } var FastNodingValidator = function FastNodingValidator () { this._li = new RobustLineIntersector() this._segStrings = null this._findAllIntersections = false this._segInt = null this._isValid = true var segStrings = arguments[0] this._segStrings = segStrings } FastNodingValidator.prototype.execute = function execute () { if (this._segInt !== null) { return null } this.checkInteriorIntersections() } FastNodingValidator.prototype.getIntersections = function getIntersections () { return this._segInt.getIntersections() } FastNodingValidator.prototype.isValid = function isValid () { this.execute() return this._isValid } FastNodingValidator.prototype.setFindAllIntersections = function setFindAllIntersections (findAllIntersections) { this._findAllIntersections = findAllIntersections } FastNodingValidator.prototype.checkInteriorIntersections = function checkInteriorIntersections () { this._isValid = true this._segInt = new InteriorIntersectionFinder(this._li) this._segInt.setFindAllIntersections(this._findAllIntersections) var noder = new MCIndexNoder() noder.setSegmentIntersector(this._segInt) noder.computeNodes(this._segStrings) if (this._segInt.hasIntersection()) { this._isValid = false return null } } FastNodingValidator.prototype.checkValid = function checkValid () { this.execute() if (!this._isValid) { throw new TopologyException(this.getErrorMessage(), this._segInt.getInteriorIntersection()) } } FastNodingValidator.prototype.getErrorMessage = function getErrorMessage () { if (this._isValid) { return 'no intersections found' } var intSegs = this._segInt.getIntersectionSegments() return 'found non-noded intersection between ' + WKTWriter.toLineString(intSegs[0], intSegs[1]) + ' and ' + WKTWriter.toLineString(intSegs[2], intSegs[3]) } FastNodingValidator.prototype.interfaces_ = function interfaces_ () { return [] } FastNodingValidator.prototype.getClass = function getClass () { return FastNodingValidator } FastNodingValidator.computeIntersections = function computeIntersections (segStrings) { var nv = new FastNodingValidator(segStrings) nv.setFindAllIntersections(true) nv.isValid() return nv.getIntersections() } var EdgeNodingValidator = function EdgeNodingValidator () { this._nv = null var edges = arguments[0] this._nv = new FastNodingValidator(EdgeNodingValidator.toSegmentStrings(edges)) } EdgeNodingValidator.prototype.checkValid = function checkValid () { this._nv.checkValid() } EdgeNodingValidator.prototype.interfaces_ = function interfaces_ () { return [] } EdgeNodingValidator.prototype.getClass = function getClass () { return EdgeNodingValidator } EdgeNodingValidator.toSegmentStrings = function toSegmentStrings (edges) { var segStrings = new ArrayList() for (var i = edges.iterator(); i.hasNext();) { var e = i.next() segStrings.add(new BasicSegmentString(e.getCoordinates(), e)) } return segStrings } EdgeNodingValidator.checkValid = function checkValid (edges) { var validator = new EdgeNodingValidator(edges) validator.checkValid() } var GeometryCollectionMapper = function GeometryCollectionMapper (mapOp) { this._mapOp = mapOp } GeometryCollectionMapper.prototype.map = function map (gc) { var this$1$1 = this var mapped = new ArrayList() for (var i = 0; i < gc.getNumGeometries(); i++) { var g = this$1$1._mapOp.map(gc.getGeometryN(i)) if (!g.isEmpty()) { mapped.add(g) } } return gc.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(mapped)) } GeometryCollectionMapper.prototype.interfaces_ = function interfaces_ () { return [] } GeometryCollectionMapper.prototype.getClass = function getClass () { return GeometryCollectionMapper } GeometryCollectionMapper.map = function map (gc, op) { var mapper = new GeometryCollectionMapper(op) return mapper.map(gc) } var LineBuilder = function LineBuilder () { this._op = null this._geometryFactory = null this._ptLocator = null this._lineEdgesList = new ArrayList() this._resultLineList = new ArrayList() var op = arguments[0] var geometryFactory = arguments[1] var ptLocator = arguments[2] this._op = op this._geometryFactory = geometryFactory this._ptLocator = ptLocator } LineBuilder.prototype.collectLines = function collectLines (opCode) { var this$1$1 = this for (var it = this._op.getGraph().getEdgeEnds().iterator(); it.hasNext();) { var de = it.next() this$1$1.collectLineEdge(de, opCode, this$1$1._lineEdgesList) this$1$1.collectBoundaryTouchEdge(de, opCode, this$1$1._lineEdgesList) } } LineBuilder.prototype.labelIsolatedLine = function labelIsolatedLine (e, targetIndex) { var loc = this._ptLocator.locate(e.getCoordinate(), this._op.getArgGeometry(targetIndex)) e.getLabel().setLocation(targetIndex, loc) } LineBuilder.prototype.build = function build (opCode) { this.findCoveredLineEdges() this.collectLines(opCode) this.buildLines(opCode) return this._resultLineList } LineBuilder.prototype.collectLineEdge = function collectLineEdge (de, opCode, edges) { var label = de.getLabel() var e = de.getEdge() if (de.isLineEdge()) { if (!de.isVisited() && OverlayOp.isResultOfOp(label, opCode) && !e.isCovered()) { edges.add(e) de.setVisitedEdge(true) } } } LineBuilder.prototype.findCoveredLineEdges = function findCoveredLineEdges () { var this$1$1 = this for (var nodeit = this._op.getGraph().getNodes().iterator(); nodeit.hasNext();) { var node = nodeit.next() node.getEdges().findCoveredLineEdges() } for (var it = this._op.getGraph().getEdgeEnds().iterator(); it.hasNext();) { var de = it.next() var e = de.getEdge() if (de.isLineEdge() && !e.isCoveredSet()) { var isCovered = this$1$1._op.isCoveredByA(de.getCoordinate()) e.setCovered(isCovered) } } } LineBuilder.prototype.labelIsolatedLines = function labelIsolatedLines (edgesList) { var this$1$1 = this for (var it = edgesList.iterator(); it.hasNext();) { var e = it.next() var label = e.getLabel() if (e.isIsolated()) { if (label.isNull(0)) { this$1$1.labelIsolatedLine(e, 0) } else { this$1$1.labelIsolatedLine(e, 1) } } } } LineBuilder.prototype.buildLines = function buildLines (opCode) { var this$1$1 = this for (var it = this._lineEdgesList.iterator(); it.hasNext();) { var e = it.next() // const label = e.getLabel() var line = this$1$1._geometryFactory.createLineString(e.getCoordinates()) this$1$1._resultLineList.add(line) e.setInResult(true) } } LineBuilder.prototype.collectBoundaryTouchEdge = function collectBoundaryTouchEdge (de, opCode, edges) { var label = de.getLabel() if (de.isLineEdge()) { return null } if (de.isVisited()) { return null } if (de.isInteriorAreaEdge()) { return null } if (de.getEdge().isInResult()) { return null } Assert.isTrue(!(de.isInResult() || de.getSym().isInResult()) || !de.getEdge().isInResult()) if (OverlayOp.isResultOfOp(label, opCode) && opCode === OverlayOp.INTERSECTION) { edges.add(de.getEdge()) de.setVisitedEdge(true) } } LineBuilder.prototype.interfaces_ = function interfaces_ () { return [] } LineBuilder.prototype.getClass = function getClass () { return LineBuilder } var PointBuilder = function PointBuilder () { this._op = null this._geometryFactory = null this._resultPointList = new ArrayList() var op = arguments[0] var geometryFactory = arguments[1] // const ptLocator = arguments[2] this._op = op this._geometryFactory = geometryFactory } PointBuilder.prototype.filterCoveredNodeToPoint = function filterCoveredNodeToPoint (n) { var coord = n.getCoordinate() if (!this._op.isCoveredByLA(coord)) { var pt = this._geometryFactory.createPoint(coord) this._resultPointList.add(pt) } } PointBuilder.prototype.extractNonCoveredResultNodes = function extractNonCoveredResultNodes (opCode) { var this$1$1 = this for (var nodeit = this._op.getGraph().getNodes().iterator(); nodeit.hasNext();) { var n = nodeit.next() if (n.isInResult()) { continue } if (n.isIncidentEdgeInResult()) { continue } if (n.getEdges().getDegree() === 0 || opCode === OverlayOp.INTERSECTION) { var label = n.getLabel() if (OverlayOp.isResultOfOp(label, opCode)) { this$1$1.filterCoveredNodeToPoint(n) } } } } PointBuilder.prototype.build = function build (opCode) { this.extractNonCoveredResultNodes(opCode) return this._resultPointList } PointBuilder.prototype.interfaces_ = function interfaces_ () { return [] } PointBuilder.prototype.getClass = function getClass () { return PointBuilder } var GeometryTransformer = function GeometryTransformer () { this._inputGeom = null this._factory = null this._pruneEmptyGeometry = true this._preserveGeometryCollectionType = true this._preserveCollections = false this._preserveType = false } GeometryTransformer.prototype.transformPoint = function transformPoint (geom, parent) { return this._factory.createPoint(this.transformCoordinates(geom.getCoordinateSequence(), geom)) } GeometryTransformer.prototype.transformPolygon = function transformPolygon (geom, parent) { var this$1$1 = this var isAllValidLinearRings = true var shell = this.transformLinearRing(geom.getExteriorRing(), geom) if (shell === null || !(shell instanceof LinearRing) || shell.isEmpty()) { isAllValidLinearRings = false } var holes = new ArrayList() for (var i = 0; i < geom.getNumInteriorRing(); i++) { var hole = this$1$1.transformLinearRing(geom.getInteriorRingN(i), geom) if (hole === null || hole.isEmpty()) { continue } if (!(hole instanceof LinearRing)) { isAllValidLinearRings = false } holes.add(hole) } if (isAllValidLinearRings) { return this._factory.createPolygon(shell, holes.toArray([])) } else { var components = new ArrayList() if (shell !== null) { components.add(shell) } components.addAll(holes) return this._factory.buildGeometry(components) } } GeometryTransformer.prototype.createCoordinateSequence = function createCoordinateSequence (coords) { return this._factory.getCoordinateSequenceFactory().create(coords) } GeometryTransformer.prototype.getInputGeometry = function getInputGeometry () { return this._inputGeom } GeometryTransformer.prototype.transformMultiLineString = function transformMultiLineString (geom, parent) { var this$1$1 = this var transGeomList = new ArrayList() for (var i = 0; i < geom.getNumGeometries(); i++) { var transformGeom = this$1$1.transformLineString(geom.getGeometryN(i), geom) if (transformGeom === null) { continue } if (transformGeom.isEmpty()) { continue } transGeomList.add(transformGeom) } return this._factory.buildGeometry(transGeomList) } GeometryTransformer.prototype.transformCoordinates = function transformCoordinates (coords, parent) { return this.copy(coords) } GeometryTransformer.prototype.transformLineString = function transformLineString (geom, parent) { return this._factory.createLineString(this.transformCoordinates(geom.getCoordinateSequence(), geom)) } GeometryTransformer.prototype.transformMultiPoint = function transformMultiPoint (geom, parent) { var this$1$1 = this var transGeomList = new ArrayList() for (var i = 0; i < geom.getNumGeometries(); i++) { var transformGeom = this$1$1.transformPoint(geom.getGeometryN(i), geom) if (transformGeom === null) { continue } if (transformGeom.isEmpty()) { continue } transGeomList.add(transformGeom) } return this._factory.buildGeometry(transGeomList) } GeometryTransformer.prototype.transformMultiPolygon = function transformMultiPolygon (geom, parent) { var this$1$1 = this var transGeomList = new ArrayList() for (var i = 0; i < geom.getNumGeometries(); i++) { var transformGeom = this$1$1.transformPolygon(geom.getGeometryN(i), geom) if (transformGeom === null) { continue } if (transformGeom.isEmpty()) { continue } transGeomList.add(transformGeom) } return this._factory.buildGeometry(transGeomList) } GeometryTransformer.prototype.copy = function copy (seq) { return seq.copy() } GeometryTransformer.prototype.transformGeometryCollection = function transformGeometryCollection (geom, parent) { var this$1$1 = this var transGeomList = new ArrayList() for (var i = 0; i < geom.getNumGeometries(); i++) { var transformGeom = this$1$1.transform(geom.getGeometryN(i)) if (transformGeom === null) { continue } if (this$1$1._pruneEmptyGeometry && transformGeom.isEmpty()) { continue } transGeomList.add(transformGeom) } if (this._preserveGeometryCollectionType) { return this._factory.createGeometryCollection(GeometryFactory.toGeometryArray(transGeomList)) } return this._factory.buildGeometry(transGeomList) } GeometryTransformer.prototype.transform = function transform (inputGeom) { this._inputGeom = inputGeom this._factory = inputGeom.getFactory() if (inputGeom instanceof Point) { return this.transformPoint(inputGeom, null) } if (inputGeom instanceof MultiPoint) { return this.transformMultiPoint(inputGeom, null) } if (inputGeom instanceof LinearRing) { return this.transformLinearRing(inputGeom, null) } if (inputGeom instanceof LineString) { return this.transformLineString(inputGeom, null) } if (inputGeom instanceof MultiLineString) { return this.transformMultiLineString(inputGeom, null) } if (inputGeom instanceof Polygon) { return this.transformPolygon(inputGeom, null) } if (inputGeom instanceof MultiPolygon) { return this.transformMultiPolygon(inputGeom, null) } if (inputGeom instanceof GeometryCollection) { return this.transformGeometryCollection(inputGeom, null) } throw new IllegalArgumentException('Unknown Geometry subtype: ' + inputGeom.getClass().getName()) } GeometryTransformer.prototype.transformLinearRing = function transformLinearRing (geom, parent) { var seq = this.transformCoordinates(geom.getCoordinateSequence(), geom) if (seq === null) { return this._factory.createLinearRing(null) } var seqSize = seq.size() if (seqSize > 0 && seqSize < 4 && !this._preserveType) { return this._factory.createLineString(seq) } return this._factory.createLinearRing(seq) } GeometryTransformer.prototype.interfaces_ = function interfaces_ () { return [] } GeometryTransformer.prototype.getClass = function getClass () { return GeometryTransformer } var LineStringSnapper = function LineStringSnapper () { this._snapTolerance = 0.0 this._srcPts = null this._seg = new LineSegment() this._allowSnappingToSourceVertices = false this._isClosed = false if (arguments[0] instanceof LineString && typeof arguments[1] === 'number') { var srcLine = arguments[0] var snapTolerance = arguments[1] LineStringSnapper.call(this, srcLine.getCoordinates(), snapTolerance) } else if (arguments[0] instanceof Array && typeof arguments[1] === 'number') { var srcPts = arguments[0] var snapTolerance$1 = arguments[1] this._srcPts = srcPts this._isClosed = LineStringSnapper.isClosed(srcPts) this._snapTolerance = snapTolerance$1 } } LineStringSnapper.prototype.snapVertices = function snapVertices (srcCoords, snapPts) { var this$1$1 = this var end = this._isClosed ? srcCoords.size() - 1 : srcCoords.size() for (var i = 0; i < end; i++) { var srcPt = srcCoords.get(i) var snapVert = this$1$1.findSnapForVertex(srcPt, snapPts) if (snapVert !== null) { srcCoords.set(i, new Coordinate(snapVert)) if (i === 0 && this$1$1._isClosed) { srcCoords.set(srcCoords.size() - 1, new Coordinate(snapVert)) } } } } LineStringSnapper.prototype.findSnapForVertex = function findSnapForVertex (pt, snapPts) { var this$1$1 = this for (var i = 0; i < snapPts.length; i++) { if (pt.equals2D(snapPts[i])) { return null } if (pt.distance(snapPts[i]) < this$1$1._snapTolerance) { return snapPts[i] } } return null } LineStringSnapper.prototype.snapTo = function snapTo (snapPts) { var coordList = new CoordinateList(this._srcPts) this.snapVertices(coordList, snapPts) this.snapSegments(coordList, snapPts) var newPts = coordList.toCoordinateArray() return newPts } LineStringSnapper.prototype.snapSegments = function snapSegments (srcCoords, snapPts) { var this$1$1 = this if (snapPts.length === 0) { return null } var distinctPtCount = snapPts.length if (snapPts[0].equals2D(snapPts[snapPts.length - 1])) { distinctPtCount = snapPts.length - 1 } for (var i = 0; i < distinctPtCount; i++) { var snapPt = snapPts[i] var index = this$1$1.findSegmentIndexToSnap(snapPt, srcCoords) if (index >= 0) { srcCoords.add(index + 1, new Coordinate(snapPt), false) } } } LineStringSnapper.prototype.findSegmentIndexToSnap = function findSegmentIndexToSnap (snapPt, srcCoords) { var this$1$1 = this var minDist = Double.MAX_VALUE var snapIndex = -1 for (var i = 0; i < srcCoords.size() - 1; i++) { this$1$1._seg.p0 = srcCoords.get(i) this$1$1._seg.p1 = srcCoords.get(i + 1) if (this$1$1._seg.p0.equals2D(snapPt) || this$1$1._seg.p1.equals2D(snapPt)) { if (this$1$1._allowSnappingToSourceVertices) { continue } else { return -1 } } var dist = this$1$1._seg.distance(snapPt) if (dist < this$1$1._snapTolerance && dist < minDist) { minDist = dist snapIndex = i } } return snapIndex } LineStringSnapper.prototype.setAllowSnappingToSourceVertices = function setAllowSnappingToSourceVertices (allowSnappingToSourceVertices) { this._allowSnappingToSourceVertices = allowSnappingToSourceVertices } LineStringSnapper.prototype.interfaces_ = function interfaces_ () { return [] } LineStringSnapper.prototype.getClass = function getClass () { return LineStringSnapper } LineStringSnapper.isClosed = function isClosed (pts) { if (pts.length <= 1) { return false } return pts[0].equals2D(pts[pts.length - 1]) } var GeometrySnapper = function GeometrySnapper (srcGeom) { this._srcGeom = srcGeom || null } var staticAccessors$41 = { SNAP_PRECISION_FACTOR: { configurable: true } } GeometrySnapper.prototype.snapTo = function snapTo (snapGeom, snapTolerance) { var snapPts = this.extractTargetCoordinates(snapGeom) var snapTrans = new SnapTransformer(snapTolerance, snapPts) return snapTrans.transform(this._srcGeom) } GeometrySnapper.prototype.snapToSelf = function snapToSelf (snapTolerance, cleanResult) { var snapPts = this.extractTargetCoordinates(this._srcGeom) var snapTrans = new SnapTransformer(snapTolerance, snapPts, true) var snappedGeom = snapTrans.transform(this._srcGeom) var result = snappedGeom if (cleanResult && hasInterface(result, Polygonal)) { result = snappedGeom.buffer(0) } return result } GeometrySnapper.prototype.computeSnapTolerance = function computeSnapTolerance (ringPts) { var minSegLen = this.computeMinimumSegmentLength(ringPts) var snapTol = minSegLen / 10 return snapTol } GeometrySnapper.prototype.extractTargetCoordinates = function extractTargetCoordinates (g) { var ptSet = new TreeSet() var pts = g.getCoordinates() for (var i = 0; i < pts.length; i++) { ptSet.add(pts[i]) } return ptSet.toArray(new Array(0).fill(null)) } GeometrySnapper.prototype.computeMinimumSegmentLength = function computeMinimumSegmentLength (pts) { var minSegLen = Double.MAX_VALUE for (var i = 0; i < pts.length - 1; i++) { var segLen = pts[i].distance(pts[i + 1]) if (segLen < minSegLen) { minSegLen = segLen } } return minSegLen } GeometrySnapper.prototype.interfaces_ = function interfaces_ () { return [] } GeometrySnapper.prototype.getClass = function getClass () { return GeometrySnapper } GeometrySnapper.snap = function snap (g0, g1, snapTolerance) { var snapGeom = new Array(2).fill(null) var snapper0 = new GeometrySnapper(g0) snapGeom[0] = snapper0.snapTo(g1, snapTolerance) var snapper1 = new GeometrySnapper(g1) snapGeom[1] = snapper1.snapTo(snapGeom[0], snapTolerance) return snapGeom } GeometrySnapper.computeOverlaySnapTolerance = function computeOverlaySnapTolerance () { if (arguments.length === 1) { var g = arguments[0] var snapTolerance = GeometrySnapper.computeSizeBasedSnapTolerance(g) var pm = g.getPrecisionModel() if (pm.getType() === PrecisionModel.FIXED) { var fixedSnapTol = 1 / pm.getScale() * 2 / 1.415 if (fixedSnapTol > snapTolerance) { snapTolerance = fixedSnapTol } } return snapTolerance } else if (arguments.length === 2) { var g0 = arguments[0] var g1 = arguments[1] return Math.min(GeometrySnapper.computeOverlaySnapTolerance(g0), GeometrySnapper.computeOverlaySnapTolerance(g1)) } } GeometrySnapper.computeSizeBasedSnapTolerance = function computeSizeBasedSnapTolerance (g) { var env = g.getEnvelopeInternal() var minDimension = Math.min(env.getHeight(), env.getWidth()) var snapTol = minDimension * GeometrySnapper.SNAP_PRECISION_FACTOR return snapTol } GeometrySnapper.snapToSelf = function snapToSelf (geom, snapTolerance, cleanResult) { var snapper0 = new GeometrySnapper(geom) return snapper0.snapToSelf(snapTolerance, cleanResult) } staticAccessors$41.SNAP_PRECISION_FACTOR.get = function () { return 1e-9 } Object.defineProperties(GeometrySnapper, staticAccessors$41) var SnapTransformer = (function (GeometryTransformer$$1) { function SnapTransformer (snapTolerance, snapPts, isSelfSnap) { GeometryTransformer$$1.call(this) this._snapTolerance = snapTolerance || null this._snapPts = snapPts || null this._isSelfSnap = (isSelfSnap !== undefined) ? isSelfSnap : false } if (GeometryTransformer$$1) SnapTransformer.__proto__ = GeometryTransformer$$1 SnapTransformer.prototype = Object.create(GeometryTransformer$$1 && GeometryTransformer$$1.prototype) SnapTransformer.prototype.constructor = SnapTransformer SnapTransformer.prototype.snapLine = function snapLine (srcPts, snapPts) { var snapper = new LineStringSnapper(srcPts, this._snapTolerance) snapper.setAllowSnappingToSourceVertices(this._isSelfSnap) return snapper.snapTo(snapPts) } SnapTransformer.prototype.transformCoordinates = function transformCoordinates (coords, parent) { var srcPts = coords.toCoordinateArray() var newPts = this.snapLine(srcPts, this._snapPts) return this._factory.getCoordinateSequenceFactory().create(newPts) } SnapTransformer.prototype.interfaces_ = function interfaces_ () { return [] } SnapTransformer.prototype.getClass = function getClass () { return SnapTransformer } return SnapTransformer }(GeometryTransformer)) var CommonBits = function CommonBits () { this._isFirst = true this._commonMantissaBitsCount = 53 this._commonBits = 0 this._commonSignExp = null } CommonBits.prototype.getCommon = function getCommon () { return Double.longBitsToDouble(this._commonBits) } CommonBits.prototype.add = function add (num) { var numBits = Double.doubleToLongBits(num) if (this._isFirst) { this._commonBits = numBits this._commonSignExp = CommonBits.signExpBits(this._commonBits) this._isFirst = false return null } var numSignExp = CommonBits.signExpBits(numBits) if (numSignExp !== this._commonSignExp) { this._commonBits = 0 return null } this._commonMantissaBitsCount = CommonBits.numCommonMostSigMantissaBits(this._commonBits, numBits) this._commonBits = CommonBits.zeroLowerBits(this._commonBits, 64 - (12 + this._commonMantissaBitsCount)) } CommonBits.prototype.toString = function toString () { if (arguments.length === 1) { var bits = arguments[0] var x = Double.longBitsToDouble(bits) var numStr = Double.toBinaryString(bits) var padStr = '0000000000000000000000000000000000000000000000000000000000000000' + numStr var bitStr = padStr.substring(padStr.length - 64) var str = bitStr.substring(0, 1) + ' ' + bitStr.substring(1, 12) + '(exp) ' + bitStr.substring(12) + ' [ ' + x + ' ]' return str } } CommonBits.prototype.interfaces_ = function interfaces_ () { return [] } CommonBits.prototype.getClass = function getClass () { return CommonBits } CommonBits.getBit = function getBit (bits, i) { var mask = 1 << i return (bits & mask) !== 0 ? 1 : 0 } CommonBits.signExpBits = function signExpBits (num) { return num >> 52 } CommonBits.zeroLowerBits = function zeroLowerBits (bits, nBits) { var invMask = (1 << nBits) - 1 var mask = ~invMask var zeroed = bits & mask return zeroed } CommonBits.numCommonMostSigMantissaBits = function numCommonMostSigMantissaBits (num1, num2) { var count = 0 for (var i = 52; i >= 0; i--) { if (CommonBits.getBit(num1, i) !== CommonBits.getBit(num2, i)) { return count } count++ } return 52 } var CommonBitsRemover = function CommonBitsRemover () { this._commonCoord = null this._ccFilter = new CommonCoordinateFilter() } var staticAccessors$42 = { CommonCoordinateFilter: { configurable: true }, Translater: { configurable: true } } CommonBitsRemover.prototype.addCommonBits = function addCommonBits (geom) { var trans = new Translater(this._commonCoord) geom.apply(trans) geom.geometryChanged() } CommonBitsRemover.prototype.removeCommonBits = function removeCommonBits (geom) { if (this._commonCoord.x === 0.0 && this._commonCoord.y === 0.0) { return geom } var invCoord = new Coordinate(this._commonCoord) invCoord.x = -invCoord.x invCoord.y = -invCoord.y var trans = new Translater(invCoord) geom.apply(trans) geom.geometryChanged() return geom } CommonBitsRemover.prototype.getCommonCoordinate = function getCommonCoordinate () { return this._commonCoord } CommonBitsRemover.prototype.add = function add (geom) { geom.apply(this._ccFilter) this._commonCoord = this._ccFilter.getCommonCoordinate() } CommonBitsRemover.prototype.interfaces_ = function interfaces_ () { return [] } CommonBitsRemover.prototype.getClass = function getClass () { return CommonBitsRemover } staticAccessors$42.CommonCoordinateFilter.get = function () { return CommonCoordinateFilter } staticAccessors$42.Translater.get = function () { return Translater } Object.defineProperties(CommonBitsRemover, staticAccessors$42) var CommonCoordinateFilter = function CommonCoordinateFilter () { this._commonBitsX = new CommonBits() this._commonBitsY = new CommonBits() } CommonCoordinateFilter.prototype.filter = function filter (coord) { this._commonBitsX.add(coord.x) this._commonBitsY.add(coord.y) } CommonCoordinateFilter.prototype.getCommonCoordinate = function getCommonCoordinate () { return new Coordinate(this._commonBitsX.getCommon(), this._commonBitsY.getCommon()) } CommonCoordinateFilter.prototype.interfaces_ = function interfaces_ () { return [CoordinateFilter] } CommonCoordinateFilter.prototype.getClass = function getClass () { return CommonCoordinateFilter } var Translater = function Translater () { this.trans = null var trans = arguments[0] this.trans = trans } Translater.prototype.filter = function filter (seq, i) { var xp = seq.getOrdinate(i, 0) + this.trans.x var yp = seq.getOrdinate(i, 1) + this.trans.y seq.setOrdinate(i, 0, xp) seq.setOrdinate(i, 1, yp) } Translater.prototype.isDone = function isDone () { return false } Translater.prototype.isGeometryChanged = function isGeometryChanged () { return true } Translater.prototype.interfaces_ = function interfaces_ () { return [CoordinateSequenceFilter] } Translater.prototype.getClass = function getClass () { return Translater } var SnapOverlayOp = function SnapOverlayOp (g1, g2) { this._geom = new Array(2).fill(null) this._snapTolerance = null this._cbr = null this._geom[0] = g1 this._geom[1] = g2 this.computeSnapTolerance() } SnapOverlayOp.prototype.selfSnap = function selfSnap (geom) { var snapper0 = new GeometrySnapper(geom) var snapGeom = snapper0.snapTo(geom, this._snapTolerance) return snapGeom } SnapOverlayOp.prototype.removeCommonBits = function removeCommonBits (geom) { this._cbr = new CommonBitsRemover() this._cbr.add(geom[0]) this._cbr.add(geom[1]) var remGeom = new Array(2).fill(null) remGeom[0] = this._cbr.removeCommonBits(geom[0].copy()) remGeom[1] = this._cbr.removeCommonBits(geom[1].copy()) return remGeom } SnapOverlayOp.prototype.prepareResult = function prepareResult (geom) { this._cbr.addCommonBits(geom) return geom } SnapOverlayOp.prototype.getResultGeometry = function getResultGeometry (opCode) { var prepGeom = this.snap(this._geom) var result = OverlayOp.overlayOp(prepGeom[0], prepGeom[1], opCode) return this.prepareResult(result) } SnapOverlayOp.prototype.checkValid = function checkValid (g) { if (!g.isValid()) { System.out.println('Snapped geometry is invalid') } } SnapOverlayOp.prototype.computeSnapTolerance = function computeSnapTolerance () { this._snapTolerance = GeometrySnapper.computeOverlaySnapTolerance(this._geom[0], this._geom[1]) } SnapOverlayOp.prototype.snap = function snap (geom) { var remGeom = this.removeCommonBits(geom) var snapGeom = GeometrySnapper.snap(remGeom[0], remGeom[1], this._snapTolerance) return snapGeom } SnapOverlayOp.prototype.interfaces_ = function interfaces_ () { return [] } SnapOverlayOp.prototype.getClass = function getClass () { return SnapOverlayOp } SnapOverlayOp.overlayOp = function overlayOp (g0, g1, opCode) { var op = new SnapOverlayOp(g0, g1) return op.getResultGeometry(opCode) } SnapOverlayOp.union = function union (g0, g1) { return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.UNION) } SnapOverlayOp.intersection = function intersection (g0, g1) { return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.INTERSECTION) } SnapOverlayOp.symDifference = function symDifference (g0, g1) { return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.SYMDIFFERENCE) } SnapOverlayOp.difference = function difference (g0, g1) { return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.DIFFERENCE) } var SnapIfNeededOverlayOp = function SnapIfNeededOverlayOp (g1, g2) { this._geom = new Array(2).fill(null) this._geom[0] = g1 this._geom[1] = g2 } SnapIfNeededOverlayOp.prototype.getResultGeometry = function getResultGeometry (opCode) { var result = null var isSuccess = false var savedException = null try { result = OverlayOp.overlayOp(this._geom[0], this._geom[1], opCode) var isValid = true if (isValid) { isSuccess = true } } catch (ex) { if (ex instanceof RuntimeException) { savedException = ex } else { throw ex } } finally { } if (!isSuccess) { try { result = SnapOverlayOp.overlayOp(this._geom[0], this._geom[1], opCode) } catch (ex) { if (ex instanceof RuntimeException) { throw savedException } else { throw ex } } finally { } } return result } SnapIfNeededOverlayOp.prototype.interfaces_ = function interfaces_ () { return [] } SnapIfNeededOverlayOp.prototype.getClass = function getClass () { return SnapIfNeededOverlayOp } SnapIfNeededOverlayOp.overlayOp = function overlayOp (g0, g1, opCode) { var op = new SnapIfNeededOverlayOp(g0, g1) return op.getResultGeometry(opCode) } SnapIfNeededOverlayOp.union = function union (g0, g1) { return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.UNION) } SnapIfNeededOverlayOp.intersection = function intersection (g0, g1) { return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.INTERSECTION) } SnapIfNeededOverlayOp.symDifference = function symDifference (g0, g1) { return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.SYMDIFFERENCE) } SnapIfNeededOverlayOp.difference = function difference (g0, g1) { return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.DIFFERENCE) } var MonotoneChain$2 = function MonotoneChain () { this.mce = null this.chainIndex = null var mce = arguments[0] var chainIndex = arguments[1] this.mce = mce this.chainIndex = chainIndex } MonotoneChain$2.prototype.computeIntersections = function computeIntersections (mc, si) { this.mce.computeIntersectsForChain(this.chainIndex, mc.mce, mc.chainIndex, si) } MonotoneChain$2.prototype.interfaces_ = function interfaces_ () { return [] } MonotoneChain$2.prototype.getClass = function getClass () { return MonotoneChain$2 } var SweepLineEvent = function SweepLineEvent () { this._label = null this._xValue = null this._eventType = null this._insertEvent = null this._deleteEventIndex = null this._obj = null if (arguments.length === 2) { var x = arguments[0] var insertEvent = arguments[1] this._eventType = SweepLineEvent.DELETE this._xValue = x this._insertEvent = insertEvent } else if (arguments.length === 3) { var label = arguments[0] var x$1 = arguments[1] var obj = arguments[2] this._eventType = SweepLineEvent.INSERT this._label = label this._xValue = x$1 this._obj = obj } } var staticAccessors$43 = { INSERT: { configurable: true }, DELETE: { configurable: true } } SweepLineEvent.prototype.isDelete = function isDelete () { return this._eventType === SweepLineEvent.DELETE } SweepLineEvent.prototype.setDeleteEventIndex = function setDeleteEventIndex (deleteEventIndex) { this._deleteEventIndex = deleteEventIndex } SweepLineEvent.prototype.getObject = function getObject () { return this._obj } SweepLineEvent.prototype.compareTo = function compareTo (o) { var pe = o if (this._xValue < pe._xValue) { return -1 } if (this._xValue > pe._xValue) { return 1 } if (this._eventType < pe._eventType) { return -1 } if (this._eventType > pe._eventType) { return 1 } return 0 } SweepLineEvent.prototype.getInsertEvent = function getInsertEvent () { return this._insertEvent } SweepLineEvent.prototype.isInsert = function isInsert () { return this._eventType === SweepLineEvent.INSERT } SweepLineEvent.prototype.isSameLabel = function isSameLabel (ev) { if (this._label === null) { return false } return this._label === ev._label } SweepLineEvent.prototype.getDeleteEventIndex = function getDeleteEventIndex () { return this._deleteEventIndex } SweepLineEvent.prototype.interfaces_ = function interfaces_ () { return [Comparable] } SweepLineEvent.prototype.getClass = function getClass () { return SweepLineEvent } staticAccessors$43.INSERT.get = function () { return 1 } staticAccessors$43.DELETE.get = function () { return 2 } Object.defineProperties(SweepLineEvent, staticAccessors$43) var EdgeSetIntersector = function EdgeSetIntersector () { } EdgeSetIntersector.prototype.interfaces_ = function interfaces_ () { return [] } EdgeSetIntersector.prototype.getClass = function getClass () { return EdgeSetIntersector } var SegmentIntersector$2 = function SegmentIntersector () { this._hasIntersection = false this._hasProper = false this._hasProperInterior = false this._properIntersectionPoint = null this._li = null this._includeProper = null this._recordIsolated = null this._isSelfIntersection = null this._numIntersections = 0 this.numTests = 0 this._bdyNodes = null this._isDone = false this._isDoneWhenProperInt = false var li = arguments[0] var includeProper = arguments[1] var recordIsolated = arguments[2] this._li = li this._includeProper = includeProper this._recordIsolated = recordIsolated } SegmentIntersector$2.prototype.isTrivialIntersection = function isTrivialIntersection (e0, segIndex0, e1, segIndex1) { if (e0 === e1) { if (this._li.getIntersectionNum() === 1) { if (SegmentIntersector$2.isAdjacentSegments(segIndex0, segIndex1)) { return true } if (e0.isClosed()) { var maxSegIndex = e0.getNumPoints() - 1 if ((segIndex0 === 0 && segIndex1 === maxSegIndex) || (segIndex1 === 0 && segIndex0 === maxSegIndex)) { return true } } } } return false } SegmentIntersector$2.prototype.getProperIntersectionPoint = function getProperIntersectionPoint () { return this._properIntersectionPoint } SegmentIntersector$2.prototype.setIsDoneIfProperInt = function setIsDoneIfProperInt (isDoneWhenProperInt) { this._isDoneWhenProperInt = isDoneWhenProperInt } SegmentIntersector$2.prototype.hasProperInteriorIntersection = function hasProperInteriorIntersection () { return this._hasProperInterior } SegmentIntersector$2.prototype.isBoundaryPointInternal = function isBoundaryPointInternal (li, bdyNodes) { for (var i = bdyNodes.iterator(); i.hasNext();) { var node = i.next() var pt = node.getCoordinate() if (li.isIntersection(pt)) { return true } } return false } SegmentIntersector$2.prototype.hasProperIntersection = function hasProperIntersection () { return this._hasProper } SegmentIntersector$2.prototype.hasIntersection = function hasIntersection () { return this._hasIntersection } SegmentIntersector$2.prototype.isDone = function isDone () { return this._isDone } SegmentIntersector$2.prototype.isBoundaryPoint = function isBoundaryPoint (li, bdyNodes) { if (bdyNodes === null) { return false } if (this.isBoundaryPointInternal(li, bdyNodes[0])) { return true } if (this.isBoundaryPointInternal(li, bdyNodes[1])) { return true } return false } SegmentIntersector$2.prototype.setBoundaryNodes = function setBoundaryNodes (bdyNodes0, bdyNodes1) { this._bdyNodes = new Array(2).fill(null) this._bdyNodes[0] = bdyNodes0 this._bdyNodes[1] = bdyNodes1 } SegmentIntersector$2.prototype.addIntersections = function addIntersections (e0, segIndex0, e1, segIndex1) { if (e0 === e1 && segIndex0 === segIndex1) { return null } this.numTests++ var p00 = e0.getCoordinates()[segIndex0] var p01 = e0.getCoordinates()[segIndex0 + 1] var p10 = e1.getCoordinates()[segIndex1] var p11 = e1.getCoordinates()[segIndex1 + 1] this._li.computeIntersection(p00, p01, p10, p11) if (this._li.hasIntersection()) { if (this._recordIsolated) { e0.setIsolated(false) e1.setIsolated(false) } this._numIntersections++ if (!this.isTrivialIntersection(e0, segIndex0, e1, segIndex1)) { this._hasIntersection = true if (this._includeProper || !this._li.isProper()) { e0.addIntersections(this._li, segIndex0, 0) e1.addIntersections(this._li, segIndex1, 1) } if (this._li.isProper()) { this._properIntersectionPoint = this._li.getIntersection(0).copy() this._hasProper = true if (this._isDoneWhenProperInt) { this._isDone = true } if (!this.isBoundaryPoint(this._li, this._bdyNodes)) { this._hasProperInterior = true } } } } } SegmentIntersector$2.prototype.interfaces_ = function interfaces_ () { return [] } SegmentIntersector$2.prototype.getClass = function getClass () { return SegmentIntersector$2 } SegmentIntersector$2.isAdjacentSegments = function isAdjacentSegments (i1, i2) { return Math.abs(i1 - i2) === 1 } var SimpleMCSweepLineIntersector = (function (EdgeSetIntersector$$1) { function SimpleMCSweepLineIntersector () { EdgeSetIntersector$$1.call(this) this.events = new ArrayList() this.nOverlaps = null } if (EdgeSetIntersector$$1) SimpleMCSweepLineIntersector.__proto__ = EdgeSetIntersector$$1 SimpleMCSweepLineIntersector.prototype = Object.create(EdgeSetIntersector$$1 && EdgeSetIntersector$$1.prototype) SimpleMCSweepLineIntersector.prototype.constructor = SimpleMCSweepLineIntersector SimpleMCSweepLineIntersector.prototype.prepareEvents = function prepareEvents () { var this$1$1 = this Collections.sort(this.events) for (var i = 0; i < this.events.size(); i++) { var ev = this$1$1.events.get(i) if (ev.isDelete()) { ev.getInsertEvent().setDeleteEventIndex(i) } } } SimpleMCSweepLineIntersector.prototype.computeIntersections = function computeIntersections () { var this$1$1 = this if (arguments.length === 1) { var si = arguments[0] this.nOverlaps = 0 this.prepareEvents() for (var i = 0; i < this.events.size(); i++) { var ev = this$1$1.events.get(i) if (ev.isInsert()) { this$1$1.processOverlaps(i, ev.getDeleteEventIndex(), ev, si) } if (si.isDone()) { break } } } else if (arguments.length === 3) { if (arguments[2] instanceof SegmentIntersector$2 && (hasInterface(arguments[0], List) && hasInterface(arguments[1], List))) { var edges0 = arguments[0] var edges1 = arguments[1] var si$1 = arguments[2] this.addEdges(edges0, edges0) this.addEdges(edges1, edges1) this.computeIntersections(si$1) } else if (typeof arguments[2] === 'boolean' && (hasInterface(arguments[0], List) && arguments[1] instanceof SegmentIntersector$2)) { var edges = arguments[0] var si$2 = arguments[1] var testAllSegments = arguments[2] if (testAllSegments) { this.addEdges(edges, null) } else { this.addEdges(edges) } this.computeIntersections(si$2) } } } SimpleMCSweepLineIntersector.prototype.addEdge = function addEdge (edge, edgeSet) { var this$1$1 = this var mce = edge.getMonotoneChainEdge() var startIndex = mce.getStartIndexes() for (var i = 0; i < startIndex.length - 1; i++) { var mc = new MonotoneChain$2(mce, i) var insertEvent = new SweepLineEvent(edgeSet, mce.getMinX(i), mc) this$1$1.events.add(insertEvent) this$1$1.events.add(new SweepLineEvent(mce.getMaxX(i), insertEvent)) } } SimpleMCSweepLineIntersector.prototype.processOverlaps = function processOverlaps (start, end, ev0, si) { var this$1$1 = this var mc0 = ev0.getObject() for (var i = start; i < end; i++) { var ev1 = this$1$1.events.get(i) if (ev1.isInsert()) { var mc1 = ev1.getObject() if (!ev0.isSameLabel(ev1)) { mc0.computeIntersections(mc1, si) this$1$1.nOverlaps++ } } } } SimpleMCSweepLineIntersector.prototype.addEdges = function addEdges () { var this$1$1 = this if (arguments.length === 1) { var edges = arguments[0] for (var i = edges.iterator(); i.hasNext();) { var edge = i.next() this$1$1.addEdge(edge, edge) } } else if (arguments.length === 2) { var edges$1 = arguments[0] var edgeSet = arguments[1] for (var i$1 = edges$1.iterator(); i$1.hasNext();) { var edge$1 = i$1.next() this$1$1.addEdge(edge$1, edgeSet) } } } SimpleMCSweepLineIntersector.prototype.interfaces_ = function interfaces_ () { return [] } SimpleMCSweepLineIntersector.prototype.getClass = function getClass () { return SimpleMCSweepLineIntersector } return SimpleMCSweepLineIntersector }(EdgeSetIntersector)) var IntervalRTreeNode = function IntervalRTreeNode () { this._min = Double.POSITIVE_INFINITY this._max = Double.NEGATIVE_INFINITY } var staticAccessors$45 = { NodeComparator: { configurable: true } } IntervalRTreeNode.prototype.getMin = function getMin () { return this._min } IntervalRTreeNode.prototype.intersects = function intersects (queryMin, queryMax) { if (this._min > queryMax || this._max < queryMin) { return false } return true } IntervalRTreeNode.prototype.getMax = function getMax () { return this._max } IntervalRTreeNode.prototype.toString = function toString () { return WKTWriter.toLineString(new Coordinate(this._min, 0), new Coordinate(this._max, 0)) } IntervalRTreeNode.prototype.interfaces_ = function interfaces_ () { return [] } IntervalRTreeNode.prototype.getClass = function getClass () { return IntervalRTreeNode } staticAccessors$45.NodeComparator.get = function () { return NodeComparator } Object.defineProperties(IntervalRTreeNode, staticAccessors$45) var NodeComparator = function NodeComparator () { } NodeComparator.prototype.compare = function compare (o1, o2) { var n1 = o1 var n2 = o2 var mid1 = (n1._min + n1._max) / 2 var mid2 = (n2._min + n2._max) / 2 if (mid1 < mid2) { return -1 } if (mid1 > mid2) { return 1 } return 0 } NodeComparator.prototype.interfaces_ = function interfaces_ () { return [Comparator] } NodeComparator.prototype.getClass = function getClass () { return NodeComparator } var IntervalRTreeLeafNode = (function (IntervalRTreeNode$$1) { function IntervalRTreeLeafNode () { IntervalRTreeNode$$1.call(this) this._item = null var min = arguments[0] var max = arguments[1] var item = arguments[2] this._min = min this._max = max this._item = item } if (IntervalRTreeNode$$1) IntervalRTreeLeafNode.__proto__ = IntervalRTreeNode$$1 IntervalRTreeLeafNode.prototype = Object.create(IntervalRTreeNode$$1 && IntervalRTreeNode$$1.prototype) IntervalRTreeLeafNode.prototype.constructor = IntervalRTreeLeafNode IntervalRTreeLeafNode.prototype.query = function query (queryMin, queryMax, visitor) { if (!this.intersects(queryMin, queryMax)) { return null } visitor.visitItem(this._item) } IntervalRTreeLeafNode.prototype.interfaces_ = function interfaces_ () { return [] } IntervalRTreeLeafNode.prototype.getClass = function getClass () { return IntervalRTreeLeafNode } return IntervalRTreeLeafNode }(IntervalRTreeNode)) var IntervalRTreeBranchNode = (function (IntervalRTreeNode$$1) { function IntervalRTreeBranchNode () { IntervalRTreeNode$$1.call(this) this._node1 = null this._node2 = null var n1 = arguments[0] var n2 = arguments[1] this._node1 = n1 this._node2 = n2 this.buildExtent(this._node1, this._node2) } if (IntervalRTreeNode$$1) IntervalRTreeBranchNode.__proto__ = IntervalRTreeNode$$1 IntervalRTreeBranchNode.prototype = Object.create(IntervalRTreeNode$$1 && IntervalRTreeNode$$1.prototype) IntervalRTreeBranchNode.prototype.constructor = IntervalRTreeBranchNode IntervalRTreeBranchNode.prototype.buildExtent = function buildExtent (n1, n2) { this._min = Math.min(n1._min, n2._min) this._max = Math.max(n1._max, n2._max) } IntervalRTreeBranchNode.prototype.query = function query (queryMin, queryMax, visitor) { if (!this.intersects(queryMin, queryMax)) { return null } if (this._node1 !== null) { this._node1.query(queryMin, queryMax, visitor) } if (this._node2 !== null) { this._node2.query(queryMin, queryMax, visitor) } } IntervalRTreeBranchNode.prototype.interfaces_ = function interfaces_ () { return [] } IntervalRTreeBranchNode.prototype.getClass = function getClass () { return IntervalRTreeBranchNode } return IntervalRTreeBranchNode }(IntervalRTreeNode)) var SortedPackedIntervalRTree = function SortedPackedIntervalRTree () { this._leaves = new ArrayList() this._root = null this._level = 0 } SortedPackedIntervalRTree.prototype.buildTree = function buildTree () { var this$1$1 = this Collections.sort(this._leaves, new IntervalRTreeNode.NodeComparator()) var src = this._leaves var temp = null var dest = new ArrayList() while (true) { this$1$1.buildLevel(src, dest) if (dest.size() === 1) { return dest.get(0) } temp = src src = dest dest = temp } } SortedPackedIntervalRTree.prototype.insert = function insert (min, max, item) { if (this._root !== null) { throw new Error('Index cannot be added to once it has been queried') } this._leaves.add(new IntervalRTreeLeafNode(min, max, item)) } SortedPackedIntervalRTree.prototype.query = function query (min, max, visitor) { this.init() this._root.query(min, max, visitor) } SortedPackedIntervalRTree.prototype.buildRoot = function buildRoot () { if (this._root !== null) { return null } this._root = this.buildTree() } SortedPackedIntervalRTree.prototype.printNode = function printNode (node) { System.out.println(WKTWriter.toLineString(new Coordinate(node._min, this._level), new Coordinate(node._max, this._level))) } SortedPackedIntervalRTree.prototype.init = function init () { if (this._root !== null) { return null } this.buildRoot() } SortedPackedIntervalRTree.prototype.buildLevel = function buildLevel (src, dest) { this._level++ dest.clear() for (var i = 0; i < src.size(); i += 2) { var n1 = src.get(i) var n2 = i + 1 < src.size() ? src.get(i) : null if (n2 === null) { dest.add(n1) } else { var node = new IntervalRTreeBranchNode(src.get(i), src.get(i + 1)) dest.add(node) } } } SortedPackedIntervalRTree.prototype.interfaces_ = function interfaces_ () { return [] } SortedPackedIntervalRTree.prototype.getClass = function getClass () { return SortedPackedIntervalRTree } var ArrayListVisitor = function ArrayListVisitor () { this._items = new ArrayList() } ArrayListVisitor.prototype.visitItem = function visitItem (item) { this._items.add(item) } ArrayListVisitor.prototype.getItems = function getItems () { return this._items } ArrayListVisitor.prototype.interfaces_ = function interfaces_ () { return [ItemVisitor] } ArrayListVisitor.prototype.getClass = function getClass () { return ArrayListVisitor } var IndexedPointInAreaLocator = function IndexedPointInAreaLocator () { this._index = null var g = arguments[0] if (!hasInterface(g, Polygonal)) { throw new IllegalArgumentException('Argument must be Polygonal') } this._index = new IntervalIndexedGeometry(g) } var staticAccessors$44 = { SegmentVisitor: { configurable: true }, IntervalIndexedGeometry: { configurable: true } } IndexedPointInAreaLocator.prototype.locate = function locate (p) { var rcc = new RayCrossingCounter(p) var visitor = new SegmentVisitor(rcc) this._index.query(p.y, p.y, visitor) return rcc.getLocation() } IndexedPointInAreaLocator.prototype.interfaces_ = function interfaces_ () { return [PointOnGeometryLocator] } IndexedPointInAreaLocator.prototype.getClass = function getClass () { return IndexedPointInAreaLocator } staticAccessors$44.SegmentVisitor.get = function () { return SegmentVisitor } staticAccessors$44.IntervalIndexedGeometry.get = function () { return IntervalIndexedGeometry } Object.defineProperties(IndexedPointInAreaLocator, staticAccessors$44) var SegmentVisitor = function SegmentVisitor () { this._counter = null var counter = arguments[0] this._counter = counter } SegmentVisitor.prototype.visitItem = function visitItem (item) { var seg = item this._counter.countSegment(seg.getCoordinate(0), seg.getCoordinate(1)) } SegmentVisitor.prototype.interfaces_ = function interfaces_ () { return [ItemVisitor] } SegmentVisitor.prototype.getClass = function getClass () { return SegmentVisitor } var IntervalIndexedGeometry = function IntervalIndexedGeometry () { this._index = new SortedPackedIntervalRTree() var geom = arguments[0] this.init(geom) } IntervalIndexedGeometry.prototype.init = function init (geom) { var this$1$1 = this var lines = LinearComponentExtracter.getLines(geom) for (var i = lines.iterator(); i.hasNext();) { var line = i.next() var pts = line.getCoordinates() this$1$1.addLine(pts) } } IntervalIndexedGeometry.prototype.addLine = function addLine (pts) { var this$1$1 = this for (var i = 1; i < pts.length; i++) { var seg = new LineSegment(pts[i - 1], pts[i]) var min = Math.min(seg.p0.y, seg.p1.y) var max = Math.max(seg.p0.y, seg.p1.y) this$1$1._index.insert(min, max, seg) } } IntervalIndexedGeometry.prototype.query = function query () { if (arguments.length === 2) { var min = arguments[0] var max = arguments[1] var visitor = new ArrayListVisitor() this._index.query(min, max, visitor) return visitor.getItems() } else if (arguments.length === 3) { var min$1 = arguments[0] var max$1 = arguments[1] var visitor$1 = arguments[2] this._index.query(min$1, max$1, visitor$1) } } IntervalIndexedGeometry.prototype.interfaces_ = function interfaces_ () { return [] } IntervalIndexedGeometry.prototype.getClass = function getClass () { return IntervalIndexedGeometry } var GeometryGraph = (function (PlanarGraph$$1) { function GeometryGraph () { PlanarGraph$$1.call(this) this._parentGeom = null this._lineEdgeMap = new HashMap() this._boundaryNodeRule = null this._useBoundaryDeterminationRule = true this._argIndex = null this._boundaryNodes = null this._hasTooFewPoints = false this._invalidPoint = null this._areaPtLocator = null this._ptLocator = new PointLocator() if (arguments.length === 2) { var argIndex = arguments[0] var parentGeom = arguments[1] var boundaryNodeRule = BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE this._argIndex = argIndex this._parentGeom = parentGeom this._boundaryNodeRule = boundaryNodeRule if (parentGeom !== null) { this.add(parentGeom) } } else if (arguments.length === 3) { var argIndex$1 = arguments[0] var parentGeom$1 = arguments[1] var boundaryNodeRule$1 = arguments[2] this._argIndex = argIndex$1 this._parentGeom = parentGeom$1 this._boundaryNodeRule = boundaryNodeRule$1 if (parentGeom$1 !== null) { this.add(parentGeom$1) } } } if (PlanarGraph$$1) GeometryGraph.__proto__ = PlanarGraph$$1 GeometryGraph.prototype = Object.create(PlanarGraph$$1 && PlanarGraph$$1.prototype) GeometryGraph.prototype.constructor = GeometryGraph GeometryGraph.prototype.insertBoundaryPoint = function insertBoundaryPoint (argIndex, coord) { var n = this._nodes.addNode(coord) var lbl = n.getLabel() var boundaryCount = 1 var loc = Location.NONE loc = lbl.getLocation(argIndex, Position.ON) if (loc === Location.BOUNDARY) { boundaryCount++ } var newLoc = GeometryGraph.determineBoundary(this._boundaryNodeRule, boundaryCount) lbl.setLocation(argIndex, newLoc) } GeometryGraph.prototype.computeSelfNodes = function computeSelfNodes () { if (arguments.length === 2) { var li = arguments[0] var computeRingSelfNodes = arguments[1] return this.computeSelfNodes(li, computeRingSelfNodes, false) } else if (arguments.length === 3) { var li$1 = arguments[0] var computeRingSelfNodes$1 = arguments[1] var isDoneIfProperInt = arguments[2] var si = new SegmentIntersector$2(li$1, true, false) si.setIsDoneIfProperInt(isDoneIfProperInt) var esi = this.createEdgeSetIntersector() var isRings = this._parentGeom instanceof LinearRing || this._parentGeom instanceof Polygon || this._parentGeom instanceof MultiPolygon var computeAllSegments = computeRingSelfNodes$1 || !isRings esi.computeIntersections(this._edges, si, computeAllSegments) this.addSelfIntersectionNodes(this._argIndex) return si } } GeometryGraph.prototype.computeSplitEdges = function computeSplitEdges (edgelist) { for (var i = this._edges.iterator(); i.hasNext();) { var e = i.next() e.eiList.addSplitEdges(edgelist) } } GeometryGraph.prototype.computeEdgeIntersections = function computeEdgeIntersections (g, li, includeProper) { var si = new SegmentIntersector$2(li, includeProper, true) si.setBoundaryNodes(this.getBoundaryNodes(), g.getBoundaryNodes()) var esi = this.createEdgeSetIntersector() esi.computeIntersections(this._edges, g._edges, si) return si } GeometryGraph.prototype.getGeometry = function getGeometry () { return this._parentGeom } GeometryGraph.prototype.getBoundaryNodeRule = function getBoundaryNodeRule () { return this._boundaryNodeRule } GeometryGraph.prototype.hasTooFewPoints = function hasTooFewPoints () { return this._hasTooFewPoints } GeometryGraph.prototype.addPoint = function addPoint () { if (arguments[0] instanceof Point) { var p = arguments[0] var coord = p.getCoordinate() this.insertPoint(this._argIndex, coord, Location.INTERIOR) } else if (arguments[0] instanceof Coordinate) { var pt = arguments[0] this.insertPoint(this._argIndex, pt, Location.INTERIOR) } } GeometryGraph.prototype.addPolygon = function addPolygon (p) { var this$1$1 = this this.addPolygonRing(p.getExteriorRing(), Location.EXTERIOR, Location.INTERIOR) for (var i = 0; i < p.getNumInteriorRing(); i++) { var hole = p.getInteriorRingN(i) this$1$1.addPolygonRing(hole, Location.INTERIOR, Location.EXTERIOR) } } GeometryGraph.prototype.addEdge = function addEdge (e) { this.insertEdge(e) var coord = e.getCoordinates() this.insertPoint(this._argIndex, coord[0], Location.BOUNDARY) this.insertPoint(this._argIndex, coord[coord.length - 1], Location.BOUNDARY) } GeometryGraph.prototype.addLineString = function addLineString (line) { var coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates()) if (coord.length < 2) { this._hasTooFewPoints = true this._invalidPoint = coord[0] return null } var e = new Edge(coord, new Label(this._argIndex, Location.INTERIOR)) this._lineEdgeMap.put(line, e) this.insertEdge(e) Assert.isTrue(coord.length >= 2, 'found LineString with single point') this.insertBoundaryPoint(this._argIndex, coord[0]) this.insertBoundaryPoint(this._argIndex, coord[coord.length - 1]) } GeometryGraph.prototype.getInvalidPoint = function getInvalidPoint () { return this._invalidPoint } GeometryGraph.prototype.getBoundaryPoints = function getBoundaryPoints () { var coll = this.getBoundaryNodes() var pts = new Array(coll.size()).fill(null) var i = 0 for (var it = coll.iterator(); it.hasNext();) { var node = it.next() pts[i++] = node.getCoordinate().copy() } return pts } GeometryGraph.prototype.getBoundaryNodes = function getBoundaryNodes () { if (this._boundaryNodes === null) { this._boundaryNodes = this._nodes.getBoundaryNodes(this._argIndex) } return this._boundaryNodes } GeometryGraph.prototype.addSelfIntersectionNode = function addSelfIntersectionNode (argIndex, coord, loc) { if (this.isBoundaryNode(argIndex, coord)) { return null } if (loc === Location.BOUNDARY && this._useBoundaryDeterminationRule) { this.insertBoundaryPoint(argIndex, coord) } else { this.insertPoint(argIndex, coord, loc) } } GeometryGraph.prototype.addPolygonRing = function addPolygonRing (lr, cwLeft, cwRight) { if (lr.isEmpty()) { return null } var coord = CoordinateArrays.removeRepeatedPoints(lr.getCoordinates()) if (coord.length < 4) { this._hasTooFewPoints = true this._invalidPoint = coord[0] return null } var left = cwLeft var right = cwRight if (CGAlgorithms.isCCW(coord)) { left = cwRight right = cwLeft } var e = new Edge(coord, new Label(this._argIndex, Location.BOUNDARY, left, right)) this._lineEdgeMap.put(lr, e) this.insertEdge(e) this.insertPoint(this._argIndex, coord[0], Location.BOUNDARY) } GeometryGraph.prototype.insertPoint = function insertPoint (argIndex, coord, onLocation) { var n = this._nodes.addNode(coord) var lbl = n.getLabel() if (lbl === null) { n._label = new Label(argIndex, onLocation) } else { lbl.setLocation(argIndex, onLocation) } } GeometryGraph.prototype.createEdgeSetIntersector = function createEdgeSetIntersector () { return new SimpleMCSweepLineIntersector() } GeometryGraph.prototype.addSelfIntersectionNodes = function addSelfIntersectionNodes (argIndex) { var this$1$1 = this for (var i = this._edges.iterator(); i.hasNext();) { var e = i.next() var eLoc = e.getLabel().getLocation(argIndex) for (var eiIt = e.eiList.iterator(); eiIt.hasNext();) { var ei = eiIt.next() this$1$1.addSelfIntersectionNode(argIndex, ei.coord, eLoc) } } } GeometryGraph.prototype.add = function add () { if (arguments.length === 1) { var g = arguments[0] if (g.isEmpty()) { return null } if (g instanceof MultiPolygon) { this._useBoundaryDeterminationRule = false } if (g instanceof Polygon) { this.addPolygon(g) } else if (g instanceof LineString) { this.addLineString(g) } else if (g instanceof Point) { this.addPoint(g) } else if (g instanceof MultiPoint) { this.addCollection(g) } else if (g instanceof MultiLineString) { this.addCollection(g) } else if (g instanceof MultiPolygon) { this.addCollection(g) } else if (g instanceof GeometryCollection) { this.addCollection(g) } else { throw new Error(g.getClass().getName()) } } else { return PlanarGraph$$1.prototype.add.apply(this, arguments) } } GeometryGraph.prototype.addCollection = function addCollection (gc) { var this$1$1 = this for (var i = 0; i < gc.getNumGeometries(); i++) { var g = gc.getGeometryN(i) this$1$1.add(g) } } GeometryGraph.prototype.locate = function locate (pt) { if (hasInterface(this._parentGeom, Polygonal) && this._parentGeom.getNumGeometries() > 50) { if (this._areaPtLocator === null) { this._areaPtLocator = new IndexedPointInAreaLocator(this._parentGeom) } return this._areaPtLocator.locate(pt) } return this._ptLocator.locate(pt, this._parentGeom) } GeometryGraph.prototype.findEdge = function findEdge () { if (arguments.length === 1) { var line = arguments[0] return this._lineEdgeMap.get(line) } else { return PlanarGraph$$1.prototype.findEdge.apply(this, arguments) } } GeometryGraph.prototype.interfaces_ = function interfaces_ () { return [] } GeometryGraph.prototype.getClass = function getClass () { return GeometryGraph } GeometryGraph.determineBoundary = function determineBoundary (boundaryNodeRule, boundaryCount) { return boundaryNodeRule.isInBoundary(boundaryCount) ? Location.BOUNDARY : Location.INTERIOR } return GeometryGraph }(PlanarGraph)) var GeometryGraphOp = function GeometryGraphOp () { this._li = new RobustLineIntersector() this._resultPrecisionModel = null this._arg = null if (arguments.length === 1) { var g0 = arguments[0] this.setComputationPrecision(g0.getPrecisionModel()) this._arg = new Array(1).fill(null) this._arg[0] = new GeometryGraph(0, g0) } else if (arguments.length === 2) { var g0$1 = arguments[0] var g1 = arguments[1] var boundaryNodeRule = BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE if (g0$1.getPrecisionModel().compareTo(g1.getPrecisionModel()) >= 0) { this.setComputationPrecision(g0$1.getPrecisionModel()) } else { this.setComputationPrecision(g1.getPrecisionModel()) } this._arg = new Array(2).fill(null) this._arg[0] = new GeometryGraph(0, g0$1, boundaryNodeRule) this._arg[1] = new GeometryGraph(1, g1, boundaryNodeRule) } else if (arguments.length === 3) { var g0$2 = arguments[0] var g1$1 = arguments[1] var boundaryNodeRule$1 = arguments[2] if (g0$2.getPrecisionModel().compareTo(g1$1.getPrecisionModel()) >= 0) { this.setComputationPrecision(g0$2.getPrecisionModel()) } else { this.setComputationPrecision(g1$1.getPrecisionModel()) } this._arg = new Array(2).fill(null) this._arg[0] = new GeometryGraph(0, g0$2, boundaryNodeRule$1) this._arg[1] = new GeometryGraph(1, g1$1, boundaryNodeRule$1) } } GeometryGraphOp.prototype.getArgGeometry = function getArgGeometry (i) { return this._arg[i].getGeometry() } GeometryGraphOp.prototype.setComputationPrecision = function setComputationPrecision (pm) { this._resultPrecisionModel = pm this._li.setPrecisionModel(this._resultPrecisionModel) } GeometryGraphOp.prototype.interfaces_ = function interfaces_ () { return [] } GeometryGraphOp.prototype.getClass = function getClass () { return GeometryGraphOp } // operation.geometrygraph var GeometryMapper = function GeometryMapper () { } GeometryMapper.prototype.interfaces_ = function interfaces_ () { return [] } GeometryMapper.prototype.getClass = function getClass () { return GeometryMapper } GeometryMapper.map = function map () { if (arguments[0] instanceof Geometry$2 && hasInterface(arguments[1], GeometryMapper.MapOp)) { var geom = arguments[0] var op = arguments[1] var mapped = new ArrayList() for (var i = 0; i < geom.getNumGeometries(); i++) { var g = op.map(geom.getGeometryN(i)) if (g !== null) { mapped.add(g) } } return geom.getFactory().buildGeometry(mapped) } else if (hasInterface(arguments[0], Collection) && hasInterface(arguments[1], GeometryMapper.MapOp)) { var geoms = arguments[0] var op$1 = arguments[1] var mapped$1 = new ArrayList() for (var i$1 = geoms.iterator(); i$1.hasNext();) { var g$1 = i$1.next() var gr = op$1.map(g$1) if (gr !== null) { mapped$1.add(gr) } } return mapped$1 } } GeometryMapper.MapOp = function MapOp () { } var OverlayOp = (function (GeometryGraphOp) { function OverlayOp () { var g0 = arguments[0] var g1 = arguments[1] GeometryGraphOp.call(this, g0, g1) this._ptLocator = new PointLocator() this._geomFact = null this._resultGeom = null this._graph = null this._edgeList = new EdgeList() this._resultPolyList = new ArrayList() this._resultLineList = new ArrayList() this._resultPointList = new ArrayList() this._graph = new PlanarGraph(new OverlayNodeFactory()) this._geomFact = g0.getFactory() } if (GeometryGraphOp) OverlayOp.__proto__ = GeometryGraphOp OverlayOp.prototype = Object.create(GeometryGraphOp && GeometryGraphOp.prototype) OverlayOp.prototype.constructor = OverlayOp OverlayOp.prototype.insertUniqueEdge = function insertUniqueEdge (e) { var existingEdge = this._edgeList.findEqualEdge(e) if (existingEdge !== null) { var existingLabel = existingEdge.getLabel() var labelToMerge = e.getLabel() if (!existingEdge.isPointwiseEqual(e)) { labelToMerge = new Label(e.getLabel()) labelToMerge.flip() } var depth = existingEdge.getDepth() if (depth.isNull()) { depth.add(existingLabel) } depth.add(labelToMerge) existingLabel.merge(labelToMerge) } else { this._edgeList.add(e) } } OverlayOp.prototype.getGraph = function getGraph () { return this._graph } OverlayOp.prototype.cancelDuplicateResultEdges = function cancelDuplicateResultEdges () { for (var it = this._graph.getEdgeEnds().iterator(); it.hasNext();) { var de = it.next() var sym = de.getSym() if (de.isInResult() && sym.isInResult()) { de.setInResult(false) sym.setInResult(false) } } } OverlayOp.prototype.isCoveredByLA = function isCoveredByLA (coord) { if (this.isCovered(coord, this._resultLineList)) { return true } if (this.isCovered(coord, this._resultPolyList)) { return true } return false } OverlayOp.prototype.computeGeometry = function computeGeometry (resultPointList, resultLineList, resultPolyList, opcode) { var geomList = new ArrayList() geomList.addAll(resultPointList) geomList.addAll(resultLineList) geomList.addAll(resultPolyList) if (geomList.isEmpty()) { return OverlayOp.createEmptyResult(opcode, this._arg[0].getGeometry(), this._arg[1].getGeometry(), this._geomFact) } return this._geomFact.buildGeometry(geomList) } OverlayOp.prototype.mergeSymLabels = function mergeSymLabels () { for (var nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) { var node = nodeit.next() node.getEdges().mergeSymLabels() } } OverlayOp.prototype.isCovered = function isCovered (coord, geomList) { var this$1$1 = this for (var it = geomList.iterator(); it.hasNext();) { var geom = it.next() var loc = this$1$1._ptLocator.locate(coord, geom) if (loc !== Location.EXTERIOR) { return true } } return false } OverlayOp.prototype.replaceCollapsedEdges = function replaceCollapsedEdges () { var newEdges = new ArrayList() for (var it = this._edgeList.iterator(); it.hasNext();) { var e = it.next() if (e.isCollapsed()) { it.remove() newEdges.add(e.getCollapsedEdge()) } } this._edgeList.addAll(newEdges) } OverlayOp.prototype.updateNodeLabelling = function updateNodeLabelling () { for (var nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) { var node = nodeit.next() var lbl = node.getEdges().getLabel() node.getLabel().merge(lbl) } } OverlayOp.prototype.getResultGeometry = function getResultGeometry (overlayOpCode) { this.computeOverlay(overlayOpCode) return this._resultGeom } OverlayOp.prototype.insertUniqueEdges = function insertUniqueEdges (edges) { var this$1$1 = this for (var i = edges.iterator(); i.hasNext();) { var e = i.next() this$1$1.insertUniqueEdge(e) } } OverlayOp.prototype.computeOverlay = function computeOverlay (opCode) { this.copyPoints(0) this.copyPoints(1) this._arg[0].computeSelfNodes(this._li, false) this._arg[1].computeSelfNodes(this._li, false) this._arg[0].computeEdgeIntersections(this._arg[1], this._li, true) var baseSplitEdges = new ArrayList() this._arg[0].computeSplitEdges(baseSplitEdges) this._arg[1].computeSplitEdges(baseSplitEdges) // const splitEdges = baseSplitEdges this.insertUniqueEdges(baseSplitEdges) this.computeLabelsFromDepths() this.replaceCollapsedEdges() EdgeNodingValidator.checkValid(this._edgeList.getEdges()) this._graph.addEdges(this._edgeList.getEdges()) this.computeLabelling() this.labelIncompleteNodes() this.findResultAreaEdges(opCode) this.cancelDuplicateResultEdges() var polyBuilder = new PolygonBuilder(this._geomFact) polyBuilder.add(this._graph) this._resultPolyList = polyBuilder.getPolygons() var lineBuilder = new LineBuilder(this, this._geomFact, this._ptLocator) this._resultLineList = lineBuilder.build(opCode) var pointBuilder = new PointBuilder(this, this._geomFact, this._ptLocator) this._resultPointList = pointBuilder.build(opCode) this._resultGeom = this.computeGeometry(this._resultPointList, this._resultLineList, this._resultPolyList, opCode) } OverlayOp.prototype.labelIncompleteNode = function labelIncompleteNode (n, targetIndex) { var loc = this._ptLocator.locate(n.getCoordinate(), this._arg[targetIndex].getGeometry()) n.getLabel().setLocation(targetIndex, loc) } OverlayOp.prototype.copyPoints = function copyPoints (argIndex) { var this$1$1 = this for (var i = this._arg[argIndex].getNodeIterator(); i.hasNext();) { var graphNode = i.next() var newNode = this$1$1._graph.addNode(graphNode.getCoordinate()) newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex)) } } OverlayOp.prototype.findResultAreaEdges = function findResultAreaEdges (opCode) { for (var it = this._graph.getEdgeEnds().iterator(); it.hasNext();) { var de = it.next() var label = de.getLabel() if (label.isArea() && !de.isInteriorAreaEdge() && OverlayOp.isResultOfOp(label.getLocation(0, Position.RIGHT), label.getLocation(1, Position.RIGHT), opCode)) { de.setInResult(true) } } } OverlayOp.prototype.computeLabelsFromDepths = function computeLabelsFromDepths () { for (var it = this._edgeList.iterator(); it.hasNext();) { var e = it.next() var lbl = e.getLabel() var depth = e.getDepth() if (!depth.isNull()) { depth.normalize() for (var i = 0; i < 2; i++) { if (!lbl.isNull(i) && lbl.isArea() && !depth.isNull(i)) { if (depth.getDelta(i) === 0) { lbl.toLine(i) } else { Assert.isTrue(!depth.isNull(i, Position.LEFT), 'depth of LEFT side has not been initialized') lbl.setLocation(i, Position.LEFT, depth.getLocation(i, Position.LEFT)) Assert.isTrue(!depth.isNull(i, Position.RIGHT), 'depth of RIGHT side has not been initialized') lbl.setLocation(i, Position.RIGHT, depth.getLocation(i, Position.RIGHT)) } } } } } } OverlayOp.prototype.computeLabelling = function computeLabelling () { var this$1$1 = this for (var nodeit = this._graph.getNodes().iterator(); nodeit.hasNext();) { var node = nodeit.next() node.getEdges().computeLabelling(this$1$1._arg) } this.mergeSymLabels() this.updateNodeLabelling() } OverlayOp.prototype.labelIncompleteNodes = function labelIncompleteNodes () { var this$1$1 = this // let nodeCount = 0 for (var ni = this._graph.getNodes().iterator(); ni.hasNext();) { var n = ni.next() var label = n.getLabel() if (n.isIsolated()) { // nodeCount++ if (label.isNull(0)) { this$1$1.labelIncompleteNode(n, 0) } else { this$1$1.labelIncompleteNode(n, 1) } } n.getEdges().updateLabelling(label) } } OverlayOp.prototype.isCoveredByA = function isCoveredByA (coord) { if (this.isCovered(coord, this._resultPolyList)) { return true } return false } OverlayOp.prototype.interfaces_ = function interfaces_ () { return [] } OverlayOp.prototype.getClass = function getClass () { return OverlayOp } return OverlayOp }(GeometryGraphOp)) OverlayOp.overlayOp = function (geom0, geom1, opCode) { var gov = new OverlayOp(geom0, geom1) var geomOv = gov.getResultGeometry(opCode) return geomOv } OverlayOp.intersection = function (g, other) { if (g.isEmpty() || other.isEmpty()) { return OverlayOp.createEmptyResult(OverlayOp.INTERSECTION, g, other, g.getFactory()) } if (g.isGeometryCollection()) { var g2 = other return GeometryCollectionMapper.map(g, { interfaces_: function () { return [GeometryMapper.MapOp] }, map: function (g) { return g.intersection(g2) } }) } g.checkNotGeometryCollection(g) g.checkNotGeometryCollection(other) return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.INTERSECTION) } OverlayOp.symDifference = function (g, other) { if (g.isEmpty() || other.isEmpty()) { if (g.isEmpty() && other.isEmpty()) { return OverlayOp.createEmptyResult(OverlayOp.SYMDIFFERENCE, g, other, g.getFactory()) } if (g.isEmpty()) { return other.copy() } if (other.isEmpty()) { return g.copy() } } g.checkNotGeometryCollection(g) g.checkNotGeometryCollection(other) return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.SYMDIFFERENCE) } OverlayOp.resultDimension = function (opCode, g0, g1) { var dim0 = g0.getDimension() var dim1 = g1.getDimension() var resultDimension = -1 switch (opCode) { case OverlayOp.INTERSECTION: resultDimension = Math.min(dim0, dim1) break case OverlayOp.UNION: resultDimension = Math.max(dim0, dim1) break case OverlayOp.DIFFERENCE: resultDimension = dim0 break case OverlayOp.SYMDIFFERENCE: resultDimension = Math.max(dim0, dim1) break } return resultDimension } OverlayOp.createEmptyResult = function (overlayOpCode, a, b, geomFact) { var result = null switch (OverlayOp.resultDimension(overlayOpCode, a, b)) { case -1: result = geomFact.createGeometryCollection(new Array(0).fill(null)) break case 0: result = geomFact.createPoint() break case 1: result = geomFact.createLineString() break case 2: result = geomFact.createPolygon() break } return result } OverlayOp.difference = function (g, other) { if (g.isEmpty()) { return OverlayOp.createEmptyResult(OverlayOp.DIFFERENCE, g, other, g.getFactory()) } if (other.isEmpty()) { return g.copy() } g.checkNotGeometryCollection(g) g.checkNotGeometryCollection(other) return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.DIFFERENCE) } OverlayOp.isResultOfOp = function () { if (arguments.length === 2) { var label = arguments[0] var opCode = arguments[1] var loc0 = label.getLocation(0) var loc1 = label.getLocation(1) return OverlayOp.isResultOfOp(loc0, loc1, opCode) } else if (arguments.length === 3) { var loc0$1 = arguments[0] var loc1$1 = arguments[1] var overlayOpCode = arguments[2] if (loc0$1 === Location.BOUNDARY) { loc0$1 = Location.INTERIOR } if (loc1$1 === Location.BOUNDARY) { loc1$1 = Location.INTERIOR } switch (overlayOpCode) { case OverlayOp.INTERSECTION: return loc0$1 === Location.INTERIOR && loc1$1 === Location.INTERIOR case OverlayOp.UNION: return loc0$1 === Location.INTERIOR || loc1$1 === Location.INTERIOR case OverlayOp.DIFFERENCE: return loc0$1 === Location.INTERIOR && loc1$1 !== Location.INTERIOR case OverlayOp.SYMDIFFERENCE: return (loc0$1 === Location.INTERIOR && loc1$1 !== Location.INTERIOR) || (loc0$1 !== Location.INTERIOR && loc1$1 === Location.INTERIOR) } return false } } OverlayOp.INTERSECTION = 1 OverlayOp.UNION = 2 OverlayOp.DIFFERENCE = 3 OverlayOp.SYMDIFFERENCE = 4 var FuzzyPointLocator = function FuzzyPointLocator () { this._g = null this._boundaryDistanceTolerance = null this._linework = null this._ptLocator = new PointLocator() this._seg = new LineSegment() var g = arguments[0] var boundaryDistanceTolerance = arguments[1] this._g = g this._boundaryDistanceTolerance = boundaryDistanceTolerance this._linework = this.extractLinework(g) } FuzzyPointLocator.prototype.isWithinToleranceOfBoundary = function isWithinToleranceOfBoundary (pt) { var this$1$1 = this for (var i = 0; i < this._linework.getNumGeometries(); i++) { var line = this$1$1._linework.getGeometryN(i) var seq = line.getCoordinateSequence() for (var j = 0; j < seq.size() - 1; j++) { seq.getCoordinate(j, this$1$1._seg.p0) seq.getCoordinate(j + 1, this$1$1._seg.p1) var dist = this$1$1._seg.distance(pt) if (dist <= this$1$1._boundaryDistanceTolerance) { return true } } } return false } FuzzyPointLocator.prototype.getLocation = function getLocation (pt) { if (this.isWithinToleranceOfBoundary(pt)) { return Location.BOUNDARY } return this._ptLocator.locate(pt, this._g) } FuzzyPointLocator.prototype.extractLinework = function extractLinework (g) { var extracter = new PolygonalLineworkExtracter() g.apply(extracter) var linework = extracter.getLinework() var lines = GeometryFactory.toLineStringArray(linework) return g.getFactory().createMultiLineString(lines) } FuzzyPointLocator.prototype.interfaces_ = function interfaces_ () { return [] } FuzzyPointLocator.prototype.getClass = function getClass () { return FuzzyPointLocator } var PolygonalLineworkExtracter = function PolygonalLineworkExtracter () { this._linework = null this._linework = new ArrayList() } PolygonalLineworkExtracter.prototype.getLinework = function getLinework () { return this._linework } PolygonalLineworkExtracter.prototype.filter = function filter (g) { var this$1$1 = this if (g instanceof Polygon) { var poly = g this._linework.add(poly.getExteriorRing()) for (var i = 0; i < poly.getNumInteriorRing(); i++) { this$1$1._linework.add(poly.getInteriorRingN(i)) } } } PolygonalLineworkExtracter.prototype.interfaces_ = function interfaces_ () { return [GeometryFilter] } PolygonalLineworkExtracter.prototype.getClass = function getClass () { return PolygonalLineworkExtracter } var OffsetPointGenerator = function OffsetPointGenerator () { this._g = null this._doLeft = true this._doRight = true var g = arguments[0] this._g = g } OffsetPointGenerator.prototype.extractPoints = function extractPoints (line, offsetDistance, offsetPts) { var this$1$1 = this var pts = line.getCoordinates() for (var i = 0; i < pts.length - 1; i++) { this$1$1.computeOffsetPoints(pts[i], pts[i + 1], offsetDistance, offsetPts) } } OffsetPointGenerator.prototype.setSidesToGenerate = function setSidesToGenerate (doLeft, doRight) { this._doLeft = doLeft this._doRight = doRight } OffsetPointGenerator.prototype.getPoints = function getPoints (offsetDistance) { var this$1$1 = this var offsetPts = new ArrayList() var lines = LinearComponentExtracter.getLines(this._g) for (var i = lines.iterator(); i.hasNext();) { var line = i.next() this$1$1.extractPoints(line, offsetDistance, offsetPts) } return offsetPts } OffsetPointGenerator.prototype.computeOffsetPoints = function computeOffsetPoints (p0, p1, offsetDistance, offsetPts) { var dx = p1.x - p0.x var dy = p1.y - p0.y var len = Math.sqrt(dx * dx + dy * dy) var ux = offsetDistance * dx / len var uy = offsetDistance * dy / len var midX = (p1.x + p0.x) / 2 var midY = (p1.y + p0.y) / 2 if (this._doLeft) { var offsetLeft = new Coordinate(midX - uy, midY + ux) offsetPts.add(offsetLeft) } if (this._doRight) { var offsetRight = new Coordinate(midX + uy, midY - ux) offsetPts.add(offsetRight) } } OffsetPointGenerator.prototype.interfaces_ = function interfaces_ () { return [] } OffsetPointGenerator.prototype.getClass = function getClass () { return OffsetPointGenerator } var OverlayResultValidator = function OverlayResultValidator () { this._geom = null this._locFinder = null this._location = new Array(3).fill(null) this._invalidLocation = null this._boundaryDistanceTolerance = OverlayResultValidator.TOLERANCE this._testCoords = new ArrayList() var a = arguments[0] var b = arguments[1] var result = arguments[2] this._boundaryDistanceTolerance = OverlayResultValidator.computeBoundaryDistanceTolerance(a, b) this._geom = [a, b, result] this._locFinder = [new FuzzyPointLocator(this._geom[0], this._boundaryDistanceTolerance), new FuzzyPointLocator(this._geom[1], this._boundaryDistanceTolerance), new FuzzyPointLocator(this._geom[2], this._boundaryDistanceTolerance)] } var staticAccessors$46 = { TOLERANCE: { configurable: true } } OverlayResultValidator.prototype.reportResult = function reportResult (overlayOp, location, expectedInterior) { System.out.println('Overlay result invalid - A:' + Location.toLocationSymbol(location[0]) + ' B:' + Location.toLocationSymbol(location[1]) + ' expected:' + (expectedInterior ? 'i' : 'e') + ' actual:' + Location.toLocationSymbol(location[2])) } OverlayResultValidator.prototype.isValid = function isValid (overlayOp) { this.addTestPts(this._geom[0]) this.addTestPts(this._geom[1]) var isValid = this.checkValid(overlayOp) return isValid } OverlayResultValidator.prototype.checkValid = function checkValid () { var this$1$1 = this if (arguments.length === 1) { var overlayOp = arguments[0] for (var i = 0; i < this._testCoords.size(); i++) { var pt = this$1$1._testCoords.get(i) if (!this$1$1.checkValid(overlayOp, pt)) { this$1$1._invalidLocation = pt return false } } return true } else if (arguments.length === 2) { var overlayOp$1 = arguments[0] var pt$1 = arguments[1] this._location[0] = this._locFinder[0].getLocation(pt$1) this._location[1] = this._locFinder[1].getLocation(pt$1) this._location[2] = this._locFinder[2].getLocation(pt$1) if (OverlayResultValidator.hasLocation(this._location, Location.BOUNDARY)) { return true } return this.isValidResult(overlayOp$1, this._location) } } OverlayResultValidator.prototype.addTestPts = function addTestPts (g) { var ptGen = new OffsetPointGenerator(g) this._testCoords.addAll(ptGen.getPoints(5 * this._boundaryDistanceTolerance)) } OverlayResultValidator.prototype.isValidResult = function isValidResult (overlayOp, location) { var expectedInterior = OverlayOp.isResultOfOp(location[0], location[1], overlayOp) var resultInInterior = location[2] === Location.INTERIOR var isValid = !(expectedInterior ^ resultInInterior) if (!isValid) { this.reportResult(overlayOp, location, expectedInterior) } return isValid } OverlayResultValidator.prototype.getInvalidLocation = function getInvalidLocation () { return this._invalidLocation } OverlayResultValidator.prototype.interfaces_ = function interfaces_ () { return [] } OverlayResultValidator.prototype.getClass = function getClass () { return OverlayResultValidator } OverlayResultValidator.hasLocation = function hasLocation (location, loc) { for (var i = 0; i < 3; i++) { if (location[i] === loc) { return true } } return false } OverlayResultValidator.computeBoundaryDistanceTolerance = function computeBoundaryDistanceTolerance (g0, g1) { return Math.min(GeometrySnapper.computeSizeBasedSnapTolerance(g0), GeometrySnapper.computeSizeBasedSnapTolerance(g1)) } OverlayResultValidator.isValid = function isValid (a, b, overlayOp, result) { var validator = new OverlayResultValidator(a, b, result) return validator.isValid(overlayOp) } staticAccessors$46.TOLERANCE.get = function () { return 0.000001 } Object.defineProperties(OverlayResultValidator, staticAccessors$46) // operation.overlay var GeometryCombiner = function GeometryCombiner (geoms) { this._geomFactory = null this._skipEmpty = false this._inputGeoms = null this._geomFactory = GeometryCombiner.extractFactory(geoms) this._inputGeoms = geoms } GeometryCombiner.prototype.extractElements = function extractElements (geom, elems) { var this$1$1 = this if (geom === null) { return null } for (var i = 0; i < geom.getNumGeometries(); i++) { var elemGeom = geom.getGeometryN(i) if (this$1$1._skipEmpty && elemGeom.isEmpty()) { continue } elems.add(elemGeom) } } GeometryCombiner.prototype.combine = function combine () { var this$1$1 = this var elems = new ArrayList() for (var i = this._inputGeoms.iterator(); i.hasNext();) { var g = i.next() this$1$1.extractElements(g, elems) } if (elems.size() === 0) { if (this._geomFactory !== null) { return this._geomFactory.createGeometryCollection(null) } return null } return this._geomFactory.buildGeometry(elems) } GeometryCombiner.prototype.interfaces_ = function interfaces_ () { return [] } GeometryCombiner.prototype.getClass = function getClass () { return GeometryCombiner } GeometryCombiner.combine = function combine () { if (arguments.length === 1) { var geoms = arguments[0] var combiner = new GeometryCombiner(geoms) return combiner.combine() } else if (arguments.length === 2) { var g0 = arguments[0] var g1 = arguments[1] var combiner$1 = new GeometryCombiner(GeometryCombiner.createList(g0, g1)) return combiner$1.combine() } else if (arguments.length === 3) { var g0$1 = arguments[0] var g1$1 = arguments[1] var g2 = arguments[2] var combiner$2 = new GeometryCombiner(GeometryCombiner.createList(g0$1, g1$1, g2)) return combiner$2.combine() } } GeometryCombiner.extractFactory = function extractFactory (geoms) { if (geoms.isEmpty()) { return null } return geoms.iterator().next().getFactory() } GeometryCombiner.createList = function createList () { if (arguments.length === 2) { var obj0 = arguments[0] var obj1 = arguments[1] var list = new ArrayList() list.add(obj0) list.add(obj1) return list } else if (arguments.length === 3) { var obj0$1 = arguments[0] var obj1$1 = arguments[1] var obj2 = arguments[2] var list$1 = new ArrayList() list$1.add(obj0$1) list$1.add(obj1$1) list$1.add(obj2) return list$1 } } var CascadedPolygonUnion = function CascadedPolygonUnion () { this._inputPolys = null this._geomFactory = null var polys = arguments[0] this._inputPolys = polys if (this._inputPolys === null) { this._inputPolys = new ArrayList() } } var staticAccessors$47 = { STRTREE_NODE_CAPACITY: { configurable: true } } CascadedPolygonUnion.prototype.reduceToGeometries = function reduceToGeometries (geomTree) { var this$1$1 = this var geoms = new ArrayList() for (var i = geomTree.iterator(); i.hasNext();) { var o = i.next() var geom = null if (hasInterface(o, List)) { geom = this$1$1.unionTree(o) } else if (o instanceof Geometry$2) { geom = o } geoms.add(geom) } return geoms } CascadedPolygonUnion.prototype.extractByEnvelope = function extractByEnvelope (env, geom, disjointGeoms) { var intersectingGeoms = new ArrayList() for (var i = 0; i < geom.getNumGeometries(); i++) { var elem = geom.getGeometryN(i) if (elem.getEnvelopeInternal().intersects(env)) { intersectingGeoms.add(elem) } else { disjointGeoms.add(elem) } } return this._geomFactory.buildGeometry(intersectingGeoms) } CascadedPolygonUnion.prototype.unionOptimized = function unionOptimized (g0, g1) { var g0Env = g0.getEnvelopeInternal() var g1Env = g1.getEnvelopeInternal() if (!g0Env.intersects(g1Env)) { var combo = GeometryCombiner.combine(g0, g1) return combo } if (g0.getNumGeometries() <= 1 && g1.getNumGeometries() <= 1) { return this.unionActual(g0, g1) } var commonEnv = g0Env.intersection(g1Env) return this.unionUsingEnvelopeIntersection(g0, g1, commonEnv) } CascadedPolygonUnion.prototype.union = function union () { if (this._inputPolys === null) { throw new Error('union() method cannot be called twice') } if (this._inputPolys.isEmpty()) { return null } this._geomFactory = this._inputPolys.iterator().next().getFactory() var index = new STRtree(CascadedPolygonUnion.STRTREE_NODE_CAPACITY) for (var i = this._inputPolys.iterator(); i.hasNext();) { var item = i.next() index.insert(item.getEnvelopeInternal(), item) } this._inputPolys = null var itemTree = index.itemsTree() var unionAll = this.unionTree(itemTree) return unionAll } CascadedPolygonUnion.prototype.binaryUnion = function binaryUnion () { if (arguments.length === 1) { var geoms = arguments[0] return this.binaryUnion(geoms, 0, geoms.size()) } else if (arguments.length === 3) { var geoms$1 = arguments[0] var start = arguments[1] var end = arguments[2] if (end - start <= 1) { var g0 = CascadedPolygonUnion.getGeometry(geoms$1, start) return this.unionSafe(g0, null) } else if (end - start === 2) { return this.unionSafe(CascadedPolygonUnion.getGeometry(geoms$1, start), CascadedPolygonUnion.getGeometry(geoms$1, start + 1)) } else { var mid = Math.trunc((end + start) / 2) var g0$1 = this.binaryUnion(geoms$1, start, mid) var g1 = this.binaryUnion(geoms$1, mid, end) return this.unionSafe(g0$1, g1) } } } CascadedPolygonUnion.prototype.repeatedUnion = function repeatedUnion (geoms) { var union = null for (var i = geoms.iterator(); i.hasNext();) { var g = i.next() if (union === null) { union = g.copy() } else { union = union.union(g) } } return union } CascadedPolygonUnion.prototype.unionSafe = function unionSafe (g0, g1) { if (g0 === null && g1 === null) { return null } if (g0 === null) { return g1.copy() } if (g1 === null) { return g0.copy() } return this.unionOptimized(g0, g1) } CascadedPolygonUnion.prototype.unionActual = function unionActual (g0, g1) { return CascadedPolygonUnion.restrictToPolygons(g0.union(g1)) } CascadedPolygonUnion.prototype.unionTree = function unionTree (geomTree) { var geoms = this.reduceToGeometries(geomTree) var union = this.binaryUnion(geoms) return union } CascadedPolygonUnion.prototype.unionUsingEnvelopeIntersection = function unionUsingEnvelopeIntersection (g0, g1, common) { var disjointPolys = new ArrayList() var g0Int = this.extractByEnvelope(common, g0, disjointPolys) var g1Int = this.extractByEnvelope(common, g1, disjointPolys) var union = this.unionActual(g0Int, g1Int) disjointPolys.add(union) var overallUnion = GeometryCombiner.combine(disjointPolys) return overallUnion } CascadedPolygonUnion.prototype.bufferUnion = function bufferUnion () { if (arguments.length === 1) { var geoms = arguments[0] var factory = geoms.get(0).getFactory() var gColl = factory.buildGeometry(geoms) var unionAll = gColl.buffer(0.0) return unionAll } else if (arguments.length === 2) { var g0 = arguments[0] var g1 = arguments[1] var factory$1 = g0.getFactory() var gColl$1 = factory$1.createGeometryCollection([g0, g1]) var unionAll$1 = gColl$1.buffer(0.0) return unionAll$1 } } CascadedPolygonUnion.prototype.interfaces_ = function interfaces_ () { return [] } CascadedPolygonUnion.prototype.getClass = function getClass () { return CascadedPolygonUnion } CascadedPolygonUnion.restrictToPolygons = function restrictToPolygons (g) { if (hasInterface(g, Polygonal)) { return g } var polygons = PolygonExtracter.getPolygons(g) if (polygons.size() === 1) { return polygons.get(0) } return g.getFactory().createMultiPolygon(GeometryFactory.toPolygonArray(polygons)) } CascadedPolygonUnion.getGeometry = function getGeometry (list, index) { if (index >= list.size()) { return null } return list.get(index) } CascadedPolygonUnion.union = function union (polys) { var op = new CascadedPolygonUnion(polys) return op.union() } staticAccessors$47.STRTREE_NODE_CAPACITY.get = function () { return 4 } Object.defineProperties(CascadedPolygonUnion, staticAccessors$47) var UnionOp = function UnionOp () { } UnionOp.prototype.interfaces_ = function interfaces_ () { return [] } UnionOp.prototype.getClass = function getClass () { return UnionOp } UnionOp.union = function union (g, other) { if (g.isEmpty() || other.isEmpty()) { if (g.isEmpty() && other.isEmpty()) { return OverlayOp.createEmptyResult(OverlayOp.UNION, g, other, g.getFactory()) } if (g.isEmpty()) { return other.copy() } if (other.isEmpty()) { return g.copy() } } g.checkNotGeometryCollection(g) g.checkNotGeometryCollection(other) return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.UNION) } // Adds floating point numbers with twice the normal precision. // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3) // 305–363 (1997). // Code adapted from GeographicLib by Charles F. F. Karney, // http://geographiclib.sourceforge.net/ function adder () { return new Adder } function Adder () { this.reset() } Adder.prototype = { constructor: Adder, reset: function () { this.s = // rounded value this.t = 0 // exact error }, add: function (y) { add(temp, y, this.t) add(this, temp.s, this.s) if (this.s) this.t += temp.t else this.s = temp.t }, valueOf: function () { return this.s } } var temp = new Adder function add (adder, a, b) { var x = adder.s = a + b, bv = x - a, av = x - bv adder.t = (a - av) + (b - bv) } var epsilon = 1e-6 var pi = Math.PI var halfPi = pi / 2 var quarterPi = pi / 4 var tau = pi * 2 var degrees = 180 / pi var radians = pi / 180 var abs = Math.abs var atan$1 = Math.atan var atan2 = Math.atan2 var cos$1 = Math.cos var sin$1 = Math.sin var sqrt = Math.sqrt function acos (x) { return x > 1 ? 0 : x < -1 ? pi : Math.acos(x) } function asin (x) { return x > 1 ? halfPi : x < -1 ? -halfPi : Math.asin(x) } function noop$1 () { } function streamGeometry (geometry, stream) { if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) { streamGeometryType[geometry.type](geometry, stream) } } var streamObjectType = { Feature: function (object, stream) { streamGeometry(object.geometry, stream) }, FeatureCollection: function (object, stream) { var features = object.features, i = -1, n = features.length while (++i < n) streamGeometry(features[i].geometry, stream) } } var streamGeometryType = { Sphere: function (object, stream) { stream.sphere() }, Point: function (object, stream) { object = object.coordinates stream.point(object[0], object[1], object[2]) }, MultiPoint: function (object, stream) { var coordinates = object.coordinates, i = -1, n = coordinates.length while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]) }, LineString: function (object, stream) { streamLine(object.coordinates, stream, 0) }, MultiLineString: function (object, stream) { var coordinates = object.coordinates, i = -1, n = coordinates.length while (++i < n) streamLine(coordinates[i], stream, 0) }, Polygon: function (object, stream) { streamPolygon(object.coordinates, stream) }, MultiPolygon: function (object, stream) { var coordinates = object.coordinates, i = -1, n = coordinates.length while (++i < n) streamPolygon(coordinates[i], stream) }, GeometryCollection: function (object, stream) { var geometries = object.geometries, i = -1, n = geometries.length while (++i < n) streamGeometry(geometries[i], stream) } } function streamLine (coordinates, stream, closed) { var i = -1, n = coordinates.length - closed, coordinate stream.lineStart() while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]) stream.lineEnd() } function streamPolygon (coordinates, stream) { var i = -1, n = coordinates.length stream.polygonStart() while (++i < n) streamLine(coordinates[i], stream, 1) stream.polygonEnd() } function geoStream (object, stream) { if (object && streamObjectType.hasOwnProperty(object.type)) { streamObjectType[object.type](object, stream) } else { streamGeometry(object, stream) } } adder() adder() function spherical (cartesian) { return [atan2(cartesian[1], cartesian[0]), asin(cartesian[2])] } function cartesian (spherical) { var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi) return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)] } function cartesianDot (a, b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] } function cartesianCross (a, b) { return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]] } // TODO return a function cartesianAddInPlace (a, b) { a[0] += b[0], a[1] += b[1], a[2] += b[2] } function cartesianScale (vector, k) { return [vector[0] * k, vector[1] * k, vector[2] * k] } // TODO return d function cartesianNormalizeInPlace (d) { var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) d[0] /= l, d[1] /= l, d[2] /= l } adder() function compose (a, b) { function compose (x, y) { return x = a(x, y), b(x[0], x[1]) } if (a.invert && b.invert) compose.invert = function (x, y) { return x = b.invert(x, y), x && a.invert(x[0], x[1]) } return compose } function rotationIdentity (lambda, phi) { return [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi] } rotationIdentity.invert = rotationIdentity function rotateRadians (deltaLambda, deltaPhi, deltaGamma) { return (deltaLambda %= tau) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) : rotationLambda(deltaLambda)) : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) : rotationIdentity) } function forwardRotationLambda (deltaLambda) { return function (lambda, phi) { return lambda += deltaLambda, [lambda > pi ? lambda - tau : lambda < -pi ? lambda + tau : lambda, phi] } } function rotationLambda (deltaLambda) { var rotation = forwardRotationLambda(deltaLambda) rotation.invert = forwardRotationLambda(-deltaLambda) return rotation } function rotationPhiGamma (deltaPhi, deltaGamma) { var cosDeltaPhi = cos$1(deltaPhi), sinDeltaPhi = sin$1(deltaPhi), cosDeltaGamma = cos$1(deltaGamma), sinDeltaGamma = sin$1(deltaGamma) function rotation (lambda, phi) { var cosPhi = cos$1(phi), x = cos$1(lambda) * cosPhi, y = sin$1(lambda) * cosPhi, z = sin$1(phi), k = z * cosDeltaPhi + x * sinDeltaPhi return [ atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi), asin(k * cosDeltaGamma + y * sinDeltaGamma) ] } rotation.invert = function (lambda, phi) { var cosPhi = cos$1(phi), x = cos$1(lambda) * cosPhi, y = sin$1(lambda) * cosPhi, z = sin$1(phi), k = z * cosDeltaGamma - y * sinDeltaGamma return [ atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi), asin(k * cosDeltaPhi - x * sinDeltaPhi) ] } return rotation } // Generates a circle centered at [0°, 0°], with a given radius and precision. function circleStream (stream, radius, delta, direction, t0, t1) { if (!delta) return var cosRadius = cos$1(radius), sinRadius = sin$1(radius), step = direction * delta if (t0 == null) { t0 = radius + direction * tau t1 = radius - step / 2 } else { t0 = circleRadius(cosRadius, t0) t1 = circleRadius(cosRadius, t1) if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau } for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) { point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]) stream.point(point[0], point[1]) } } // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0]. function circleRadius (cosRadius, point) { point = cartesian(point), point[0] -= cosRadius cartesianNormalizeInPlace(point) var radius = acos(-point[1]) return ((-point[2] < 0 ? -radius : radius) + tau - epsilon) % tau } function clipBuffer () { var lines = [], line return { point: function (x, y) { line.push([x, y]) }, lineStart: function () { lines.push(line = []) }, lineEnd: noop$1, rejoin: function () { if (lines.length > 1) lines.push(lines.pop().concat(lines.shift())) }, result: function () { var result = lines lines = [] line = null return result } } } function clipLine (a, b, x0, y0, x1, y1) { var ax = a[0], ay = a[1], bx = b[0], by = b[1], t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r r = x0 - ax if (!dx && r > 0) return r /= dx if (dx < 0) { if (r < t0) return if (r < t1) t1 = r } else if (dx > 0) { if (r > t1) return if (r > t0) t0 = r } r = x1 - ax if (!dx && r < 0) return r /= dx if (dx < 0) { if (r > t1) return if (r > t0) t0 = r } else if (dx > 0) { if (r < t0) return if (r < t1) t1 = r } r = y0 - ay if (!dy && r > 0) return r /= dy if (dy < 0) { if (r < t0) return if (r < t1) t1 = r } else if (dy > 0) { if (r > t1) return if (r > t0) t0 = r } r = y1 - ay if (!dy && r < 0) return r /= dy if (dy < 0) { if (r > t1) return if (r > t0) t0 = r } else if (dy > 0) { if (r < t0) return if (r < t1) t1 = r } if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy return true } function pointEqual (a, b) { return abs(a[0] - b[0]) < epsilon && abs(a[1] - b[1]) < epsilon } function Intersection (point, points, other, entry) { this.x = point this.z = points this.o = other // another intersection this.e = entry // is an entry? this.v = false // visited this.n = this.p = null // next & previous } // A generalized polygon clipping algorithm: given a polygon that has been cut // into its visible line segments, and rejoins the segments by interpolating // along the clip edge. function clipPolygon (segments, compareIntersection, startInside, interpolate, stream) { var subject = [], clip = [], i, n segments.forEach(function (segment) { if ((n = segment.length - 1) <= 0) return var n, p0 = segment[0], p1 = segment[n], x // If the first and last points of a segment are coincident, then treat as a // closed ring. TODO if all rings are closed, then the winding order of the // exterior ring should be checked. if (pointEqual(p0, p1)) { stream.lineStart() for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]) stream.lineEnd() return } subject.push(x = new Intersection(p0, segment, null, true)) clip.push(x.o = new Intersection(p0, null, x, false)) subject.push(x = new Intersection(p1, segment, null, false)) clip.push(x.o = new Intersection(p1, null, x, true)) }) if (!subject.length) return clip.sort(compareIntersection) link(subject) link(clip) for (i = 0, n = clip.length; i < n; ++i) { clip[i].e = startInside = !startInside } var start = subject[0], points, point while (1) { // Find first unvisited intersection. var current = start, isSubject = true while (current.v) if ((current = current.n) === start) return points = current.z stream.lineStart() do { current.v = current.o.v = true if (current.e) { if (isSubject) { for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]) } else { interpolate(current.x, current.n.x, 1, stream) } current = current.n } else { if (isSubject) { points = current.p.z for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]) } else { interpolate(current.x, current.p.x, -1, stream) } current = current.p } current = current.o points = current.z isSubject = !isSubject } while (!current.v) stream.lineEnd() } } function link (array) { if (!(n = array.length)) return var n, i = 0, a = array[0], b while (++i < n) { a.n = b = array[i] b.p = a a = b } a.n = b = array[0] b.p = a } function ascending (a, b) { return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN } function bisector (compare) { if (compare.length === 1) compare = ascendingComparator(compare) return { left: function (a, x, lo, hi) { if (lo == null) lo = 0 if (hi == null) hi = a.length while (lo < hi) { var mid = lo + hi >>> 1 if (compare(a[mid], x) < 0) lo = mid + 1 else hi = mid } return lo }, right: function (a, x, lo, hi) { if (lo == null) lo = 0 if (hi == null) hi = a.length while (lo < hi) { var mid = lo + hi >>> 1 if (compare(a[mid], x) > 0) hi = mid else lo = mid + 1 } return lo } } } function ascendingComparator (f) { return function (d, x) { return ascending(f(d), x) } } bisector(ascending) function merge (arrays) { var n = arrays.length, m, i = -1, j = 0, merged, array while (++i < n) j += arrays[i].length merged = new Array(j) while (--n >= 0) { array = arrays[n] m = array.length while (--m >= 0) { merged[--j] = array[m] } } return merged } var clipMax = 1e9, clipMin = -clipMax // TODO Use d3-polygon’s polygonContains here for the ring check? // TODO Eliminate duplicate buffering in clipBuffer and polygon.push? function clipExtent (x0, y0, x1, y1) { function visible (x, y) { return x0 <= x && x <= x1 && y0 <= y && y <= y1 } function interpolate (from, to, direction, stream) { var a = 0, a1 = 0 if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoint(from, to) < 0 ^ direction > 0) { do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0) while ((a = (a + direction + 4) % 4) !== a1) } else { stream.point(to[0], to[1]) } } function corner (p, direction) { return abs(p[0] - x0) < epsilon ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < epsilon ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < epsilon ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2 // abs(p[1] - y1) < epsilon } function compareIntersection (a, b) { return comparePoint(a.x, b.x) } function comparePoint (a, b) { var ca = corner(a, 1), cb = corner(b, 1) return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0] } return function (stream) { var activeStream = stream, bufferStream = clipBuffer(), segments, polygon, ring, x__, y__, v__, // first point x_, y_, v_, // previous point first, clean var clipStream = { point: point, lineStart: lineStart, lineEnd: lineEnd, polygonStart: polygonStart, polygonEnd: polygonEnd } function point (x, y) { if (visible(x, y)) activeStream.point(x, y) } function polygonInside () { var winding = 0 for (var i = 0, n = polygon.length; i < n; ++i) { for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) { a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1] if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding } else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding } } } return winding } // Buffer geometry within a polygon and then clip it en masse. function polygonStart () { activeStream = bufferStream, segments = [], polygon = [], clean = true } function polygonEnd () { var startInside = polygonInside(), cleanInside = clean && startInside, visible = (segments = merge(segments)).length if (cleanInside || visible) { stream.polygonStart() if (cleanInside) { stream.lineStart() interpolate(null, null, 1, stream) stream.lineEnd() } if (visible) { clipPolygon(segments, compareIntersection, startInside, interpolate, stream) } stream.polygonEnd() } activeStream = stream, segments = polygon = ring = null } function lineStart () { clipStream.point = linePoint if (polygon) polygon.push(ring = []) first = true v_ = false x_ = y_ = NaN } // TODO rather than special-case polygons, simply handle them separately. // Ideally, coincident intersection points should be jittered to avoid // clipping issues. function lineEnd () { if (segments) { linePoint(x__, y__) if (v__ && v_) bufferStream.rejoin() segments.push(bufferStream.result()) } clipStream.point = point if (v_) activeStream.lineEnd() } function linePoint (x, y) { var v = visible(x, y) if (polygon) ring.push([x, y]) if (first) { x__ = x, y__ = y, v__ = v first = false if (v) { activeStream.lineStart() activeStream.point(x, y) } } else { if (v && v_) activeStream.point(x, y) else { var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))] if (clipLine(a, b, x0, y0, x1, y1)) { if (!v_) { activeStream.lineStart() activeStream.point(a[0], a[1]) } activeStream.point(b[0], b[1]) if (!v) activeStream.lineEnd() clean = false } else if (v) { activeStream.lineStart() activeStream.point(x, y) clean = false } } } x_ = x, y_ = y, v_ = v } return clipStream } } var sum = adder() function polygonContains (polygon, point) { var lambda = point[0], phi = point[1], normal = [sin$1(lambda), -cos$1(lambda), 0], angle = 0, winding = 0 sum.reset() for (var i = 0, n = polygon.length; i < n; ++i) { if (!(m = (ring = polygon[i]).length)) continue var ring, m, point0 = ring[m - 1], lambda0 = point0[0], phi0 = point0[1] / 2 + quarterPi, sinPhi0 = sin$1(phi0), cosPhi0 = cos$1(phi0) for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) { var point1 = ring[j], lambda1 = point1[0], phi1 = point1[1] / 2 + quarterPi, sinPhi1 = sin$1(phi1), cosPhi1 = cos$1(phi1), delta = lambda1 - lambda0, sign = delta >= 0 ? 1 : -1, absDelta = sign * delta, antimeridian = absDelta > pi, k = sinPhi0 * sinPhi1 sum.add(atan2(k * sign * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta))) angle += antimeridian ? delta + sign * tau : delta // Are the longitudes either side of the point’s meridian (lambda), // and are the latitudes smaller than the parallel (phi)? if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) { var arc = cartesianCross(cartesian(point0), cartesian(point1)) cartesianNormalizeInPlace(arc) var intersection = cartesianCross(normal, arc) cartesianNormalizeInPlace(intersection) var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]) if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) { winding += antimeridian ^ delta >= 0 ? 1 : -1 } } } } // First, determine whether the South pole is inside or outside: // // It is inside if: // * the polygon winds around it in a clockwise direction. // * the polygon does not (cumulatively) wind around it, but has a negative // (counter-clockwise) area. // // Second, count the (signed) number of times a segment crosses a lambda // from the point to the South pole. If it is zero, then the point is the // same side as the South pole. return (angle < -epsilon || angle < epsilon && sum < -epsilon) ^ (winding & 1) } adder() function identity (x) { return x } adder() adder() var x0 = Infinity, y0 = x0, x1 = -x0, y1 = x1 var boundsStream = { point: boundsPoint, lineStart: noop$1, lineEnd: noop$1, polygonStart: noop$1, polygonEnd: noop$1, result: function () { var bounds = [[x0, y0], [x1, y1]] x1 = y1 = -(y0 = x0 = Infinity) return bounds } } function boundsPoint (x, y) { if (x < x0) x0 = x if (x > x1) x1 = x if (y < y0) y0 = y if (y > y1) y1 = y } adder() function clip (pointVisible, clipLine, interpolate, start) { return function (rotate, sink) { var line = clipLine(sink), rotatedStart = rotate.invert(start[0], start[1]), ringBuffer = clipBuffer(), ringSink = clipLine(ringBuffer), polygonStarted = false, polygon, segments, ring var clip = { point: point, lineStart: lineStart, lineEnd: lineEnd, polygonStart: function () { clip.point = pointRing clip.lineStart = ringStart clip.lineEnd = ringEnd segments = [] polygon = [] }, polygonEnd: function () { clip.point = point clip.lineStart = lineStart clip.lineEnd = lineEnd segments = merge(segments) var startInside = polygonContains(polygon, rotatedStart) if (segments.length) { if (!polygonStarted) sink.polygonStart(), polygonStarted = true clipPolygon(segments, compareIntersection, startInside, interpolate, sink) } else if (startInside) { if (!polygonStarted) sink.polygonStart(), polygonStarted = true sink.lineStart() interpolate(null, null, 1, sink) sink.lineEnd() } if (polygonStarted) sink.polygonEnd(), polygonStarted = false segments = polygon = null }, sphere: function () { sink.polygonStart() sink.lineStart() interpolate(null, null, 1, sink) sink.lineEnd() sink.polygonEnd() } } function point (lambda, phi) { var point = rotate(lambda, phi) if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi) } function pointLine (lambda, phi) { var point = rotate(lambda, phi) line.point(point[0], point[1]) } function lineStart () { clip.point = pointLine line.lineStart() } function lineEnd () { clip.point = point line.lineEnd() } function pointRing (lambda, phi) { ring.push([lambda, phi]) var point = rotate(lambda, phi) ringSink.point(point[0], point[1]) } function ringStart () { ringSink.lineStart() ring = [] } function ringEnd () { pointRing(ring[0][0], ring[0][1]) ringSink.lineEnd() var clean = ringSink.clean(), ringSegments = ringBuffer.result(), i, n = ringSegments.length, m, segment, point ring.pop() polygon.push(ring) ring = null if (!n) return // No intersections. if (clean & 1) { segment = ringSegments[0] if ((m = segment.length - 1) > 0) { if (!polygonStarted) sink.polygonStart(), polygonStarted = true sink.lineStart() for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]) sink.lineEnd() } return } // Rejoin connected segments. // TODO reuse ringBuffer.rejoin()? if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift())) segments.push(ringSegments.filter(validSegment)) } return clip } } function validSegment (segment) { return segment.length > 1 } // Intersections are sorted along the clip edge. For both antimeridian cutting // and circle clipping, the same comparison is used. function compareIntersection (a, b) { return ((a = a.x)[0] < 0 ? a[1] - halfPi - epsilon : halfPi - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon : halfPi - b[1]) } var clipAntimeridian = clip( function () { return true }, clipAntimeridianLine, clipAntimeridianInterpolate, [-pi, -halfPi] ) // Takes a line and cuts into visible segments. Return values: 0 - there were // intersections or the line was empty; 1 - no intersections; 2 - there were // intersections, and the first and last segments should be rejoined. function clipAntimeridianLine (stream) { var lambda0 = NaN, phi0 = NaN, sign0 = NaN, clean // no intersections return { lineStart: function () { stream.lineStart() clean = 1 }, point: function (lambda1, phi1) { var sign1 = lambda1 > 0 ? pi : -pi, delta = abs(lambda1 - lambda0) if (abs(delta - pi) < epsilon) { // line crosses a pole stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi) stream.point(sign0, phi0) stream.lineEnd() stream.lineStart() stream.point(sign1, phi0) stream.point(lambda1, phi0) clean = 0 } else if (sign0 !== sign1 && delta >= pi) { // line crosses antimeridian if (abs(lambda0 - sign0) < epsilon) lambda0 -= sign0 * epsilon // handle degeneracies if (abs(lambda1 - sign1) < epsilon) lambda1 -= sign1 * epsilon phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) stream.point(sign0, phi0) stream.lineEnd() stream.lineStart() stream.point(sign1, phi0) clean = 0 } stream.point(lambda0 = lambda1, phi0 = phi1) sign0 = sign1 }, lineEnd: function () { stream.lineEnd() lambda0 = phi0 = NaN }, clean: function () { return 2 - clean // if intersections, rejoin first and last segments } } } function clipAntimeridianIntersect (lambda0, phi0, lambda1, phi1) { var cosPhi0, cosPhi1, sinLambda0Lambda1 = sin$1(lambda0 - lambda1) return abs(sinLambda0Lambda1) > epsilon ? atan$1((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1) - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0)) / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) : (phi0 + phi1) / 2 } function clipAntimeridianInterpolate (from, to, direction, stream) { var phi if (from == null) { phi = direction * halfPi stream.point(-pi, phi) stream.point(0, phi) stream.point(pi, phi) stream.point(pi, 0) stream.point(pi, -phi) stream.point(0, -phi) stream.point(-pi, -phi) stream.point(-pi, 0) stream.point(-pi, phi) } else if (abs(from[0] - to[0]) > epsilon) { var lambda = from[0] < to[0] ? pi : -pi phi = direction * lambda / 2 stream.point(-lambda, phi) stream.point(0, phi) stream.point(lambda, phi) } else { stream.point(to[0], to[1]) } } function clipCircle (radius, delta) { var cr = cos$1(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > epsilon // TODO optimise for this common case function interpolate (from, to, direction, stream) { circleStream(stream, radius, delta, direction, from, to) } function visible (lambda, phi) { return cos$1(lambda) * cos$1(phi) > cr } // Takes a line and cuts into visible segments. Return values used for polygon // clipping: 0 - there were intersections or the line was empty; 1 - no // intersections 2 - there were intersections, and the first and last segments // should be rejoined. function clipLine (stream) { var point0, // previous point c0, // code for previous point v0, // visibility of previous point v00, // visibility of first point clean // no intersections return { lineStart: function () { v00 = v0 = false clean = 1 }, point: function (lambda, phi) { var point1 = [lambda, phi], point2, v = visible(lambda, phi), c = smallRadius ? v ? 0 : code(lambda, phi) : v ? code(lambda + (lambda < 0 ? pi : -pi), phi) : 0 if (!point0 && (v00 = v0 = v)) stream.lineStart() // Handle degeneracies. // TODO ignore if not clipping polygons. if (v !== v0) { point2 = intersect(point0, point1) if (!point2 || pointEqual(point0, point2) || pointEqual(point1, point2)) { point1[0] += epsilon point1[1] += epsilon v = visible(point1[0], point1[1]) } } if (v !== v0) { clean = 0 if (v) { // outside going in stream.lineStart() point2 = intersect(point1, point0) stream.point(point2[0], point2[1]) } else { // inside going out point2 = intersect(point0, point1) stream.point(point2[0], point2[1]) stream.lineEnd() } point0 = point2 } else if (notHemisphere && point0 && smallRadius ^ v) { var t // If the codes for two points are different, or are both zero, // and there this segment intersects with the small circle. if (!(c & c0) && (t = intersect(point1, point0, true))) { clean = 0 if (smallRadius) { stream.lineStart() stream.point(t[0][0], t[0][1]) stream.point(t[1][0], t[1][1]) stream.lineEnd() } else { stream.point(t[1][0], t[1][1]) stream.lineEnd() stream.lineStart() stream.point(t[0][0], t[0][1]) } } } if (v && (!point0 || !pointEqual(point0, point1))) { stream.point(point1[0], point1[1]) } point0 = point1, v0 = v, c0 = c }, lineEnd: function () { if (v0) stream.lineEnd() point0 = null }, // Rejoin first and last segments if there were intersections and the first // and last points were visible. clean: function () { return clean | ((v00 && v0) << 1) } } } // Intersects the great circle between a and b with the clip circle. function intersect (a, b, two) { var pa = cartesian(a), pb = cartesian(b) // We have two planes, n1.p = d1 and n2.p = d2. // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2). var n1 = [1, 0, 0], // normal n2 = cartesianCross(pa, pb), n2n2 = cartesianDot(n2, n2), n1n2 = n2[0], // cartesianDot(n1, n2), determinant = n2n2 - n1n2 * n1n2 // Two polar points. if (!determinant) return !two && a var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = cartesianCross(n1, n2), A = cartesianScale(n1, c1), B = cartesianScale(n2, c2) cartesianAddInPlace(A, B) // Solve |p(t)|^2 = 1. var u = n1xn2, w = cartesianDot(A, u), uu = cartesianDot(u, u), t2 = w * w - uu * (cartesianDot(A, A) - 1) if (t2 < 0) return var t = sqrt(t2), q = cartesianScale(u, (-w - t) / uu) cartesianAddInPlace(q, A) q = spherical(q) if (!two) return q // Two intersection points. var lambda0 = a[0], lambda1 = b[0], phi0 = a[1], phi1 = b[1], z if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z var delta = lambda1 - lambda0, polar = abs(delta - pi) < epsilon, meridian = polar || delta < epsilon if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z // Check that the first point is between a and b. if (meridian ? polar ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon ? phi0 : phi1) : phi0 <= q[1] && q[1] <= phi1 : delta > pi ^ (lambda0 <= q[0] && q[0] <= lambda1)) { var q1 = cartesianScale(u, (-w + t) / uu) cartesianAddInPlace(q1, A) return [q, spherical(q1)] } } // Generates a 4-bit vector representing the location of a point relative to // the small circle's bounding box. function code (lambda, phi) { var r = smallRadius ? radius : pi - radius, code = 0 if (lambda < -r) code |= 1 // left else if (lambda > r) code |= 2 // right if (phi < -r) code |= 4 // below else if (phi > r) code |= 8 // above return code } return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi, radius - pi]) } function transformer (methods) { return function (stream) { var s = new TransformStream for (var key in methods) s[key] = methods[key] s.stream = stream return s } } function TransformStream () { } TransformStream.prototype = { constructor: TransformStream, point: function (x, y) { this.stream.point(x, y) }, sphere: function () { this.stream.sphere() }, lineStart: function () { this.stream.lineStart() }, lineEnd: function () { this.stream.lineEnd() }, polygonStart: function () { this.stream.polygonStart() }, polygonEnd: function () { this.stream.polygonEnd() } } function fitExtent (projection, extent, object) { var w = extent[1][0] - extent[0][0], h = extent[1][1] - extent[0][1], clip = projection.clipExtent && projection.clipExtent() projection .scale(150) .translate([0, 0]) if (clip != null) projection.clipExtent(null) geoStream(object, projection.stream(boundsStream)) var b = boundsStream.result(), k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2, y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2 if (clip != null) projection.clipExtent(clip) return projection .scale(k * 150) .translate([x, y]) } function fitSize (projection, size, object) { return fitExtent(projection, [[0, 0], size], object) } var maxDepth = 16, // maximum depth of subdivision cosMinDistance = cos$1(30 * radians) // cos(minimum angular distance) function resample (project, delta2) { return +delta2 ? resample$1(project, delta2) : resampleNone(project) } function resampleNone (project) { return transformer({ point: function (x, y) { x = project(x, y) this.stream.point(x[0], x[1]) } }) } function resample$1 (project, delta2) { function resampleLineTo (x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) { var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy if (d2 > 4 * delta2 && depth--) { var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = sqrt(a * a + b * b + c * c), phi2 = asin(c /= m), lambda2 = abs(abs(c) - 1) < epsilon || abs(lambda0 - lambda1) < epsilon ? (lambda0 + lambda1) / 2 : atan2(b, a), p = project(lambda2, phi2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2 if (dz * dz / d2 > delta2 // perpendicular projected distance || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream) stream.point(x2, y2) resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream) } } } return function (stream) { var lambda00, x00, y00, a00, b00, c00, // first point lambda0, x0, y0, a0, b0, c0 // previous point var resampleStream = { point: point, lineStart: lineStart, lineEnd: lineEnd, polygonStart: function () { stream.polygonStart(); resampleStream.lineStart = ringStart }, polygonEnd: function () { stream.polygonEnd(); resampleStream.lineStart = lineStart } } function point (x, y) { x = project(x, y) stream.point(x[0], x[1]) } function lineStart () { x0 = NaN resampleStream.point = linePoint stream.lineStart() } function linePoint (lambda, phi) { var c = cartesian([lambda, phi]), p = project(lambda, phi) resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream) stream.point(x0, y0) } function lineEnd () { resampleStream.point = point stream.lineEnd() } function ringStart () { lineStart() resampleStream.point = ringPoint resampleStream.lineEnd = ringEnd } function ringPoint (lambda, phi) { linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0 resampleStream.point = linePoint } function ringEnd () { resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream) resampleStream.lineEnd = lineEnd lineEnd() } return resampleStream } } var transformRadians = transformer({ point: function (x, y) { this.stream.point(x * radians, y * radians) } }) function projection (project) { return projectionMutator(function () { return project })() } function projectionMutator (projectAt) { var project, k = 150, // scale x = 480, y = 250, // translate dx, dy, lambda = 0, phi = 0, // center deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate theta = null, preclip = clipAntimeridian, // clip angle x0 = null, y0, x1, y1, postclip = identity, // clip extent delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision cache, cacheStream function projection (point) { point = projectRotate(point[0] * radians, point[1] * radians) return [point[0] * k + dx, dy - point[1] * k] } function invert (point) { point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k) return point && [point[0] * degrees, point[1] * degrees] } function projectTransform (x, y) { return x = project(x, y), [x[0] * k + dx, dy - x[1] * k] } projection.stream = function (stream) { return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream)))) } projection.clipAngle = function (_) { return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees } projection.clipExtent = function (_) { return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]] } projection.scale = function (_) { return arguments.length ? (k = +_, recenter()) : k } projection.translate = function (_) { return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y] } projection.center = function (_) { return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees, phi * degrees] } projection.rotate = function (_) { return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees, deltaPhi * degrees, deltaGamma * degrees] } projection.precision = function (_) { return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2) } projection.fitExtent = function (extent, object) { return fitExtent(projection, extent, object) } projection.fitSize = function (size, object) { return fitSize(projection, size, object) } function recenter () { projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project) var center = project(lambda, phi) dx = x - center[0] * k dy = y + center[1] * k return reset() } function reset () { cache = cacheStream = null return projection } return function () { project = projectAt.apply(this, arguments) projection.invert = project.invert && invert return recenter() } } function azimuthalRaw (scale) { return function (x, y) { var cx = cos$1(x), cy = cos$1(y), k = scale(cx * cy) return [ k * cy * sin$1(x), k * sin$1(y) ] } } function azimuthalInvert (angle) { return function (x, y) { var z = sqrt(x * x + y * y), c = angle(z), sc = sin$1(c), cc = cos$1(c) return [ atan2(x * sc, z * cc), asin(z && y * sc / z) ] } } var azimuthalEqualAreaRaw = azimuthalRaw(function (cxcy) { return sqrt(2 / (1 + cxcy)) }) azimuthalEqualAreaRaw.invert = azimuthalInvert(function (z) { return 2 * asin(z / 2) }) var azimuthalEquidistantRaw = azimuthalRaw(function (c) { return (c = acos(c)) && c / sin$1(c) }) azimuthalEquidistantRaw.invert = azimuthalInvert(function (z) { return z }) function geoAzimuthalEquidistant () { return projection(azimuthalEquidistantRaw) .scale(79.4188) .clipAngle(180 - 1e-3) } function equirectangularRaw (lambda, phi) { return [lambda, phi] } equirectangularRaw.invert = equirectangularRaw /** * Calculates a buffer for input features for a given radius. Units supported are miles, kilometers, and degrees. * * When using a negative radius, the resulting geometry may be invalid if * it's too small compared to the radius magnitude. If the input is a * FeatureCollection, only valid members will be returned in the output * FeatureCollection - i.e., the output collection may have fewer members than * the input, or even be empty. * * @name buffer * @param {FeatureCollection|Geometry|Feature} geojson input to be buffered * @param {number} radius distance to draw the buffer (negative values are allowed) * @param {Object} [options={}] Optional parameters * @param {string} [options.units="kilometers"] any of the options supported by turf units * @param {number} [options.steps=8] number of steps * @returns {FeatureCollection|Feature|undefined} buffered features * @example * var point = turf.point([-90.548630, 14.616599]); * var buffered = turf.buffer(point, 500, {units: 'miles'}); * * //addToMap * var addToMap = [point, buffered] */ function buffer (geojson, radius, options) { // Optional params options = options || {} // use user supplied options or default values var units = options.units || "kilometers" var steps = options.steps || 8 // validation if (!geojson) throw new Error("geojson is required") if (typeof options !== "object") throw new Error("options must be an object") if (typeof steps !== "number") throw new Error("steps must be an number") // Allow negative buffers ("erosion") or zero-sized buffers ("repair geometry") if (radius === undefined) throw new Error("radius is required") if (steps <= 0) throw new Error("steps must be greater than 0") var results = [] switch (geojson.type) { case "GeometryCollection": geomEach(geojson, function (geometry) { var buffered = bufferFeature(geometry, radius, units, steps) if (buffered) results.push(buffered) }) return featureCollection(results) case "FeatureCollection": featureEach(geojson, function (feature) { var multiBuffered = bufferFeature(feature, radius, units, steps) if (multiBuffered) { featureEach(multiBuffered, function (buffered) { if (buffered) results.push(buffered) }) } }) return featureCollection(results) } return bufferFeature(geojson, radius, units, steps) } /** * Buffer single Feature/Geometry * * @private * @param {Feature} geojson input to be buffered * @param {number} radius distance to draw the buffer * @param {string} [units='kilometers'] any of the options supported by turf units * @param {number} [steps=8] number of steps * @returns {Feature} buffered feature */ function bufferFeature (geojson, radius, units, steps) { var properties = geojson.properties || {} var geometry = geojson.type === "Feature" ? geojson.geometry : geojson // Geometry Types faster than jsts if (geometry.type === "GeometryCollection") { var results = [] geomEach(geojson, function (geometry) { var buffered = bufferFeature(geometry, radius, units, steps) if (buffered) results.push(buffered) }) return featureCollection(results) } // Project GeoJSON to Azimuthal Equidistant projection (convert to Meters) var projection = defineProjection(geometry) var projected = { type: geometry.type, coordinates: projectCoords(geometry.coordinates, projection), } // JSTS buffer operation var reader = new GeoJSONReader() var geom = reader.read(projected) var distance = radiansToLength(lengthToRadians(radius, units), "meters") var buffered = BufferOp.bufferOp(geom, distance, steps) var writer = new GeoJSONWriter() buffered = writer.write(buffered) // Detect if empty geometries if (coordsIsNaN(buffered.coordinates)) return undefined // Unproject coordinates (convert to Degrees) var result = { type: buffered.type, coordinates: unprojectCoords(buffered.coordinates, projection), } return feature(result, properties) } /** * Coordinates isNaN * * @private * @param {Array} coords GeoJSON Coordinates * @returns {boolean} if NaN exists */ function coordsIsNaN (coords) { if (Array.isArray(coords[0])) return coordsIsNaN(coords[0]) return isNaN(coords[0]) } /** * Project coordinates to projection * * @private * @param {Array} coords to project * @param {GeoProjection} proj D3 Geo Projection * @returns {Array} projected coordinates */ function projectCoords (coords, proj) { if (typeof coords[0] !== "object") return proj(coords) return coords.map(function (coord) { return projectCoords(coord, proj) }) } /** * Un-Project coordinates to projection * * @private * @param {Array} coords to un-project * @param {GeoProjection} proj D3 Geo Projection * @returns {Array} un-projected coordinates */ function unprojectCoords (coords, proj) { if (typeof coords[0] !== "object") return proj.invert(coords) return coords.map(function (coord) { return unprojectCoords(coord, proj) }) } /** * Define Azimuthal Equidistant projection * * @private * @param {Geometry|Feature} geojson Base projection on center of GeoJSON * @returns {GeoProjection} D3 Geo Azimuthal Equidistant Projection */ function defineProjection (geojson) { var coords = center(geojson).geometry.coordinates var rotation = [-coords[0], -coords[1]] return geoAzimuthalEquidistant().rotate(rotation).scale(earthRadius) } /** * Takes two {@link (Multi)Polygon(s)} and returns a combined polygon. If the input polygons are not contiguous, this function returns a {@link MultiPolygon} feature. * * @name union * @param {Feature} polygon1 input Polygon feature * @param {Feature} polygon2 Polygon feature to difference from polygon1 * @param {Object} [options={}] Optional Parameters * @param {Object} [options.properties={}] Translate Properties to output Feature * @returns {Feature<(Polygon|MultiPolygon)>} a combined {@link Polygon} or {@link MultiPolygon} feature, or null if the inputs are empty * @example * var poly1 = turf.polygon([[ * [-82.574787, 35.594087], * [-82.574787, 35.615581], * [-82.545261, 35.615581], * [-82.545261, 35.594087], * [-82.574787, 35.594087] * ]], {"fill": "#0f0"}); * var poly2 = turf.polygon([[ * [-82.560024, 35.585153], * [-82.560024, 35.602602], * [-82.52964, 35.602602], * [-82.52964, 35.585153], * [-82.560024, 35.585153] * ]], {"fill": "#00f"}); * * var union = turf.union(poly1, poly2); * * //addToMap * var addToMap = [poly1, poly2, union]; */ function union (poly1, poly2, options) { if (options === void 0) { options = {} } var geom1 = getGeom(poly1) var geom2 = getGeom(poly2) var unioned = polygonClipping.union(geom1.coordinates, geom2.coordinates) if (unioned.length === 0) return null if (unioned.length === 1) return polygon(unioned[0], options.properties) else return multiPolygon(unioned, options.properties) } /** * Takes two {@link Polygon|polygon} or {@link MultiPolygon|multi-polygon} geometries and * finds their polygonal intersection. If they don't intersect, returns null. * * @name intersect * @param {Feature} poly1 the first polygon or multipolygon * @param {Feature} poly2 the second polygon or multipolygon * @param {Object} [options={}] Optional Parameters * @param {Object} [options.properties={}] Translate GeoJSON Properties to Feature * @returns {Feature|null} returns a feature representing the area they share (either a {@link Polygon} or * {@link MultiPolygon}). If they do not share any area, returns `null`. * @example * var poly1 = turf.polygon([[ * [-122.801742, 45.48565], * [-122.801742, 45.60491], * [-122.584762, 45.60491], * [-122.584762, 45.48565], * [-122.801742, 45.48565] * ]]); * * var poly2 = turf.polygon([[ * [-122.520217, 45.535693], * [-122.64038, 45.553967], * [-122.720031, 45.526554], * [-122.669906, 45.507309], * [-122.723464, 45.446643], * [-122.532577, 45.408574], * [-122.487258, 45.477466], * [-122.520217, 45.535693] * ]]); * * var intersection = turf.intersect(poly1, poly2); * * //addToMap * var addToMap = [poly1, poly2, intersection]; */ function intersect (poly1, poly2, options) { if (options === void 0) { options = {} } var geom1 = getGeom(poly1) var geom2 = getGeom(poly2) var intersection = polygonClipping.intersection(geom1.coordinates, geom2.coordinates) if (intersection.length === 0) return null if (intersection.length === 1) return polygon(intersection[0], options.properties) return multiPolygon(intersection, options.properties) } /** * Takes a bounding box and a cell depth and returns a set of triangular {@link Polygon|polygons} in a grid. * * @name triangleGrid * @param {Array} bbox extent in [minX, minY, maxX, maxY] order * @param {number} cellSide dimension of each cell * @param {Object} [options={}] Optional parameters * @param {string} [options.units='kilometers'] used in calculating cellSide, can be degrees, radians, miles, or kilometers * @param {Feature} [options.mask] if passed a Polygon or MultiPolygon, the grid Points will be created only inside it * @param {Object} [options.properties={}] passed to each point of the grid * @returns {FeatureCollection} grid of polygons * @example * var bbox = [-95, 30 ,-85, 40]; * var cellSide = 50; * var options = {units: 'miles'}; * * var triangleGrid = turf.triangleGrid(bbox, cellSide, options); * * //addToMap * var addToMap = [triangleGrid]; */ function triangleGrid (bbox, cellSide, options) { if (options === void 0) { options = {} } // Containers var results = [] // Input Validation is being handled by Typescript // if (cellSide === null || cellSide === undefined) throw new Error('cellSide is required'); // if (!isNumber(cellSide)) throw new Error('cellSide is invalid'); // if (!bbox) throw new Error('bbox is required'); // if (!Array.isArray(bbox)) throw new Error('bbox must be array'); // if (bbox.length !== 4) throw new Error('bbox must contain 4 numbers'); // if (mask && ['Polygon', 'MultiPolygon'].indexOf(getType(mask)) === -1) throw new Error('options.mask must be a (Multi)Polygon'); // Main var xFraction = cellSide / distance([bbox[0], bbox[1]], [bbox[2], bbox[1]], options) var cellWidth = xFraction * (bbox[2] - bbox[0]) var yFraction = cellSide / distance([bbox[0], bbox[1]], [bbox[0], bbox[3]], options) var cellHeight = yFraction * (bbox[3] - bbox[1]) var xi = 0 var currentX = bbox[0] while (currentX <= bbox[2]) { var yi = 0 var currentY = bbox[1] while (currentY <= bbox[3]) { var cellTriangle1 = null var cellTriangle2 = null if (xi % 2 === 0 && yi % 2 === 0) { cellTriangle1 = polygon([ [ [currentX, currentY], [currentX, currentY + cellHeight], [currentX + cellWidth, currentY], [currentX, currentY], ], ], options.properties) cellTriangle2 = polygon([ [ [currentX, currentY + cellHeight], [currentX + cellWidth, currentY + cellHeight], [currentX + cellWidth, currentY], [currentX, currentY + cellHeight], ], ], options.properties) } else if (xi % 2 === 0 && yi % 2 === 1) { cellTriangle1 = polygon([ [ [currentX, currentY], [currentX + cellWidth, currentY + cellHeight], [currentX + cellWidth, currentY], [currentX, currentY], ], ], options.properties) cellTriangle2 = polygon([ [ [currentX, currentY], [currentX, currentY + cellHeight], [currentX + cellWidth, currentY + cellHeight], [currentX, currentY], ], ], options.properties) } else if (yi % 2 === 0 && xi % 2 === 1) { cellTriangle1 = polygon([ [ [currentX, currentY], [currentX, currentY + cellHeight], [currentX + cellWidth, currentY + cellHeight], [currentX, currentY], ], ], options.properties) cellTriangle2 = polygon([ [ [currentX, currentY], [currentX + cellWidth, currentY + cellHeight], [currentX + cellWidth, currentY], [currentX, currentY], ], ], options.properties) } else if (yi % 2 === 1 && xi % 2 === 1) { cellTriangle1 = polygon([ [ [currentX, currentY], [currentX, currentY + cellHeight], [currentX + cellWidth, currentY], [currentX, currentY], ], ], options.properties) cellTriangle2 = polygon([ [ [currentX, currentY + cellHeight], [currentX + cellWidth, currentY + cellHeight], [currentX + cellWidth, currentY], [currentX, currentY + cellHeight], ], ], options.properties) } if (options.mask) { if (intersect(options.mask, cellTriangle1)) results.push(cellTriangle1) if (intersect(options.mask, cellTriangle2)) results.push(cellTriangle2) } else { results.push(cellTriangle1) results.push(cellTriangle2) } currentY += cellHeight yi++ } xi++ currentX += cellWidth } return featureCollection(results) } let CesiumProError$1 = class CesiumProError extends Error { /** * 定义CesiumPro抛出的错误 * @extends Error * @param {String} message 描述错误消息的内容 * @example * function flyTo(viewer,entity){ * if(!viewer){ * throw(new CesiumPro.CesiumProError("viewer未定义")) * } * viewer.flyTo(entity) * } * */ constructor(message) { super(message) this.name = 'CesiumProError' } } CesiumProError$1.throwInstantiationError = function () { throw new DeveloperError( "This function defines an interface and should not be called directly." ) } CesiumProError$1.throwNoInstance = function () { throw new CesiumProError$1('它的定义了一个接口,不能被以直接调用.') } /** * 如果第一个参数未定义,返回第二个参数,否则返回第一个参数,用于设置默认值。 * * @exports defaultValue * * @param {*} a * @param {*} b * @returns {*} 如果第一个参数未定义,返回第二个参数,否则返回第一个参数,用于设置默认值。 * * @example * param = CesiumPro.defaultValue(param, 'default'); */ function defaultValue$c (a, b) { if (a !== undefined && a !== null) { return a } return b } /** * 判断一个变量是否被定义 * @param value * @exports defined * @returns {Boolean} value是否被定义 */ function defined$e (value) { return value !== undefined && value !== null } class LonLat { /** * 用经纬度(度)和海拔(米)描述一个地理位置。 * @param {Number} lon 经度,单位:度 * @param {Number} lat 经度,单位:度 * @param {Number} alt 海拔,单位:米 */ constructor(lon, lat, alt) { if (!defined$e(lon)) { throw new CesiumProError$1('longitude is required.') } if (!defined$e(lat)) { throw new CesiumProError$1('latitude is required.') } this.lon = lon this.lat = lat this.alt = defaultValue$c(alt, 0) } get height () { return this.alt } /** * 转为屏幕坐标 * @param {Cesium.Scene} scene * @returns {Cesium.Cartesian2} 屏幕坐标 */ toPixel (scene) { return LonLat.toPixel(this, scene) } /** * 转为笛卡尔坐标 * @returns {Cesium.Cartesian3} 笛卡尔坐标 */ toCartesian () { return LonLat.toCartesian(this) } /** * 转为地理坐标 * @returns {Cesium.Cartographic} 地理坐标 */ toCartographic () { return LonLat.toCartographic(this) } /** * 获得该点的弧度形式 * @returns 弧度表示的点 */ getRadias () { return { lon: Cesium.Math.toRadians(this.lon), lat: Cesium.Math.toRadians(this.lat), alt } } /** * 判断该点是否在场景内,且在球的正面 * @returns {Boolean} 可见性 */ isVisible (viewer) { return LonLat.isVisible(this, viewer) } /** * 转为字符串 * @returns 表示该点位置的字符串 */ toString () { return `{lon: ${this.lon}, lat: ${this.lat}, alt: ${this.alt}}` } /** * 转为JSON对象 * @returns 表示该点位置的对象 */ toJson () { return { lon: this.lon, lat: this.lat, alt: this.alt } } /** * 从地理点坐标转换成数组 * @returns 表示该点位置的数组 */ toArray () { return [this.lon, this.lat, this.alt] } /** * 判断一个点在当前场景是否可见。这里的可见指的是是否在屏幕范围内且在球的正面。 * @param {LonLat} point 点 * @param {Cesium.Viewer} viewer Viewer对象 * @returns {Boolean} 可见性 */ static isVisible (point, viewer) { if (viewer instanceof Cesium.Viewer === false) { throw new CesiumProError$1('viewer不是一个有效的Cesium.Viewer对象') } if (!defined$e(point)) { return false } const position = LonLat.toCartesian(point) if (!position) { return false } if (viewer.scene.mode === Cesium.SceneMode.SCENE3D) { const visibility = new Cesium.EllipsoidalOccluder(Cesium.Ellipsoid.WGS84, viewer.camera.position) .isPointVisible(position) if (!visibility) { return false } const windowPosition = LonLat.toPixel(point, viewer.scene) if (!defined$e(windowPosition)) { return false } const width = viewer.canvas.width || viewer.canvas.clientWidth const height = viewer.canvas.height || viewer.canvas.clientHeight return (windowPosition.x > 0 && windowPosition.x < width) && (windowPosition.y > 0 && windowPosition.y < height) } else if (viewer.scene.mode === Cesium.SceneMode.SCENE2D) { const frustum = viewer.scene.camera.frustum const { positionWC, directionWC, upWC } = viewer.scene.camera const cullingVolume = frustum.computeCullingVolume(positionWC, directionWC, upWC) const bounding = Cesium.BoundingSphere.projectTo2D(new BoundingSphere(position, 1)) const visibility = cullingVolume.computeVisibility(bounding) return visibility === Cesium.Intersect.INSIDE || visibility === Cesium.Intersect.INERSECTING } } /** * 转屏幕坐标 * @param {LonLat|Cesium.Cartesian3|Cesium.Cartographic} point * @param {Cesium.Scene} scene * @returns 对应的屏幕坐标 */ static toPixel (point, scene) { //>>includeStart('debug', pragmas.debug); if (!defined$e(scene)) { throw new CesiumProError$1('scene未定义。') } //>>includeEnd('debug', pragmas.debug); if (!defined$e(point)) { return undefined } const cartesian = LonLat.toCartesian(point) if (!defined$e(cartesian)) { return undefined } return Cesium.SceneTransforms.wgs84ToWindowCoordinates( scene, cartesian, ) } /** * 转弧度坐标 * @param {LonLat} point * @returns 用弧度表示的坐标点 */ static toCartographic (point, viewer) { //>>includeStart('debug', pragmas.debug); if (!defined$e(point)) { throw new CesiumProError$1('point is not defined.') } //>>includeEnd('debug', pragmas.debug); if (point instanceof LonLat) { return Cesium.Cartographic.fromDegrees(point.lon, point.lat, point.alt) } else if (point instanceof Cesium.Cartesian3) { return Cesium.Cartographic.fromCartesian(point) } else if (point instanceof Cesium.Cartographic) { return point } else if (point instanceof Cesium.Cartesian2) { const cartesian = LonLat.toCartesian(point, viewer) return LonLat.toCartographic(cartesian) } } /** * 转笛卡尔坐标 * @param {LonLat|Cesium.Cartesian3|Cesium.Cartographic|Cesium.Cartesian2} point * @param {Viewer} [viewer] viewer对象, 如果point是Cesium.Cartesian2类型,该参数需要被提供 * @returns 用笛卡尔坐标表示的点 */ static toCartesian (point, viewer) { //>>includeStart('debug', pragmas.debug); if (!defined$e(point)) { return undefined } //>>includeEnd('debug', pragmas.debug); if (point instanceof Cesium.Cartesian3) { return point } if (point instanceof Cesium.Cartographic) { return Cesium.Cartographic.toCartesian(point) } if (point instanceof LonLat) { return Cesium.Cartesian3.fromDegrees(point.lon, point.lat, point.alt) } if (point instanceof Cesium.Cartesian2) { if (!viewer) { return } const ray = viewer.scene.camera.getPickRay(point) return viewer.scene.globe.pick(ray, viewer.scene) } } /** * 从一个笛卡尔坐标创建点 * @param {Cesium.Cartesian3} cartesian 笛卡尔坐标点 * @returns GeoPoint点 */ static fromCartesian (cartesian) { //>>includeStart('debug', pragmas.debug); if (!defined$e(cartesian)) { return undefined } //>>includeEnd('debug', pragmas.debug); const cartographic = Cesium.Cartographic.fromCartesian(cartesian) if (!defined$e(cartographic)) { return undefined } return LonLat.fromCartographic(cartographic) } /** * 从一个地理坐标点创建点 * @param {Cesium.Cartographic} cartographic 地理坐标点 * @returns GeoPoint点 */ static fromCartographic (cartographic) { //>>includeStart('debug', pragmas.debug); if (!defined$e(cartographic)) { throw new CesiumProError$1('cartographic is not defined.') } //>>includeEnd('debug', pragmas.debug); return new LonLat( Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude), cartographic.height ) } /** * 从一个窗口坐标创建点 * @param {Cesium.Cartesian2} pixel 窗口坐标 * @param {Cesium.Viewer} viewer Viewer对象 * @returns {LonLat} GeoPoint点 */ static fromPixel (pixel, viewer) { if (!viewer.scene.globe) { return undefined } //>>includeStart('debug', pragmas.debug); if (!defined$e(pixel)) { throw new CesiumProError$1('pixel is not defined.') } if (viewer instanceof Cesium.Viewer === false) { throw new CesiumProError$1('viewer不是一个有效的Cesium.Viewer对象') } //>>includeEnd('debug', pragmas.debug); const ray = viewer.scene.camera.getPickRay(pixel) const cartesian = viewer.scene.globe.pick(ray, viewer.scene) if (!defined$e(cartesian)) { return undefined } return LonLat.fromCartesian(cartesian) } /** * 从经纬度创建点 * @param {Number} lon 经度(度) * @param {Number} lat 纬度(度) * @param {Number} height 海拔(米) * @returns {LonLat} */ static fromDegrees (lon, lat, height) { return new LonLat(lon, lat, height) } /** * 获得一个经纬度数组 * @param {*} positions * @returns {LonLat[]} 经纬度数组 * @example * LonLat.fromDegreesArray([110, 30, 111, 31]) */ static fromDegreesArray (positions) { const ps = [] for (let i = 0, n = positions.length; i < n; i += 2) { ps.push(new LonLat(positions[i], positions[i + 1])) } return ps } /** * 获得一个经纬度数组 * @param {*} positions * @returns {LonLat[]} 经纬度数组 * @example * LonLat.fromDegreesArrayHeights([110, 30,1000, 111, 31, 1000]) */ static fromDegreesArrayHeights (positions) { const ps = [] for (let i = 0, n = positions.length; i < n; i += 3) { ps.push(new LonLat(positions[i], positions[i + 1], positions[i + 2])) } return ps } /** * 从经纬度创建点 * @param {Number} lon 经度(弧度) * @param {Number} lat 纬度(弧度) * @param {Number} height 海拔(米) * @returns {LonLat} */ static fromRadians (lon, lat, height) { return new LonLat(Cesium.Math.toDegrees(lon), Cesium.Math.toDegrees(lat), height) } /** * 判断一个点或经纬度是否在中国范围内(粗略) * @param {LonLat|Number[]} args * @returns 如果在中国范围内,返回true */ static inChina (...args) { if (args.length === 1) { const p = args[0] if (args[0] instanceof LonLat) { return LonLat.inChina(p.lon, p.lat) } } else { const lon = +args[0] const lat = +args[1] return lon > 73.66 && lon < 135.05 && lat > 3.86 && lat < 53.55 } } /** * 从经纬度数组创建点, 经纬度数组,经度在前,纬度在后 * @param {Array} lonlat * @returns {LonLat} */ static fromArray (lonlat) { return new LonLat(...lonlat) } /** * 从经纬度数组创建点, 经纬度数组,经度在前,纬度在后 * @param {Object} lonlat * @returns {LonLat} */ static fromJson (lonlat) { return new LonLat(lonlat.lon, lonlat.lat, lonlat.alt) } /** * 判断对象是不是一个有效的点 * @param {any} v */ static isValid (v) { if (v instanceof LonLat) { if (!defined$e(v.lon)) { return false } if (!defined$e(v.lat)) { return false } if (!defined$e(v.alt)) { return false } return true } if (v instanceof Cesium.Cartesian3) { if (!defined$e(v.x)) { return false } if (!defined$e(v.y)) { return false } if (!defined$e(v.z)) { return false } return true } return false } // /** // * 经纬度转CGCS2000平面坐标 // * @param {LonLat|Cesium.Cartesian3} position // */ // static toCGCS2000(position) { // if (position instanceof Cesium.Cartesian3) { // position = LonLat.fromCartesian(position); // } // if (position instanceof LonLat === false) { // throw new CesiumProError(position + 'is invalid position.') // } // } } const { Cartographic: Cartographic$e, Cartesian3: Cartesian3$p } = Cesium function formatTurfPolygonPoints (points) { if (points.length < 2) { return points } const first = points[0] const last = points[points.length - 1] if (!(first.lon == last.lon && first.lat == last.lat)) { points.push(first) } return points } /** * 空间分析工具集 * @exports AnalyserUtil */ const AnalyserUtil = {} /** * 直线分段 * @param {LonLat[]} positions 直线顶点 * @param {number} segmentLength 分段长度 * @param {object} options 具有以下属性 * @param {string} [options.units = 'kilometers'] 长度单位,有效值为degrees、radians、miles、kilometers * @param {boolean} [options.reverse = false] 是否反向分割 * @returns {LineString[]} * * @example * const positions = [new CesiumPro.LonLat(110, 30), new CesiumPro.LonLat(111, 31), new CesiumPro.LonLat(112, 31)] * const chunks = CesiumPro.AnalyserUtil.lineChunk(positions, 10, {units: 'meter'}); */ AnalyserUtil.lineChunk = function (positions, segmentLength, options = {}) { try { const line = lineString(positions.map(_ => [_.lon, _.lat])) return lineChunk(line, segmentLength, options) } catch (e) { throw new CesiumProError$1('计算错误', e) } } /** * 将多边形分割成点集 * @param {LonLat[]} positions 多边形顶点坐标 * @param {number} cellSide 网格大小 * @param {object} options 具有以下属性 * @param {string} [options.units = 'kilometers'] cellSize的单位, 有效值为degrees, radians, miles, 或 kilometers * @param {object} [options.properties = {}] 附加的属性信息 */ AnalyserUtil.polygonToGrid = function (positions, cellSize, options = {}) { positions = formatTurfPolygonPoints(positions) const pg = polygon([positions.map(_ => [_.lon, _.lat])]) const box = bbox(pg) options.mask = pg return pointGrid(box, cellSize, options) } /** * 将多边形分析Voronoi多边形 * @param {LonLat[]} positions 多边形顶点 * @param {number} cellSize 多边形分割成点时需要的点集密度 * @param {object} [options] * @param {string} [options.units = 'kilometers'] cellSize的单位, 有效值为degrees, radians, miles, 或 kilometers * @param {object} [options.properties = {}] 附加的属性信息 * @returns {PolygonFeature} Voronoi多边形 */ AnalyserUtil.polygonToVoronoi = function (positions, cellSize, options = {}) { positions = formatTurfPolygonPoints(positions) const pg = polygon([positions.map(_ => [_.lon, _.lat])]) const box = bbox(pg) options.mask = pg const points = pointGrid(box, cellSize, options) return voronoi(points, { bbox: box }) } /** * 将多边形分割三角形 * @param {LonLat[]} positions 多边形顶点坐标 * @param {number} cellSide 网格大小 * @param {object} options 具有以下属性 * @param {string} [options.units = 'kilometers'] cellSize的单位, 有效值为degrees, radians, miles, 或 kilometers * @param {object} [options.properties = {}] 附加的属性信息 */ AnalyserUtil.triangleGrid = function (positions, cellSize, options = {}) { positions = formatTurfPolygonPoints(positions) const pg = polygon([positions.map(_ => [_.lon, _.lat])]) const box = bbox(pg) options.mask = pg return triangleGrid(box, cellSize, options) } AnalyserUtil.getCartesians = function (positions) { if (!positions) return const first = positions[0] if (first instanceof LonLat) { return positions.map(_ => _.toCartesian()) } if (first instanceof Cartesian3$p) { return positions } if (first instanceof Cartographic$e) { return positions.map(_ => Cartographic$e.toCartesian(_)) } if (typeof first === 'number') { return Cartesian3$p.fromDegreesArray(positions) } return positions } AnalyserUtil.getLonLats = function (positions) { const first = positions[0] if (first instanceof LonLat) { return positions } if (first instanceof Cartesian3$p) { return positions.map(_ => LonLat.fromCartesian(_)) } if (first instanceof Cartographic$e) { return positions.map(_ => LonLat.fromCartographic(_)) } if (typeof first === 'number') { return LonLat.fromDegreesArray(positions) } return positions } AnalyserUtil.getArea = function (positions) { const pg = polygon([positions]) return area(pg) } /** * 获得两个多边形相交的部分 * @param {PolygonFeature} pg1 * @param {PolygonFeature} pg2 * @returns {PolygonFeature} 两个多边形相交的部分 */ AnalyserUtil.intersect = function (pg1, pg2) { return intersect(pg1, pg2) } /** * 获得点集的外接矩形 * @param {*} positions * @returns {PolygonFeature} 点集的外接矩形 */ AnalyserUtil.bbox = function (positions) { positions = formatTurfPolygonPoints(positions) const pg = polygon([positions.map(_ => [_.lon, _.lat])]) const box = bbox(pg) return bboxPolygon(box) } /** * 检查变是否是一个Cesium.Viewer对象 * @exports checkViewer * * @param {any} viewer 将要检查的对象 */ function checkViewer (viewer) { if (!(viewer && viewer instanceof Cesium.Viewer)) { const type = typeof viewer throw new CesiumProError$1(`Expected viewer to be typeof Viewer, actual typeof was ${type}`) } } /* eslint-disable prefer-rest-params */ function compareNumber (a, b) { return b - a } let Event$a = class Event { /** * 事件管理器 * @example * const addMarkerEvent=new Event(); * function saveMark(marker){ * console.log("添加了一个marker",marker.id) * } * addMarkerEvent.on(saveMark) * const mark=viewer.entities.add({ * id:"mark1", * billboard:{ * image:"./icon/pin.png" * } * }) * addMarkerEvent.emit(mark) */ constructor() { this._listeners = [] this._scopes = [] this._toRemove = [] this._insideRaiseEvent = false } /** * 当前订阅事件的侦听器个数 * @type {Number} */ get numberOfListeners () { return this._listeners.length - this._toRemove.length } /** * 注册事件触发时执行的回调函数 * @param {Function} listener 事件触发时执行的回调函数 * @param {Object} [scope] 侦听器函数中this的指针 * @return {Function} 用于取消侦听器监测的函数 * * @see Event#removeEventListener * @see Event#raise */ addEventListener (listener, scope) { if (typeof listener !== 'function') { throw new CesiumProError$1('侦听器应该是一个函数') } this._listeners.push(listener) this._scopes.push(scope) const event = this return function () { event.removeEventListener(listener, scope) } } /** * 注销事件触发时的回调函数 * @param {Function} listener 将要被注销的函数 * @param {Object} [scope] 侦听器函数中this的指针 * @return {Boolean} 如果为真,事件被成功注销,否则,事件注销失败 * * @see Event#addEventListener * @see Event#raise */ removeEventListener (listener, scope) { if (typeof listener !== 'function') { throw new CesiumProError$1('侦听器应该是一个函数') } const listeners = this._listeners const scopes = this._scopes let index = -1 for (let i = 0; i < listeners.length; i++) { if (listeners[i] === listener && scopes[i] === scope) { index = i break } } if (index !== -1) { if (this._insideRaiseEvent) { // In order to allow removing an event subscription from within // a callback, we don't actually remove the items here. Instead // remember the index they are at and undefined their value. this._toRemove.push(index) listeners[index] = undefined scopes[index] = undefined } else { listeners.splice(index, 1) scopes.splice(index, 1) } return true } return false } /** * 触发事件 * @param {*} arguments 此方法接受任意数据的参数并传递给侦听器函数 * * @see Event#addEventListener * @see Event#removeEventListener */ raise () { this._insideRaiseEvent = true let i const listeners = this._listeners const scopes = this._scopes let { length, } = listeners for (i = 0; i < length; i++) { const listener = listeners[i] if (Cesium.defined(listener)) { listeners[i].apply(scopes[i], arguments) } } // Actually remove items removed in removeEventListener. const toRemove = this._toRemove length = toRemove.length // 降序排列,从后往前删 if (length > 0) { toRemove.sort(compareNumber) for (i = 0; i < length; i++) { const index = toRemove[i] listeners.splice(index, 1) scopes.splice(index, 1) } toRemove.length = 0 } this._insideRaiseEvent = false } raiseEvent () { this.raise(...arguments) } } /** * 生成符合RFC4122 v4的guid * @exports guid * @return {String} guid */ function guid () { // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = Math.floor((Math.random() * 16)) // y值限定在[8,B] /* eslint-disable */ const v = c === 'x' ? r : (r & 0x3 | 0x8) return v.toString(16) }) } class BaseAnalyser { /** * 空间分析 * @param {Cesium.Viewer} viewer viewer对象 * @param {object} options 空间分析配置项 */ constructor(viewer, options = {}) { checkViewer(viewer) this._id = defaultValue$c(options.id, guid()) this.options = options this._viewer = viewer /** * 分析开始前触发的事件 * @type {Event} * @readonly */ this.preAnalysis = new Event$a() /** * @deprecated * 请使用preAnalysis */ this.preDo = this.preAnalysis /** * 分析完成后触发的事件 * @type {Event} * @readonly */ this.postAnalysis = new Event$a() /** * @deprecated * 请使用postAnalysis */ this.postDo = this.postAnalysis } /** * 空间分析类型 * @readonly * @type {string} */ get type () { return this._type } /** * 开始分析 * @param {*} options */ do (options) { // throw new CesiumProError("abstract method cannot be called"); if (this._doing) { throw new CesiumProError$1("当前有正在分析的任务,请稍候再试") } } isDestroyed () { return false } clear () { } /** * 销毁对象 */ destroy () { this.clear() destroyObject(this) } } class Feature { /** * OGC Feature * @see {@link https://datatracker.ietf.org/doc/html/rfc7946#section-3.2 |Feature} */ constructor(type, coordinates, properties) { /** * geometry,定义了要素的几何信息 * @type {object} * @see {@link https://datatracker.ietf.org/doc/html/rfc7946#section-3.1|OGC Geometry} */ this.geometry = { type, coordinates } /** * 要素类型 * @type {string} */ this.type = 'Feature' /** * @type {object} * 定义了要素的属性信息 */ this.properties = properties } /** * 转为cesium entity * @returns {Cesium.Entity} entity对象 */ toEntity (options = {}) { const geometry = this.geometry const properties = this.properties const { type, coordinates } = geometry if (type === 'Point') { return new Cesium.Entity({ position: Cesium.Cartesian3.fromDegrees(...coordinates), point: options, properties: properties }) } if (type === 'LineString') { options.positions = Cesium.Cartesian3.fromDegreesArray(coordinates.flat()) return new Cesium.Entity({ properties: properties, polyline: options }) } if (type === 'Polygon') { options.hierarchy = this.points.map(_ => Cesium.Cartesian3.fromDegrees(_.x, _.y)) return new Cesium.Entity({ properties: this.properties, polygon: options }) } } static fromEntity (entity) { const props = {} if (entity.properties) { const keys = entity.properties._propertyNames for (let key of keys) { props[key] = entity.properties[key].getValue() } } return props } } class PointFeature extends Feature { /** * 定义一个点 * @extends Feature * @param {number} x 经纬 * @param {number} y 纬度 * @param {object} properties 属性 */ constructor(x, y, properties) { const coordinates = [x, y] super('Point', coordinates, properties) this.x = x this.y = y } /** * 从数组创建一个点 * @static * @param {number[]} points * @returns {PointFeature} point 对象 */ static fromArray (points) { return new PointFeature(points[0], points[1]) } /** * 转为cesium entity */ toEntity (options = {}) { return new Cesium.Entity({ position: Cesium.Cartesian3.fromDegrees(this.x, this.y), point: options, properties: this.properties }) } /** * 从Cesium Entity 对象生成Feature * @param {Cesium.Entity} entity * @returns {Feature} feature对象 */ static fromEntity (entity) { if (entity instanceof Cesium.Entity === false) { throw new CesiumProError('entity must be a Cesium.Entity') } const time = Cesium.JulianDate.now() let properties = Feature.fromEntity(entity) if (entity.position) { const position = entity.position.getValue(time) const lonlat = LonLat.fromCartesian(position) return new PointFeature(lonlat.lon, lonlat.lat, properties) } } } class PolylineFeature extends Feature { /** * 定义一个线段 * @param {PointFeature[]} points * @param {object} properties * @extends Feature * @example * const p1 = new CesiumPro.PointFeature(110,30); * const p2 = new CesiumPro.PointFeature(110,40); * const polyline = new CesiumPro.PolylineFeature([p1, p2]); */ constructor(points, properties) { if (points.length < 2) { throw new CesiumProError$1("Polyline feature positions must have at least 2 point") } const coordinates = [] for (const point of points) { coordinates.push([point.x, point.y]) } super('LineString', coordinates, properties) this.points = points } /** * 从经纬度数组创建线段 * @param {number[]} positions * @returns {PolylineFeature} polyline对象 */ static fromArray (positions) { const points = [] for (let i = 0, n = positions.length; i < n; i += 2) { const point = new PointFeature(positions[i], positions[i + 1]) points.push(point) } return new PolylineFeature(points) } /** * 转为cesium entity * @returns {Cesium.Entity} entity对象 */ toEntity (options = {}) { options.positions = this.points.map(_ => Cesium.Cartesian3.fromDegrees(_.x, _.y)) return new Cesium.Entity({ properties: this.properties, polyline: options }) } /** * 从Cesium Entity 对象生成Feature * @param {Cesium.Entity} entity * @returns {Feature} feature对象 */ static fromEntity (entity) { if (entity instanceof Cesium.Entity === false) { throw new CesiumProError$1('entity must be a Cesium.Entity') } const time = Cesium.JulianDate.now() let properties = Feature.fromEntity(entity) if (entity.polyline && entity.polyline.positions) { let positions = entity.polyline.positions positions = positions.getValue(time) const points = [] for (let position of positions) { const lonlat = LonLat.fromCartesian(position) points.push(new PointFeature(lonlat.lon, lonlat.lat)) } return new PolylineFeature(points, properties) } } } class PolygonFeature extends Feature { /** * 定义一个线段 * @extends Feature * @param {PointFeature[]} points * @param {object} properties * @example * const p1 = new CesiumPro.PointFeature(110,30); * const p2 = new CesiumPro.PointFeature(110,40); * const p3 = new CesiumPro.PointFeature(120,40); * const polygon = new CesiumPro.PolygonFeature([p1, p2, p3]); */ constructor(points, properties) { if (points.length < 3) { throw new CesiumProError$1("Polygon feature positions must have at least 3 point") } const coordinates = [] for (const point of points) { coordinates.push([point.x, point.y]) } coordinates.push(coordinates[0]) super('Polygon', [coordinates], properties) this.points = points } /** * 从经纬度数组创建线段 * @param {number[]} positions * @returns {PolygonFeature} polygon对象 */ static fromArray (positions) { const points = [] for (let i = 0, n = positions.length; i < n; i += 2) { const point = new PointFeature(positions[i], positions[i + 1]) points.push(point) } return new PolygonFeature(points) } /** * 转为cesium entity * @returns {Cesium.Entity} entity对象 */ toEntity (options = {}) { options.hierarchy = this.points.map(_ => Cesium.Cartesian3.fromDegrees(_.x, _.y)) return new Cesium.Entity({ properties: this.properties, polygon: options }) } /** * 从Cesium Entity 对象生成Feature * @param {Cesium.Entity} entity * @returns {Feature} feature对象 */ static fromEntity (entity) { if (entity instanceof Cesium.Entity === false) { throw new CesiumProError$1('entity must be a Cesium.Entity') } const time = Cesium.JulianDate.now() let properties = Feature.fromEntity(entity) if (entity.polygon && entity.polygon.hierarchy) { const hierarchy = entity.polygon.hierarchy.getValue(time) const positions = hierarchy.positions const points = [] for (let position of positions) { const lonlat = LonLat.fromCartesian(position) points.push(new PointFeature(lonlat.lon, lonlat.lat)) } return new PolygonFeature(points, properties) } } static toEntity (feature) { if (!defined$e(feature)) { return } let coordinates if (feature.geometry.type.toUpperCase() === 'POLYGON') { coordinates = [feature.geometry.coordinates] } else if (feature.geometry.type.toUpperCase() === 'MULTIPOLYGON') { coordinates = feature.geometry.coordinates } else { throw new CesiumProError$1('Unknown feature type.') } const entities = [] for (let coordinate of coordinates) { let hierarchy = [] if (!defined$e(coordinate) || !Array.isArray(coordinate)) { return } for (let coords of coordinate) { if (!Array.isArray(coords)) { return } for (let coor of coords) { const ll = Cesium.Cartesian3.fromDegrees(coor[0], coor[1]) if (!defined$e(ll)) return hierarchy.push(ll) } } const entity = new Cesium.Entity({ polygon: { material: Cesium.Color.fromCssColorString('rgba(247,224,32,0.5)'), outlineColor: Cesium.Color.RED, perPositionHeight: false, hierarchy } }) entities.push(entity) } return entities } } const { DataSource: DataSource$2, EntityCluster: EntityCluster$1, EntityCollection: EntityCollection$1 } = Cesium /** * A {@link DataSource} implementation which can be used to manually manage a group of entities. * * @alias CustomDataSource * @constructor * * @param {String} [name] A human-readable name for this instance. * * @example * const dataSource = new Cesium.CustomDataSource('myData'); * * const entity = dataSource.entities.add({ * position : Cesium.Cartesian3.fromDegrees(1, 2, 0), * billboard : { * image : 'image.png' * } * }); * * viewer.dataSources.add(dataSource); */ function CustomDataSource$3 (name) { this._name = name this._clock = undefined this._changed = new Event$a() this._error = new Event$a() this._isLoading = false this._loading = new Event$a() this._entityCollection = new EntityCollection$1(this) this._entityCluster = new EntityCluster$1() } Object.defineProperties(CustomDataSource$3.prototype, { /** * Gets or sets a human-readable name for this instance. * @memberof CustomDataSource.prototype * @type {String} */ name: { get: function () { return this._name }, set: function (value) { if (this._name !== value) { this._name = value this._changed.raiseEvent(this) } }, }, /** * Gets or sets the clock for this instance. * @memberof CustomDataSource.prototype * @type {DataSourceClock} */ clock: { get: function () { return this._clock }, set: function (value) { if (this._clock !== value) { this._clock = value this._changed.raiseEvent(this) } }, }, /** * Gets the collection of {@link Entity} instances. * @memberof CustomDataSource.prototype * @type {EntityCollection} */ entities: { get: function () { return this._entityCollection }, }, /** * Gets or sets whether the data source is currently loading data. * @memberof CustomDataSource.prototype * @type {Boolean} */ isLoading: { get: function () { return this._isLoading }, set: function (value) { DataSource$2.setLoading(this, value) }, }, /** * Gets an event that will be raised when the underlying data changes. * @memberof CustomDataSource.prototype * @type {Event} */ changedEvent: { get: function () { return this._changed }, }, /** * Gets an event that will be raised if an error is encountered during processing. * @memberof CustomDataSource.prototype * @type {Event} */ errorEvent: { get: function () { return this._error }, }, /** * Gets an event that will be raised when the data source either starts or stops loading. * @memberof CustomDataSource.prototype * @type {Event} */ loadingEvent: { get: function () { return this._loading }, }, /** * Gets whether or not this data source should be displayed. * @memberof CustomDataSource.prototype * @type {Boolean} */ show: { get: function () { return this._entityCollection.show }, set: function (value) { this._entityCollection.show = value }, }, /** * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources. * * @memberof CustomDataSource.prototype * @type {EntityCluster} */ clustering: { get: function () { return this._entityCluster }, set: function (value) { //>>includeStart('debug', pragmas.debug); if (!defined$e(value)) { throw new CesiumProError$1("value must be defined.") } //>>includeEnd('debug'); this._entityCluster = value }, }, }) /** * Updates the data source to the provided time. This function is optional and * is not required to be implemented. It is provided for data sources which * retrieve data based on the current animation time or scene state. * If implemented, update will be called by {@link DataSourceDisplay} once a frame. * * @param {JulianDate} time The simulation time. * @returns {Boolean} True if this data source is ready to be displayed at the provided time, false otherwise. */ CustomDataSource$3.prototype.update = function (time) { return true } CustomDataSource$3.prototype.add = function (entity) { return this.entities.add(entity) } CustomDataSource$3.prototype.removeAll = function () { return this.entities.removeAll() } class BufferAnalyser extends BaseAnalyser { /** * 缓冲区分析 * @extends BaseAnalyser * @param {Viewer} viewer Cesium Viewer对象 * @param {Object} [options={}] 具有以下属性 * @param {PointFeature[]|PolylineFeature[]|PolygonFeature[]} [options.graphics=[]] 参加缓冲区分析的要素集合 * @param {Number} [options.bufferRadius=100] 缓冲区半径,单位米,如果graphics中的要素定义了bufferRadius属性,该值将会被覆盖 * @param {Number} [options.samplerSize=8] 缓冲区分析的迭代步数,值越大,多边形越精细,分析速度越慢 * @param {Object} [options.material=Cesium.Color.GOLD.withAlpha(0.6)] 分析结果使用的材质 * @param {Cesium.HeightReference} [options.heightReference=Cesium.HeightReference.NONE] 分析结果使得的高程参考. * * @example * const point = new CesiumPro.PointGraphic({ position: Cesium.Cartesian3.fromDegrees(110.025, 30.021), pixelSize: 10, color: Cesium.Color.RED, properties: { bufferRadius: 1000 } }) const point1 = new CesiumPro.PointGraphic({ position: Cesium.Cartesian3.fromDegrees(110.009, 30.021), pixelSize: 10, color: Cesium.Color.RED, properties: { bufferRadius: 1400 } }) const point2 = new CesiumPro.PointGraphic({ position: Cesium.Cartesian3.fromDegrees(110.045, 30.011), pixelSize: 10, color: Cesium.Color.RED, properties: { bufferRadius: 1200 } }) const line = new CesiumPro.PolylineGraphic({ positions: Cesium.Cartesian3.fromDegreesArray([110.012, 30.015, 110.02, 30.01, 110.05, 30.02]), width: 3, material: Cesium.Color.GOLD }) line.properties.addProperty('bufferRadius', 500) const polygon = new CesiumPro.PolygonGraphic({ positions: Cesium.Cartesian3.fromDegreesArray([110.01, 30.02, 110.03, 30.03, 110.04, 30.005]), material: Cesium.Color.WHITE.withAlpha(0.5) }) viewer.flyTo([point.entity, line.entity, polygon.entity]); const graphics = [point, point1, point2, line, polygon]; const buffer = new BufferAnalyser(viewer, { graphics, material: Cesium.Color.RED.withAlpha(0.6) }) buffer.do(); */ constructor(viewer, options = {}) { super(viewer) this._graphics = options.graphics this._steps = defaultValue$c(options.steps, 8) this._bufferRadius = defaultValue$c(options.bufferRadius, 100) this._material = defaultValue$c(options.material, Cesium.Color.GOLD.withAlpha(0.6)) this._heightReference = defaultValue$c(options.heightReference, Cesium.HeightReference.NONE) this._buffered = [] this._root = new CustomDataSource$3('buffer-analysis') viewer.dataSources.add(this._root) } /** * 缓冲区分析半径 * @type {Number} */ get bufferRadius () { return this._bufferRadius } set bufferRadius (val) { val = parseFloat(val) if (val < 0) { return } this._bufferRadius = val } /** * 多边形分割的步数,值越大,多边形越精细,分析速度越慢 * @type {Number} */ get steps () { this._steps } set steps (val) { this._steps = val } /** * 缓冲分析结果使用的材质 * @type {Object} * @example * const buffer=CesiumPro.BufferAnalyser(viewer); * buffer.material=Cesium.Color.RED; */ get material () { return this._material } set material (val) { this._material = val } /** * 设置缓冲区分析的图形 * @param {PointFeature[]|PolylineFeature[]|PolygonFeature[]} graphics */ setGraphic (graphics) { const isArray = Array.isArray(graphics) if (!isArray) { graphics = [graphics] } this._graphics = graphics.filter(_ => _ instanceof Feature) } /** * 开始分析 * @returns {array} 缓冲区分析结果 */ do () { this.preAnalysis.raise() const graphics = this._graphics if (!(Array.isArray(graphics) && graphics.length)) { //>>includeStart('debug', pragmas.debug) throw new CesiumProError$1("the graphics must be provided, you can call setGraphic method set graphics.") //>>includeEnd('debug') } if (!(Array.isArray(graphics) && graphics.length)) { return } let bufferedGraphic const bufferedList = [] for (let graphic of graphics) { const feat = graphic.geometry let radius = this._bufferRadius if (graphic.properties && defined$e(graphic.properties.bufferRadius)) { radius = graphic.properties.bufferRadius } radius = radius / 1000.0 const buffered = buffer(feat, radius, { steps: this._steps, units: 'kilometers', radius }) bufferedList.push(buffered) } let unionFeature if (bufferedList.length > 1) { let unionFeature = bufferedList[0] for (let i = 1; i < bufferedList.length; i++) { unionFeature = union(unionFeature, bufferedList[i]) } bufferedGraphic = PolygonFeature.toEntity(unionFeature) } else { unionFeature = bufferedList bufferedGraphic = PolygonFeature.toEntity(unionFeature[0]) } if (!defined$e(bufferedGraphic)) { this.postAnalysis.raise() return } for (let graphic of bufferedGraphic) { graphic.polygon.material = this._material graphic.polygon.heightReference = this._heightReference this._root.add(graphic) } this.postAnalysis.raise(bufferedGraphic) } clear () { this._root.removeAll() } /** * 定位到分析结果 */ zoomTo () { if (this._viewer) { this._viewer.flyTo(this._root.entities) } } destroy () { this._viewer.dataSources.remove(this._root) this._viewer = undefined super.destroy() } } /** * 地图量算工具,包括距离量算、面积量算、角度量算、高度量算 * @namespace Cartometry */ const Cartometry = {} /** * 贴地距离 * @param {Cesium.Cartesian3[]} positions 构成直线的顶点坐标 * @return {Number} 长度,单位米 */ Cartometry.surfaceDistance = function (positions) { let distance = 0 for (let i = 0; i < positions.length - 1; i += 1) { const point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]) const point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1]) /** 根据经纬度计算出距离* */ const geodesic = new Cesium.EllipsoidGeodesic() geodesic.setEndPoints(point1cartographic, point2cartographic) const s = geodesic.surfaceDistance distance += s } return distance } /** * 空间距离 * @param {Cesium.Cartesian3[]} positions 构成直线的顶点坐标 * @return {Number} 长度,单位米 */ Cartometry.spaceDistance = function (positions) { let dis = 0 for (let i = 1; i < positions.length; i++) { const s = positions[i - 1] const e = positions[i] dis += Cesium.Cartesian3.distance(s, e) } return dis } /** * * 计算两个向量之间的夹角,两个向量必须拥有相同的起点。 * @param {Cesium.Cartesian3} p1 向量起点 * @param {Cesium.Cartesian3} p2 向量1终点 * @param {Cesium.Cartesian3} p3 向量2终点 * @return {Number} 返回p1p2和p1p3之间的夹角,单位:度 */ Cartometry.angle = function (p1, p2, p3) { // 以任意一点为原点建立局部坐标系 let angle = 0 try { const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(p1) const inverseMatrix = Cesium.Matrix4.inverseTransformation(matrix, new Cesium.Matrix4()) // 将其它两个点坐标转换到局部坐标 const localp2 = Cesium.Matrix4.multiplyByPoint(inverseMatrix, p2, new Cesium.Cartesian3()) const localp3 = Cesium.Matrix4.multiplyByPoint(inverseMatrix, p3, new Cesium.Cartesian3()) // 归一化 const normalizep2 = Cesium.Cartesian3.normalize(localp2, new Cesium.Cartesian3()) const normalizep3 = Cesium.Cartesian3.normalize(localp3, new Cesium.Cartesian3()) // 计算两点夹角 const cos = Cesium.Cartesian3.dot(normalizep2, normalizep3) angle = Cesium.Math.acosClamped(cos) } catch (e) { console.log(e) angle = 0 } return Cesium.Math.toDegrees(angle) } /** * 计算向量的方位角 * @param {Cesium.Cartesian3} center 向量起点 * @param {Cesium.Cartesian3} point 向量终点 * @return {Number} 角度,单位:度 * @example * * const start=Cesium.Cartesian3.fromDegrees(110,30); * const end=Cesium.Cartesian3.fromDegrees(110,40) * const angle = CesiumPro.Cartometry.angleBetweenNorth(start,end); */ Cartometry.angleBetweenNorth = function (center, point) { const matrix = Cesium.Transforms.eastNorthUpToFixedFrame(center) const inverseMatrix = Cesium.Matrix4.inverseTransformation(matrix, new Cesium.Matrix4()) const localp = Cesium.Matrix4.multiplyByPoint(inverseMatrix, point, new Cesium.Cartesian3()) const normalize = Cesium.Cartesian3.normalize(localp, new Cesium.Cartesian3()) const north = new Cesium.Cartesian3(0, 1, 0) const cos = Cesium.Cartesian3.dot(normalize, north) let angle = Cesium.Math.acosClamped(cos) angle = Cesium.Math.toDegrees(angle) const east = new Cesium.Cartesian3(1, 0, 0) const arceast = Cesium.Cartesian3.dot(east, normalize) if (arceast < 0) { angle = 360 - angle } return angle } /** * 贴地面积 * @param {Cesium.Cartesian3[]} positions 构成多边形的顶点坐标 * @return {Number} 面积,单位:平方米 */ Cartometry.surfaceArea = function (positions) { // TODO:计算方法有问题 let res = 0 // 拆分三角曲面 for (let i = 0; i < positions.length - 2; i += 1) { const j = (i + 1) % positions.length const k = (i + 2) % positions.length const totalAngle = Cartometry.angle(positions[i], positions[j], positions[k]) const distemp1 = Cartometry.spaceDistance([positions[i], positions[j]]) const distemp2 = Cartometry.spaceDistance([positions[j], positions[k]]) res += distemp1 * distemp2 * Math.abs(Math.sin(Cesium.Math.toRadians(totalAngle))) } return res } /** * 空间面积 * @param {Cesium.Cartesian3[]} positions 构成多边形的顶点坐标 * @return {Number} 面积,单位:平方米 */ Cartometry.spaceArea = function (positions) { const points = [] for (let position of positions) { const coord = LonLat.fromCartesian(position) points.push([coord.lon, coord.lat]) } points.push(points[0]) const polygon$1 = polygon([points]) return area(polygon$1) } /** * 计算相邻两个点之间的高度差 * @param {} positions * @return {} 相信两个顶点之间的高度差,单位m */ Cartometry.heightFromCartesianArray = function (positions) { if (positions.length < 2) { return 0 } const rst = [] for (let i = 1; i < positions.length; i++) { const startC = Cesium.Cartographic.fromCartesian(positions[i - 1]) const endC = Cesium.Cartographic.fromCartesian(positions[i]) if (startC && endC) { rst.push(endC.height - startC.height) } else { rst.push('NaN') } } return rst } const { Color: Color$u, Cartesian3: Cartesian3$o, Cartographic: Cartographic$d, PrimitiveCollection: PrimitiveCollection$5, PolygonGeometry: PolygonGeometry$3, PolygonHierarchy: PolygonHierarchy$4, GeometryInstance: GeometryInstance$5, Primitive: Primitive$8, GroundPrimitive: GroundPrimitive$3, PerInstanceColorAppearance: PerInstanceColorAppearance$1 } = Cesium /** * 获得三角形顶点 */ function getNodesAndHeight (viewer, points, exclude = []) { const positions = [] let h = 0 const area = AnalyserUtil.getArea(points) for (let i = 0; i < 3; i++) { const point = points[i] const carto = Cartographic$d.fromDegrees(...point) const height = viewer.scene.sampleHeight(carto, exclude) h += height const cartesian = Cartesian3$o.fromDegrees(point[0], point[1], height) positions.push(cartesian) } return { positions, height: h / 3, area } } function createPolygon$2 (positions, color, height, clamp) { const polygon = new PolygonGeometry$3({ polygonHierarchy: new PolygonHierarchy$4(positions), perPositionHeight: true, extrudedHeight: height }) const instance = new GeometryInstance$5({ geometry: polygon, attributes: { color: Cesium.ColorGeometryInstanceAttribute.fromColor(color) } }) const constructor = clamp ? GroundPrimitive$3 : Primitive$8 return new constructor({ geometryInstances: [instance], appearance: new PerInstanceColorAppearance$1() }) } class FillAnalyser extends BaseAnalyser { /** * 挖方分析 * @extends BaseAnalyser * @param {*} viewer * @param {*} options 具有以下属性 * @param {LonLat[]|Cesium.Cartesian3[]} [options.mask] 分析范围 * @param {Cesium.Color} [options.fillColor = Cesium.Color.RED] 需要填充的区域的颜色 * @param {Cesium.Color} [options.excavatedColor = Cesium.Color.GREEN] 需要挖掘的区域的颜色 * @param {number} [options.height] 挖填高度 * @param {number} [options.samplerSize] 采样间距 * @param {array} [options.excludeObject = []] 分析时需要排除的对象 * @param {boolean} [options.renderToViewer = true] 是否将分析结果渲染到场景 */ constructor(viewer, options = {}) { super(viewer, options) // if (!options.mask) { // throw new CesiumProError('parameter mask must be provided.') // } const mask = AnalyserUtil.getCartesians(options.mask) if (mask) { this._mask = [...mask, mask[0]] } if (this._mask instanceof Cartesian3$o) { this._mask = this._mask.map(_ => LonLat.fromCartesian(_)) } this.excavatedColor = defaultValue$c(options.excavatedColor, Color$u.RED.withAlpha(0.5)) this.fillColor = defaultValue$c(options.fillColor, Color$u.GREEN.withAlpha(0.5)) this._type = 'excavation-analysis' this._height = defaultValue$c(options.height, 0) this._samplerSize = options.samplerSize this._excludeObject = defaultValue$c(options.excludeObject, []) this._renderToViewer = defaultValue$c(options.renderToViewer, true) this._doing = false } /** * 设置分析范围 * @param {*} mask */ setMask (mask) { if (!Array.isArray(mask)) { throw new CesiumProError$1('mask must be an array') } const maskCartesians = AnalyserUtil.getCartesians(options.mask) this._mask = [...maskCartesians, maskCartesians[0]] if (this._mask instanceof Cartesian3$o) { this._mask = this._mask.map(_ => LonLat.fromCartesian(_)) } } /** * 建议采样间距 * @type {number} */ static suggestGridCount = 300; /** * 开始分析 * @returns {object} 分析参数及结果 */ do () { super.do() if (!this._mask) { if (!Array.isArray(mask)) { throw new CesiumProError$1('请通过setMask方法指定分析范围') } } if (this._doing) { throw new CesiumProError$1('上一次分析正在进行,请稍候...') } if (!this._mask) { return } this.clear() this._doing = true this.preDo.raise({ samplerSize: this._samplerSize, id: this._id }) const area = Cartometry.surfaceArea(this._mask) const cellSize = this._samplerSize || Math.sqrt(area / 1e6 / FillAnalyser.suggestGridCount) const polygon = AnalyserUtil.getLonLats(this._mask) const grid = AnalyserUtil.triangleGrid(polygon, cellSize) const collection = new PrimitiveCollection$5() this._root = collection collection.name = this.type if (this._renderToViewer) { this._viewer.scene.primitives.add(collection) } const points = grid.features.map(_ => _.geometry.coordinates[0]) const result = [] let fillVolume = 0 let excavaVolume = 0 for (let point of points) { const { height, positions, area } = getNodesAndHeight(this._viewer, point, this._excludeObject) const volume = area * (height - this._height) if (volume > 0) { excavaVolume += volume } else { fillVolume += Math.abs(volume) } result.push({ height, positions, volume }) this._render(positions, height) } const data = { samplerSize: cellSize, id: this._id, grid: grid, result, fillVolume, excavaVolume, graphicCollection: this._root } this.postAnalysis.raise(data) this._doing = false return data } _render (positions, height) { const color = height < this._height ? this.excavatedColor : this.fillColor const clamp = height > this._height ? true : false const polygon = createPolygon$2(positions, color, this._height, clamp) this._root.add(polygon) } /** * 清空分析结果 */ clear () { if (this._root) { this._viewer.scene.primitives.remove(this._root) } } } const { Cartesian3: Cartesian3$n, RenderState: RenderState$6, Cartesian4: Cartesian4$2, Matrix4: Matrix4$9, Texture: Texture$4, PixelFormat: PixelFormat$3, PixelDatatype: PixelDatatype$3, Framebuffer: Framebuffer$3, DrawCommand: DrawCommand$5, Pass: Pass$5, ShaderProgram: ShaderProgram$6, BoundingSphere: BoundingSphere$a, VertexArray: VertexArray$4, PolygonHierarchy: PolygonHierarchy$3, PolygonGeometry: PolygonGeometry$2, BoundingRectangle: BoundingRectangle$5, Transforms: Transforms$7, ClearCommand: ClearCommand$3, Color: Color$t, PassState: PassState$3, OrthographicOffCenterFrustum: OrthographicOffCenterFrustum$2, Cartographic: Cartographic$c, defined: defined$d, destroyObject: destroyObject$b, BufferUsage: BufferUsage$4, WebGLConstants: WebGLConstants$5, PrimitiveType: PrimitiveType$5 } = Cesium const vs$2 = ` attribute vec3 position; varying float depth; uniform mat4 u_inverseMatrix; void main() { vec4 pos = vec4(position, 1.0); vec4 positionLC = u_inverseMatrix * pos; depth = positionLC.z; gl_Position = czm_projection * vec4(positionLC.xy, 0.0, 1.0); } ` const fs$2 = ` varying float depth; void main() { float fDepth = depth / 1024.0; gl_FragColor = czm_packDepth(fDepth); } ` let OrthographicCamera$1 = class OrthographicCamera { constructor() { this.viewMatrix = Matrix4$9.IDENTITY this.inverseViewMatrix = Matrix4$9.IDENTITY this.frustum = new OrthographicOffCenterFrustum$2() this.positionCartographic = new Cartographic$c() this.upWC = Cartesian3$n.clone(Cartesian3$n.UNIT_Y) this.rightWC = Cartesian3$n.clone(Cartesian3$n.UNIT_X) this.directionWC = Cartesian3$n.clone(Cartesian3$n.UNIT_Z) this.viewPorjectionMatrix = Matrix4$9.IDENTITY } clone (camera) { Matrix4$9.clone(camera.viewMatrix, this.viewMatrix) Matrix4$9.clone(camera.inverseViewMatrix, this.inverseViewMatrix) this.frustum = camera.frustum.clone(this.frustum) Cartographic$c.clone(camera.positionCartographic, this.positionCartographic) Cartesian3$n.clone(camera.upWC, this.upWC) Cartesian3$n.clone(camera.rigtWC, this.rightWC) Cartesian3$n.clone(camera.directionWC, this.directionWC) } } class ClipRegion { /** * 创建一个clipRegion * @param {Cesium.Cartesian3[]} positions 定义clip区域的笛卡尔坐标 */ constructor(positions) { if (!Array.isArray(positions)) { throw CesiumProError$1('positions must be a cartesian3 array.') } this.positions = positions.filter(_ => _ instanceof Cartesian3$n) this._colorTexture = undefined this._depthStenclilTexture = undefined this.frameBuffer = undefined this._viewport = new BoundingRectangle$5() this._rs = undefined this._clearColorCommand = new ClearCommand$3({ depth: 1, coloe: new Color$t(0.0, 0.0, 0.0, 1.0) }) this._useScissorTest = false this._scissorRectangle = false this._command = undefined this._camera = new OrthographicCamera$1() this._passState = undefined this._clearPassState = undefined this._positions = [] this._delta = 0.0 this._localModel = undefined this._inverseLocalModel = undefined this._uniforms = {} this._initShaderSource = false this._colorTexture = undefined this._enabled = true const bounding = BoundingSphere$a.fromPoints(this.positions) let center = bounding.center const cartographic = Cartographic$c.fromCartesian(center) center = Cartesian3$n.fromRadians(cartographic.longitude, cartographic.latitude, 0) this._localModel = Transforms$7.eastNorthUpToFixedFrame(center) this._inverseLocalModel = Matrix4$9.inverse(this._localModel, {}) const localPositions = positions.map(_ => Matrix4$9.multiplyByPoint(this._inverseLocalModel, _, {})) const boundingRect = BoundingRectangle$5.fromPoints(localPositions) this.boundingRect = new Cartesian4$2(boundingRect.x, boundingRect.y, boundingRect.x + boundingRect.width, boundingRect.y + boundingRect.height) const frustum = this._camera.frustum frustum.left = boundingRect.x frustum.top = boundingRect.y + boundingRect.height frustum.right = boundingRect.x + boundingRect.width frustum.bottom = boundingRect.y this.normal = Cartesian3$n.normalize(this.positions[0], {}) this._width = 256 this._height = 256 this._id = guid() } /** * 是否有效 * @type {boolean} */ get enabled () { return this._enabled } set enabled (enabled) { this._enabled = enabled } _createVertexArray (frameState) { const polygon = new PolygonGeometry$2({ polygonHierarchy: new PolygonHierarchy$3(this.positions) }) const geometry = PolygonGeometry$2.createGeometry(polygon) return VertexArray$4.fromGeometry({ context: frameState.context, geometry, attributeLocations: { position: 0 }, bufferUsage: BufferUsage$4.STREAM_DRAW, interleave: true, }) } _createDrawcommand (frameState) { this._passState = new PassState$3(frameState.context) this._passState.viewport = new BoundingRectangle$5(100, 100, this._width, this._height) this._clearPassState = new PassState$3(frameState.context) const va = this._createVertexArray(frameState) const sp = ShaderProgram$6.fromCache({ context: frameState.context, vertexShaderSource: vs$2, fragmentShaderSource: fs$2, }) const renderState = RenderState$6.fromCache({ viewport: new BoundingRectangle$5(0, 0, this._width, this._height), depthTest: { enabled: true, // func: Cesium.DepthFunction.ALWAYS // always pass depth test for full control of depth information }, cull: { enabled: true, face: WebGLConstants$5.BACK }, depthMask: true }) const command = new DrawCommand$5({ primitiveType: PrimitiveType$5.TRIANGLES, vertexArray: va, shaderProgram: sp, uniformMap: { u_inverseMatrix: () => { return this._inverseLocalModel } }, renderState, pass: Pass$5.OPAQUE }) this._command = command } _updateFramebuffer (frameState) { const colorTexture = this._colorTexture const isEqual = defined$d(colorTexture) && colorTexture.width !== this._width && colorTexture.height !== this._height if ((defined$d(this.frameBuffer) || isEqual)) { return } if (colorTexture && !colorTexture.isDestroyed()) { colorTexture.destroy() } if (this._depthStenclilTexture && !this._depthStenclilTexture.isDestroyed()) { this._depthStenclilTexture.destroy() } if (this.frameBuffer && !this.frameBuffer.isDestroyed()) { this.frameBuffer.destroy() } this._colorTexture = new Texture$4({ context: frameState.context, width: this._width, height: this._height, pixelFormat: PixelFormat$3.RGBA, pixelDatatype: PixelDatatype$3.UNSIGNED_BYTE }) this._depthStenclilTexture = new Texture$4({ context: frameState.context, width: this._width, height: this._height, pixelFormat: PixelFormat$3.DEPTH_STENCIL, pixelDatatype: PixelDatatype$3.UNSIGNED_INT_24_8 }) this.frameBuffer = new Framebuffer$3({ context: frameState.context, colorTextures: [this._colorTexture], depthStencilTexture: this._depthStenclilTexture, destroyAttachments: false }) } /** * 不是主动调用该方法 * @param {Cesium.FrameState} frameState */ update (frameState) { if (!this._enabled) { return } if (!this._command) { this._createDrawcommand(frameState) } this._updateFramebuffer(frameState) const uniformState = frameState.context.uniformState uniformState.updateCamera(this._camera) this._clear(frameState) uniformState.updatePass(this._command.pass) this._command.framebuffer = this.frameBuffer this._command.execute(frameState.context, this._passState) } _clear (frameState) { if (this._clearColorCommand) { this._clearColorCommand.framebuffer = this.frameBuffer this._clearColorCommand.execute(frameState.context, this._clearPassState) } } /** * 是否被销毁 * @returns {boolean} true 并未已经被销毁,该实例的所有方法将被释放 */ isDestroyed () { return false } /** * 销毁对象 */ destroy () { if (this._colorTexture && !this._colorTexture.isDestroyed()) { this._colorTexture.destroy() } if (this._depthStenclilTexture && !this._depthStenclilTexture.isDestroyed()) { this._depthStenclilTexture.destroy() } if (this.frameBuffer && !this.frameBuffer.isDestroyed()) { this.frameBuffer.destroy() } destroyObject$b(this) } } function returnTrue$1 () { return true } /** * 销毁一个对象,对象的所有属性和方法都被替换为一个会抛出{@link CesiumProError}异常的函数 * * @exports destroyObject * * @param {Object} object The object to destroy. * @param {String} [message] The message to include in the exception that is thrown if * a destroyed object's function is called. * * * @example * // How a texture would destroy itself. * this.destroy = function () { * _gl.deleteTexture(_texture); * return Cesium.destroyObject(this); * }; * * @see CesiumProError */ function destroyObject$a (object, message) { message = defaultValue$c( message, "This object was destroyed, i.e., destroy() was called." ) function throwOnDestroyed () { //>>includeStart('debug', pragmas.debug); throw new CesiumProError$1(message) //>>includeEnd('debug'); } const properties = Object.getOwnPropertyNames(object) const methods = Object.getOwnPropertyNames(Object.getPrototypeOf(object)) const keys = [...properties, ...methods] for (var key of keys) { if (typeof object[key] === "function") { object[key] = throwOnDestroyed } } object.isDestroyed = returnTrue$1 return undefined } const shader$p = ` uniform float height; uniform vec4 color; czm_material czm_getMaterial(czm_materialInput materialInput) { czm_material material = czm_getDefaultMaterial(materialInput); if (materialInput.height < height) { material.alpha = color.a; } else { material.alpha = 0.0; } material.diffuse = color.rgb; return material; } ` const { Cartographic: Cartographic$b } = Cesium function computeHeight (positions, viewer, exclude = []) { let max = Number.MIN_SAFE_INTEGER let min = Number.MAX_SAFE_INTEGER let h = 0 positions.map(_ => { let height try { if (viewer.scene.globe.depthTestAgainstTerrain) { height = viewer.scene.sampleHeight(_, exclude) } else { height = viewer.scene.globe.getHeight(position) } } catch (e) { height = viewer.scene.globe.getHeight(position) } if (isNaN(height)) { return } if (height > max) { max = height } if (height < min) { min = height } h += height }) return { max, min, avg: h / positions.length } } class HeightAnalyser extends BaseAnalyser { /** * 分析给定范围的的高度,获得最大高度,最小高度和平均高度 * @extends BaseAnalyser * @param {*} viewer * @param {object} options 具有以下属性 * @param {boolean} [options.autoDepthTest = true] 准确的采样高度需要地球开启尝试测试,如果未开启,是否允许自动开启 * @param {number} [options.samplerSize] 采样间距,单位米,值越小获得的结果越准确,但是相应的性能开销会更大, 如果未定义将自动计算 * @param {LonLat[]|Cesium.Cartesian3[]|number[]} options.mask 分析范围 */ constructor(viewer, options = {}) { super(viewer) this._samplerSize = options.samplerSize ? options.samplerSize / 1e3 : undefined this.autoDepthTest = defaultValue$c(options.autoDepthTest, true) const position = AnalyserUtil.getCartesians(options.mask) this._mask = [] if (position && position.length) { this._mask = [...position, position[0]] } this._type = 'height-analysis' } /** * 采样间距,单位米 */ get samplerSize () { return this._samplerSize * 1000 } set samplerSize (val) { val = parseFloat(val) if (typeof val === 'number') { this._samplerSize = val / 1e3 // this.do(); } } get mask () { return this._mask.slice(0, this._mask.length - 1) } set mask (mask) { const position = AnalyserUtil.getCartesians(mask) if (position && position.length) { this._mask = [...position, position[0]] } } /** * 建议采样个数 */ static suggestGridCount = 300; /** * 开始分析 * @param {Array} 分析高度时需要排除的对象 * @returns {object} 最大高度,最小高度和平均高度 */ do (excludeObject = []) { if (!this._mask.length) { return {} } this.preDo.raise({ id: this._id, mask: this._mask }) const depthTest = viewer.scene.globe.depthTestAgainstTerrain if (depthTest === false && this.autoDepthTest) { viewer.scene.globe.depthTestAgainstTerrain = true } const area = Cartometry.surfaceArea(this._mask) const cellSize = Math.sqrt(area / 1e6 / HeightAnalyser.suggestGridCount) const polygon = AnalyserUtil.getLonLats(this._mask) const samplerSize = this._samplerSize || cellSize const grid = AnalyserUtil.polygonToGrid(polygon, samplerSize) const samplerPoints = grid.features.map(_ => Cartographic$b.fromDegrees(..._.geometry.coordinates)) const { max, min, avg } = computeHeight(samplerPoints, this._viewer, excludeObject) this.postAnalysis.raise({ id: this._id, mask: this._mask, samplerSize: samplerSize * 1e3 }) if (depthTest === false && this.autoDepthTest) { viewer.scene.globe.depthTestAgainstTerrain = depthTest } return { max, min, avg, samplerSize: samplerSize } } } const { Material: Material$k, Color: Color$s, JulianDate: JulianDate$3, Clock } = Cesium Material$k.FloodMaterial = "FloodMaterial" Material$k._materialCache.addMaterial(Material$k.FloodMaterial, { fabric: { type: Material$k.FloodMaterial, uniforms: { color: Color$s.fromCssColorString('rgba(0, 123, 230, 0.5)'), height: 0 }, source: shader$p } }) class FloodAnalyser extends BaseAnalyser { /** * * @param {*} viewer * @param {object} options 具有以下属性 * @param {LonLat[]|Cesium.Cartesian3[]|number[]} options.mask 分析范围 * @param {number} [options.minHeight] 最小高度,如果不指定在开始分析前,会通过插值自动 * @param {number} [options.maxHeight] 最大高度,如果不指定在开始分析前,会通过插值自动 */ constructor(viewer, options = {}) { super(viewer) this._mask = [] const positions = AnalyserUtil.getCartesians(options.mask) if (positions && positions.length) { this._mask = positions const clipRegion = new ClipRegion(this._mask) if (this.clipRegion) { this._viewer.scene.globe.clipRegion.remove(this.clipRegion) } this._viewer.scene.globe.clipRegion.add(clipRegion) this.clipRegion = clipRegion } this._color = defaultValue$c(options.color, 'rgba(0, 123, 230, 0.5)') this._speed = defaultValue$c(options.speed, 1) this.clock = new Clock({ startTime: JulianDate$3.now(), shouldAnimate: true }) this.minHeight = options.minHeight this.maxHeight = options.maxHeight this.currentHeight = undefined this._doing = false this.removeEventListener = viewer.clock.onTick.addEventListener(() => { this.clock.tick() if (!this._doing) { return } if (!this.clipRegion) { return } const currentTime = this.clock.currentTime const seconds = JulianDate$3.secondsDifference(currentTime, this.clock.startTime) const height = seconds * this.speed const currentHeight = this.minHeight + height if (currentHeight >= this.maxHeight) { this._doing = false } this.currentHeight = Math.min(currentHeight, this.maxHeight) viewer.scene.globe.material.uniforms.height = this.currentHeight }) } get multiplier () { return this.clock.multiplier } set multiplier (val) { this.clock.multiplier = val } /** * 淹没区域的颜色 * @type {string} */ get color () { return Color$s.fromCssColorString(this._color) } set color (val) { if (val instanceof Cesium.Color) { this._color = val } } /** * 淹没速度,单位m/s,如果不小于0 */ get speed () { return this._speed } set speed (val) { if (val > 0) { this._speed = val } else { this._speed = 0 } } /** * 分析范围 * @type {LonLat[]|Cesium.Cartesian3[]|number[]} */ get mask () { return this._mask } set mask (val) { const positions = AnalyserUtil.getCartesians(val) if (positions && positions.length) { this._mask = positions const clipRegion = new ClipRegion(this._mask) if (this.clipRegion) { this._viewer.scene.globe.clipRegion.remove(this.clipRegion) } this._viewer.scene.globe.clipRegion.add(clipRegion) this.clipRegion = clipRegion } } calcRegionElevation () { const analyser = new HeightAnalyser(this._viewer, { mask: this.mask }) const v = analyser.do() this.minHeight = v.min this.maxHeight = v.max return { minHeight: this.minHeight, maxHeight: this.maxHeight } } /** * 开始分析 */ do () { if (!this._mask.length) { console.warn('mask must be specified.') return } if (!(typeof this.minHeight === 'number' && typeof this.maxHeight === 'number')) { this.calcRegionElevation() } this.preAnalysis.raise() this.clear() this._doing = true this.clock.startTime = JulianDate$3.now() this._viewer.scene.globe.material = Material$k.fromType('FloodMaterial', { color: this.color }) this.postAnalysis.raise({ minHeight: this.minHeight, maxHeight: this.maxHeight }) return { minHeight: this.minHeight, maxHeight: this.maxHeight } } /** * 暂停/继续 */ pause () { this.clock.shouldAnimate = !this.clock.shouldAnimate } /** * 清除分析结果 */ clear () { this._viewer.scene.globe.material = undefined this.currentHeight = this.minHeight } /** * 对象是否被销毁, * @returns {boolean} true表示对象已经被销毁,其除isDestroyed外所有方法将不能调用 */ isDestroyed () { return false } /** * 销毁对象 */ destroy () { this.clear() this.clipRegion && this._viewer.scene.globe.clipRegion.remove(this.clipRegion) this.clipRegion = undefined this.removeEventListener() destroyObject$a(this) } } class ViewShadowPrimitive { /** * 视域分析图元 * @private * @extends CustomPrimitive * @param {Cesium.ShadowMap} shadowMap 视域阴影 */ constructor(shadowMap) { if (!defined$e(shadowMap)) { throw new CesiumProError$1('parameter shadowMap is required.') } this._shadowMap = shadowMap } /** * 是否渲染该图元 * @type {Bool} */ get show () { return this._show } set show (val) { this._show = val } /** * 场景渲染时scene会自动调用该方法,请勿主动调用。 * @override * @param {FrameState} frameState */ update (frameState) { frameState.shadowMaps.push(this._shadowMap) } /** * 销毁对象并释放WebGL资源 */ destroy () { if (this._shadowMap && !this._shadowMap.isDestroyed()) { this._shadowMap.destroy() } destroyObject$a(this) } } const BoundingRectangle$4 = Cesium.BoundingRectangle const BoundingSphere$9 = Cesium.BoundingSphere const BoxOutlineGeometry = Cesium.BoxOutlineGeometry const Cartesian2$7 = Cesium.Cartesian2 const Cartesian3$m = Cesium.Cartesian3 const Cartesian4$1 = Cesium.Cartesian4 const Cartographic$a = Cesium.Cartographic const Color$r = Cesium.Color const ColorGeometryInstanceAttribute = Cesium.ColorGeometryInstanceAttribute const combine$1 = Cesium.combine const CullingVolume = Cesium.CullingVolume const defaultValue$b = Cesium.defaultValue const defined$c = Cesium.defined const defineProperties$1 = Object.defineProperties const destroyObject$9 = Cesium.destroyObject const DeveloperError$4 = Cesium.DeveloperError const FeatureDetection$1 = Cesium.FeatureDetection const GeometryInstance$4 = Cesium.GeometryInstance const Intersect = Cesium.Intersect const CesiumMath$9 = Cesium.Math const Matrix4$8 = Cesium.Matrix4 const OrthographicOffCenterFrustum$1 = Cesium.OrthographicOffCenterFrustum const PerspectiveFrustum = Cesium.PerspectiveFrustum const PixelFormat$2 = Cesium.PixelFormat const Quaternion$1 = Cesium.Quaternion const SphereOutlineGeometry = Cesium.SphereOutlineGeometry const WebGLConstants$4 = Cesium.WebGLConstants const ClearCommand$2 = Cesium.ClearCommand const ContextLimits = Cesium.ContextLimits const CubeMap$1 = Cesium.CubeMap const DrawCommand$4 = Cesium.DrawCommand const Framebuffer$2 = Cesium.Framebuffer const Pass$4 = Cesium.Pass const PassState$2 = Cesium.PassState const PixelDatatype$2 = Cesium.PixelDatatype const Renderbuffer$1 = Cesium.Renderbuffer const RenderbufferFormat$1 = Cesium.RenderbufferFormat const RenderState$5 = Cesium.RenderState const Sampler$1 = Cesium.Sampler const Texture$3 = Cesium.Texture const TextureMagnificationFilter = Cesium.TextureMagnificationFilter const TextureMinificationFilter = Cesium.TextureMinificationFilter const TextureWrap$1 = Cesium.TextureWrap const Camera$1 = Cesium.Camera const CullFace$1 = Cesium.CullFace const DebugCameraPrimitive = Cesium.DebugCameraPrimitive const PerInstanceColorAppearance = Cesium.PerInstanceColorAppearance const Primitive$7 = Cesium.Primitive const ShadowMapShader = Cesium.ShadowMapShader const ShaderSource$7 = Cesium.ShaderSource /** * Use {@link Viewer#shadowMap} to get the scene's shadow map originating from the sun. Do not construct this directly. * *

* The normalOffset bias pushes the shadows forward slightly, and may be disabled * for applications that require ultra precise shadows. *

* * @alias ViewshedMap * @private * @internalConstructor * @class * * @param {Object} options An object containing the following properties: * @param {Camera} options.lightCamera A camera representing the light source. * @param {Boolean} [options.enabled=true] Whether the shadow map is enabled. * @param {Boolean} [options.isPointLight=false] Whether the light source is a point light. Point light shadows do not use cascades. * @param {Boolean} [options.pointLightRadius=100.0] Radius of the point light. * @param {Boolean} [options.cascadesEnabled=true] Use multiple shadow maps to cover different partitions of the view frustum. * @param {Number} [options.numberOfCascades=4] The number of cascades to use for the shadow map. Supported values are one and four. * @param {Number} [options.maximumDistance=5000.0] The maximum distance used for generating cascaded shadows. Lower values improve shadow quality. * @param {Number} [options.size=2048] The width and height, in pixels, of each shadow map. * @param {Boolean} [options.softShadows=false] Whether percentage-closer-filtering is enabled for producing softer shadows. * @param {Number} [options.darkness=0.3] The shadow darkness. * @param {Boolean} [options.normalOffset=true] Whether a normal bias is applied to shadows. * * @exception {DeveloperError} Only one or four cascades are supported. * * @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=Shadows.html|Cesium Sandcastle Shadows Demo} */ function ViewshedMap (options) { options = defaultValue$b(options, defaultValue$b.EMPTY_OBJECT) // options.context is an undocumented option var context = options.context //>>includeStart('debug', pragmas.debug); if (!defined$c(context)) { throw new DeveloperError$4("context is required.") } if (!defined$c(options.lightCamera)) { throw new DeveloperError$4("lightCamera is required.") } if (defined$c(options.numberOfCascades) && (options.numberOfCascades !== 1 && options.numberOfCascades !== 4)) { throw new DeveloperError$4("Only one or four cascades are supported.") } //>>includeEnd('debug'); this._enabled = defaultValue$b(options.enabled, true) this._softShadows = defaultValue$b(options.softShadows, false) this._normalOffset = defaultValue$b(options.normalOffset, true) this.dirty = true /** * Specifies whether the shadow map originates from a light source. Shadow maps that are used for analytical * purposes should set this to false so as not to affect scene rendering. * * @private */ this.fromLightSource = defaultValue$b(options.fromLightSource, true) /** * Determines the darkness of the shadows. * * @type {Number} * @default 0.3 */ this.darkness = 0.0 this._darkness = this.darkness /** * Determines the maximum distance of the shadow map. Only applicable for cascaded shadows. Larger distances may result in lower quality shadows. * * @type {Number} * @default 5000.0 */ this.maximumDistance = defaultValue$b(options.maximumDistance, 5000.0) this._outOfView = false this._outOfViewPrevious = false this._needsUpdate = true // In IE11 and Edge polygon offset is not functional. // TODO : Also disabled for instances of Firefox and Chrome running ANGLE that do not support depth textures. // Re-enable once https://github.com/AnalyticalGraphicsInc/cesium/issues/4560 is resolved. var polygonOffsetSupported = true if ( FeatureDetection$1.isInternetExplorer() || FeatureDetection$1.isEdge() || ((FeatureDetection$1.isChrome() || FeatureDetection$1.isFirefox()) && FeatureDetection$1.isWindows() && !context.depthTexture) ) { polygonOffsetSupported = false } this._polygonOffsetSupported = polygonOffsetSupported this._terrainBias = { polygonOffset: polygonOffsetSupported, polygonOffsetFactor: 1.1, polygonOffsetUnits: 4.0, normalOffset: this._normalOffset, normalOffsetScale: 0.5, normalShading: true, normalShadingSmooth: 0.3, depthBias: 0.0001 } this._primitiveBias = { polygonOffset: polygonOffsetSupported, polygonOffsetFactor: 1.1, polygonOffsetUnits: 4.0, normalOffset: this._normalOffset, normalOffsetScale: 0.1, normalShading: true, normalShadingSmooth: 0.05, depthBias: 0.00002 } this._pointBias = { polygonOffset: false, polygonOffsetFactor: 1.1, polygonOffsetUnits: 4.0, normalOffset: this._normalOffset, normalOffsetScale: 0.0, normalShading: true, normalShadingSmooth: 0.1, depthBias: 0.0005 } // Framebuffer resources this._depthAttachment = undefined this._colorAttachment = undefined // Uniforms this._shadowMapMatrix = new Matrix4$8() this._shadowMapTexture = undefined this._lightDirectionEC = new Cartesian3$m() this._lightPositionEC = new Cartesian4$1() this._distance = 0.0 this._lightCamera = options.lightCamera this._shadowMapCamera = new ShadowMapCamera() this._shadowMapCullingVolume = undefined this._sceneCamera = undefined // this._boundingSphere = new BoundingSphere(); this._boundingSphere = defaultValue$b(options.boundingSphere, new BoundingSphere$9()) this._isPointLight = defaultValue$b(options.isPointLight, false) this._pointLightRadius = defaultValue$b(options.pointLightRadius, 100.0) this._cascadesEnabled = false this._numberOfCascades = !this._cascadesEnabled ? 0 : defaultValue$b(options.numberOfCascades, 4) this._fitNearFar = true this._maximumCascadeDistances = [25.0, 150.0, 700.0, Number.MAX_VALUE] this._textureSize = new Cartesian2$7() this._isSpotLight = false if (this._cascadesEnabled) { // Cascaded shadows are always orthographic. The frustum dimensions are calculated on the fly. this._shadowMapCamera.frustum = new OrthographicOffCenterFrustum$1() } else if (defined$c(this._lightCamera.frustum.fov)) { // If the light camera uses a perspective frustum, then the light source is a spot light this._isSpotLight = true } // Uniforms this._cascadeSplits = [new Cartesian4$1(), new Cartesian4$1()] this._cascadeMatrices = [new Matrix4$8(), new Matrix4$8(), new Matrix4$8(), new Matrix4$8()] this._cascadeDistances = new Cartesian4$1() var numberOfPasses if (this._isPointLight) { numberOfPasses = 6 // One shadow map for each direction } else if (!this._cascadesEnabled) { numberOfPasses = 1 } else { numberOfPasses = this._numberOfCascades } this._passes = new Array(numberOfPasses) for (var i = 0; i < numberOfPasses; ++i) { this._passes[i] = new ShadowPass(context) } this.debugShow = false this.debugFreezeFrame = false this._debugFreezeFrame = false this._debugCascadeColors = false this._debugLightFrustum = undefined this._debugCameraFrustum = undefined this._debugCascadeFrustums = new Array(this._numberOfCascades) this._debugShadowViewCommand = undefined this._usesDepthTexture = context.depthTexture if (this._isPointLight) { this._usesDepthTexture = false } // Create render states for shadow casters this._primitiveRenderState = undefined this._terrainRenderState = undefined this._pointRenderState = undefined createRenderStates(this) // For clearing the shadow map texture every frame this._clearCommand = new ClearCommand$2({ depth: 1.0, color: new Color$r() }) this._clearPassState = new PassState$2(context) this._size = defaultValue$b(options.size, 2048) this.size = this._size } /** * Global maximum shadow distance used to prevent far off receivers from extending * the shadow far plane. This helps set a tighter near/far when viewing objects from space. * * @private */ ViewshedMap.MAXIMUM_DISTANCE = 20000.0 function ShadowPass (context) { this.camera = new ShadowMapCamera() this.passState = new PassState$2(context) this.framebuffer = undefined this.textureOffsets = undefined this.commandList = [] this.cullingVolume = undefined } function createRenderState$1 (colorMask, bias) { return RenderState$5.fromCache({ cull: { enabled: true, face: CullFace$1.BACK }, depthTest: { enabled: true }, colorMask: { red: colorMask, green: colorMask, blue: colorMask, alpha: colorMask }, depthMask: true, polygonOffset: { enabled: bias.polygonOffset, factor: bias.polygonOffsetFactor, units: bias.polygonOffsetUnits } }) } function createRenderStates (shadowMap) { // Enable the color mask if the shadow map is backed by a color texture, e.g. when depth textures aren't supported var colorMask = !shadowMap._usesDepthTexture shadowMap._primitiveRenderState = createRenderState$1(colorMask, shadowMap._primitiveBias) shadowMap._terrainRenderState = createRenderState$1(colorMask, shadowMap._terrainBias) shadowMap._pointRenderState = createRenderState$1(colorMask, shadowMap._pointBias) } /** * @private */ ViewshedMap.prototype.debugCreateRenderStates = function () { createRenderStates(this) } defineProperties$1(ViewshedMap.prototype, { /** * Determines if the shadow map will be shown. * * @memberof ViewshedMap.prototype * @type {Boolean} * @default true */ enabled: { get: function () { return this._enabled }, set: function (value) { this.dirty = this._enabled !== value this._enabled = value } }, isViewShed: { get: function () { return true } }, /** * Determines if a normal bias will be applied to shadows. * * @memberof ViewshedMap.prototype * @type {Boolean} * @default true */ normalOffset: { get: function () { return this._normalOffset }, set: function (value) { this.dirty = this._normalOffset !== value this._normalOffset = value this._terrainBias.normalOffset = value this._primitiveBias.normalOffset = value this._pointBias.normalOffset = value } }, /** * Determines if soft shadows are enabled. Uses pcf filtering which requires more texture reads and may hurt performance. * * @memberof ViewshedMap.prototype * @type {Boolean} * @default false */ softShadows: { get: function () { return this._softShadows }, set: function (value) { this.dirty = this._softShadows !== value this._softShadows = value } }, /** * The width and height, in pixels, of each shadow map. * * @memberof ViewshedMap.prototype * @type {Number} * @default 2048 */ size: { get: function () { return this._size }, set: function (value) { resize(this, value) } }, /** * Whether the shadow map is out of view of the scene camera. * * @memberof ViewshedMap.prototype * @type {Boolean} * @readonly * @private */ outOfView: { get: function () { return this._outOfView } }, /** * The culling volume of the shadow frustum. * * @memberof ViewshedMap.prototype * @type {CullingVolume} * @readonly * @private */ shadowMapCullingVolume: { get: function () { return this._shadowMapCullingVolume } }, /** * The passes used for rendering shadows. Each face of a point light or each cascade for a cascaded shadow map is a separate pass. * * @memberof ViewshedMap.prototype * @type {ShadowPass[]} * @readonly * @private */ passes: { get: function () { return this._passes } }, /** * Whether the light source is a point light. * * @memberof ViewshedMap.prototype * @type {Boolean} * @readonly * @private */ isPointLight: { get: function () { return this._isPointLight } }, /** * Debug option for visualizing the cascades by color. * * @memberof ViewshedMap.prototype * @type {Boolean} * @default false * @private */ debugCascadeColors: { get: function () { return this._debugCascadeColors }, set: function (value) { this.dirty = this._debugCascadeColors !== value this._debugCascadeColors = value } } }) function destroyFramebuffer (shadowMap) { var length = shadowMap._passes.length for (var i = 0; i < length; ++i) { var pass = shadowMap._passes[i] var framebuffer = pass.framebuffer if (defined$c(framebuffer) && !framebuffer.isDestroyed()) { framebuffer.destroy() } pass.framebuffer = undefined } // Destroy the framebuffer attachments shadowMap._depthAttachment = shadowMap._depthAttachment && shadowMap._depthAttachment.destroy() shadowMap._colorAttachment = shadowMap._colorAttachment && shadowMap._colorAttachment.destroy() } function createSampler () { return new Sampler$1({ wrapS: TextureWrap$1.CLAMP_TO_EDGE, wrapT: TextureWrap$1.CLAMP_TO_EDGE, minificationFilter: TextureMinificationFilter.NEAREST, magnificationFilter: TextureMagnificationFilter.NEAREST }) } function createFramebufferColor (shadowMap, context) { var depthRenderbuffer = new Renderbuffer$1({ context: context, width: shadowMap._textureSize.x, height: shadowMap._textureSize.y, format: RenderbufferFormat$1.DEPTH_COMPONENT16 }) var colorTexture = new Texture$3({ context: context, width: shadowMap._textureSize.x, height: shadowMap._textureSize.y, pixelFormat: PixelFormat$2.RGBA, pixelDatatype: PixelDatatype$2.UNSIGNED_BYTE, sampler: createSampler() }) var framebuffer = new Framebuffer$2({ context: context, depthRenderbuffer: depthRenderbuffer, colorTextures: [colorTexture], destroyAttachments: false }) var length = shadowMap._passes.length for (var i = 0; i < length; ++i) { var pass = shadowMap._passes[i] pass.framebuffer = framebuffer pass.passState.framebuffer = framebuffer } shadowMap._shadowMapTexture = colorTexture shadowMap._depthAttachment = depthRenderbuffer shadowMap._colorAttachment = colorTexture } function createFramebufferDepth (shadowMap, context) { var depthStencilTexture = new Texture$3({ context: context, width: shadowMap._textureSize.x, height: shadowMap._textureSize.y, pixelFormat: PixelFormat$2.DEPTH_STENCIL, pixelDatatype: PixelDatatype$2.UNSIGNED_INT_24_8, sampler: createSampler() }) var framebuffer = new Framebuffer$2({ context: context, depthStencilTexture: depthStencilTexture, destroyAttachments: false }) var length = shadowMap._passes.length for (var i = 0; i < length; ++i) { var pass = shadowMap._passes[i] pass.framebuffer = framebuffer pass.passState.framebuffer = framebuffer } shadowMap._shadowMapTexture = depthStencilTexture shadowMap._depthAttachment = depthStencilTexture } function createFramebufferCube (shadowMap, context) { var depthRenderbuffer = new Renderbuffer$1({ context: context, width: shadowMap._textureSize.x, height: shadowMap._textureSize.y, format: RenderbufferFormat$1.DEPTH_COMPONENT16 }) var cubeMap = new CubeMap$1({ context: context, width: shadowMap._textureSize.x, height: shadowMap._textureSize.y, pixelFormat: PixelFormat$2.RGBA, pixelDatatype: PixelDatatype$2.UNSIGNED_BYTE, sampler: createSampler() }) var faces = [ cubeMap.negativeX, cubeMap.negativeY, cubeMap.negativeZ, cubeMap.positiveX, cubeMap.positiveY, cubeMap.positiveZ ] for (var i = 0; i < 6; ++i) { var framebuffer = new Framebuffer$2({ context: context, depthRenderbuffer: depthRenderbuffer, colorTextures: [faces[i]], destroyAttachments: false }) var pass = shadowMap._passes[i] pass.framebuffer = framebuffer pass.passState.framebuffer = framebuffer } shadowMap._shadowMapTexture = cubeMap shadowMap._depthAttachment = depthRenderbuffer shadowMap._colorAttachment = cubeMap } function createFramebuffer$1 (shadowMap, context) { if (shadowMap._isPointLight) { createFramebufferCube(shadowMap, context) } else if (shadowMap._usesDepthTexture) { createFramebufferDepth(shadowMap, context) } else { createFramebufferColor(shadowMap, context) } } function checkFramebuffer (shadowMap, context) { // Attempt to make an FBO with only a depth texture. If it fails, fallback to a color texture. if ( shadowMap._usesDepthTexture && shadowMap._passes[0].framebuffer.status !== WebGLConstants$4.FRAMEBUFFER_COMPLETE ) { shadowMap._usesDepthTexture = false createRenderStates(shadowMap) destroyFramebuffer(shadowMap) createFramebuffer$1(shadowMap, context) } } function updateFramebuffer$1 (shadowMap, context) { if (!defined$c(shadowMap._passes[0].framebuffer) || shadowMap._shadowMapTexture.width !== shadowMap._textureSize.x) { destroyFramebuffer(shadowMap) createFramebuffer$1(shadowMap, context) checkFramebuffer(shadowMap, context) clearFramebuffer(shadowMap, context) } } function clearFramebuffer (shadowMap, context, shadowPass) { shadowPass = defaultValue$b(shadowPass, 0) if (shadowMap._isPointLight || shadowPass === 0) { shadowMap._clearCommand.framebuffer = shadowMap._passes[shadowPass].framebuffer shadowMap._clearCommand.execute(context, shadowMap._clearPassState) } } function resize (shadowMap, size) { shadowMap._size = size var passes = shadowMap._passes var numberOfPasses = passes.length var textureSize = shadowMap._textureSize if (shadowMap._isPointLight) { size = ContextLimits.maximumCubeMapSize >= size ? size : ContextLimits.maximumCubeMapSize textureSize.x = size textureSize.y = size var faceViewport = new BoundingRectangle$4(0, 0, size, size) passes[0].passState.viewport = faceViewport passes[1].passState.viewport = faceViewport passes[2].passState.viewport = faceViewport passes[3].passState.viewport = faceViewport passes[4].passState.viewport = faceViewport passes[5].passState.viewport = faceViewport } else if (numberOfPasses === 1) { // +----+ // | 1 | // +----+ size = ContextLimits.maximumTextureSize >= size ? size : ContextLimits.maximumTextureSize textureSize.x = size textureSize.y = size passes[0].passState.viewport = new BoundingRectangle$4(0, 0, size, size) } else if (numberOfPasses === 4) { // +----+----+ // | 3 | 4 | // +----+----+ // | 1 | 2 | // +----+----+ size = ContextLimits.maximumTextureSize >= size * 2 ? size : ContextLimits.maximumTextureSize / 2 textureSize.x = size * 2 textureSize.y = size * 2 passes[0].passState.viewport = new BoundingRectangle$4(0, 0, size, size) passes[1].passState.viewport = new BoundingRectangle$4(size, 0, size, size) passes[2].passState.viewport = new BoundingRectangle$4(0, size, size, size) passes[3].passState.viewport = new BoundingRectangle$4(size, size, size, size) } // Update clear pass state shadowMap._clearPassState.viewport = new BoundingRectangle$4(0, 0, textureSize.x, textureSize.y) // Transforms shadow coordinates [0, 1] into the pass's region of the texture for (var i = 0; i < numberOfPasses; ++i) { var pass = passes[i] var viewport = pass.passState.viewport var biasX = viewport.x / textureSize.x var biasY = viewport.y / textureSize.y var scaleX = viewport.width / textureSize.x var scaleY = viewport.height / textureSize.y pass.textureOffsets = new Matrix4$8( scaleX, 0.0, 0.0, biasX, 0.0, scaleY, 0.0, biasY, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ) } } var scratchViewport = new BoundingRectangle$4() function createDebugShadowViewCommand (shadowMap, context) { var fs if (shadowMap._isPointLight) { fs = "uniform samplerCube shadowMap_textureCube; \n" + "varying vec2 v_textureCoordinates; \n" + "void main() \n" + "{ \n" + " vec2 uv = v_textureCoordinates; \n" + " vec3 dir; \n" + " \n" + " if (uv.y < 0.5) \n" + " { \n" + " if (uv.x < 0.333) \n" + " { \n" + " dir.x = -1.0; \n" + " dir.y = uv.x * 6.0 - 1.0; \n" + " dir.z = uv.y * 4.0 - 1.0; \n" + " } \n" + " else if (uv.x < 0.666) \n" + " { \n" + " dir.y = -1.0; \n" + " dir.x = uv.x * 6.0 - 3.0; \n" + " dir.z = uv.y * 4.0 - 1.0; \n" + " } \n" + " else \n" + " { \n" + " dir.z = -1.0; \n" + " dir.x = uv.x * 6.0 - 5.0; \n" + " dir.y = uv.y * 4.0 - 1.0; \n" + " } \n" + " } \n" + " else \n" + " { \n" + " if (uv.x < 0.333) \n" + " { \n" + " dir.x = 1.0; \n" + " dir.y = uv.x * 6.0 - 1.0; \n" + " dir.z = uv.y * 4.0 - 3.0; \n" + " } \n" + " else if (uv.x < 0.666) \n" + " { \n" + " dir.y = 1.0; \n" + " dir.x = uv.x * 6.0 - 3.0; \n" + " dir.z = uv.y * 4.0 - 3.0; \n" + " } \n" + " else \n" + " { \n" + " dir.z = 1.0; \n" + " dir.x = uv.x * 6.0 - 5.0; \n" + " dir.y = uv.y * 4.0 - 3.0; \n" + " } \n" + " } \n" + " \n" + " float shadow = czm_unpackDepth(textureCube(shadowMap_textureCube, dir)); \n" + " gl_FragColor = vec4(vec3(shadow), 1.0); \n" + "} \n" } else { fs = "uniform sampler2D shadowMap_texture; \n" + "varying vec2 v_textureCoordinates; \n" + "void main() \n" + "{ \n" + (shadowMap._usesDepthTexture ? " float shadow = texture2D(shadowMap_texture, v_textureCoordinates).r; \n" : " float shadow = czm_unpackDepth(texture2D(shadowMap_texture, v_textureCoordinates)); \n") + " gl_FragColor = vec4(vec3(shadow), 1.0); \n" + "} \n" } var drawCommand = context.createViewportQuadCommand(fs, { uniformMap: { shadowMap_texture: function () { return shadowMap._shadowMapTexture }, shadowMap_textureCube: function () { return shadowMap._shadowMapTexture } } }) drawCommand.pass = Pass$4.OVERLAY return drawCommand } function updateDebugShadowViewCommand (shadowMap, frameState) { // Draws the shadow map on the bottom-right corner of the screen var context = frameState.context var screenWidth = frameState.context.drawingBufferWidth var screenHeight = frameState.context.drawingBufferHeight var size = Math.min(screenWidth, screenHeight) * 0.3 var viewport = scratchViewport viewport.x = screenWidth - size viewport.y = 0 viewport.width = size viewport.height = size var debugCommand = shadowMap._debugShadowViewCommand if (!defined$c(debugCommand)) { debugCommand = createDebugShadowViewCommand(shadowMap, context) shadowMap._debugShadowViewCommand = debugCommand } // Get a new RenderState for the updated viewport size if (!defined$c(debugCommand.renderState) || !BoundingRectangle$4.equals(debugCommand.renderState.viewport, viewport)) { debugCommand.renderState = RenderState$5.fromCache({ viewport: BoundingRectangle$4.clone(viewport) }) } frameState.commandList.push(shadowMap._debugShadowViewCommand) } var frustumCornersNDC = new Array(8) frustumCornersNDC[0] = new Cartesian4$1(-1.0, -1.0, -1.0, 1.0) frustumCornersNDC[1] = new Cartesian4$1(1.0, -1.0, -1.0, 1.0) frustumCornersNDC[2] = new Cartesian4$1(1.0, 1.0, -1.0, 1.0) frustumCornersNDC[3] = new Cartesian4$1(-1.0, 1.0, -1.0, 1.0) frustumCornersNDC[4] = new Cartesian4$1(-1.0, -1.0, 1.0, 1.0) frustumCornersNDC[5] = new Cartesian4$1(1.0, -1.0, 1.0, 1.0) frustumCornersNDC[6] = new Cartesian4$1(1.0, 1.0, 1.0, 1.0) frustumCornersNDC[7] = new Cartesian4$1(-1.0, 1.0, 1.0, 1.0) var scratchMatrix = new Matrix4$8() var scratchFrustumCorners = new Array(8) for (var i = 0; i < 8; ++i) { scratchFrustumCorners[i] = new Cartesian4$1() } function createDebugPointLight (modelMatrix, color) { var box = new GeometryInstance$4({ geometry: new BoxOutlineGeometry({ minimum: new Cartesian3$m(-0.5, -0.5, -0.5), maximum: new Cartesian3$m(0.5, 0.5, 0.5) }), attributes: { color: ColorGeometryInstanceAttribute.fromColor(color) } }) var sphere = new GeometryInstance$4({ geometry: new SphereOutlineGeometry({ radius: 0.5 }), attributes: { color: ColorGeometryInstanceAttribute.fromColor(color) } }) return new Primitive$7({ geometryInstances: [box, sphere], appearance: new PerInstanceColorAppearance({ translucent: false, flat: true }), asynchronous: false, modelMatrix: modelMatrix }) } var debugOutlineColors = [Color$r.RED, Color$r.GREEN, Color$r.BLUE, Color$r.MAGENTA] var scratchScale = new Cartesian3$m() function applyDebugSettings (shadowMap, frameState) { updateDebugShadowViewCommand(shadowMap, frameState) var enterFreezeFrame = shadowMap.debugFreezeFrame && !shadowMap._debugFreezeFrame shadowMap._debugFreezeFrame = shadowMap.debugFreezeFrame // Draw scene camera in freeze frame mode if (shadowMap.debugFreezeFrame) { if (enterFreezeFrame) { // Recreate debug camera when entering freeze frame mode shadowMap._debugCameraFrustum = shadowMap._debugCameraFrustum && shadowMap._debugCameraFrustum.destroy() shadowMap._debugCameraFrustum = new DebugCameraPrimitive({ camera: shadowMap._sceneCamera, color: Color$r.CYAN, updateOnChange: false }) } shadowMap._debugCameraFrustum.update(frameState) } if (shadowMap._cascadesEnabled) { // Draw cascades only in freeze frame mode if (shadowMap.debugFreezeFrame) { if (enterFreezeFrame) { // Recreate debug frustum when entering freeze frame mode shadowMap._debugLightFrustum = shadowMap._debugLightFrustum && shadowMap._debugLightFrustum.destroy() shadowMap._debugLightFrustum = new DebugCameraPrimitive({ camera: shadowMap._shadowMapCamera, color: Color$r.YELLOW, updateOnChange: false }) } shadowMap._debugLightFrustum.update(frameState) for (var i = 0; i < shadowMap._numberOfCascades; ++i) { if (enterFreezeFrame) { // Recreate debug frustum when entering freeze frame mode shadowMap._debugCascadeFrustums[i] = shadowMap._debugCascadeFrustums[i] && shadowMap._debugCascadeFrustums[i].destroy() shadowMap._debugCascadeFrustums[i] = new DebugCameraPrimitive({ camera: shadowMap._passes[i].camera, color: debugOutlineColors[i], updateOnChange: false }) } shadowMap._debugCascadeFrustums[i].update(frameState) } } } else if (shadowMap._isPointLight) { if (!defined$c(shadowMap._debugLightFrustum) || shadowMap._needsUpdate) { var translation = shadowMap._shadowMapCamera.positionWC var rotation = Quaternion$1.IDENTITY var uniformScale = shadowMap._pointLightRadius * 2.0 var scale = Cartesian3$m.fromElements(uniformScale, uniformScale, uniformScale, scratchScale) var modelMatrix = Matrix4$8.fromTranslationQuaternionRotationScale( translation, rotation, scale, scratchMatrix ) shadowMap._debugLightFrustum = shadowMap._debugLightFrustum && shadowMap._debugLightFrustum.destroy() shadowMap._debugLightFrustum = createDebugPointLight(modelMatrix, Color$r.YELLOW) } shadowMap._debugLightFrustum.update(frameState) } else { if (!defined$c(shadowMap._debugLightFrustum) || shadowMap._needsUpdate) { shadowMap._debugLightFrustum = new DebugCameraPrimitive({ camera: shadowMap._shadowMapCamera, color: Color$r.YELLOW, updateOnChange: false }) } shadowMap._debugLightFrustum.update(frameState) } } function ShadowMapCamera () { this.viewMatrix = new Matrix4$8() this.inverseViewMatrix = new Matrix4$8() this.frustum = undefined this.positionCartographic = new Cartographic$a() this.positionWC = new Cartesian3$m() this.directionWC = Cartesian3$m.clone(Cartesian3$m.UNIT_Z) this.upWC = Cartesian3$m.clone(Cartesian3$m.UNIT_Y) this.rightWC = Cartesian3$m.clone(Cartesian3$m.UNIT_X) this.viewProjectionMatrix = new Matrix4$8() } ShadowMapCamera.prototype.clone = function (camera) { Matrix4$8.clone(camera.viewMatrix, this.viewMatrix) Matrix4$8.clone(camera.inverseViewMatrix, this.inverseViewMatrix) this.frustum = camera.frustum.clone(this.frustum) Cartographic$a.clone(camera.positionCartographic, this.positionCartographic) Cartesian3$m.clone(camera.positionWC, this.positionWC) Cartesian3$m.clone(camera.directionWC, this.directionWC) Cartesian3$m.clone(camera.upWC, this.upWC) Cartesian3$m.clone(camera.rightWC, this.rightWC) } // Converts from NDC space to texture space var scaleBiasMatrix = new Matrix4$8(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0) ShadowMapCamera.prototype.getViewProjection = function () { var view = this.viewMatrix var projection = this.frustum.projectionMatrix Matrix4$8.multiply(projection, view, this.viewProjectionMatrix) Matrix4$8.multiply(scaleBiasMatrix, this.viewProjectionMatrix, this.viewProjectionMatrix) return this.viewProjectionMatrix } var scratchSplits = new Array(5) var scratchFrustum = new PerspectiveFrustum() var scratchCascadeDistances = new Array(4) var scratchMin = new Cartesian3$m() var scratchMax = new Cartesian3$m() function computeCascades (shadowMap, frameState) { var shadowMapCamera = shadowMap._shadowMapCamera var sceneCamera = shadowMap._sceneCamera var cameraNear = sceneCamera.frustum.near var cameraFar = sceneCamera.frustum.far var numberOfCascades = shadowMap._numberOfCascades // Split cascades. Use a mix of linear and log splits. var i var range = cameraFar - cameraNear var ratio = cameraFar / cameraNear var lambda = 0.9 var clampCascadeDistances = false // When the camera is close to a relatively small model, provide more detail in the closer cascades. // If the camera is near or inside a large model, such as the root tile of a city, then use the default values. // To get the most accurate cascade splits we would need to find the min and max values from the depth texture. if (frameState.shadowState.closestObjectSize < 200.0) { clampCascadeDistances = true lambda = 0.9 } var cascadeDistances = scratchCascadeDistances var splits = scratchSplits splits[0] = cameraNear splits[numberOfCascades] = cameraFar // Find initial splits for (i = 0; i < numberOfCascades; ++i) { var p = (i + 1) / numberOfCascades var logScale = cameraNear * Math.pow(ratio, p) var uniformScale = cameraNear + range * p var split = CesiumMath$9.lerp(uniformScale, logScale, lambda) splits[i + 1] = split cascadeDistances[i] = split - splits[i] } if (clampCascadeDistances) { // Clamp each cascade to its maximum distance for (i = 0; i < numberOfCascades; ++i) { cascadeDistances[i] = Math.min(cascadeDistances[i], shadowMap._maximumCascadeDistances[i]) } // Recompute splits var distance = splits[0] for (i = 0; i < numberOfCascades - 1; ++i) { distance += cascadeDistances[i] splits[i + 1] = distance } } Cartesian4$1.unpack(splits, 0, shadowMap._cascadeSplits[0]) Cartesian4$1.unpack(splits, 1, shadowMap._cascadeSplits[1]) Cartesian4$1.unpack(cascadeDistances, 0, shadowMap._cascadeDistances) var shadowFrustum = shadowMapCamera.frustum var left = shadowFrustum.left var right = shadowFrustum.right var bottom = shadowFrustum.bottom var top = shadowFrustum.top var near = shadowFrustum.near var far = shadowFrustum.far var position = shadowMapCamera.positionWC var direction = shadowMapCamera.directionWC var up = shadowMapCamera.upWC var cascadeSubFrustum = sceneCamera.frustum.clone(scratchFrustum) var shadowViewProjection = shadowMapCamera.getViewProjection() for (i = 0; i < numberOfCascades; ++i) { // Find the bounding box of the camera sub-frustum in shadow map texture space cascadeSubFrustum.near = splits[i] cascadeSubFrustum.far = splits[i + 1] var viewProjection = Matrix4$8.multiply( cascadeSubFrustum.projectionMatrix, sceneCamera.viewMatrix, scratchMatrix ) var inverseViewProjection = Matrix4$8.inverse(viewProjection, scratchMatrix) var shadowMapMatrix = Matrix4$8.multiply(shadowViewProjection, inverseViewProjection, scratchMatrix) // Project each corner from camera NDC space to shadow map texture space. Min and max will be from 0 to 1. var min = Cartesian3$m.fromElements(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, scratchMin) var max = Cartesian3$m.fromElements(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, scratchMax) for (var k = 0; k < 8; ++k) { var corner = Cartesian4$1.clone(frustumCornersNDC[k], scratchFrustumCorners[k]) Matrix4$8.multiplyByVector(shadowMapMatrix, corner, corner) Cartesian3$m.divideByScalar(corner, corner.w, corner) // Handle the perspective divide Cartesian3$m.minimumByComponent(corner, min, min) Cartesian3$m.maximumByComponent(corner, max, max) } // Limit light-space coordinates to the [0, 1] range min.x = Math.max(min.x, 0.0) min.y = Math.max(min.y, 0.0) min.z = 0.0 // Always start cascade frustum at the top of the light frustum to capture objects in the light's path max.x = Math.min(max.x, 1.0) max.y = Math.min(max.y, 1.0) max.z = Math.min(max.z, 1.0) var pass = shadowMap._passes[i] var cascadeCamera = pass.camera cascadeCamera.clone(shadowMapCamera) // PERFORMANCE_IDEA : could do a shallow clone for all properties except the frustum var frustum = cascadeCamera.frustum frustum.left = left + min.x * (right - left) frustum.right = left + max.x * (right - left) frustum.bottom = bottom + min.y * (top - bottom) frustum.top = bottom + max.y * (top - bottom) frustum.near = near + min.z * (far - near) frustum.far = near + max.z * (far - near) pass.cullingVolume = cascadeCamera.frustum.computeCullingVolume(position, direction, up) // Transforms from eye space to the cascade's texture space var cascadeMatrix = shadowMap._cascadeMatrices[i] Matrix4$8.multiply(cascadeCamera.getViewProjection(), sceneCamera.inverseViewMatrix, cascadeMatrix) Matrix4$8.multiply(pass.textureOffsets, cascadeMatrix, cascadeMatrix) } } var scratchLightView = new Matrix4$8() var scratchRight = new Cartesian3$m() var scratchUp = new Cartesian3$m() var scratchTranslation = new Cartesian3$m() function fitShadowMapToScene (shadowMap, frameState) { var shadowMapCamera = shadowMap._shadowMapCamera var sceneCamera = shadowMap._sceneCamera // 1. First find a tight bounding box in light space that contains the entire camera frustum. var viewProjection = Matrix4$8.multiply(sceneCamera.frustum.projectionMatrix, sceneCamera.viewMatrix, scratchMatrix) var inverseViewProjection = Matrix4$8.inverse(viewProjection, scratchMatrix) // Start to construct the light view matrix. Set translation later once the bounding box is found. var lightDir = shadowMapCamera.directionWC var lightUp = sceneCamera.directionWC // Align shadows to the camera view. var lightRight = Cartesian3$m.cross(lightDir, lightUp, scratchRight) lightUp = Cartesian3$m.cross(lightRight, lightDir, scratchUp) // Recalculate up now that right is derived Cartesian3$m.normalize(lightUp, lightUp) Cartesian3$m.normalize(lightRight, lightRight) var lightPosition = Cartesian3$m.fromElements(0.0, 0.0, 0.0, scratchTranslation) var lightView = Matrix4$8.computeView(lightPosition, lightDir, lightUp, lightRight, scratchLightView) var cameraToLight = Matrix4$8.multiply(lightView, inverseViewProjection, scratchMatrix) // Project each corner from NDC space to light view space, and calculate a min and max in light view space var min = Cartesian3$m.fromElements(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE, scratchMin) var max = Cartesian3$m.fromElements(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE, scratchMax) for (var i = 0; i < 8; ++i) { var corner = Cartesian4$1.clone(frustumCornersNDC[i], scratchFrustumCorners[i]) Matrix4$8.multiplyByVector(cameraToLight, corner, corner) Cartesian3$m.divideByScalar(corner, corner.w, corner) // Handle the perspective divide Cartesian3$m.minimumByComponent(corner, min, min) Cartesian3$m.maximumByComponent(corner, max, max) } // 2. Set bounding box back to include objects in the light's view max.z += 1000.0 // Note: in light space, a positive number is behind the camera min.z -= 10.0 // Extend the shadow volume forward slightly to avoid problems right at the edge // 3. Adjust light view matrix so that it is centered on the bounding volume var translation = scratchTranslation translation.x = -(0.5 * (min.x + max.x)) translation.y = -(0.5 * (min.y + max.y)) translation.z = -max.z var translationMatrix = Matrix4$8.fromTranslation(translation, scratchMatrix) lightView = Matrix4$8.multiply(translationMatrix, lightView, lightView) // 4. Create an orthographic frustum that covers the bounding box extents var halfWidth = 0.5 * (max.x - min.x) var halfHeight = 0.5 * (max.y - min.y) var depth = max.z - min.z var frustum = shadowMapCamera.frustum frustum.left = -halfWidth frustum.right = halfWidth frustum.bottom = -halfHeight frustum.top = halfHeight frustum.near = 0.01 frustum.far = depth // 5. Update the shadow map camera Matrix4$8.clone(lightView, shadowMapCamera.viewMatrix) Matrix4$8.inverse(lightView, shadowMapCamera.inverseViewMatrix) Matrix4$8.getTranslation(shadowMapCamera.inverseViewMatrix, shadowMapCamera.positionWC) frameState.mapProjection.ellipsoid.cartesianToCartographic( shadowMapCamera.positionWC, shadowMapCamera.positionCartographic ) Cartesian3$m.clone(lightDir, shadowMapCamera.directionWC) Cartesian3$m.clone(lightUp, shadowMapCamera.upWC) Cartesian3$m.clone(lightRight, shadowMapCamera.rightWC) } var directions = [ new Cartesian3$m(-1.0, 0.0, 0.0), new Cartesian3$m(0.0, -1.0, 0.0), new Cartesian3$m(0.0, 0.0, -1.0), new Cartesian3$m(1.0, 0.0, 0.0), new Cartesian3$m(0.0, 1.0, 0.0), new Cartesian3$m(0.0, 0.0, 1.0) ] var ups = [ new Cartesian3$m(0.0, -1.0, 0.0), new Cartesian3$m(0.0, 0.0, -1.0), new Cartesian3$m(0.0, -1.0, 0.0), new Cartesian3$m(0.0, -1.0, 0.0), new Cartesian3$m(0.0, 0.0, 1.0), new Cartesian3$m(0.0, -1.0, 0.0) ] var rights = [ new Cartesian3$m(0.0, 0.0, 1.0), new Cartesian3$m(1.0, 0.0, 0.0), new Cartesian3$m(-1.0, 0.0, 0.0), new Cartesian3$m(0.0, 0.0, -1.0), new Cartesian3$m(1.0, 0.0, 0.0), new Cartesian3$m(1.0, 0.0, 0.0) ] function computeOmnidirectional (shadowMap, frameState) { // All sides share the same frustum var frustum = new PerspectiveFrustum() frustum.fov = CesiumMath$9.PI_OVER_TWO frustum.near = 1.0 frustum.far = shadowMap._pointLightRadius frustum.aspectRatio = 1.0 for (var i = 0; i < 6; ++i) { var camera = shadowMap._passes[i].camera camera.positionWC = shadowMap._shadowMapCamera.positionWC camera.positionCartographic = frameState.mapProjection.ellipsoid.cartesianToCartographic( camera.positionWC, camera.positionCartographic ) camera.directionWC = directions[i] camera.upWC = ups[i] camera.rightWC = rights[i] Matrix4$8.computeView(camera.positionWC, camera.directionWC, camera.upWC, camera.rightWC, camera.viewMatrix) Matrix4$8.inverse(camera.viewMatrix, camera.inverseViewMatrix) camera.frustum = frustum } } var scratchCartesian1 = new Cartesian3$m() var scratchCartesian2 = new Cartesian3$m() var scratchBoundingSphere = new BoundingSphere$9() var scratchCenter = scratchBoundingSphere.center function checkVisibility (shadowMap, frameState) { var sceneCamera = shadowMap._sceneCamera var shadowMapCamera = shadowMap._shadowMapCamera var boundingSphere = scratchBoundingSphere // Check whether the shadow map is in view and needs to be updated if (shadowMap._cascadesEnabled) { // If the nearest shadow receiver is further than the shadow map's maximum distance then the shadow map is out of view. if (sceneCamera.frustum.near >= shadowMap.maximumDistance) { shadowMap._outOfView = true shadowMap._needsUpdate = false return } // If the light source is below the horizon then the shadow map is out of view var surfaceNormal = frameState.mapProjection.ellipsoid.geodeticSurfaceNormal( sceneCamera.positionWC, scratchCartesian1 ) var lightDirection = Cartesian3$m.negate(shadowMapCamera.directionWC, scratchCartesian2) var dot = Cartesian3$m.dot(surfaceNormal, lightDirection) // Shadows start to fade out once the light gets closer to the horizon. // At this point the globe uses vertex lighting alone to darken the surface. var darknessAmount = CesiumMath$9.clamp(dot / 0.1, 0.0, 1.0) shadowMap._darkness = CesiumMath$9.lerp(1.0, shadowMap.darkness, darknessAmount) if (dot < 0.0) { shadowMap._outOfView = true shadowMap._needsUpdate = false return } // By default cascaded shadows need to update and are always in view shadowMap._needsUpdate = true shadowMap._outOfView = false } else if (shadowMap._isPointLight) { // Sphere-frustum intersection test boundingSphere.center = shadowMapCamera.positionWC boundingSphere.radius = shadowMap._pointLightRadius shadowMap._outOfView = frameState.cullingVolume.computeVisibility(boundingSphere) === Intersect.OUTSIDE shadowMap._needsUpdate = !shadowMap._outOfView && !shadowMap._boundingSphere.equals(boundingSphere) BoundingSphere$9.clone(boundingSphere, shadowMap._boundingSphere) } else { // Simplify frustum-frustum intersection test as a sphere-frustum test var frustumRadius = shadowMapCamera.frustum.far / 2.0 var frustumCenter = Cartesian3$m.add( shadowMapCamera.positionWC, Cartesian3$m.multiplyByScalar(shadowMapCamera.directionWC, frustumRadius, scratchCenter), scratchCenter ) boundingSphere.center = frustumCenter boundingSphere.radius = frustumRadius shadowMap._outOfView = frameState.cullingVolume.computeVisibility(boundingSphere) === Intersect.OUTSIDE shadowMap._needsUpdate = !shadowMap._outOfView && !shadowMap._boundingSphere.equals(boundingSphere) BoundingSphere$9.clone(boundingSphere, shadowMap._boundingSphere) } } function updateCameras (shadowMap, frameState) { var camera = frameState.camera // The actual camera in the scene var lightCamera = shadowMap._lightCamera // The external camera representing the light source var sceneCamera = shadowMap._sceneCamera // Clone of camera, with clamped near and far planes var shadowMapCamera = shadowMap._shadowMapCamera // Camera representing the shadow volume, initially cloned from lightCamera // Clone light camera into the shadow map camera if (shadowMap._cascadesEnabled) { Cartesian3$m.clone(lightCamera.directionWC, shadowMapCamera.directionWC) } else if (shadowMap._isPointLight) { Cartesian3$m.clone(lightCamera.positionWC, shadowMapCamera.positionWC) } else { shadowMapCamera.clone(lightCamera) } // Get the light direction in eye coordinates var lightDirection = shadowMap._lightDirectionEC Matrix4$8.multiplyByPointAsVector(camera.viewMatrix, shadowMapCamera.directionWC, lightDirection) Cartesian3$m.normalize(lightDirection, lightDirection) Cartesian3$m.negate(lightDirection, lightDirection) // Get the light position in eye coordinates Matrix4$8.multiplyByPoint(camera.viewMatrix, shadowMapCamera.positionWC, shadowMap._lightPositionEC) shadowMap._lightPositionEC.w = shadowMap._pointLightRadius // Get the near and far of the scene camera var near var far if (shadowMap.isViewShed) { near = lightCamera.frustum.near far = lightCamera.frustum.far } else if (shadowMap._fitNearFar) { // shadowFar can be very large, so limit to shadowMap.maximumDistance // Push the far plane slightly further than the near plane to avoid degenerate frustum near = Math.min(frameState.shadowState.nearPlane, shadowMap.maximumDistance) far = Math.min(frameState.shadowState.farPlane, shadowMap.maximumDistance + 1.0) } else { near = camera.frustum.near far = shadowMap.maximumDistance } shadowMap._sceneCamera = Camera$1.clone(camera, sceneCamera) camera.frustum.clone(shadowMap._sceneCamera.frustum) shadowMap._sceneCamera.frustum.near = near shadowMap._sceneCamera.frustum.far = far shadowMap._distance = far - near checkVisibility(shadowMap, frameState) if (!shadowMap._outOfViewPrevious && shadowMap._outOfView) { shadowMap._needsUpdate = true } shadowMap._outOfViewPrevious = shadowMap._outOfView } /** * @private */ ViewshedMap.prototype.update = function (frameState) { updateCameras(this, frameState) if (this._needsUpdate) { updateFramebuffer$1(this, frameState.context) if (this._isPointLight) { computeOmnidirectional(this, frameState) } if (this._cascadesEnabled) { fitShadowMapToScene(this, frameState) if (this._numberOfCascades > 1) { computeCascades(this, frameState) } } if (!this._isPointLight) { // Compute the culling volume var shadowMapCamera = this._shadowMapCamera var position = shadowMapCamera.positionWC var direction = shadowMapCamera.directionWC var up = shadowMapCamera.upWC this._shadowMapCullingVolume = shadowMapCamera.frustum.computeCullingVolume(position, direction, up) if (this._passes.length === 1) { // Since there is only one pass, use the shadow map camera as the pass camera. this._passes[0].camera.clone(shadowMapCamera) } } else { this._shadowMapCullingVolume = CullingVolume.fromBoundingSphere(this._boundingSphere) } } if (this._passes.length === 1) { // Transforms from eye space to shadow texture space. // Always requires an update since the scene camera constantly changes. var inverseView = this._sceneCamera.inverseViewMatrix Matrix4$8.multiply(this._shadowMapCamera.getViewProjection(), inverseView, this._shadowMapMatrix) } if (this.debugShow) { applyDebugSettings(this, frameState) } } /** * @private */ ViewshedMap.prototype.updatePass = function (context, shadowPass) { clearFramebuffer(this, context, shadowPass) } var scratchTexelStepSize = new Cartesian2$7() function combineUniforms (shadowMap, uniforms, isTerrain) { var bias = shadowMap._isPointLight ? shadowMap._pointBias : isTerrain ? shadowMap._terrainBias : shadowMap._primitiveBias var mapUniforms = { shadowMap_texture: function () { return shadowMap._shadowMapTexture }, shadowMap_textureCube: function () { return shadowMap._shadowMapTexture }, shadowMap_matrix: function () { return shadowMap._shadowMapMatrix }, shadowMap_cascadeSplits: function () { return shadowMap._cascadeSplits }, shadowMap_cascadeMatrices: function () { return shadowMap._cascadeMatrices }, shadowMap_lightDirectionEC: function () { return shadowMap._lightDirectionEC }, shadowMap_lightPositionEC: function () { return shadowMap._lightPositionEC }, shadowMap_cascadeDistances: function () { return shadowMap._cascadeDistances }, shadowMap_texelSizeDepthBiasAndNormalShadingSmooth: function () { var texelStepSize = scratchTexelStepSize texelStepSize.x = 1.0 / shadowMap._textureSize.x texelStepSize.y = 1.0 / shadowMap._textureSize.y return Cartesian4$1.fromElements( texelStepSize.x, texelStepSize.y, bias.depthBias, bias.normalShadingSmooth, this.combinedUniforms1 ) }, shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness: function () { return Cartesian4$1.fromElements( bias.normalOffsetScale, shadowMap._distance, shadowMap.maximumDistance, shadowMap._darkness, this.combinedUniforms2 ) }, combinedUniforms1: new Cartesian4$1(), combinedUniforms2: new Cartesian4$1() } return combine$1(uniforms, mapUniforms, false) } function getShadowReceiveShaderKeyword (shadowMap, castShadows, isTerrain, hasTerrainNormal) { var usesDepthTexture = shadowMap._usesDepthTexture var polygonOffsetSupported = shadowMap._polygonOffsetSupported var isPointLight = shadowMap._isPointLight var isSpotLight = shadowMap._isSpotLight var hasCascades = shadowMap._numberOfCascades > 1 var debugCascadeColors = shadowMap.debugCascadeColors var softShadows = shadowMap.softShadows return ( "view receiveShadow " + usesDepthTexture + polygonOffsetSupported + isPointLight + isSpotLight + hasCascades + debugCascadeColors + softShadows + castShadows + isTerrain + hasTerrainNormal ) } function createShadowReceiveFragmentShader (fs, shadowMap, castShadows, isTerrain, hasTerrainNormal) { var normalVaryingName = ShaderSource$7.findNormalVarying(fs) var hasNormalVarying = (!isTerrain && defined$c(normalVaryingName)) || (isTerrain && hasTerrainNormal) var positionVaryingName = ShaderSource$7.findPositionVarying(fs) var hasPositionVarying = defined$c(positionVaryingName) var usesDepthTexture = shadowMap._usesDepthTexture var polygonOffsetSupported = shadowMap._polygonOffsetSupported var isPointLight = shadowMap._isPointLight var isSpotLight = shadowMap._isSpotLight var hasCascades = shadowMap._numberOfCascades > 1 var debugCascadeColors = shadowMap.debugCascadeColors var softShadows = shadowMap.softShadows var bias = isPointLight ? shadowMap._pointBias : isTerrain ? shadowMap._terrainBias : shadowMap._primitiveBias var defines = fs.defines.slice(0) var sources = fs.sources.slice(0) var length = sources.length for (var i = 0; i < length; ++i) { sources[i] = ShaderSource$7.replaceMain(sources[i], "czm_shadow_receive_main") } if (isPointLight) { defines.push("USE_CUBE_MAP_SHADOW") } else if (usesDepthTexture) { defines.push("USE_SHADOW_DEPTH_TEXTURE") } if (softShadows && !isPointLight) { defines.push("USE_SOFT_SHADOWS") } // Enable day-night shading so that the globe is dark when the light is below the horizon if (hasCascades && castShadows && isTerrain) { if (hasNormalVarying) { defines.push("ENABLE_VERTEX_LIGHTING") } else { defines.push("ENABLE_DAYNIGHT_SHADING") } } if (castShadows && bias.normalShading && hasNormalVarying) { defines.push("USE_NORMAL_SHADING") if (bias.normalShadingSmooth > 0.0) { defines.push("USE_NORMAL_SHADING_SMOOTH") } } var fsSource = "" if (isPointLight) { fsSource += "uniform samplerCube shadowMap_textureCube; \n" } else { fsSource += "uniform sampler2D shadowMap_texture; \n" } var returnPositionEC if (hasPositionVarying) { returnPositionEC = " return vec4(" + positionVaryingName + ", 1.0); \n" } else { returnPositionEC = "#ifndef LOG_DEPTH \n" + " return czm_windowToEyeCoordinates(gl_FragCoord); \n" + "#else \n" + " return vec4(v_logPositionEC, 1.0); \n" + "#endif \n" } fsSource += "uniform mat4 shadowMap_matrix; \n" + "uniform vec3 shadowMap_lightDirectionEC; \n" + "uniform vec4 shadowMap_lightPositionEC; \n" + "uniform vec4 shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness; \n" + "uniform vec4 shadowMap_texelSizeDepthBiasAndNormalShadingSmooth; \n" + "#ifdef LOG_DEPTH \n" + "varying vec3 v_logPositionEC; \n" + "#endif \n" + "vec4 getPositionEC() \n" + "{ \n" + returnPositionEC + "} \n" + "vec3 getNormalEC() \n" + "{ \n" + (hasNormalVarying ? " return normalize(" + normalVaryingName + "); \n" : " return vec3(1.0); \n") + "} \n" + // Offset the shadow position in the direction of the normal for perpendicular and back faces "void applyNormalOffset(inout vec4 positionEC, vec3 normalEC, float nDotL) \n" + "{ \n" + (bias.normalOffset && hasNormalVarying ? " float normalOffset = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.x; \n" + " float normalOffsetScale = 1.0 - nDotL; \n" + " vec3 offset = normalOffset * normalOffsetScale * normalEC; \n" + " positionEC.xyz += offset; \n" : "") + "} \n" fsSource += "void main() \n" + "{ \n" + " czm_shadow_receive_main(); \n" + " vec4 positionEC = getPositionEC(); \n" + " vec3 normalEC = getNormalEC(); \n" + " float depth = -positionEC.z; \n" fsSource += " czm_shadowParameters shadowParameters; \n" + " shadowParameters.texelStepSize = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.xy; \n" + " shadowParameters.depthBias = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.z; \n" + " shadowParameters.normalShadingSmooth = shadowMap_texelSizeDepthBiasAndNormalShadingSmooth.w; \n" + " shadowParameters.darkness = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.w; \n" if (isTerrain) { // Scale depth bias based on view distance to reduce z-fighting in distant terrain fsSource += " shadowParameters.depthBias *= max(depth * 0.01, 1.0); \n" } else if (!polygonOffsetSupported) { // If polygon offset isn't supported push the depth back based on view, however this // causes light leaking at further away views fsSource += " shadowParameters.depthBias *= mix(1.0, 100.0, depth * 0.0015); \n" } if (isPointLight) { fsSource += " vec3 directionEC = positionEC.xyz - shadowMap_lightPositionEC.xyz; \n" + " float distance = length(directionEC); \n" + " directionEC = normalize(directionEC); \n" + " float radius = shadowMap_lightPositionEC.w; \n" + " // Stop early if the fragment is beyond the point light radius \n" + " if (distance > radius) \n" + " { \n" + " return; \n" + " } \n" + " vec3 directionWC = czm_inverseViewRotation * directionEC; \n" + " shadowParameters.depth = distance / radius; \n" + " shadowParameters.nDotL = clamp(dot(normalEC, -directionEC), 0.0, 1.0); \n" + " shadowParameters.texCoords = directionWC; \n" + " float visibility = czm_shadowVisibility(shadowMap_textureCube, shadowParameters); \n" } else if (isSpotLight) { fsSource += " vec3 directionEC1 = positionEC.xyz - shadowMap_lightPositionEC.xyz; \n" + " float distance = length(directionEC1); \n" + " if (distance > shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.y) \n" + " { \n" + " return; \n" + " } \n" + " vec3 directionEC = normalize(positionEC.xyz - shadowMap_lightPositionEC.xyz); \n" + " float nDotL = clamp(dot(normalEC, -directionEC), 0.0, 1.0); \n" + " applyNormalOffset(positionEC, normalEC, nDotL); \n" + " vec4 shadowPosition = shadowMap_matrix * positionEC; \n" + " // Spot light uses a perspective projection, so perform the perspective divide \n" + " shadowPosition /= shadowPosition.w; \n" + " // Stop early if the fragment is not in the shadow bounds \n" + " if (any(lessThan(shadowPosition.xyz, vec3(0.0))) || any(greaterThan(shadowPosition.xyz, vec3(1.0)))) \n" + " { \n" + " return; \n" + " } \n" + " shadowParameters.texCoords = shadowPosition.xy; \n" + " shadowParameters.depth = shadowPosition.z; \n" + " shadowParameters.nDotL = nDotL; \n" + " float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n" } else if (hasCascades) { fsSource += " float maxDepth = shadowMap_cascadeSplits[1].w; \n" + " // Stop early if the eye depth exceeds the last cascade \n" + " if (depth > maxDepth) \n" + " { \n" + " return; \n" + " } \n" + " // Get the cascade based on the eye-space depth \n" + " vec4 weights = czm_cascadeWeights(depth); \n" + " // Apply normal offset \n" + " float nDotL = clamp(dot(normalEC, shadowMap_lightDirectionEC), 0.0, 1.0); \n" + " applyNormalOffset(positionEC, normalEC, nDotL); \n" + " // Transform position into the cascade \n" + " vec4 shadowPosition = czm_cascadeMatrix(weights) * positionEC; \n" + " // Get visibility \n" + " shadowParameters.texCoords = shadowPosition.xy; \n" + " shadowParameters.depth = shadowPosition.z; \n" + " shadowParameters.nDotL = nDotL; \n" + " float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n" + " // Fade out shadows that are far away \n" + " float shadowMapMaximumDistance = shadowMap_normalOffsetScaleDistanceMaxDistanceAndDarkness.z; \n" + " float fade = max((depth - shadowMapMaximumDistance * 0.8) / (shadowMapMaximumDistance * 0.2), 0.0); \n" + " visibility = mix(visibility, 1.0, fade); \n" + (debugCascadeColors ? " // Draw cascade colors for debugging \n" + " gl_FragColor *= czm_cascadeColor(weights); \n" : "") } else { fsSource += " float nDotL = clamp(dot(normalEC, shadowMap_lightDirectionEC), 0.0, 1.0); \n" + " applyNormalOffset(positionEC, normalEC, nDotL); \n" + " vec4 shadowPosition = shadowMap_matrix * positionEC; \n" + " // Stop early if the fragment is not in the shadow bounds \n" + " if (any(lessThan(shadowPosition.xyz, vec3(0.0))) || any(greaterThan(shadowPosition.xyz, vec3(1.0)))) \n" + " { \n" + " return; \n" + " } \n" + " shadowParameters.texCoords = shadowPosition.xy; \n" + " shadowParameters.depth = shadowPosition.z; \n" + " shadowParameters.nDotL = nDotL; \n" + " float visibility = czm_shadowVisibility(shadowMap_texture, shadowParameters); \n" } fsSource += " if(visibility==0.0) \n" + " {\n" + " gl_FragColor.rgb *= vec3(0.8,0.0,0.0);\n" + " }else{\n" + " gl_FragColor.rgb *= vec3(0.0,0.8,0.0) * visibility;\n" + " } \n " + "} \n " sources.push(fsSource) return new ShaderSource$7({ defines: defines, sources: sources }) } Cesium.ShadowMap.createReceiveDerivedCommand = function (lightShadowMaps, command, shadowsDirty, context, result) { if (!defined$c(result)) { result = {} } var lightShadowMapsEnabled = lightShadowMaps.length > 0 var shaderProgram = command.shaderProgram var vertexShaderSource = shaderProgram.vertexShaderSource var fragmentShaderSource = shaderProgram.fragmentShaderSource var isTerrain = command.pass === Pass$4.GLOBE var hasTerrainNormal = false if (isTerrain) { hasTerrainNormal = command.owner.data.renderedMesh.encoding.hasVertexNormals } if (command.receiveShadows && lightShadowMapsEnabled) { // Only generate a receiveCommand if there is a shadow map originating from a light source. var receiveShader var receiveUniformMap if (defined$c(result.receiveCommand)) { receiveShader = result.receiveCommand.shaderProgram receiveUniformMap = result.receiveCommand.uniformMap } result.receiveCommand = DrawCommand$4.shallowClone(command, result.receiveCommand) result.castShadows = false result.receiveShadows = true // If castShadows changed, recompile the receive shadows shader. The normal shading technique simulates // self-shadowing so it should be turned off if castShadows is false. var castShadowsDirty = result.receiveShaderCastShadows !== command.castShadows var shaderDirty = result.receiveShaderProgramId !== command.shaderProgram.id if (!defined$c(receiveShader) || shaderDirty || shadowsDirty || castShadowsDirty) { var keyword if (lightShadowMaps[0].isViewShed) { keyword = getShadowReceiveShaderKeyword( lightShadowMaps[0], command.castShadows, isTerrain, hasTerrainNormal ) } else { keyword = ShadowMapShader.getShadowReceiveShaderKeyword( lightShadowMaps[0], command.castShadows, isTerrain, hasTerrainNormal ) } receiveShader = context.shaderCache.getDerivedShaderProgram(shaderProgram, keyword) if (!defined$c(receiveShader)) { var receiveVS = ShadowMapShader.createShadowReceiveVertexShader( vertexShaderSource, isTerrain, hasTerrainNormal ) var receiveFS if (lightShadowMaps[0].isViewShed) { receiveFS = createShadowReceiveFragmentShader( fragmentShaderSource, lightShadowMaps[0], command.castShadows, isTerrain, hasTerrainNormal ) } else { receiveFS = ShadowMapShader.createShadowReceiveFragmentShader( fragmentShaderSource, lightShadowMaps[0], command.castShadows, isTerrain, hasTerrainNormal ) } receiveShader = context.shaderCache.createDerivedShaderProgram(shaderProgram, keyword, { vertexShaderSource: receiveVS, fragmentShaderSource: receiveFS, attributeLocations: shaderProgram._attributeLocations }) } receiveUniformMap = combineUniforms(lightShadowMaps[0], command.uniformMap, isTerrain) } result.receiveCommand.shaderProgram = receiveShader result.receiveCommand.uniformMap = receiveUniformMap result.receiveShaderProgramId = command.shaderProgram.id result.receiveShaderCastShadows = command.castShadows } return result } /** * @private */ ViewshedMap.prototype.isDestroyed = function () { return false } /** * @private */ ViewshedMap.prototype.destroy = function () { destroyFramebuffer(this) this._debugLightFrustum = this._debugLightFrustum && this._debugLightFrustum.destroy() this._debugCameraFrustum = this._debugCameraFrustum && this._debugCameraFrustum.destroy() this._debugShadowViewCommand = this._debugShadowViewCommand && this._debugShadowViewCommand.shaderProgram && this._debugShadowViewCommand.shaderProgram.destroy() for (var i = 0; i < this._numberOfCascades; ++i) { this._debugCascadeFrustums[i] = this._debugCascadeFrustums[i] && this._debugCascadeFrustums[i].destroy() } return destroyObject$9(this) } var scanPlaneFS = `#ifdef GL_OES_standard_derivatives #extension GL_OES_standard_derivatives : enable #endif uniform bool u_showIntersection; uniform bool u_showThroughEllipsoid; uniform float u_radius; uniform float u_xHalfAngle; uniform float u_yHalfAngle; uniform float u_normalDirection; uniform vec4 u_color; varying vec3 v_position; varying vec3 v_positionWC; varying vec3 v_positionEC; varying vec3 v_normalEC; vec4 getColor(float sensorRadius, vec3 pointEC) { czm_materialInput materialInput; vec3 pointMC = (czm_inverseModelView * vec4(pointEC, 1.0)).xyz; materialInput.st = sensor2dTextureCoordinates(sensorRadius, pointMC); materialInput.str = pointMC / sensorRadius; vec3 positionToEyeEC = -v_positionEC; materialInput.positionToEyeEC = positionToEyeEC; vec3 normalEC = normalize(v_normalEC); materialInput.normalEC = u_normalDirection * normalEC; czm_material material = czm_getMaterial(materialInput); material.diffuse = u_color.rgb; material.alpha = u_color.a; return mix(czm_phong(normalize(positionToEyeEC), material), vec4(material.diffuse, material.alpha), 0.4); } bool isOnBoundary(float value, float epsilon) { float width = getIntersectionWidth(); float tolerance = width * epsilon; #ifdef GL_OES_standard_derivatives float delta = max(abs(dFdx(value)), abs(dFdy(value))); float pixels = width * delta; float temp = abs(value); // There are a couple things going on here. // First we test the value at the current fragment to see if it is within the tolerance. // We also want to check if the value of an adjacent pixel is within the tolerance, // but we don't want to admit points that are obviously not on the surface. // For example, if we are looking for "value" to be close to 0, but value is 1 and the adjacent value is 2, // then the delta would be 1 and "temp - delta" would be "1 - 1" which is zero even though neither of // the points is close to zero. return temp < tolerance && temp < pixels || (delta < 10.0 * tolerance && temp - delta < tolerance && temp < pixels); #else return abs(value) < tolerance; #endif } vec4 shade(bool isOnBoundary) { if (u_showIntersection && isOnBoundary) { return getIntersectionColor(); } return getColor(u_radius, v_positionEC); } float ellipsoidSurfaceFunction(czm_ellipsoid ellipsoid, vec3 point) { vec3 scaled = ellipsoid.inverseRadii * point; return dot(scaled, scaled) - 1.0; } void main() { vec3 sensorVertexWC = czm_model[3].xyz; // (0.0, 0.0, 0.0) in model coordinates vec3 sensorVertexEC = czm_modelView[3].xyz; // (0.0, 0.0, 0.0) in model coordinates //vec3 pixDir = normalize(v_position); float positionX = v_position.x; float positionY = v_position.y; float positionZ = v_position.z; vec3 zDir = vec3(0.0, 0.0, 1.0); vec3 lineX = vec3(positionX, 0 ,positionZ); vec3 lineY = vec3(0, positionY, positionZ); float resX = dot(normalize(lineX), zDir); if(resX < cos(u_xHalfAngle) - 0.0001){ discard; } float resY = dot(normalize(lineY), zDir); if(resY < cos(u_yHalfAngle)- 0.0001){ discard; } czm_ellipsoid ellipsoid = czm_getWgs84EllipsoidEC(); float ellipsoidValue = ellipsoidSurfaceFunction(ellipsoid, v_positionWC); // Occluded by the ellipsoid? if (!u_showThroughEllipsoid) { // Discard if in the ellipsoid // PERFORMANCE_IDEA: A coarse check for ellipsoid intersection could be done on the CPU first. if (ellipsoidValue < 0.0) { discard; } // Discard if in the sensor's shadow if (inSensorShadow(sensorVertexWC, ellipsoid, v_positionWC)) { discard; } } // Notes: Each surface functions should have an associated tolerance based on the floating point error. bool isOnEllipsoid = isOnBoundary(ellipsoidValue, czm_epsilon3); gl_FragColor = shade(isOnEllipsoid); }` var sensorComm = ` uniform vec4 u_intersectionColor; uniform float u_intersectionWidth; uniform vec4 u_lineColor; bool inSensorShadow(vec3 coneVertexWC, czm_ellipsoid ellipsoidEC, vec3 pointWC) { // Diagonal matrix from the unscaled ellipsoid space to the scaled space. vec3 D = ellipsoidEC.inverseRadii; // Sensor vertex in the scaled ellipsoid space vec3 q = D * coneVertexWC; float qMagnitudeSquared = dot(q, q); float test = qMagnitudeSquared - 1.0; // Sensor vertex to fragment vector in the ellipsoid's scaled space vec3 temp = D * pointWC - q; float d = dot(temp, q); // Behind silhouette plane and inside silhouette cone return (d < -test) && (d / length(temp) < -sqrt(test)); } /////////////////////////////////////////////////////////////////////////////// vec4 getLineColor() { return u_lineColor; } vec4 getIntersectionColor() { return u_intersectionColor; } float getIntersectionWidth() { return u_intersectionWidth; } vec2 sensor2dTextureCoordinates(float sensorRadius, vec3 pointMC) { // (s, t) both in the range [0, 1] float t = pointMC.z / sensorRadius; float s = 1.0 + (atan(pointMC.y, pointMC.x) / czm_twoPi); s = s - floor(s); return vec2(s, t); }` var sensorFS = ` #ifdef GL_OES_standard_derivatives #extension GL_OES_standard_derivatives : enable #endif uniform bool u_showIntersection; uniform bool u_showThroughEllipsoid; uniform float u_radius; uniform float u_xHalfAngle; uniform float u_yHalfAngle; uniform float u_normalDirection; uniform float u_type; varying vec3 v_position; varying vec3 v_positionWC; varying vec3 v_positionEC; varying vec3 v_normalEC; vec4 getColor(float sensorRadius, vec3 pointEC) { czm_materialInput materialInput; vec3 pointMC = (czm_inverseModelView * vec4(pointEC, 1.0)).xyz; materialInput.st = sensor2dTextureCoordinates(sensorRadius, pointMC); materialInput.str = pointMC / sensorRadius; vec3 positionToEyeEC = -v_positionEC; materialInput.positionToEyeEC = positionToEyeEC; vec3 normalEC = normalize(v_normalEC); materialInput.normalEC = u_normalDirection * normalEC; czm_material material = czm_getMaterial(materialInput); return mix(czm_phong(normalize(positionToEyeEC), material), vec4(material.diffuse, material.alpha), 0.4); } bool isOnBoundary(float value, float epsilon) { float width = getIntersectionWidth(); float tolerance = width * epsilon; #ifdef GL_OES_standard_derivatives float delta = max(abs(dFdx(value)), abs(dFdy(value))); float pixels = width * delta; float temp = abs(value); // There are a couple things going on here. // First we test the value at the current fragment to see if it is within the tolerance. // We also want to check if the value of an adjacent pixel is within the tolerance, // but we don't want to admit points that are obviously not on the surface. // For example, if we are looking for "value" to be close to 0, but value is 1 and the adjacent value is 2, // then the delta would be 1 and "temp - delta" would be "1 - 1" which is zero even though neither of // the points is close to zero. return temp < tolerance && temp < pixels || (delta < 10.0 * tolerance && temp - delta < tolerance && temp < pixels); #else return abs(value) < tolerance; #endif } vec4 shade(bool isOnBoundary) { if (u_showIntersection && isOnBoundary) { return getIntersectionColor(); } if(u_type == 1.0){ return getLineColor(); } return getColor(u_radius, v_positionEC); } float ellipsoidSurfaceFunction(czm_ellipsoid ellipsoid, vec3 point) { vec3 scaled = ellipsoid.inverseRadii * point; return dot(scaled, scaled) - 1.0; } void main() { vec3 sensorVertexWC = czm_model[3].xyz; // (0.0, 0.0, 0.0) in model coordinates vec3 sensorVertexEC = czm_modelView[3].xyz; // (0.0, 0.0, 0.0) in model coordinates //vec3 pixDir = normalize(v_position); float positionX = v_position.x; float positionY = v_position.y; float positionZ = v_position.z; vec3 zDir = vec3(0.0, 0.0, 1.0); vec3 lineX = vec3(positionX, 0 ,positionZ); vec3 lineY = vec3(0, positionY, positionZ); float resX = dot(normalize(lineX), zDir); if(resX < cos(u_xHalfAngle)-0.00001){ discard; } float resY = dot(normalize(lineY), zDir); if(resY < cos(u_yHalfAngle)-0.00001){ discard; } czm_ellipsoid ellipsoid = czm_getWgs84EllipsoidEC(); float ellipsoidValue = ellipsoidSurfaceFunction(ellipsoid, v_positionWC); // Occluded by the ellipsoid? if (!u_showThroughEllipsoid) { // Discard if in the ellipsoid // PERFORMANCE_IDEA: A coarse check for ellipsoid intersection could be done on the CPU first. if (ellipsoidValue < 0.0) { discard; } // Discard if in the sensor's shadow if (inSensorShadow(sensorVertexWC, ellipsoid, v_positionWC)) { discard; } } // Notes: Each surface functions should have an associated tolerance based on the floating point error. bool isOnEllipsoid = isOnBoundary(ellipsoidValue, czm_epsilon3); //isOnEllipsoid = false; //if((resX >= 0.8 && resX <= 0.81)||(resY >= 0.8 && resY <= 0.81)){ /*if(false){ gl_FragColor = vec4(1.0,0.0,0.0,1.0); }else{ gl_FragColor = shade(isOnEllipsoid); } */ gl_FragColor = shade(isOnEllipsoid); }` var sensorVS = `attribute vec4 position; attribute vec3 normal; varying vec3 v_position; varying vec3 v_positionWC; varying vec3 v_positionEC; varying vec3 v_normalEC; void main() { gl_Position = czm_modelViewProjection * position; v_position = vec3(position); v_positionWC = (czm_model * position).xyz; v_positionEC = (czm_modelView * position).xyz; v_normalEC = czm_normal * normal; }` const { Matrix4: Matrix4$7, Material: Material$j, Color: Color$q, JulianDate: JulianDate$2, BoundingSphere: BoundingSphere$8, DrawCommand: DrawCommand$3, PrimitiveType: PrimitiveType$4, SceneMode: SceneMode$7, Matrix3: Matrix3$3, Buffer: Buffer$1, BufferUsage: BufferUsage$3, VertexArray: VertexArray$3, VertexFormat: VertexFormat$4, ComponentDatatype: ComponentDatatype$3, RenderState: RenderState$4, BlendingState: BlendingState$2, Pass: Pass$3, combine, CullFace, Cartesian3: Cartesian3$l, EllipsoidGeometry, EllipsoidOutlineGeometry, ShaderSource: ShaderSource$6, ShaderProgram: ShaderProgram$5, } = Cesium const { cos, sin, tan, atan } = Math const CesiumMath$8 = Cesium.Math const attributeLocations = { position: 0, normal: 1 } class RectangularSensorPrimitive { /** * 模拟相控阵雷达。 * @param {Object} options 具有以下属性 * @param {Boolean} [options.show] 是否显示 * @param {Cartesian3|LonLat} [options.position] 图形位置 * @param {Matrix4} [options.modelMatrix] 模型矩阵,如果定义,则覆盖position属性 * @param {Number} [options.slice=32] 切分程度 * @param {Number} [options.radius=1] 半径 * @param {Color} [options.lineColor=Color.RED] 线的颜色 * @param {Number} [options.xHalfAngle] 水平半夹角,单位度 * @param {Number} [options.xyHalfAngle] 垂直半夹角,单位度 * @param {Boolean} [options.showSectorLines=true] 是否显示扇面线 * @param {Boolean} [options.showSectorSegmentLines=true] 是否显示扇面和圆顶面连接线 * @param {Boolean} [options.showLateralSurfaces=true] 是否显示侧面 * @param {Material} [options.material=Material.ColorType] 材质 * @param {Material} [options.lateralSurfaceMaterial=Material.ColorType] 侧面材质 * @param {Boolean} [options.showDomeSurfaces=true] 是否显示圆弧顶表面 * @param {Material} [options.domeSurfaceMaterial=Material.ColorType] 圆弧顶表面材质 * @param {Boolean} [options.showDomeLines=true] 是否显示圆弧顶表面线 * @param {Boolean} [options.showIntersection = false] 是否显示与地球相交的线 * @param {Color} [options.intersectionColor] 与地球相交的线的颜色 * @param {Number} [options.intersectionWidth=5] 与地球相交的线的宽度 * @param {Boolean} [options.showThroughEllipsoid=false] 是否穿过地球 * @param {Boolean} [options.showScanPlane=true] 是否显示扫描面 * @param {Color} [options.scanPlaneColor=Color.WHITE] 扫描面颜色 * @param {String} [options.scanPlaneMode='H'] 扫描方向,H表示水平扫描,V表示垂直扫描 * @param {Number} [options.speed=10] 扫描速度,值越大,扫描越快 */ constructor(options) { options = defaultValue$c(options, defaultValue$c.EMPTY_OBJECT) const self = this this._createVS = true this._createRS = true this._createSP = true /** * 是否显示 * @type {Boolean} */ this.show = defaultValue$c(options.show, true) //切分程度 this.slice = defaultValue$c(options.slice, 32) //传感器的模型矩阵 if (!options.modelMatrix) { if (!options.position) { throw new CesiumProError$1('parameter position or modelMatrix must be provided.') } this._modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(LonLat.toCartesian(options.position)) } else { this._modelMatrix = Matrix4$7.clone(options.modelMatrix, new Matrix4$7()) } this._computedModelMatrix = new Matrix4$7() this._computedScanPlaneModelMatrix = new Matrix4$7() //传感器的半径 this._radius = defaultValue$c(options.radius, Number.POSITIVE_INFINITY) //传感器水平半角 this._xHalfAngle = CesiumMath$8.toRadians(defaultValue$c(options.xHalfAngle, 0)) //传感器垂直半角 this._yHalfAngle = CesiumMath$8.toRadians(defaultValue$c(options.yHalfAngle, 0)) this._color = defaultValue$c(options._color, Color$q.AQUA.withAlpha(0.4)) /** * 线的颜色 * @type {Cesium.Color} */ this.lineColor = defaultValue$c(options.lineColor, Color$q.WHITE) /** * 是否显示扇面的线 * @type {Boolean} */ this.showSectorLines = defaultValue$c(options.showSectorLines, true) /** * 是否显示扇面和圆顶面连接的线 * @type {Boolean} */ this.showSectorSegmentLines = defaultValue$c(options.showSectorSegmentLines, true) /** * 是否显示侧面 * @type {Boolean} */ this.showLateralSurfaces = defaultValue$c(options.showLateralSurfaces, true) //目前用的统一材质 this._material = defined$e(options.material) ? options.material : Material$j.fromType(Material$j.ColorType) this._material.uniforms.color = this._color this._translucent = undefined /** * 侧面材质 * @type {Material} */ this.lateralSurfaceMaterial = defined$e(options.lateralSurfaceMaterial) ? options.lateralSurfaceMaterial : Material$j.fromType(Material$j.ColorType) this._lateralSurfaceMaterial = undefined this._lateralSurfaceTranslucent = undefined /** * 是否显示圆顶表面 * @type {Boolean} */ this.showDomeSurfaces = defaultValue$c(options.showDomeSurfaces, true) /** * 圆顶表面材质 * @type {Material} */ this.domeSurfaceMaterial = defined$e(options.domeSurfaceMaterial) ? options.domeSurfaceMaterial : Material$j.fromType(Material$j.ColorType) /** * 是否显示圆顶面线 * @type {Boolean} */ this.showDomeLines = defaultValue$c(options.showDomeLines, true) /** * 是否显示与地球相交的线 * @type {Boolean} */ this.showIntersection = defaultValue$c(options.showIntersection, false) /** * 与地球相交的线的颜色 * @type {Color} */ this.intersectionColor = defaultValue$c(options.intersectionColor, Color$q.WHITE) /** * 与地球相交的线的宽度(像素) * @type {Number} */ this.intersectionWidth = defaultValue$c(options.intersectionWidth, 5.0) //是否穿过地球 this._showThroughEllipsoid = defaultValue$c(options.showThroughEllipsoid, false) /** * 是否显示扫描面 * @type {Boolean} */ this.showScanPlane = defaultValue$c(options.showScanPlane, true) /** * 扫描面颜色 * @type {Color} */ this.scanPlaneColor = defaultValue$c(options.scanPlaneColor, Color$q.AQUA) /** * 扫描面模式 垂直V/水平H * @type {String} */ this.scanPlaneMode = defaultValue$c(options.scanPlaneMode, 'H') /** * 扫描速率,值越大,扫描越慢 * @type {Number} */ this.speed = defaultValue$c(options.speed, 10) this._scanePlaneXHalfAngle = 0 this._scanePlaneYHalfAngle = 0 //时间计算的起点 this._time = JulianDate$2.now() this._boundingSphere = new BoundingSphere$8() this._boundingSphereWC = new BoundingSphere$8() this._boundingSphere = new BoundingSphere$8(Cartesian3$l.ZERO, this._radius) Matrix4$7.multiplyByUniformScale(this._modelMatrix, this._radius, this._computedModelMatrix) BoundingSphere$8.transform(this._boundingSphere, this._modelMatrix, this._boundingSphereWC) //扇面 sector this._sectorFrontCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.TRIANGLES, boundingVolume: this._boundingSphereWC }) this._sectorBackCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.TRIANGLES, boundingVolume: this._boundingSphereWC }) this._sectorVA = undefined //扇面边线 sectorLine this._sectorLineCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.LINES, boundingVolume: this._boundingSphereWC }) this._sectorLineVA = undefined //扇面分割线 sectorSegmentLine this._sectorSegmentLineCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.LINES, boundingVolume: this._boundingSphereWC }) this._sectorSegmentLineVA = undefined //弧面 dome this._domeFrontCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.TRIANGLES, boundingVolume: this._boundingSphereWC }) this._domeBackCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.TRIANGLES, boundingVolume: this._boundingSphereWC }) this._domeVA = undefined //弧面线 domeLine this._domeLineCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.LINES, boundingVolume: this._boundingSphereWC }) this._domeLineVA = undefined //扫描面 scanPlane/scanRadial this._scanPlaneFrontCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.TRIANGLES, boundingVolume: this._boundingSphereWC }) this._scanPlaneBackCommand = new DrawCommand$3({ owner: this, primitiveType: PrimitiveType$4.TRIANGLES, boundingVolume: this._boundingSphereWC }) this._scanRadialCommand = undefined this._colorCommands = [] this._frontFaceRS = undefined this._backFaceRS = undefined this._sp = undefined this._uniforms = { u_type: function u_type () { return 0 //面 }, u_xHalfAngle: function u_xHalfAngle () { return self._xHalfAngle }, u_yHalfAngle: function u_yHalfAngle () { return self._yHalfAngle }, u_radius: function u_radius () { return self.radius }, u_showThroughEllipsoid: function u_showThroughEllipsoid () { return self.showThroughEllipsoid }, u_showIntersection: function u_showIntersection () { return self.showIntersection }, u_intersectionColor: function u_intersectionColor () { return self.intersectionColor }, u_intersectionWidth: function u_intersectionWidth () { return self.intersectionWidth }, u_normalDirection: function u_normalDirection () { return 1.0 }, u_lineColor: function u_lineColor () { return self.lineColor } } this._scanUniforms = { u_xHalfAngle: function u_xHalfAngle () { return self._scanePlaneXHalfAngle }, u_yHalfAngle: function u_yHalfAngle () { return self._scanePlaneYHalfAngle }, u_radius: function u_radius () { return self.radius }, u_color: function u_color () { return self.scanPlaneColor }, u_showThroughEllipsoid: function u_showThroughEllipsoid () { return self.showThroughEllipsoid }, u_showIntersection: function u_showIntersection () { return self.showIntersection }, u_intersectionColor: function u_intersectionColor () { return self.intersectionColor }, u_intersectionWidth: function u_intersectionWidth () { return self.intersectionWidth }, u_normalDirection: function u_normalDirection () { return 1.0 }, u_lineColor: function u_lineColor () { return self.lineColor } } } get color () { return this._color } set color (val) { this._color = val this._material.uniforms.color = val } get boundingSphere () { return this._boundingSphere } /** * 水平面半夹角,单位:度 * @type {Number} */ get xHalfAngle () { return CesiumMath$8.toDegrees(this._xHalfAngle) } set xHalfAngle (val) { if (this._xHalfAngle !== val) { this._xHalfAngle = CesiumMath$8.toRadians(val) this._createVS = true } } /** * 垂直面半夹角,单位:度 * @type {Number} */ get yHalfAngle () { return CesiumMath$8.toDegrees(this._yHalfAngle) } set yHalfAngle (val) { if (this._yHalfAngle !== val) { this._yHalfAngle = CesiumMath$8.toRadians(val) this._createVS = true } } /** * 传感器半径 * @type {Number} */ get radius () { return this._radius } set radius (val) { if (this._radius !== val) { this._radius = val this._boundingSphere = new BoundingSphere$8(Cartesian3$l.ZERO, val) Matrix4$7.multiplyByUniformScale(this._modelMatrix, this._radius, this._computedModelMatrix) BoundingSphere$8.transform(this._boundingSphere, this._modelMatrix, this._boundingSphereWC) } } /** * 传感器模型矩阵 * @type {Matrix4} */ get modelMatrix () { return this._modelMatrix } set modelMatrix (val) { const modelMatrixChanged = !Matrix4$7.equals(val, this._modelMatrix) if (modelMatrixChanged) { Matrix4$7.clone(val, this._modelMatrix) Matrix4$7.multiplyByUniformScale(this._modelMatrix, this._radius, this._computedModelMatrix) BoundingSphere$8.transform(this._boundingSphere, this._modelMatrix, this._boundingSphereWC) } } /** * 是否传过地球 * @type {Boolean} */ get showThroughEllipsoid () { return this._showThroughEllipsoid } set showThroughEllipsoid (val) { if (this._showThroughEllipsoid !== val) { this._showThroughEllipsoid = val this._createRS = true } } /** * 材质 * @type {Material} */ get material () { return this._material } set material (val) { this._material = val this._createRS = true this._createSP = true } /** * 每一帧在渲染时Cesium会自动调用该方法。不要主动调用该方法 * @override * @param {frameState} frameState */ update (frameState) { const mode = frameState.mode if (!this.show || mode !== SceneMode$7.SCENE3D) { return } const xHalfAngle = this._xHalfAngle const yHalfAngle = this._yHalfAngle if (xHalfAngle < 0.0 || yHalfAngle < 0.0) { throw new CesiumProError$1('halfAngle must be greater than or equal to zero.') } if (xHalfAngle == 0.0 || yHalfAngle == 0.0) { return } const radius = this.radius if (radius < 0.0) { throw new CesiumProError$1('this.radius must be greater than or equal to zero.') } const showThroughEllipsoid = this.showThroughEllipsoid const material = this.material const translucent = material.isTranslucent() if (this._translucent !== translucent) { this._translucent = translucent this._createRS = true } if (this.showScanPlane) { const time = frameState.time let timeDiff = JulianDate$2.secondsDifference(time, this._time) if (timeDiff < 0) { this._time = JulianDate$2.clone(time, this._time) } let percentage if (this.speed <= 0) { percentage = 0 } else { const speet = 10 / this.speed percentage = Math.max(timeDiff % speet / speet, 0) } let angle const matrix3Scratch = new Matrix3$3 if (this.scanPlaneMode == 'H') { angle = 2 * yHalfAngle * percentage - yHalfAngle const cosYHalfAngle = cos(angle) const tanXHalfAngle = tan(xHalfAngle) const maxX = atan(cosYHalfAngle * tanXHalfAngle) this._scanePlaneXHalfAngle = maxX this._scanePlaneYHalfAngle = angle Matrix3$3.fromRotationX(this._scanePlaneYHalfAngle, matrix3Scratch) } else { angle = 2 * xHalfAngle * percentage - xHalfAngle const tanYHalfAngle = tan(yHalfAngle) const cosXHalfAngle = cos(angle) const maxY = atan(cosXHalfAngle * tanYHalfAngle) this._scanePlaneXHalfAngle = angle this._scanePlaneYHalfAngle = maxY Matrix3$3.fromRotationY(this._scanePlaneXHalfAngle, matrix3Scratch) } Matrix4$7.multiplyByMatrix3(this.modelMatrix, matrix3Scratch, this._computedScanPlaneModelMatrix) Matrix4$7.multiplyByUniformScale(this._computedScanPlaneModelMatrix, this.radius, this._computedScanPlaneModelMatrix) } if (this._createVS) { createVertexArray(this, frameState) } if (this._createRS) { createRenderState(this, showThroughEllipsoid, translucent) } if (this._createSP) { createShaderProgram(this, frameState, material) } if (this._createRS || this._createSP) { createCommands(this, translucent) } const commandList = frameState.commandList const passes = frameState.passes const colorCommands = this._colorCommands if (passes.render) { for (let i = 0, len = colorCommands.length; i < len; i++) { const colorCommand = colorCommands[i] commandList.push(colorCommand) } } } /** * 销毁对象并翻译WebGL资源 * @example * const radar=new CesiumPro.RectangularSensorPrimitive(); * if(!radar.isDestroyed()){ * radar.destroy(); * } */ destroy () { this._pickSP.destroy() this._sp = this._sp.destroy() this._scanePlaneSP && (this._scanePlaneSP = this._scanePlaneSP.destroy()) destroyObject$a(this) } } function createCommand (primitive, frontCommand, backCommand, frontFaceRS, backFaceRS, sp, va, uniforms, modelMatrix, translucent, pass, isLine) { if (translucent && backCommand) { backCommand.vertexArray = va backCommand.renderState = backFaceRS backCommand.shaderProgram = sp backCommand.uniformMap = combine(uniforms, primitive._material._uniforms) backCommand.uniformMap.u_normalDirection = function () { return -1.0 } backCommand.pass = pass backCommand.modelMatrix = modelMatrix primitive._colorCommands.push(backCommand) } frontCommand.vertexArray = va frontCommand.renderState = frontFaceRS frontCommand.shaderProgram = sp frontCommand.uniformMap = combine(uniforms, primitive._material._uniforms) if (isLine) { frontCommand.uniformMap.u_type = function () { return 1 } } frontCommand.pass = pass frontCommand.modelMatrix = modelMatrix primitive._colorCommands.push(frontCommand) } function createCommands (primitive, translucent) { primitive._colorCommands.length = 0 const pass = translucent ? Pass$3.TRANSLUCENT : Pass$3.OPAQUE //显示扇面 if (primitive.showLateralSurfaces) { createCommand(primitive, primitive._sectorFrontCommand, primitive._sectorBackCommand, primitive._frontFaceRS, primitive._backFaceRS, primitive._sp, primitive._sectorVA, primitive._uniforms, primitive._computedModelMatrix, translucent, pass) } //显示扇面线 if (primitive.showSectorLines) { createCommand(primitive, primitive._sectorLineCommand, undefined, primitive._frontFaceRS, primitive._backFaceRS, primitive._sp, primitive._sectorLineVA, primitive._uniforms, primitive._computedModelMatrix, translucent, pass, true) } //显示扇面交接线 if (primitive.showSectorSegmentLines) { createCommand(primitive, primitive._sectorSegmentLineCommand, undefined, primitive._frontFaceRS, primitive._backFaceRS, primitive._sp, primitive._sectorSegmentLineVA, primitive._uniforms, primitive._computedModelMatrix, translucent, pass, true) } //显示弧面 if (primitive.showDomeSurfaces) { createCommand(primitive, primitive._domeFrontCommand, primitive._domeBackCommand, primitive._frontFaceRS, primitive._backFaceRS, primitive._sp, primitive._domeVA, primitive._uniforms, primitive._computedModelMatrix, translucent, pass) } //显示弧面线 if (primitive.showDomeLines) { createCommand(primitive, primitive._domeLineCommand, undefined, primitive._frontFaceRS, primitive._backFaceRS, primitive._sp, primitive._domeLineVA, primitive._uniforms, primitive._computedModelMatrix, translucent, pass, true) } //显示扫描面 if (primitive.showScanPlane) { createCommand(primitive, primitive._scanPlaneFrontCommand, primitive._scanPlaneBackCommand, primitive._frontFaceRS, primitive._backFaceRS, primitive._scanePlaneSP, primitive._scanPlaneVA, primitive._scanUniforms, primitive ._computedScanPlaneModelMatrix, translucent, pass) } return } function createCommonShaderProgram (primitive, frameState, material) { const context = frameState.context const vs = sensorVS const fs = new ShaderSource$6({ sources: [sensorComm, material.shaderSource, sensorFS] }) primitive._sp = ShaderProgram$5.replaceCache({ context: context, shaderProgram: primitive._sp, vertexShaderSource: vs, fragmentShaderSource: fs, attributeLocations: attributeLocations }) const pickFS = new ShaderSource$6({ sources: [sensorComm, material.shaderSource, sensorFS], pickColorQualifier: 'uniform' }) primitive._pickSP = ShaderProgram$5.replaceCache({ context: context, shaderProgram: primitive._pickSP, vertexShaderSource: vs, fragmentShaderSource: pickFS, attributeLocations: attributeLocations }) } function createScanPlaneShaderProgram (primitive, frameState, material) { const context = frameState.context const vs = sensorVS const fs = new ShaderSource$6({ sources: [sensorComm, material.shaderSource, scanPlaneFS] }) primitive._scanePlaneSP = ShaderProgram$5.replaceCache({ context: context, shaderProgram: primitive._scanePlaneSP, vertexShaderSource: vs, fragmentShaderSource: fs, attributeLocations: attributeLocations }) } function createShaderProgram (primitive, frameState, material) { createCommonShaderProgram(primitive, frameState, material) if (primitive.showScanPlane) { createScanPlaneShaderProgram(primitive, frameState, material) } } function createRenderState (primitive, showThroughEllipsoid, translucent) { if (translucent) { primitive._frontFaceRS = RenderState$4.fromCache({ depthTest: { enabled: !showThroughEllipsoid }, depthMask: false, blending: BlendingState$2.ALPHA_BLEND, cull: { enabled: true, face: CullFace.BACK } }) primitive._backFaceRS = RenderState$4.fromCache({ depthTest: { enabled: !showThroughEllipsoid }, depthMask: false, blending: BlendingState$2.ALPHA_BLEND, cull: { enabled: true, face: CullFace.FRONT } }) primitive._pickRS = RenderState$4.fromCache({ depthTest: { enabled: !showThroughEllipsoid }, depthMask: false, blending: BlendingState$2.ALPHA_BLEND }) } else { primitive._frontFaceRS = RenderState$4.fromCache({ depthTest: { enabled: !showThroughEllipsoid }, depthMask: true }) primitive._pickRS = RenderState$4.fromCache({ depthTest: { enabled: true }, depthMask: true }) } } function computeUnitPosiiton (primitive, xHalfAngle, yHalfAngle) { const slice = primitive.slice //以中心为角度 const cosYHalfAngle = cos(yHalfAngle) const tanYHalfAngle = tan(yHalfAngle) const cosXHalfAngle = cos(xHalfAngle) const tanXHalfAngle = tan(xHalfAngle) const maxY = atan(cosXHalfAngle * tanYHalfAngle) const maxX = atan(cosYHalfAngle * tanXHalfAngle) //ZOY面单位圆 const zoy = [] for (let i = 0; i < slice; i++) { const phi = 2 * maxY * i / (slice - 1) - maxY zoy.push(new Cartesian3$l(0, sin(phi), cos(phi))) } //zox面单位圆 const zox = [] for (let i = 0; i < slice; i++) { const phi = 2 * maxX * i / (slice - 1) - maxX zox.push(new Cartesian3$l(sin(phi), 0, cos(phi))) } return { zoy: zoy, zox: zox } } function computeSectorPositions (primitive, unitPosition) { const xHalfAngle = primitive._xHalfAngle, yHalfAngle = primitive._yHalfAngle, zoy = unitPosition.zoy, zox = unitPosition.zox const positions = [] //zoy面沿y轴逆时针转xHalfAngle const matrix3Scratch = new Matrix3$3() let matrix3 = Matrix3$3.fromRotationY(xHalfAngle, matrix3Scratch) positions.push(zoy.map(function (p) { return Matrix3$3.multiplyByVector(matrix3, p, new Cartesian3$l()) })) //zox面沿x轴顺时针转yHalfAngle matrix3 = Matrix3$3.fromRotationX(-yHalfAngle, matrix3Scratch) positions.push(zox.map(function (p) { return Matrix3$3.multiplyByVector(matrix3, p, new Cartesian3$l()) }).reverse()) //zoy面沿y轴顺时针转xHalfAngle matrix3 = Matrix3$3.fromRotationY(-xHalfAngle, matrix3Scratch) positions.push(zoy.map(function (p) { return Matrix3$3.multiplyByVector(matrix3, p, new Cartesian3$l()) }).reverse()) //zox面沿x轴逆时针转yHalfAngle matrix3 = Matrix3$3.fromRotationX(yHalfAngle, matrix3Scratch) positions.push(zox.map(function (p) { return Matrix3$3.multiplyByVector(matrix3, p, new Cartesian3$l()) })) return positions } /** * 创建扇面顶点 * @private * @param context * @param positions * @returns {*} */ function createSectorVertexArray (context, positions) { const planeLength = Array.prototype.concat.apply([], positions).length - positions.length const vertices = new Float32Array(2 * 3 * 3 * planeLength) let k = 0 for (let i = 0, len = positions.length; i < len; i++) { const planePositions = positions[i] const nScratch = new Cartesian3$l() const n = Cartesian3$l.normalize(Cartesian3$l.cross(planePositions[0], planePositions[planePositions.length - 1], nScratch), nScratch) for (let j = 0, planeLength = planePositions.length - 1; j < planeLength; j++) { vertices[k++] = 0.0 vertices[k++] = 0.0 vertices[k++] = 0.0 vertices[k++] = -n.x vertices[k++] = -n.y vertices[k++] = -n.z vertices[k++] = planePositions[j].x vertices[k++] = planePositions[j].y vertices[k++] = planePositions[j].z vertices[k++] = -n.x vertices[k++] = -n.y vertices[k++] = -n.z vertices[k++] = planePositions[j + 1].x vertices[k++] = planePositions[j + 1].y vertices[k++] = planePositions[j + 1].z vertices[k++] = -n.x vertices[k++] = -n.y vertices[k++] = -n.z } } const vertexBuffer = Buffer$1.createVertexBuffer({ context: context, typedArray: vertices, usage: BufferUsage$3.STATIC_DRAW }) const stride = 2 * 3 * Float32Array.BYTES_PER_ELEMENT const attributes = [{ index: attributeLocations.position, vertexBuffer: vertexBuffer, componentsPerAttribute: 3, componentDatatype: ComponentDatatype$3.FLOAT, offsetInBytes: 0, strideInBytes: stride }, { index: attributeLocations.normal, vertexBuffer: vertexBuffer, componentsPerAttribute: 3, componentDatatype: ComponentDatatype$3.FLOAT, offsetInBytes: 3 * Float32Array.BYTES_PER_ELEMENT, strideInBytes: stride }] return new VertexArray$3({ context: context, attributes: attributes }) } /** * 创建扇面边线顶点 * @param context * @param positions * @returns {*} */ function createSectorLineVertexArray (context, positions) { const planeLength = positions.length const vertices = new Float32Array(3 * 3 * planeLength) let k = 0 for (let i = 0, len = positions.length; i < len; i++) { const planePositions = positions[i] vertices[k++] = 0.0 vertices[k++] = 0.0 vertices[k++] = 0.0 vertices[k++] = planePositions[0].x vertices[k++] = planePositions[0].y vertices[k++] = planePositions[0].z } const vertexBuffer = Buffer$1.createVertexBuffer({ context: context, typedArray: vertices, usage: BufferUsage$3.STATIC_DRAW }) const stride = 3 * Float32Array.BYTES_PER_ELEMENT const attributes = [{ index: attributeLocations.position, vertexBuffer: vertexBuffer, componentsPerAttribute: 3, componentDatatype: ComponentDatatype$3.FLOAT, offsetInBytes: 0, strideInBytes: stride }] return new VertexArray$3({ context: context, attributes: attributes }) } /** * 创建扇面圆顶面连接线顶点 * @private * @param context * @param positions * @returns {*} */ function createSectorSegmentLineVertexArray (context, positions) { const planeLength = Array.prototype.concat.apply([], positions).length - positions.length const vertices = new Float32Array(3 * 3 * planeLength) let k = 0 for (let i = 0, len = positions.length; i < len; i++) { const planePositions = positions[i] for (let j = 0, planeLength = planePositions.length - 1; j < planeLength; j++) { vertices[k++] = planePositions[j].x vertices[k++] = planePositions[j].y vertices[k++] = planePositions[j].z vertices[k++] = planePositions[j + 1].x vertices[k++] = planePositions[j + 1].y vertices[k++] = planePositions[j + 1].z } } const vertexBuffer = Buffer$1.createVertexBuffer({ context: context, typedArray: vertices, usage: BufferUsage$3.STATIC_DRAW }) const stride = 3 * Float32Array.BYTES_PER_ELEMENT const attributes = [{ index: attributeLocations.position, vertexBuffer: vertexBuffer, componentsPerAttribute: 3, componentDatatype: ComponentDatatype$3.FLOAT, offsetInBytes: 0, strideInBytes: stride }] return new VertexArray$3({ context: context, attributes: attributes }) } /** * 创建圆顶面顶点 * @param context */ function createDomeVertexArray (context) { const geometry = EllipsoidGeometry.createGeometry(new EllipsoidGeometry({ vertexFormat: VertexFormat$4.POSITION_ONLY, stackPartitions: 32, slicePartitions: 32 })) const vertexArray = VertexArray$3.fromGeometry({ context: context, geometry: geometry, attributeLocations: attributeLocations, bufferUsage: BufferUsage$3.STATIC_DRAW, interleave: false }) return vertexArray } /** * 创建圆顶面连线顶点 * @param context */ function createDomeLineVertexArray (context) { const geometry = EllipsoidOutlineGeometry.createGeometry(new EllipsoidOutlineGeometry({ vertexFormat: VertexFormat$4.POSITION_ONLY, stackPartitions: 32, slicePartitions: 32 })) const vertexArray = VertexArray$3.fromGeometry({ context: context, geometry: geometry, attributeLocations: attributeLocations, bufferUsage: BufferUsage$3.STATIC_DRAW, interleave: false }) return vertexArray } /** * 创建扫描面顶点 * @param context * @param positions * @returns {*} */ function createScanPlaneVertexArray (context, positions) { const planeLength = positions.length - 1 const vertices = new Float32Array(3 * 3 * planeLength) let k = 0 for (let i = 0; i < planeLength; i++) { vertices[k++] = 0.0 vertices[k++] = 0.0 vertices[k++] = 0.0 vertices[k++] = positions[i].x vertices[k++] = positions[i].y vertices[k++] = positions[i].z vertices[k++] = positions[i + 1].x vertices[k++] = positions[i + 1].y vertices[k++] = positions[i + 1].z } const vertexBuffer = Buffer$1.createVertexBuffer({ context: context, typedArray: vertices, usage: BufferUsage$3.STATIC_DRAW }) const stride = 3 * Float32Array.BYTES_PER_ELEMENT const attributes = [{ index: attributeLocations.position, vertexBuffer: vertexBuffer, componentsPerAttribute: 3, componentDatatype: ComponentDatatype$3.FLOAT, offsetInBytes: 0, strideInBytes: stride }] return new VertexArray$3({ context: context, attributes: attributes }) } function createVertexArray (primitive, frameState) { const context = frameState.context const unitSectorPositions = computeUnitPosiiton(primitive, primitive._xHalfAngle, primitive._yHalfAngle) const positions = computeSectorPositions(primitive, unitSectorPositions) //显示扇面 if (primitive.showLateralSurfaces) { primitive._sectorVA = createSectorVertexArray(context, positions) } //显示扇面线 if (primitive.showSectorLines) { primitive._sectorLineVA = createSectorLineVertexArray(context, positions) } //显示扇面圆顶面的交线 if (primitive.showSectorSegmentLines) { primitive._sectorSegmentLineVA = createSectorSegmentLineVertexArray(context, positions) } //显示弧面 if (primitive.showDomeSurfaces) { primitive._domeVA = createDomeVertexArray(context) } //显示弧面线 if (primitive.showDomeLines) { primitive._domeLineVA = createDomeLineVertexArray(context) } //显示扫描面 if (primitive.showScanPlane) { if (primitive.scanPlaneMode == 'H') { const unitScanPlanePositions = computeUnitPosiiton(primitive, CesiumMath$8.PI_OVER_TWO, 0) primitive._scanPlaneVA = createScanPlaneVertexArray(context, unitScanPlanePositions.zox) } else { const unitScanPlanePositions = computeUnitPosiiton(primitive, 0, CesiumMath$8.PI_OVER_TWO) primitive._scanPlaneVA = createScanPlaneVertexArray(context, unitScanPlanePositions.zoy) } } } const CesiumMath$7 = Cesium.Math function getHeading (direction, up) { var heading if ( !CesiumMath$7.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath$7.EPSILON3) ) { heading = Math.atan2(direction.y, direction.x) - CesiumMath$7.PI_OVER_TWO } else { heading = Math.atan2(up.y, up.x) - CesiumMath$7.PI_OVER_TWO } return CesiumMath$7.TWO_PI - CesiumMath$7.zeroToTwoPi(heading) } function getPitch (direction) { return CesiumMath$7.PI_OVER_TWO - CesiumMath$7.acosClamped(direction.z) } function getRoll (direction, up, right) { var roll = 0.0 if ( !CesiumMath$7.equalsEpsilon(Math.abs(direction.z), 1.0, CesiumMath$7.EPSILON3) ) { roll = Math.atan2(-right.z, up.z) roll = CesiumMath$7.zeroToTwoPi(roll + CesiumMath$7.TWO_PI) } return roll } class ViewShedAnalyser extends BaseAnalyser { /** *

视域分析

* Note:使用视域分析时需要关闭场景的阴影. * @extends BaseAnalyser * @param {Cesium.Viewer} viewer viewer对象 * @param {Object} options 具有以下属性 * @param {Cesium.Cartesian3} options.observe 观察位置,即视点所在的位置 * @param {Cesium.Cartesian3} options.viewPosition 相机方法向视锥机远裁剪面的交点 * @param {Number} [options.far] 远裁剪面的距离 * @param {Number} [options.near=0.001*options.far] 近裁剪面的距离 * @param {Number} [options.aspectRatio=1.5] 视锥宽高比 * @param {Number} [options.fov=120] 视锥体的水面夹角,单位度 * */ constructor(viewer, options) { super(viewer) options = defaultValue$c(options, {}) this._options = options if (!defined$e(options.observe)) { throw new CesiumProError$1('parameter options.observe is required.') } if (!defined$e(options.viewPosition)) { throw new CesiumProError$1('parameter options.viewPosition is required.') } this._observe = options.observe this._viewPosition = options.viewPosition this._debug = defaultValue$c(options.debug, false) this._far = defaultValue$c(options.far, Cesium.Cartesian3.distance(this._observe, this._viewPosition)) this._near = defaultValue$c(options.near, 0.001 * this._far) this._aspectRatio = defaultValue$c(options.aspectRatio, 1.5) this._fov = defaultValue$c(options.fov, 120) const direction = Cesium.Cartesian3.subtract(this._viewPosition, this._observe, new Cesium.Cartesian3) this._direction = Cesium.Cartesian3.normalize(direction, direction) this._up = viewer.scene.mapProjection.ellipsoid.geodeticSurfaceNormal(this._observe, new Cesium.Cartesian3) this._heading = undefined this._pitch = undefined this._roll = undefined } do () { this.preAnalysis.raise() this.update() this.postAnalysis.raise() } clear () { this._viewer.scene.primitives.remove(this._frustum) this._viewer.scene.primitives.remove(this._shadowMap) } destroy () { this.clear() if (this._frustum && !this._frustum.isDestroyed()) { this._frustum.destroy() } if (this._shadowMap && !this._shadowMap.isDestroyed()) { this._shadowMap.destroy() } super.destroy(this) } /** * 视锥体 * @type {any} */ get frustum () { return this._frustum } /** * 是否显示辅助调试的元素 * @type {Boolean} */ get debug () { return this._debug } set debug (val) { if (this._debug !== val) { this._debug = val this._frustum.show = val // this.createOrUpdateFrustum(); } } /** * 观察位置,即相机所在的位置 * @type {Cesium.Cartesian3} */ get observe () { return this._observe } set observe (val) { if (this._observe !== val) { this._observe = val this.update() } } /** * 相机方法向视锥机远裁剪面的交点 * @type {Cesium.Cartesian3} */ get viewPosition () { return this._viewPosition } set viewPosition (val) { if (this._viewPosition !== val) { this._viewPosition = val this.update() } } /** * 相机方向,由viewPosition和observe决定 * @readonly * @type {Cesium.Cartesian3} */ get direction () { return this._direction } /** * 相机远裁剪面到视点的距离 * @type {Number} */ get far () { return this._far } set far (val) { if (this._far !== val) { this._far = val this.update() } } /** * 相机近裁剪面到视点的距离 * @type {Number} */ get near () { return this._near } set near (val) { if (this._near !== val) { this._near = val this.update() } } /** * 视锥体水平夹角,单位:度 * @type {Number} */ get fov () { return this._fov } set fov (val) { if (this._fov !== val) { this._fov = val this.update() } } /** * 视锥宽高比 * @type {Number} */ get aspectRatio () { return this._aspectRatio } set aspectRatio (val) { if (this._aspectRatio !== val) { this._aspectRatio = val this.update() } } /** * 旋转角,单位:度 * @type {Number} * @readonly */ get heading () { this.updateHeadingPitchRoll() return Cesium.Math.toDegrees(this._heading) } /** * 俯仰角,单位:度 * @type {Number} * @readonly */ get pitch () { this.updateHeadingPitchRoll() return Cesium.Math.toDegrees(this._pitch) } /** * 翻滚角,单位:度 * @type {Number} * @readonly */ get roll () { this.updateHeadingPitchRoll() return Cesium.Math.toDegrees(this._roll) } update () { this.createOrupdateCamera() this.createOrUpdateFrustum() this.createOrUpdateShadowMap() } createOrupdateCamera () { if (!defined$e(this._viewCamera)) { this._viewCamera = new Cesium.Camera(viewer.scene) } this._viewCamera.frustum.near = this._near this._viewCamera.frustum.far = this._far this._viewCamera.frustum.aspectRatio = this._aspectRatio this._viewCamera.frustum.fov = Cesium.Math.toRadians(this.fov); this._viewCamera.direction = Cesium.Cartesian3.normalize(this._direction, this._viewCamera.direction) this._viewCamera.position = Cesium.Cartesian3.clone(this._observe, this._viewCamera.position) this._viewCamera.up = this._up this._viewCamera.right = Cesium.Cartesian3.cross(this._viewCamera.up, this._viewCamera.direction, new Cesium.Cartesian3) // // const transform = Cesium.Transforms.eastNorthUpToFixedFrame( // this._viewCamera.position, this._viewCamera._projection.ellipsoid // ); // this._viewCamera._setTransform(transform); if (!defined$e(this._heading) && !defined$e(this._pitch) && !defined$e(this._roll)) { this.updateHeadingPitchRoll() } } updateHeadingPitchRoll () { const oldTransform = Cesium.Matrix4.clone(this._viewCamera._transform, new Cesium.Matrix4) const transform = Cesium.Transforms.eastNorthUpToFixedFrame( this._viewCamera.positionWC, this._viewCamera._projection.ellipsoid ) this._viewCamera._setTransform(transform) this._pitch = getPitch(this._viewCamera.direction) this._heading = getHeading(this._viewCamera.direction, this._viewCamera.up) this._roll = getRoll(this._viewCamera.direction, this._viewCamera.up, this._viewCamera.right) this._viewCamera._setTransform(oldTransform) } /** * 相机向左旋转 * @param {Number} angle 旋转角度,单位:度 */ rotateLeft (angle) { const oldTransform = Cesium.Matrix4.clone(this._viewCamera._transform, new Cesium.Matrix4) const transform = Cesium.Transforms.eastNorthUpToFixedFrame( this._viewCamera.position, this._viewCamera._projection.ellipsoid ) this._viewCamera._setTransform(transform) this._viewCamera.rotateLeft(Cesium.Math.toRadians(angle)) this._viewCamera._setTransform(oldTransform) Cesium.Cartesian3.clone(this._viewCamera.directionWC, this._direction) this.update() } /** * 相机向右旋转 * @param {Number} angle 旋转角度,单位:度 */ rotateRight (angle) { this.rotateLeft(-angle) } /** * 相机向下旋转 * @param {Number} angle 旋转角度,单位:度 */ rotateDown (angle) { const oldTransform = Cesium.Matrix4.clone(this._viewCamera._transform, new Cesium.Matrix4) const transform = Cesium.Transforms.eastNorthUpToFixedFrame( this._viewCamera.position, this._viewCamera._projection.ellipsoid ) this._viewCamera._setTransform(transform) this._viewCamera.rotateDown(Cesium.Math.toRadians(angle)) this._viewCamera._setTransform(oldTransform) Cesium.Cartesian3.clone(this._viewCamera.directionWC, this._direction) this.update() } /** * 相机向上旋转 * @param {Number} angle 旋转角度,单位:度 */ rotateUp (angle) { this.rotateDown(-angle) } createOrUpdateFrustum () { const position = this._viewCamera.positionWC const rotation = new Cesium.Matrix3 const up = this._up const direction = this.direction // this._up = viewer.scene.mapProjection.ellipsoid.geodeticSurfaceNormal(this._observe, new Cesium.Cartesian3); const right = Cesium.Cartesian3.cross(up, direction, new Cesium.Cartesian3) Cesium.Matrix3.setColumn(rotation, 0, right, rotation) Cesium.Matrix3.setColumn(rotation, 1, up, rotation) Cesium.Matrix3.setColumn(rotation, 2, direction, rotation) // const hpr = new Cesium.HeadingPitchRoll(this._heading, this._pitch, this._roll); // const orientation = Cesium.Quaternion.fromHeadingPitchRoll(hpr, new Cesium.Quaternion); const orientation = Cesium.Quaternion.fromRotationMatrix(rotation, new Cesium.Quaternion) const modelMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale( position, orientation, new Cesium.Cartesian3(1, 1, 1), new Cesium.Matrix4 ) if (this._frustum) { // this._viewer.scene.primitives.remove(this._frustum); this._frustum.modelMatrix = modelMatrix this._frustum.xHalfAngle = this._fov / 2 this._frustum.yHalfAngle = this._fov / 2 / this._aspectRatio this._frustum.radius = this._far return } // const frustum = new Cesium.GeometryInstance({ // geometry: new Cesium.FrustumOutlineGeometry({ // frustum: this._viewCamera.frustum, // origin: position, // orientation: orientation // }), // attributes: { // color: Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(0, 1, 0, 1)), // show: new Cesium.ShowGeometryInstanceAttribute(true) // } // }) // this._frustum = new Cesium.Primitive({ // id: 'viewshed', // geometryInstances: frustum, // appearance: new Cesium.PerInstanceColorAppearance({ // translucent: false, // flat: true // }) // }) this._frustum = new RectangularSensorPrimitive({ radius: this._far, modelMatrix, xHalfAngle: this._fov / 2, yHalfAngle: this._fov / 2 / this._aspectRatio, showScanPlane: false, showLateralSurfaces: false, material: Cesium.Material.fromType(Cesium.Material.ColorType, { color: Cesium.Color.AQUA.withAlpha(0.3) }), show: this.debug }) this._viewer.scene.primitives.add(this._frustum) return this._frustum } createOrUpdateShadowMap () { if (defined$e(this._shadowMap)) { this._viewer.scene.primitives.remove(this._shadowMap) } if (!(this._viewCamera && this._frustum._boundingSphereWC)) { return } this._frustum._boundingSphereWC const options = this._options options.lightCamera = this._viewCamera options.context = this._viewer.scene.context // options.cascadesEnabled = false; // options.darkness = 0.0; // options.boundingShpere = boundingShpere const shadowMap = new ViewshedMap(options) const primitive = new ViewShadowPrimitive(shadowMap) this._shadowMap = this._viewer.scene.primitives.add(primitive) return this._shadowMap } } function abstract () { throw new CesiumProError$1('抽象方法无法被调用。') } const { WebGLConstants: WebGLConstants$3, } = Cesium const datatypeToGlsl$1 = {} datatypeToGlsl$1[WebGLConstants$3.FLOAT] = "float" datatypeToGlsl$1[WebGLConstants$3.FLOAT_VEC2] = "vec2" datatypeToGlsl$1[WebGLConstants$3.FLOAT_VEC3] = "vec3" datatypeToGlsl$1[WebGLConstants$3.FLOAT_VEC4] = "vec4" datatypeToGlsl$1[WebGLConstants$3.INT] = "int" datatypeToGlsl$1[WebGLConstants$3.INT_VEC2] = "ivec2" datatypeToGlsl$1[WebGLConstants$3.INT_VEC3] = "ivec3" datatypeToGlsl$1[WebGLConstants$3.INT_VEC4] = "ivec4" datatypeToGlsl$1[WebGLConstants$3.BOOL] = "bool" datatypeToGlsl$1[WebGLConstants$3.BOOL_VEC2] = "bvec2" datatypeToGlsl$1[WebGLConstants$3.BOOL_VEC3] = "bvec3" datatypeToGlsl$1[WebGLConstants$3.BOOL_VEC4] = "bvec4" datatypeToGlsl$1[WebGLConstants$3.FLOAT_MAT2] = "mat2" datatypeToGlsl$1[WebGLConstants$3.FLOAT_MAT3] = "mat3" datatypeToGlsl$1[WebGLConstants$3.FLOAT_MAT4] = "mat4" datatypeToGlsl$1[WebGLConstants$3.SAMPLER_2D] = "sampler2D" datatypeToGlsl$1[WebGLConstants$3.SAMPLER_CUBE] = "samplerCube" function AutomaticUniform$1 (options) { this._size = options.size this._datatype = options.datatype this.getValue = options.getValue } const CesiumAutomaticUniforms$1 = Cesium.AutomaticUniforms // 卷帘对比uniforms const splitUniforms = { czm_p_drawingBufferWidth: new AutomaticUniform$1({ size: 1, datatype: WebGLConstants$3.FLOAT, getValue: function (uniformState) { return uniformState.frameState.context.drawingBufferWidth }, }), czm_p_drawingBufferHeight: new AutomaticUniform$1({ size: 1, datatype: WebGLConstants$3.FLOAT, getValue: function (uniformState) { return uniformState.frameState.context.drawingBufferHeight }, }), czm_p_splitPosition: new AutomaticUniform$1({ size: 1, datatype: WebGLConstants$3.FLOAT, getValue: function (uniformState) { return uniformState.frameState.splitPosition }, }) } function attachCustomUniforms (scene) { const uniforms = Object.assign({}, splitUniforms) const us = Object.keys(uniforms) for (let u of us) { CesiumAutomaticUniforms$1[u] = uniforms[u] } } const { Cartesian3: Cartesian3$k, Primitive: Primitive$6, Material: Material$i, Geometry: Geometry$1, MaterialAppearance: MaterialAppearance$6, GeometryAttribute: GeometryAttribute$1, ComponentDatatype: ComponentDatatype$2, PrimitiveType: PrimitiveType$3, BoundingSphere: BoundingSphere$7, VertexFormat: VertexFormat$3, defaultValue: defaultValue$a, GeometryAttributes: GeometryAttributes$1, Check, } = Cesium const scratchVertexFormat$1 = new VertexFormat$3() const scratchNormal = new Cartesian3$k() class AxisPlaneGeometry { constructor(options = {}) { this._normal = options.normal this._radius = options.radius this._center = options.center const vertexFormat = defaultValue$a( options.vertexFormat, VertexFormat$3.DEFAULT ) this._vertexFormat = vertexFormat } static packedLength = VertexFormat$3.packedLength + Cartesian3$k.packedLength + 1; static pack (value, array, startingIndex) { //>>includeStart('debug', pragmas.debug); Check.typeOf.object("value", value) Check.defined("array", array) //>>includeEnd('debug'); startingIndex = defaultValue$a(startingIndex, 0) VertexFormat$3.pack(value._vertexFormat, array, startingIndex) startingIndex += VertexFormat$3.packedLength Cartesian3$k.pack(value._normal, array, startingIndex) startingIndex += Cartesian3$k.packedLength array[startingIndex++] = value._radius return array } static unpack (array, startingIndex, result) { //>>includeStart('debug', pragmas.debug); Check.defined("array", array) //>>includeEnd('debug'); startingIndex = defaultValue$a(startingIndex, 0) const vertexFormat = VertexFormat$3.unpack( array, startingIndex, scratchVertexFormat$1 ) startingIndex += VertexFormat$3.packedLength const normal = Cartesian3$k.unpack(array, startingIndex, scratchNormal) startingIndex += Cartesian3$k.packedLength const radius = array[startingIndex] if (!defined(result)) { return new PlaneGeometry({ vertexFormat, normal, radius, }) } result._vertexFormat = VertexFormat$3.clone( vertexFormat, result._vertexFormat ) result._normal = Cartesian3$k.clone(normal, result._normal) result._radius = radius return result } static createGeometry (planeGeometry) { const v1 = Math.max(1, planeGeometry._radius * 0.02) const v2 = Math.max(planeGeometry._radius * 0.2, v1 * 2) let positions = [] let normal = [] const { x, y, z } = planeGeometry._center let center if (Cartesian3$k.equals(planeGeometry._normal, Cartesian3$k.UNIT_X)) { positions = [x, -v1 + y, v1 + z, x, -v2 + y, v1 + z, x, -v2 + y, v2 + z, x, -v1 + y, v2 + z] center = new Cartesian3$k(x, -(v1 + v2) / 2 + y, (v1 + v2) / 2 + z) normal = [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0] } else if (Cartesian3$k.equals(planeGeometry._normal, Cartesian3$k.UNIT_Y)) { positions = [v1 + x, y, v1 + z, v2 + x, y, v1 + z, v2 + x, y, v2 + z, v1 + x, y, v2 + z] center = new Cartesian3$k((v1 + v2) / 2 + x, y, (v1 + v2) / 2 + z) normal = [0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0] } else if (Cartesian3$k.equals(planeGeometry._normal, Cartesian3$k.UNIT_Z)) { positions = [v1 + x, -v1 + y, z, v2 + x, -v1 + y, z, v2 + x, -v2 + y, z, v1 + x, -v2 + y, z] center = new Cartesian3$k((v1 + v2) / 2 + x, -(v1 + v2) / 2 + y, z) normal = [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1] } positions = new Float32Array([...positions]) const sts = new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]) const indices = new Uint16Array([0, 1, 2, 2, 3, 0]) return new Geometry$1({ attributes: new GeometryAttributes$1({ position: new GeometryAttribute$1({ componentDatatype: ComponentDatatype$2.DOUBLE, componentsPerAttribute: 3, values: positions, }), normal: new GeometryAttribute$1({ componentDatatype: ComponentDatatype$2.FLOAT, componentsPerAttribute: 3, values: normal, }), st: new GeometryAttribute$1({ componentDatatype: ComponentDatatype$2.FLOAT, componentsPerAttribute: 2, values: sts, }), }), indices: indices, primitiveType: PrimitiveType$3.TRIANGLES, boundingSphere: new BoundingSphere$7(center, (v1 + v2) / 2), }) } } class AxisPlane { /** * 坐标轴平面 * @private * @param {*} options */ constructor(options = {}) { this._center = options.center this._modelMatrix = options.modelMatrix this._color = options.color const radius = options.radius; this._normal = options.normal const planeGeometry = new AxisPlaneGeometry({ normal: this._normal, radius: radius, vertexFormat: VertexFormat$3.DEFAULT, center: this._center, }) const instance = new Cesium.GeometryInstance({ geometry: AxisPlaneGeometry.createGeometry(planeGeometry), }) const primitive = new Primitive$6({ asynchronous: false, geometryInstances: instance, modelMatrix: this._modelMatrix, appearance: new MaterialAppearance$6({ material: Material$i.fromType("Color", { color: this._color, }), }), }) primitive.isAxisPlane = true primitive.normal = this._normal primitive.axis = options.axis primitive.color = this._color return primitive } } /** * 地图量算类型 * @exports CartometryType * @enum {Number} */ const CartometryType = { /** * 贴地距离 * @type {Number} * @constant */ SURFACE_DISTANCE: 1, /** * 空间距离 * @type {Number} * @constant */ SPACE_DISTANCE: 2, /** * 空间面积 * @type {Number} * @constant */ SPACE_AREA: 3, /** * 贴地面积 * @type {Number} * @constant */ SURFACE_AREA: 4, /** * 高度 * @type {Number} * @constant */ HEIGHT: 5, /** * 方位角 * @type {Number} * @constant */ ANGLE: 6, } /** * 验证是否是合法类型 * @param {CartometryType} * @returns {Number} true表示有效 */ CartometryType.validate = function (type) { return type === CartometryType.SURFACE_AREA || type === CartometryType.SURFACE_DISTANCE || type === CartometryType.SPACE_AREA || type === CartometryType.SPACE_DISTANCE || type === CartometryType.HEIGHT || type === CartometryType.ANGLE } /** * 从枚举值获得枚举标签 * @param {CartometryType} value 枚举值 * @returns {String} 枚举值对应的类型 */ CartometryType.getKey = function (value) { let key switch (value) { case 1: key = 'SURFACE_DISTANCE' break case 2: key = 'SPACE_DISTANCE' break case 3: key = 'SPACE_AREA' break case 4: key = 'SURFACE_AREA' break case 5: key = 'HEIGHT' break case 6: key = 'ANGLE' break default: key = undefined } return key } /** * 根据key获得中文名 * @param {*} value * @returns {String} 枚举值对应的类型 */ CartometryType.getValue = function (value) { let key switch (value) { case 1: key = '贴地距离' break case 2: key = '空间距离' break case 3: key = '空间面积' break case 4: key = '贴地面积' break case 5: key = '高度' break case 6: key = '方位角' break default: key = undefined } return key } var CartometryType$1 = Object.freeze(CartometryType) const { RequestState: RequestState$1, AttributeCompression, BoundingSphere: BoundingSphere$6, Cartesian3: Cartesian3$j, Credit: Credit$2, defaultValue: defaultValue$9, defined: defined$b, DeveloperError: DeveloperError$3, GeographicTilingScheme: GeographicTilingScheme$5, WebMercatorTilingScheme: WebMercatorTilingScheme$1, getJsonFromTypedArray, HeightmapTerrainData, IndexDatatype: IndexDatatype$2, OrientedBoundingBox, QuantizedMeshTerrainData, Request: Request$1, RequestType: RequestType$1, Resource: Resource$7, RuntimeError: RuntimeError$2, TerrainProvider: TerrainProvider$1, TileAvailability, TileProviderError: TileProviderError$1 } = Cesium function LayerInformation (layer) { this.resource = layer.resource this.version = layer.version this.isHeightmap = layer.isHeightmap this.tileUrlTemplates = layer.tileUrlTemplates this.availability = layer.availability this.hasVertexNormals = layer.hasVertexNormals this.hasWaterMask = layer.hasWaterMask this.hasMetadata = layer.hasMetadata this.availabilityLevels = layer.availabilityLevels this.availabilityTilesLoaded = layer.availabilityTilesLoaded this.littleEndianExtensionSize = layer.littleEndianExtensionSize this.availabilityPromiseCache = {} } /** * A {@link TerrainProvider} that accesses terrain data in a Cesium terrain format. * Terrain formats can be one of the following: *
    *
  • {@link https://github.com/AnalyticalGraphicsInc/quantized-mesh Quantized Mesh}
  • *
  • {@link https://github.com/AnalyticalGraphicsInc/cesium/wiki/heightmap-1.0 Height Map}
  • *
* * @alias CesiumTerrainProvider * @constructor * * @param {Object} options Object with the following properties: * @param {Resource|String|Promise|Promise} options.url The URL of the Cesium terrain server. * @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available. * @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server, if available. * @param {Boolean} [options.requestMetadata=true] Flag that indicates if the client should request per tile metadata from the server, if available. * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used. * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas. * * * @example * // Create Arctic DEM terrain with normals. * const viewer = new Cesium.Viewer('cesiumContainer', { * terrainProvider : new Cesium.CesiumTerrainProvider({ * url : Cesium.IonResource.fromAssetId(3956), * requestVertexNormals : true * }) * }); * * @see createWorldTerrain * @see TerrainProvider */ function CesiumTerrainProvider$1 (options) { //>>includeStart('debug', pragmas.debug) if (!defined$b(options) || !defined$b(options.url)) { throw new DeveloperError$3("options.url is required.") } //>>includeEnd('debug'); this._heightmapWidth = 65 this._heightmapStructure = undefined this._hasWaterMask = false this._hasVertexNormals = false this._ellipsoid = options.ellipsoid /** * Boolean flag that indicates if the client should request vertex normals from the server. * @type {Boolean} * @default false * @private */ this._requestVertexNormals = defaultValue$9( options.requestVertexNormals, false ) /** * Boolean flag that indicates if the client should request tile watermasks from the server. * @type {Boolean} * @default false * @private */ this._requestWaterMask = defaultValue$9(options.requestWaterMask, false) /** * Boolean flag that indicates if the client should request tile metadata from the server. * @type {Boolean} * @default true * @private */ this._requestMetadata = defaultValue$9(options.requestMetadata, true) this._errorEvent = new Event$a() let credit = options.credit if (typeof credit === "string") { credit = new Credit$2(credit) } this._credit = credit this._availability = undefined this._ready = false this._tileCredits = undefined const that = this let lastResource let layerJsonResource let metadataError const layers = (this._layers = []) let attribution = "" const overallAvailability = [] let overallMaxZoom = 0 this._readyPromise = Promise.resolve(options.url).then(function (url) { const resource = Resource$7.createIfNeeded(url) resource.appendForwardSlash() lastResource = resource layerJsonResource = lastResource.getDerivedResource({ url: "layer.json", }) // ion resources have a credits property we can use for additional attribution. that._tileCredits = resource.credits return requestLayerJson() }) function parseMetadataSuccess (data) { let message if (!data.format) { message = "The tile format is not specified in the layer.json file." metadataError = TileProviderError$1.reportError( metadataError, that, that._errorEvent, message ) if (metadataError.retry) { return requestLayerJson() } return Promise.reject(new RuntimeError$2(message)) } if (!data.tiles || data.tiles.length === 0) { message = "The layer.json file does not specify any tile URL templates." metadataError = TileProviderError$1.reportError( metadataError, that, that._errorEvent, message ) if (metadataError.retry) { return requestLayerJson() } return Promise.reject(new RuntimeError$2(message)) } let hasVertexNormals = false let hasWaterMask = false let hasMetadata = false let littleEndianExtensionSize = true let isHeightmap = false if (data.format === "heightmap-1.0") { isHeightmap = true if (!defined$b(that._heightmapStructure)) { that._heightmapStructure = { heightScale: 1.0 / 5.0, heightOffset: -1000.0, elementsPerHeight: 1, stride: 1, elementMultiplier: 256.0, isBigEndian: false, lowestEncodedHeight: 0, highestEncodedHeight: 256 * 256 - 1, } } hasWaterMask = true that._requestWaterMask = true } else if (data.format.indexOf("quantized-mesh-1.") !== 0) { message = `The tile format "${data.format}" is invalid or not supported.` metadataError = TileProviderError$1.reportError( metadataError, that, that._errorEvent, message ) if (metadataError.retry) { return requestLayerJson() } return Promise.reject(new RuntimeError$2(message)) } const tileUrlTemplates = data.tiles const maxZoom = data.maxzoom overallMaxZoom = Math.max(overallMaxZoom, maxZoom) // Keeps track of which of the availablity containing tiles have been loaded if (!data.projection || data.projection === "EPSG:4326") { that._tilingScheme = new GeographicTilingScheme$5({ numberOfLevelZeroTilesX: 2, numberOfLevelZeroTilesY: 1, ellipsoid: that._ellipsoid, }) } else if (data.projection === "EPSG:3857") { that._tilingScheme = new WebMercatorTilingScheme$1({ numberOfLevelZeroTilesX: 1, numberOfLevelZeroTilesY: 1, ellipsoid: that._ellipsoid, }) } else { message = `The projection "${data.projection}" is invalid or not supported.` metadataError = TileProviderError$1.reportError( metadataError, that, that._errorEvent, message ) if (metadataError.retry) { return requestLayerJson() } return Promise.reject(new RuntimeError$2(message)) } that._levelZeroMaximumGeometricError = TerrainProvider$1.getEstimatedLevelZeroGeometricErrorForAHeightmap( that._tilingScheme.ellipsoid, that._heightmapWidth, that._tilingScheme.getNumberOfXTilesAtLevel(0) ) if (!data.scheme || data.scheme === "tms" || data.scheme === "slippyMap") { that._scheme = data.scheme } else { message = `The scheme "${data.scheme}" is invalid or not supported.` metadataError = TileProviderError$1.reportError( metadataError, that, that._errorEvent, message ) if (metadataError.retry) { return requestLayerJson() } return Promise.reject(new RuntimeError$2(message)) } let availabilityTilesLoaded // The vertex normals defined in the 'octvertexnormals' extension is identical to the original // contents of the original 'vertexnormals' extension. 'vertexnormals' extension is now // deprecated, as the extensionLength for this extension was incorrectly using big endian. // We maintain backwards compatibility with the legacy 'vertexnormal' implementation // by setting the _littleEndianExtensionSize to false. Always prefer 'octvertexnormals' // over 'vertexnormals' if both extensions are supported by the server. if ( defined$b(data.extensions) && data.extensions.indexOf("octvertexnormals") !== -1 ) { hasVertexNormals = true } else if ( defined$b(data.extensions) && data.extensions.indexOf("vertexnormals") !== -1 ) { hasVertexNormals = true littleEndianExtensionSize = false } if ( defined$b(data.extensions) && data.extensions.indexOf("watermask") !== -1 ) { hasWaterMask = true } if ( defined$b(data.extensions) && data.extensions.indexOf("metadata") !== -1 ) { hasMetadata = true } const availabilityLevels = data.metadataAvailability const availableTiles = data.available let availability if (defined$b(availableTiles) && !defined$b(availabilityLevels)) { availability = new TileAvailability( that._tilingScheme, availableTiles.length ) for (let level = 0; level < availableTiles.length; ++level) { const rangesAtLevel = availableTiles[level] const yTiles = that._tilingScheme.getNumberOfYTilesAtLevel(level) if (!defined$b(overallAvailability[level])) { overallAvailability[level] = [] } for ( let rangeIndex = 0; rangeIndex < rangesAtLevel.length; ++rangeIndex ) { const range = rangesAtLevel[rangeIndex] const yStart = yTiles - range.endY - 1 const yEnd = yTiles - range.startY - 1 overallAvailability[level].push([ range.startX, yStart, range.endX, yEnd, ]) availability.addAvailableTileRange( level, range.startX, yStart, range.endX, yEnd ) } } } else if (defined$b(availabilityLevels)) { availabilityTilesLoaded = new TileAvailability( that._tilingScheme, maxZoom ) availability = new TileAvailability(that._tilingScheme, maxZoom) overallAvailability[0] = [[0, 0, 1, 0]] availability.addAvailableTileRange(0, 0, 0, 1, 0) } that._hasWaterMask = that._hasWaterMask || hasWaterMask that._hasVertexNormals = that._hasVertexNormals || hasVertexNormals that._hasMetadata = that._hasMetadata || hasMetadata if (defined$b(data.attribution)) { if (attribution.length > 0) { attribution += " " } attribution += data.attribution } layers.push( new LayerInformation({ resource: lastResource, version: data.version, isHeightmap: isHeightmap, tileUrlTemplates: tileUrlTemplates, availability: availability, hasVertexNormals: hasVertexNormals, hasWaterMask: hasWaterMask, hasMetadata: hasMetadata, availabilityLevels: availabilityLevels, availabilityTilesLoaded: availabilityTilesLoaded, littleEndianExtensionSize: littleEndianExtensionSize, }) ) const parentUrl = data.parentUrl if (defined$b(parentUrl)) { if (!defined$b(availability)) { console.log( "A layer.json can't have a parentUrl if it does't have an available array." ) return Promise.resolve(true) } lastResource = lastResource.getDerivedResource({ url: parentUrl, }) lastResource.appendForwardSlash() // Terrain always expects a directory layerJsonResource = lastResource.getDerivedResource({ url: "layer.json", }) const parentMetadata = layerJsonResource.fetchJson() return Promise.resolve(parentMetadata) .then(parseMetadataSuccess) .catch(parseMetadataFailure) } return Promise.resolve(true) } function parseMetadataFailure (data) { const message = `An error occurred while accessing ${layerJsonResource.url}.` metadataError = TileProviderError$1.reportError( metadataError, that, that._errorEvent, message ) if (metadataError.retry) { return requestLayerJson() } return Promise.reject(new RuntimeError$2(message)) } function metadataSuccess (data) { return parseMetadataSuccess(data).then(function () { if (defined$b(metadataError)) { return } const length = overallAvailability.length if (length > 0) { const availability = (that._availability = new TileAvailability( that._tilingScheme, overallMaxZoom )) for (let level = 0; level < length; ++level) { const levelRanges = overallAvailability[level] for (let i = 0; i < levelRanges.length; ++i) { const range = levelRanges[i] availability.addAvailableTileRange( level, range[0], range[1], range[2], range[3] ) } } } if (attribution.length > 0) { const layerJsonCredit = new Credit$2(attribution) if (defined$b(that._tileCredits)) { that._tileCredits.push(layerJsonCredit) } else { that._tileCredits = [layerJsonCredit] } } that._ready = true return Promise.resolve(true) }) } function metadataFailure (data) { // If the metadata is not found, assume this is a pre-metadata heightmap tileset. if (defined$b(data) && data.statusCode === 404) { return metadataSuccess({ tilejson: "2.1.0", format: "heightmap-1.0", version: "1.0.0", scheme: "tms", tiles: ["{z}/{x}/{y}.terrain?v={version}"], }) } return parseMetadataFailure() } function requestLayerJson () { return Promise.resolve(layerJsonResource.fetchJson()) .then(metadataSuccess) .catch(metadataFailure) } } /** * When using the Quantized-Mesh format, a tile may be returned that includes additional extensions, such as PerVertexNormals, watermask, etc. * This enumeration defines the unique identifiers for each type of extension data that has been appended to the standard mesh data. * * @namespace QuantizedMeshExtensionIds * @see CesiumTerrainProvider * @private */ const QuantizedMeshExtensionIds = { /** * Oct-Encoded Per-Vertex Normals are included as an extension to the tile mesh * * @type {Number} * @constant * @default 1 */ OCT_VERTEX_NORMALS: 1, /** * A watermask is included as an extension to the tile mesh * * @type {Number} * @constant * @default 2 */ WATER_MASK: 2, /** * A json object contain metadata about the tile * * @type {Number} * @constant * @default 4 */ METADATA: 4, } function getRequestHeader (extensionsList) { if (!defined$b(extensionsList) || extensionsList.length === 0) { return { Accept: "application/vnd.quantized-mesh,application/octet-stream;q=0.9,*/*;q=0.01", } } const extensions = extensionsList.join("-") return { Accept: `application/vnd.quantized-mesh;extensions=${extensions},application/octet-stream;q=0.9,*/*;q=0.01`, } } function createHeightmapTerrainData (provider, buffer, level, x, y) { const heightBuffer = new Uint16Array( buffer, 0, provider._heightmapWidth * provider._heightmapWidth ) return new HeightmapTerrainData({ buffer: heightBuffer, childTileMask: new Uint8Array(buffer, heightBuffer.byteLength, 1)[0], waterMask: new Uint8Array( buffer, heightBuffer.byteLength + 1, buffer.byteLength - heightBuffer.byteLength - 1 ), width: provider._heightmapWidth, height: provider._heightmapWidth, structure: provider._heightmapStructure, credits: provider._tileCredits, }) } function createQuantizedMeshTerrainData (provider, buffer, level, x, y, layer) { const littleEndianExtensionSize = layer.littleEndianExtensionSize let pos = 0 const cartesian3Elements = 3 const boundingSphereElements = cartesian3Elements + 1 const cartesian3Length = Float64Array.BYTES_PER_ELEMENT * cartesian3Elements const boundingSphereLength = Float64Array.BYTES_PER_ELEMENT * boundingSphereElements const encodedVertexElements = 3 const encodedVertexLength = Uint16Array.BYTES_PER_ELEMENT * encodedVertexElements const triangleElements = 3 let bytesPerIndex = Uint16Array.BYTES_PER_ELEMENT let triangleLength = bytesPerIndex * triangleElements const view = new DataView(buffer) const center = new Cartesian3$j( view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true) ) pos += cartesian3Length const minimumHeight = view.getFloat32(pos, true) pos += Float32Array.BYTES_PER_ELEMENT const maximumHeight = view.getFloat32(pos, true) pos += Float32Array.BYTES_PER_ELEMENT const boundingSphere = new BoundingSphere$6( new Cartesian3$j( view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true) ), view.getFloat64(pos + cartesian3Length, true) ) pos += boundingSphereLength const horizonOcclusionPoint = new Cartesian3$j( view.getFloat64(pos, true), view.getFloat64(pos + 8, true), view.getFloat64(pos + 16, true) ) pos += cartesian3Length const vertexCount = view.getUint32(pos, true) pos += Uint32Array.BYTES_PER_ELEMENT const encodedVertexBuffer = new Uint16Array(buffer, pos, vertexCount * 3) pos += vertexCount * encodedVertexLength if (vertexCount > 64 * 1024) { // More than 64k vertices, so indices are 32-bit. bytesPerIndex = Uint32Array.BYTES_PER_ELEMENT triangleLength = bytesPerIndex * triangleElements } // Decode the vertex buffer. const uBuffer = encodedVertexBuffer.subarray(0, vertexCount) const vBuffer = encodedVertexBuffer.subarray(vertexCount, 2 * vertexCount) const heightBuffer = encodedVertexBuffer.subarray( vertexCount * 2, 3 * vertexCount ) AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer) // skip over any additional padding that was added for 2/4 byte alignment if (pos % bytesPerIndex !== 0) { pos += bytesPerIndex - (pos % bytesPerIndex) } const triangleCount = view.getUint32(pos, true) pos += Uint32Array.BYTES_PER_ELEMENT const indices = IndexDatatype$2.createTypedArrayFromArrayBuffer( vertexCount, buffer, pos, triangleCount * triangleElements ) pos += triangleCount * triangleLength // High water mark decoding based on decompressIndices_ in webgl-loader's loader.js. // https://code.google.com/p/webgl-loader/source/browse/trunk/samples/loader.js?r=99#55 // Copyright 2012 Google Inc., Apache 2.0 license. let highest = 0 const length = indices.length for (let i = 0; i < length; ++i) { const code = indices[i] indices[i] = highest - code if (code === 0) { ++highest } } const westVertexCount = view.getUint32(pos, true) pos += Uint32Array.BYTES_PER_ELEMENT const westIndices = IndexDatatype$2.createTypedArrayFromArrayBuffer( vertexCount, buffer, pos, westVertexCount ) pos += westVertexCount * bytesPerIndex const southVertexCount = view.getUint32(pos, true) pos += Uint32Array.BYTES_PER_ELEMENT const southIndices = IndexDatatype$2.createTypedArrayFromArrayBuffer( vertexCount, buffer, pos, southVertexCount ) pos += southVertexCount * bytesPerIndex const eastVertexCount = view.getUint32(pos, true) pos += Uint32Array.BYTES_PER_ELEMENT const eastIndices = IndexDatatype$2.createTypedArrayFromArrayBuffer( vertexCount, buffer, pos, eastVertexCount ) pos += eastVertexCount * bytesPerIndex const northVertexCount = view.getUint32(pos, true) pos += Uint32Array.BYTES_PER_ELEMENT const northIndices = IndexDatatype$2.createTypedArrayFromArrayBuffer( vertexCount, buffer, pos, northVertexCount ) pos += northVertexCount * bytesPerIndex let encodedNormalBuffer let waterMaskBuffer while (pos < view.byteLength) { const extensionId = view.getUint8(pos, true) pos += Uint8Array.BYTES_PER_ELEMENT const extensionLength = view.getUint32(pos, littleEndianExtensionSize) pos += Uint32Array.BYTES_PER_ELEMENT if ( extensionId === QuantizedMeshExtensionIds.OCT_VERTEX_NORMALS && provider._requestVertexNormals ) { encodedNormalBuffer = new Uint8Array(buffer, pos, vertexCount * 2) } else if ( extensionId === QuantizedMeshExtensionIds.WATER_MASK && provider._requestWaterMask ) { waterMaskBuffer = new Uint8Array(buffer, pos, extensionLength) } else if ( extensionId === QuantizedMeshExtensionIds.METADATA && provider._requestMetadata ) { const stringLength = view.getUint32(pos, true) if (stringLength > 0) { const metadata = getJsonFromTypedArray( new Uint8Array(buffer), pos + Uint32Array.BYTES_PER_ELEMENT, stringLength ) const availableTiles = metadata.available if (defined$b(availableTiles)) { for (let offset = 0; offset < availableTiles.length; ++offset) { const availableLevel = level + offset + 1 const rangesAtLevel = availableTiles[offset] const yTiles = provider._tilingScheme.getNumberOfYTilesAtLevel( availableLevel ) for ( let rangeIndex = 0; rangeIndex < rangesAtLevel.length; ++rangeIndex ) { const range = rangesAtLevel[rangeIndex] const yStart = yTiles - range.endY - 1 const yEnd = yTiles - range.startY - 1 provider.availability.addAvailableTileRange( availableLevel, range.startX, yStart, range.endX, yEnd ) layer.availability.addAvailableTileRange( availableLevel, range.startX, yStart, range.endX, yEnd ) } } } } layer.availabilityTilesLoaded.addAvailableTileRange(level, x, y, x, y) } pos += extensionLength } const skirtHeight = provider.getLevelMaximumGeometricError(level) * 5.0 // The skirt is not included in the OBB computation. If this ever // causes any rendering artifacts (cracks), they are expected to be // minor and in the corners of the screen. It's possible that this // might need to be changed - just change to `minimumHeight - skirtHeight` // A similar change might also be needed in `upsampleQuantizedTerrainMesh.js`. const rectangle = provider._tilingScheme.tileXYToRectangle(x, y, level) const orientedBoundingBox = OrientedBoundingBox.fromRectangle( rectangle, minimumHeight, maximumHeight, provider._tilingScheme.ellipsoid ) return new QuantizedMeshTerrainData({ center: center, minimumHeight: minimumHeight, maximumHeight: maximumHeight, boundingSphere: boundingSphere, orientedBoundingBox: orientedBoundingBox, horizonOcclusionPoint: horizonOcclusionPoint, quantizedVertices: encodedVertexBuffer, encodedNormals: encodedNormalBuffer, indices: indices, westIndices: westIndices, southIndices: southIndices, eastIndices: eastIndices, northIndices: northIndices, westSkirtHeight: skirtHeight, southSkirtHeight: skirtHeight, eastSkirtHeight: skirtHeight, northSkirtHeight: skirtHeight, childTileMask: provider.availability.computeChildMaskForTile(level, x, y), waterMask: waterMaskBuffer, credits: provider._tileCredits, }) } /** * Requests the geometry for a given tile. This function should not be called before * {@link CesiumTerrainProvider#ready} returns true. The result must include terrain data and * may optionally include a water mask and an indication of which child tiles are available. * * @param {Number} x The X coordinate of the tile for which to request geometry. * @param {Number} y The Y coordinate of the tile for which to request geometry. * @param {Number} level The level of the tile for which to request geometry. * @param {Request} [request] The request object. Intended for internal use only. * * @returns {Promise.|undefined} A promise for the requested geometry. If this method * returns undefined instead of a promise, it is an indication that too many requests are already * pending and the request will be retried later. * * @exception {DeveloperError} This function must not be called before {@link CesiumTerrainProvider#ready} * returns true. */ CesiumTerrainProvider$1.prototype.requestTileGeometry = function ( x, y, level, request ) { //>>includeStart('debug', pragmas.debug) if (!this._ready) { throw new DeveloperError$3( "requestTileGeometry must not be called before the terrain provider is ready." ) } //>>includeEnd('debug'); const layers = this._layers let layerToUse const layerCount = layers.length if (layerCount === 1) { // Optimized path for single layers layerToUse = layers[0] } else { for (let i = 0; i < layerCount; ++i) { const layer = layers[i] if ( !defined$b(layer.availability) || layer.availability.isTileAvailable(level, x, y) ) { layerToUse = layer break } } } return requestTileGeometry(this, x, y, level, layerToUse, request) } function requestTileGeometry (provider, x, y, level, layerToUse, request) { if (!defined$b(layerToUse)) { return Promise.reject(new RuntimeError$2("Terrain tile doesn't exist")) } const urlTemplates = layerToUse.tileUrlTemplates if (urlTemplates.length === 0) { return undefined } // The TileMapService scheme counts from the bottom left let terrainY if (!provider._scheme || provider._scheme === "tms") { const yTiles = provider._tilingScheme.getNumberOfYTilesAtLevel(level) terrainY = yTiles - y - 1 } else { terrainY = y } const extensionList = [] if (provider._requestVertexNormals && layerToUse.hasVertexNormals) { extensionList.push( layerToUse.littleEndianExtensionSize ? "octvertexnormals" : "vertexnormals" ) } if (provider._requestWaterMask && layerToUse.hasWaterMask) { extensionList.push("watermask") } if (provider._requestMetadata && layerToUse.hasMetadata) { extensionList.push("metadata") } let headers let query const url = urlTemplates[(x + terrainY + level) % urlTemplates.length] const resource = layerToUse.resource if ( defined$b(resource._ionEndpoint) && !defined$b(resource._ionEndpoint.externalType) ) { // ion uses query paremeters to request extensions if (extensionList.length !== 0) { query = { extensions: extensionList.join("-") } } headers = getRequestHeader(undefined) } else { //All other terrain servers headers = getRequestHeader(extensionList) } const promise = resource .getDerivedResource({ url: url, templateValues: { version: layerToUse.version, z: level, x: x, y: terrainY, }, queryParameters: query, headers: headers, request: request, }) .fetchArrayBuffer() if (resource.request.state === RequestState$1.ISSUED || resource.request.state === RequestState$1.ACTIVE) { return } if (!defined$b(promise)) { return undefined } return promise.then(function (buffer) { if (!defined$b(buffer)) { return Promise.reject(new RuntimeError$2("Mesh buffer doesn't exist.")) } if (defined$b(provider._heightmapStructure)) { return createHeightmapTerrainData(provider, buffer) } return createQuantizedMeshTerrainData( provider, buffer, level, x, y, layerToUse ) }) } Object.defineProperties(CesiumTerrainProvider$1.prototype, { /** * Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing * to the event, you will be notified of the error and can potentially recover from it. Event listeners * are passed an instance of {@link TileProviderError}. * @memberof CesiumTerrainProvider.prototype * @type {Event} * @readonly */ errorEvent: { get: function () { return this._errorEvent }, }, /** * Gets the credit to display when this terrain provider is active. Typically this is used to credit * the source of the terrain. This function should not be called before {@link CesiumTerrainProvider#ready} returns true. * @memberof CesiumTerrainProvider.prototype * @type {Credit} * @readonly */ credit: { get: function () { //>>includeStart('debug', pragmas.debug) if (!this._ready) { throw new DeveloperError$3( "credit must not be called before the terrain provider is ready." ) } //>>includeEnd('debug'); return this._credit }, }, /** * Gets the tiling scheme used by this provider. This function should * not be called before {@link CesiumTerrainProvider#ready} returns true. * @memberof CesiumTerrainProvider.prototype * @type {GeographicTilingScheme} * @readonly */ tilingScheme: { get: function () { //>>includeStart('debug', pragmas.debug) if (!this._ready) { throw new DeveloperError$3( "tilingScheme must not be called before the terrain provider is ready." ) } //>>includeEnd('debug'); return this._tilingScheme }, }, /** * Gets a value indicating whether or not the provider is ready for use. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} * @readonly */ ready: { get: function () { return this._ready }, }, /** * Gets a promise that resolves to true when the provider is ready for use. * @memberof CesiumTerrainProvider.prototype * @type {Promise.} * @readonly */ readyPromise: { get: function () { return this._readyPromise }, }, /** * Gets a value indicating whether or not the provider includes a water mask. The water mask * indicates which areas of the globe are water rather than land, so they can be rendered * as a reflective surface with animated waves. This function should not be * called before {@link CesiumTerrainProvider#ready} returns true. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} * @readonly * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready} */ hasWaterMask: { get: function () { //>>includeStart('debug', pragmas.debug) if (!this._ready) { throw new DeveloperError$3( "hasWaterMask must not be called before the terrain provider is ready." ) } //>>includeEnd('debug'); return this._hasWaterMask && this._requestWaterMask }, }, /** * Gets a value indicating whether or not the requested tiles include vertex normals. * This function should not be called before {@link CesiumTerrainProvider#ready} returns true. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} * @readonly * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready} */ hasVertexNormals: { get: function () { //>>includeStart('debug', pragmas.debug) if (!this._ready) { throw new DeveloperError$3( "hasVertexNormals must not be called before the terrain provider is ready." ) } //>>includeEnd('debug'); // returns true if we can request vertex normals from the server return this._hasVertexNormals && this._requestVertexNormals }, }, /** * Gets a value indicating whether or not the requested tiles include metadata. * This function should not be called before {@link CesiumTerrainProvider#ready} returns true. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} * @readonly * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready} */ hasMetadata: { get: function () { //>>includeStart('debug', pragmas.debug) if (!this._ready) { throw new DeveloperError$3( "hasMetadata must not be called before the terrain provider is ready." ) } //>>includeEnd('debug'); // returns true if we can request metadata from the server return this._hasMetadata && this._requestMetadata }, }, /** * Boolean flag that indicates if the client should request vertex normals from the server. * Vertex normals data is appended to the standard tile mesh data only if the client requests the vertex normals and * if the server provides vertex normals. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} * @readonly */ requestVertexNormals: { get: function () { return this._requestVertexNormals }, }, /** * Boolean flag that indicates if the client should request a watermask from the server. * Watermask data is appended to the standard tile mesh data only if the client requests the watermask and * if the server provides a watermask. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} * @readonly */ requestWaterMask: { get: function () { return this._requestWaterMask }, }, /** * Boolean flag that indicates if the client should request metadata from the server. * Metadata is appended to the standard tile mesh data only if the client requests the metadata and * if the server provides a metadata. * @memberof CesiumTerrainProvider.prototype * @type {Boolean} * @readonly */ requestMetadata: { get: function () { return this._requestMetadata }, }, /** * Gets an object that can be used to determine availability of terrain from this provider, such as * at points and in rectangles. This function should not be called before * {@link CesiumTerrainProvider#ready} returns true. This property may be undefined if availability * information is not available. Note that this reflects tiles that are known to be available currently. * Additional tiles may be discovered to be available in the future, e.g. if availability information * exists deeper in the tree rather than it all being discoverable at the root. However, a tile that * is available now will not become unavailable in the future. * @memberof CesiumTerrainProvider.prototype * @type {TileAvailability} * @readonly */ availability: { get: function () { //>>includeStart('debug', pragmas.debug) if (!this._ready) { throw new DeveloperError$3( "availability must not be called before the terrain provider is ready." ) } //>>includeEnd('debug'); return this._availability }, }, }) /** * Gets the maximum geometric error allowed in a tile at a given level. * * @param {Number} level The tile level for which to get the maximum geometric error. * @returns {Number} The maximum geometric error. */ CesiumTerrainProvider$1.prototype.getLevelMaximumGeometricError = function ( level ) { return this._levelZeroMaximumGeometricError / (1 << level) } /** * Determines whether data for a tile is available to be loaded. * * @param {Number} x The X coordinate of the tile for which to request geometry. * @param {Number} y The Y coordinate of the tile for which to request geometry. * @param {Number} level The level of the tile for which to request geometry. * @returns {Boolean|undefined} Undefined if not supported or availability is unknown, otherwise true or false. */ CesiumTerrainProvider$1.prototype.getTileDataAvailable = function (x, y, level) { if (!defined$b(this._availability)) { return undefined } if (level > this._availability._maximumLevel) { return false } if (this._availability.isTileAvailable(level, x, y)) { // If the tile is listed as available, then we are done return true } if (!this._hasMetadata) { // If we don't have any layers with the metadata extension then we don't have this tile return false } const layers = this._layers const count = layers.length for (let i = 0; i < count; ++i) { const layerResult = checkLayer(this, x, y, level, layers[i], i === 0) if (layerResult.result) { // There is a layer that may or may not have the tile return undefined } } return false } /** * Makes sure we load availability data for a tile * * @param {Number} x The X coordinate of the tile for which to request geometry. * @param {Number} y The Y coordinate of the tile for which to request geometry. * @param {Number} level The level of the tile for which to request geometry. * @returns {undefined|Promise} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded */ CesiumTerrainProvider$1.prototype.loadTileDataAvailability = function ( x, y, level ) { if ( !defined$b(this._availability) || level > this._availability._maximumLevel || this._availability.isTileAvailable(level, x, y) || !this._hasMetadata ) { // We know the tile is either available or not available so nothing to wait on return undefined } const layers = this._layers const count = layers.length for (let i = 0; i < count; ++i) { const layerResult = checkLayer(this, x, y, level, layers[i], i === 0) if (defined$b(layerResult.promise)) { return layerResult.promise } } } function getAvailabilityTile (layer, x, y, level) { if (level === 0) { return } const availabilityLevels = layer.availabilityLevels const parentLevel = level % availabilityLevels === 0 ? level - availabilityLevels : ((level / availabilityLevels) | 0) * availabilityLevels const divisor = 1 << (level - parentLevel) const parentX = (x / divisor) | 0 const parentY = (y / divisor) | 0 return { level: parentLevel, x: parentX, y: parentY, } } function checkLayer (provider, x, y, level, layer, topLayer) { if (!defined$b(layer.availabilityLevels)) { // It's definitely not in this layer return { result: false, } } let cacheKey const deleteFromCache = function () { delete layer.availabilityPromiseCache[cacheKey] } const availabilityTilesLoaded = layer.availabilityTilesLoaded const availability = layer.availability let tile = getAvailabilityTile(layer, x, y, level) while (defined$b(tile)) { if ( availability.isTileAvailable(tile.level, tile.x, tile.y) && !availabilityTilesLoaded.isTileAvailable(tile.level, tile.x, tile.y) ) { let requestPromise if (!topLayer) { cacheKey = `${tile.level}-${tile.x}-${tile.y}` requestPromise = layer.availabilityPromiseCache[cacheKey] if (!defined$b(requestPromise)) { // For cutout terrain, if this isn't the top layer the availability tiles // may never get loaded, so request it here. const request = new Request$1({ throttle: false, throttleByServer: true, type: RequestType$1.TERRAIN, }) requestPromise = requestTileGeometry( provider, tile.x, tile.y, tile.level, layer, request ) if (defined$b(requestPromise)) { layer.availabilityPromiseCache[cacheKey] = requestPromise requestPromise.then(deleteFromCache) } } } // The availability tile is available, but not loaded, so there // is still a chance that it may become available at some point return { result: true, promise: requestPromise, } } tile = getAvailabilityTile(layer, tile.x, tile.y, tile.level) } return { result: false, } } // Used for testing CesiumTerrainProvider$1._getAvailabilityTile = getAvailabilityTile const { AssociativeArray: AssociativeArray$4, AutomaticUniforms: AutomaticUniforms$1, ShaderSource: ShaderSource$5, WebGLConstants: WebGLConstants$2 } = Cesium const datatypeToGlsl = {} datatypeToGlsl[WebGLConstants$2.FLOAT] = "float" datatypeToGlsl[WebGLConstants$2.FLOAT_VEC2] = "vec2" datatypeToGlsl[WebGLConstants$2.FLOAT_VEC3] = "vec3" datatypeToGlsl[WebGLConstants$2.FLOAT_VEC4] = "vec4" datatypeToGlsl[WebGLConstants$2.INT] = "int" datatypeToGlsl[WebGLConstants$2.INT_VEC2] = "ivec2" datatypeToGlsl[WebGLConstants$2.INT_VEC3] = "ivec3" datatypeToGlsl[WebGLConstants$2.INT_VEC4] = "ivec4" datatypeToGlsl[WebGLConstants$2.BOOL] = "bool" datatypeToGlsl[WebGLConstants$2.BOOL_VEC2] = "bvec2" datatypeToGlsl[WebGLConstants$2.BOOL_VEC3] = "bvec3" datatypeToGlsl[WebGLConstants$2.BOOL_VEC4] = "bvec4" datatypeToGlsl[WebGLConstants$2.FLOAT_MAT2] = "mat2" datatypeToGlsl[WebGLConstants$2.FLOAT_MAT3] = "mat3" datatypeToGlsl[WebGLConstants$2.FLOAT_MAT4] = "mat4" datatypeToGlsl[WebGLConstants$2.SAMPLER_2D] = "sampler2D" datatypeToGlsl[WebGLConstants$2.SAMPLER_CUBE] = "samplerCube" class AutomaticDynamicUniform { constructor(options) { this._size = options.size this._datatype = options.datatype this.getValue = options.getValue this._simpleType = defaultValue$c(options.simpleType, false) } getDeclaration (name) { let declaration = `uniform ${datatypeToGlsl[this._datatype]} ${name}` const size = this._size if (this._simpleType) { declaration += ";" } else { declaration += `[${size.toString()}];` } return declaration }; } class ClipRegionCollection { /** * 指定一组剪裁区域,用于使某些着色仅在指定区域内生效。 */ constructor() { this._values = new AssociativeArray$4() this._enabled = true this._hasUpdated = false } /** * ClipRegion是否生效 * @type {boolean} */ get enabled () { return this._enabled } set enabled (enabled) { this._enabled = enabled } /** * clip 区域的数量 * @type {number} */ get count () { if (!this._hasUpdated) { return 0 } return this._values._array.filter(_ => _.enabled).filter(_ => _._colorTexture).length } get boundingRect () { const result = [] for (let clipRegion of this._values._array) { if (!clipRegion.enabled) { continue } result.push(clipRegion.boundingRect) } return result } get inverseLocalModel () { const result = [] for (let clipRegion of this._values._array) { if (!clipRegion.enabled) { continue } result.push(clipRegion._inverseLocalModel) } return result } get depthTexture () { const result = [] for (let clipRegion of this._values._array) { if (!clipRegion.enabled) { continue } if (!clipRegion._colorTexture) { continue } result.push(clipRegion._colorTexture) } return result } get normal () { const result = [] for (let clipRegion of this._values._array) { if (!clipRegion.enabled) { continue } if (!clipRegion._colorTexture) { continue } result.push(clipRegion.normal) } return result } /** * 添加一个clipRegion * @param {ClipRegion} clipRegion */ add (clipRegion) { if (clipRegion instanceof ClipRegion === false) { throw new CesiumProError$1('parameter clipRegion must be a ClipRegion instance.') } this._values.set(clipRegion._id, clipRegion) this._updateGlobeUniforms() } /** * 删除一个clipRegion * @param {string} clipRegion 需要删除的clipRegion或其id */ remove (clipRegion) { let id = clipRegion if (clipRegion instanceof ClipRegion) { id = clipRegion.id } this._values.remove(id) this._updateGlobeUniforms() } /** * 删除所有 */ removeAll () { this._values.removeAll() this._updateGlobeUniforms() } /** * 根据id获得ClipRegion * @param {string} id * @returns */ get (id) { return this._values.get(id) } /** * 根据序号获得ClipRegion * @param {number} index clipRegion index * @returns */ getByIndex (index) { return this._values._array[index] } /** * 判断clipRegion是否存在 * @param {ClipRegion} clipRegion * @returns */ contains (clipRegion) { return this._values.contains(clipRegion._id) } update (frameState) { for (let clipRegion of this._values._array) { if (!clipRegion.enabled) { continue } clipRegion.update(frameState) } this._hasUpdated = true this._updateGlobeUniforms() } _updateGlobeUniforms () { const size = this.count const globeUniforms = { czm_p_clipEnabled: new AutomaticDynamicUniform({ size: 1, simpleType: true, datatype: WebGLConstants$2.BOOL, getValue: function (uniformState) { return uniformState.clipEnabled } }), czm_p_clipDepthTexture: new AutomaticDynamicUniform({ size: size, datatype: WebGLConstants$2.SAMPLER_2D, getValue: function (uniformState) { return uniformState.clipDepthTexture }, }), czm_p_clipBoundingRect: new AutomaticDynamicUniform({ size: size, datatype: WebGLConstants$2.FLOAT_VEC4, getValue: function (uniformState) { return uniformState.clipBoundingRect }, }), czm_p_clipNormal: new AutomaticDynamicUniform({ size: size, datatype: WebGLConstants$2.FLOAT_VEC3, getValue: function (uniformState) { return uniformState.clipNormal }, }), czm_p_clipInverseLocalModel: new AutomaticDynamicUniform({ size: size, datatype: WebGLConstants$2.FLOAT_MAT4, getValue: function (uniformState) { return uniformState.clipInverseLocalModel }, }) } for (const uniformName in globeUniforms) { AutomaticUniforms$1[uniformName] = globeUniforms[uniformName] if (AutomaticUniforms$1.hasOwnProperty(uniformName)) { let uniform = AutomaticUniforms$1[uniformName] if (typeof uniform.getDeclaration === "function") { ShaderSource$5._czmBuiltinsAndUniforms[ uniformName ] = uniform.getDeclaration(uniformName) } } } } } /** * @exports clone * 生成一个对象的副本 * @param {Object} object 被克隆的对象 * @param {Bool} deep 是否深度遍历 * @return {Object} object的副本 */ function clone (object, deep) { if (object === null || typeof object !== 'object') { return object } deep = defaultValue$c(deep, false) const result = new object.constructor() for (const propertyName in object) { if (object.hasOwnProperty(propertyName)) { let value = object[propertyName] if (deep) { value = clone(value, deep) } result[propertyName] = value } } return result } const cesiumScriptRegex$1 = /((?:.*\/)|^)CesiumPro\.js(?:\?|#|$)/ let a$1 /*global CESIUMPRO_BASE_URL*/ function tryMakeAbsolute$1 (url) { if (typeof document === 'undefined') { // Node.js and Web Workers. In both cases, the URL will already be absolute. return url } if (!defined$e(a$1)) { a$1 = document.createElement('a') } a$1.href = url // IE only absolutizes href on get, not set // eslint-disable-next-line no-self-assign a$1.href = a$1.href return a$1.href } let baseResource$1 let implementation$1 function getBaseUrlFromCesiumScript$1 () { const scripts = document.getElementsByTagName('script') for (let i = 0, len = scripts.length; i < len; ++i) { const src = scripts[i].getAttribute('src') const result = cesiumScriptRegex$1.exec(src) if (result !== null) { return result[1] } } return undefined } function buildModuleUrlFromRequireToUrl$1 (moduleID) { // moduleID will be non-relative, so require it relative to this module, in Core. return tryMakeAbsolute$1(`../${moduleID}`) } function getCesiumProBaseUrl$1 () { if (defined$e(baseResource$1)) { return baseResource$1 } let baseUrlString if (typeof CESIUMPRO_BASE_URL != 'undefined') { baseUrlString = CESIUMPRO_BASE_URL } else if ( typeof window.define === 'object' && defined$e(window.define.amd) && !window.define.amd.toUrlUndefined ) { baseUrlString = Cesium.getAbsoluteUri( '..', 'core/Url.js', ) } else { baseUrlString = getBaseUrlFromCesiumScript$1() } // >>includeStart('debug'); if (!defined$e(baseUrlString)) { throw new CesiumProError$1( 'Unable to determine CesiumPro base URL automatically, try defining a global variable called CESIUMPRO_BASE_URL.', ) } // >>includeEnd('debug'); if (!defined$e(baseUrlString)) { baseUrlString = '' } baseResource$1 = new Cesium.Resource({ url: tryMakeAbsolute$1(baseUrlString), }) baseResource$1.appendForwardSlash() return baseResource$1 } function buildModuleUrlFromBaseUrl$1 (moduleID) { const resource = getCesiumProBaseUrl$1().getDerivedResource({ url: moduleID, }) return resource.url } function buildModuleUrl$3 (relativeUrl) { if (!defined$e(implementation$1)) { // select implementation if ( typeof window.define === 'object' && defined$e(window.define.amd) && !window.define.amd.toUrlUndefined ) { implementation$1 = buildModuleUrlFromRequireToUrl$1 } else { implementation$1 = buildModuleUrlFromBaseUrl$1 } } const url = implementation$1(relativeUrl) return url } /** * URL相关工具 * @namespace Url * */ const Url$1 = {} /** * 从多个字符串拼接url,以/为分割符 * @param {...String} args * @return {String} url * * @example * * URL.join("www.baidu.com/",'/tieba/','cesium') * //www.baidu.com/tieba/cesium */ Url$1.join = function (...args) { const formatArgs = [] for (let arg of args) { if (arg.startsWith('/')) { arg = arg.substring(1) } if (arg.endsWith('/')) { arg = arg.substring(0, arg.length - 1) } formatArgs.push(arg) } const urlstr = formatArgs.join('/') // if (!(urlstr.startsWith('http') || urlstr.startsWith('ftp'))) { // urlstr = `http://${urlstr}`; // } return urlstr } /** * 获取CesiumPro静态资源的完整路径 * @param {String} path 指定文件 * @returns {String} 完整的Url地址 * @example * Url.buildModuleUrl('assets/tiles/{z}/{x}/{y}.png') */ Url$1.buildModuleUrl = function (path) { return buildModuleUrl$3(path) } Url$1.getCesiumProBaseUrl = getCesiumProBaseUrl$1 const { FeatureDetection, isCrossOriginUrl } = Cesium function getWorkerUrl (moduleID) { let url = Cesium.buildModuleUrl(moduleID) if (isCrossOriginUrl(url)) { //to load cross-origin, create a shim worker from a blob URL const script = 'importScripts("' + url + '");' let blob try { blob = new Blob([script], { type: "application/javascript", }) } catch (e) { let BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder let blobBuilder = new BlobBuilder() blobBuilder.append(script) blob = blobBuilder.getBlob("application/javascript") } const URL = window.URL || window.webkitURL url = URL.createObjectURL(blob) } return url } let bootstrapperUrlResult function getBootstrapperUrl () { if (!defined$e(bootstrapperUrlResult)) { bootstrapperUrlResult = getWorkerUrl("Workers/cesiumWorkerBootstrapper.js") } return bootstrapperUrlResult } function createWorker (processor) { const worker = new Worker(getBootstrapperUrl()) worker.postMessage = defaultValue$c( worker.webkitPostMessage, worker.postMessage ) const bootstrapMessage = { loaderConfig: { paths: { Workers: buildModuleUrl$3("workers"), }, baseUrl: getCesiumProBaseUrl$1().url, }, workerModule: processor._workerPath, } worker.postMessage(bootstrapMessage) worker.onmessage = function (event) { completeTask(processor, event.data) } worker.postMessage(processor._options) return worker } function completeTask (processor, data) { console.log(processor, data, '------complete-----') } class TaskProcessor { /** * 处理worker任务 * @private */ constructor(path, options = {}) { this._workers = [] this._workerPath = 'workers/' + path this._options = options Math.max( FeatureDetection.hardwareConcurrency - 1, 1 ) this._worker = createWorker(this) } } const { kdbush, Cartesian3: Cartesian3$i, Cartographic: Cartographic$9, PointPrimitive: PointPrimitive$1, BoundingRectangle: BoundingRectangle$3, SceneMode: SceneMode$6, EllipsoidalOccluder, } = Cesium function computedScreenPosition (objects, scene) { const result = [] const occluder = new EllipsoidalOccluder(scene.globe.ellipsoid, scene.camera.positionWC) for (let object of objects) { if (!object.position) { continue } if (scene.mode === SceneMode$6.SCENE3D && !occluder.isPointVisible(object.position)) { continue } object.__pixel = Cesium.SceneTransforms.wgs84ToWindowCoordinates( scene, object.position, ) // object.__pixel = LonLat.toPixel(object.position, scene); object.__pixel && result.push(object) } return result } function getX (point) { return point.__pixel.x } function getY (point) { return point.__pixel.y } function expandBoundingBox (bbox, pixelRange) { bbox.x -= pixelRange bbox.y -= pixelRange bbox.width += pixelRange * 2.0 bbox.height += pixelRange * 2.0 } function getScreenBoundingBox (object, pixel) { const bbox = new BoundingRectangle$3() PointPrimitive$1.getScreenSpaceBoundingBox(object, pixel, bbox) expandBoundingBox(bbox, this.pixelRange) return bbox } class Cluster { constructor(scene, options = {}) { this._objects = defaultValue$c(options.objects, []) this._getScreenBoundingBox = defaultValue$c(options.getScreenBoundingBox, getScreenBoundingBox) this._scene = scene this.clusterSize = 3 this.pixelRange = 50 this._clusterObjects = [] } get objects () { return this._objects } set objects (val) { this._objects = val } _clearCluster () { this._objects.map(_ => _.cluster = false) this._clusterObjects = [] } update () { const objects = this._objects this._clearCluster() const filterObject = computedScreenPosition(objects, this._scene) const index = new kdbush(filterObject, getX, getY, 64, Int32Array) for (let object of filterObject) { if (object.cluster) { continue } const bbox = this._getScreenBoundingBox(object, object.__pixel) const totalBBox = BoundingRectangle$3.clone(bbox, new BoundingRectangle$3()) object.cluster = true const neighbors = index.range(bbox.x, bbox.y, bbox.x + bbox.width, bbox.y + bbox.height) const neighborLength = neighbors.length const clusterPosition = Cartesian3$i.clone(object.position) let numPoints = 1, lastObject = undefined const ids = [] for (let i = 0; i < neighborLength; i++) { const neighborIndex = neighbors[i] const neighborObject = filterObject[neighborIndex] if (neighborObject.cluster) { continue } ids.push(neighborObject.id) neighborObject.cluster = true const neightborbox = this._getScreenBoundingBox(neighborObject, neighborObject.__pixel) Cartesian3$i.add(neighborObject.position, clusterPosition, clusterPosition) BoundingRectangle$3.union(totalBBox, neightborbox, totalBBox) numPoints++ lastObject = neighborObject } if (numPoints >= this.clusterSize) { Cartesian3$i.multiplyByScalar(clusterPosition, 1.0 / numPoints, clusterPosition) this._clusterObjects.push({ position: new Cartesian3$i(clusterPosition.x, clusterPosition.y, clusterPosition.z), number: numPoints, ids, id: lastObject.id + numPoints }) } else { this._clusterObjects.push(object) } } } } let lastUpdateTime = undefined /** * 计算场景中单位像素的长度所对应的真实距离 * @ignore * @param {Cesium.Viewer} viewer * @returns {Number} 当前屏幕中心的地图比例尺 */ function computeDistancePerPixel (viewer) { if (!viewer.scene.globe) { return undefined } const now = Cesium.getTimestamp() const scene = viewer.scene if (defined$e(lastUpdateTime) && now - lastUpdateTime < 250) { return } lastUpdateTime = now const width = scene.canvas.clientWidth const height = scene.canvas.clientHeight const startRay = scene.camera.getPickRay(new Cesium.Cartesian2(width / 2, height / 2)) const endRay = scene.camera.getPickRay(new Cesium.Cartesian2(width / 2 + 1, height / 2)) const startPosition = scene.globe.pick(startRay, scene) const endPosition = scene.globe.pick(endRay, scene) if (!(defined$e(startPosition) && defined$e(endPosition))) { return } const geodesic = new Cesium.EllipsoidGeodesic( scene.globe.ellipsoid.cartesianToCartographic(startPosition), scene.globe.ellipsoid.cartesianToCartographic(endPosition) ) const distance = geodesic.surfaceDistance return distance } /** * 计算场景中心的坐标 * @ignore * @param {*} viewer */ function computeSceneCenterPoint (viewer) { const canvas = viewer.canvas const bounding = canvas.getBoundingClientRect() // center pixel const pixel = new Cesium.Cartesian2(bounding.width / 2, bounding.height / 2) return LonLat.fromPixel(pixel, viewer) } function computeSceneExtent (viewer) { // const rect = viewer.camera.computeViewRectangle(); // todo 该方法获得的是相机的范围,有实际场景的范围有一定误差 if (!viewer.scene.globe) { return {} } if (viewer.scene.mode === Cesium.SceneMode.SCENE3D) { const rect = viewer.camera.computeViewRectangle() if (!defined$e(rect)) { return undefined } return { west: Cesium.Math.toDegrees(rect.west), south: Cesium.Math.toDegrees(rect.south), east: Cesium.Math.toDegrees(rect.east), north: Cesium.Math.toDegrees(rect.north) } } const canvas = viewer.canvas const bounding = canvas.getBoundingClientRect() const left = LonLat.fromPixel(new Cesium.Cartesian2(0, bounding.height / 2), viewer) || { lon: -180 } const right = LonLat.fromPixel(new Cesium.Cartesian2(bounding.width, bounding.height / 2), viewer) || { lon: 180 } const top = LonLat.fromPixel(new Cesium.Cartesian2(bounding.width / 2, 0), viewer) || { lat: 90 } const bottom = LonLat.fromPixel(new Cesium.Cartesian2(bounding.width / 2, bounding.height), viewer) || { lat: -90 } return { west: left.lon, south: bottom.lat, east: right.lon, north: top.lat } } class ContextMenu { /** * 右键菜单 * @param {Cesium.Viewer} viewer Viewer对象 * @param {Object} options 具有以下属性 * @param {ContextMenuItem[]} [options.items] 菜单项 * @param {Cesium.Cartesian3} options.position 菜单显示的位置 */ constructor(viewer, options) { checkViewer(viewer) this._viewer = viewer options = defaultValue$c(options, {}) const items = defaultValue$c(options.items, []) this._items = new Cesium.AssociativeArray() this._position = options.position this._container = defaultValue$c(options.container, viewer.container) this._root = this.createMenu() this.createItems(items) this._show = true this._activeSubMenu = undefined this.parent = options.parent } /** * 菜单可见性 * @type {Boolean} */ get show () { return this._show } set show (val) { this._show = val this._root.style.display = val ? 'block' : 'none' this._menu.style.display = val ? 'block' : 'none' } /** * 菜单位置 * @type {Cesium.Cartesian2} */ get position () { return this._position } set position (val) { this._position = val if (this._root) { const pixel = LonLat.toPixel(this._position, this._viewer.scene) this._root.style.left = pixel.x + 'px' this._root.style.top = pixel.y + 'px' } } /** * 返回指定序号的菜单项 * @param {Number} index 菜单序号 * @return {Object} 菜单项 */ get (index) { return this._items.values[index] } /** * 返回指定id的菜单项 * @param {Number} id 菜单项id * @return {Object} 菜单项 */ getById (id) { return this._items.get(id) } /** * 添加一个菜单项 * @param {Object} item 具有以下属性 * @param {String} item.text 菜单项要显示的文字 * @param {any} [item.id] 菜单项id; * @param {String} [item.class] 菜单项类名,支持bootstrap css类 */ add (item) { if (this._items.contains(item.id)) { return } const contextItem = this.createItem(item) this._items.set(contextItem.id, contextItem) this._menu.appendChild(contextItem.el) } /** * 删除菜单项 * @param {Object} item 需要被删除的菜单项 * @return {Boolean} 是否删除成功 * * @example * const item=contextMenu.get(0); * contextMenu.remove(item); */ remove (item) { const ele = item.el try { this._root.removeChild(ele) this._items.remove(item.id) return true } catch (e) { return false } } /** * 删除所有菜单项 */ removeAll () { for (let item of this._items.values) { this.remove(item) } } createMenu () { const root = document.createElement('div') root.className = 'context-root' const ul = document.createElement('ul') ul.className = 'context-menu context-ul' root.appendChild(ul) this._container.appendChild(root) if (this._position) { const pixel = LonLat.toPixel(this._position, this._viewer.scene) root.style.left = pixel.x + 'px' root.style.top = pixel.y + 'px' } this._menu = ul root.oncontextmenu = function () { return false } return root } /** * 更新菜单项文字 * @param {ContextMenuItem} item 菜单项 * @param {HTML|String} text 文字描述,支持html */ updateItemText (item, text) { const textEle = document.getElementById(item.id + '-text') if (textEle) { textEle.innerHTML = text } } /** * 更新菜单项的不可用状态 * @param {ContextMenuItem} item 菜单项 * @param {Boolean} disabled 是否不可用 */ updateItemDistabled (item, disabled) { if (item && item.a) { item.disabled = disabled item.a.className = disabled ? "context-item-disabled" : "context-item" } } createItems (items) { for (let item of items) { this.add(item) } } createItem (item = {}) { const li = document.createElement('li') li.className = "context-menu" const a = document.createElement('a') a.className = item.disabled ? "context-item-disabled" : "context-item" const i = document.createElement('i') i.className = item.class a.appendChild(i) a.innerHTML += `${item.text}` li.appendChild(a) li.id = item.id item.el = li item.a = a if (item.children) { const arrow = document.createElement('i') arrow.className = 'fa fa-caret-right' a.appendChild(arrow) const sub = new ContextMenu(this._viewer, { items: item.children, position: this._position, parent: this, }) li.appendChild(sub._menu) sub._menu.className += ' context-submenu' item.subMenu = sub sub.container = item } item.el.onmouseover = (event) => { event.stopPropagation() if (item.disabled) { return } this._activeSubMenu && (this._activeSubMenu.show = false) item.subMenu && (item.subMenu.show = true) this._activeSubMenu = item.subMenu } // item.el.onmouseout = function() { // sub.show = false; // } item.el.onclick = (event) => { event.stopPropagation() if (item.disabled) { return } item.callback && item.callback(item) this.show = false this.parent && (this.parent.show = false) } return item } /** * @callback ContextMenu~ContextMenuItem * 具有以下属性 * @param {Object} options 具有以下属性 * @param {String} [options.class] 菜单项样式 * @param {String} [options.text] 菜单项将要显示的文字描述 * @param {String} [options.id] 菜单项id,如果未定义,将创建guid * @param {String} [options.disabled=false] 是否不可用 * @param {ContextMenu} [options.container] 父菜单 * @param {HTMLElement} [options.container] 插入菜单的容器 */ ContextMenuItem (options) { } destroy () { } } /** * 创建全局唯一标识,长度128 bit,可以确保时间和空间上的唯一性。 * * @exports createGuid * * @returns {String} guid * * * @example * this.guid = CesiumPro.createGuid(); * * @see {@link http://www.ietf.org/rfc/rfc4122.txt|RFC 4122 A Universally Unique IDentifier (UUID) URN Namespace} */ function createGuid$3 () { // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { const r = (Math.random() * 16) | 0 const v = c === "x" ? r : (r & 0x3) | 0x8 return v.toString(16) }) } const { ShaderSource: ShaderSource$4 } = Cesium /** * @private * @param {CesiumProError.Scene} scene * @returns */ function createInRegionShader (scene) { // console.log('createInRegionShader') const functionName = 'czm_p_inClipRegion' if (!scene.globe) { return ShaderSource$4._czmBuiltinsAndUniforms[functionName] = `bool czm_p_inClipRegion(vec3 positionWC) {return !czm_p_clipEnabled;}` } const clipRegion = scene.globe.clipRegion const count = clipRegion.count if (count === 0) { return ShaderSource$4._czmBuiltinsAndUniforms[functionName] = `bool czm_p_inClipRegion(vec3 positionWC) {return !czm_p_clipEnabled;}` } let shader = ` bool inBoundingRect(vec2 st) { return st.s >= 0.0 && st.s <=1.0 && st.t >= 0.0 && st.t <= 1.0; } bool in_clipRegion(sampler2D texture, vec3 positionWC, vec4 boundingRect, vec3 normalEC, mat4 inverseMatrix) { vec2 st; vec4 positionLC = inverseMatrix * vec4(positionWC, 1.0); st.s = (positionLC.x-boundingRect.x)/(boundingRect.z-boundingRect.x); st.t = (positionLC.y-boundingRect.y)/(boundingRect.w-boundingRect.y); if (inBoundingRect(st)) { float depth = czm_unpackDepth(texture2D(texture, st)); depth = depth * 1024.0; if (depth > 1.0 && dot(normalEC, (vec4(positionWC, 1.0)).xyz) > 0.0) { return true; } } return false; } bool czm_p_inClipRegion(vec3 positionWC) { if(!czm_p_clipEnabled) { return true; } for (int i = 0; i < ${count}; i++) { bool isIn = in_clipRegion(czm_p_clipDepthTexture[i], positionWC, czm_p_clipBoundingRect[i], czm_p_clipNormal[i], czm_p_clipInverseLocalModel[i]); if (isIn) { return true; } } return false; }` ShaderSource$4._czmBuiltinsAndUniforms[functionName] = shader } /* eslint-disable */ const arr = [] const { document: document$1 } = window const getProto = Object.getPrototypeOf const { slice: slice$1 } = arr const { concat: concat$2 } = arr const { push } = arr const { indexOf } = arr const class2type = {} const { toString: toString$2 } = class2type const hasOwn = class2type.hasOwnProperty const fnToString = hasOwn.toString const ObjectFunctionString = fnToString.call(Object) const support = {} const isFunction = function isFunction (obj) { // Support: Chrome <=57, Firefox <=52 // In some browsers, typeof returns "function" for HTML elements // (i.e., `typeof document.createElement( "object" ) === "function"`). // We don't want to classify *any* DOM node as a function. return typeof obj === 'function' && typeof obj.nodeType !== 'number' } const isWindow = function isWindow (obj) { return obj != null && obj === obj.window } const preservedScriptAttributes = { type: true, src: true, nonce: true, noModule: true, } function DOMEval (code, node, doc) { doc = doc || document$1 let i; let val const script = doc.createElement('script') script.text = code if (node) { for (i in preservedScriptAttributes) { // Support: Firefox 64+, Edge 18+ // Some browsers don't support the "nonce" property on scripts. // On the other hand, just using `getAttribute` is not enough as // the `nonce` attribute is reset to an empty string whenever it // becomes browsing-context connected. // See https://github.com/whatwg/html/issues/2369 // See https://html.spec.whatwg.org/#nonce-attributes // The `node.getAttribute` check was added for the sake of // `jQuery.globalEval` so that it can fake a nonce-containing node // via an object. val = node[i] || node.getAttribute && node.getAttribute(i) if (val) { script.setAttribute(i, val) } } } doc.head.appendChild(script).parentNode.removeChild(script) } function toType (obj) { if (obj == null) { return `${obj}` } // Support: Android <=2.3 only (functionish RegExp) return typeof obj === 'object' || typeof obj === 'function' ? class2type[toString$2.call(obj)] || 'object' : typeof obj } /* global Symbol */ // Defining this global in .eslintrc.json would create a danger of using the global // unguarded in another place, it seems safer to define global only for this module const version = '3.4.1' // Define a local copy of jQuery var jQuery = function (selector, context) { // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init(selector, context) } // Support: Android <=4.0 only // Make sure we trim BOM and NBSP const rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g jQuery.fn = jQuery.prototype = { // The current version of jQuery being used jquery: version, constructor: jQuery, // The default length of a jQuery object is 0 length: 0, toArray () { return slice$1.call(this) }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get (num) { // Return all the elements in a clean array if (num == null) { return slice$1.call(this) } // Return just the one element from the set return num < 0 ? this[num + this.length] : this[num] }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack (elems) { // Build a new jQuery matched element set const ret = jQuery.merge(this.constructor(), elems) // Add the old object onto the stack (as a reference) ret.prevObject = this // Return the newly-formed element set return ret }, // Execute a callback for every element in the matched set. each (callback) { return jQuery.each(this, callback) }, map (callback) { return this.pushStack(jQuery.map(this, (elem, i) => callback.call(elem, i, elem))) }, slice () { return this.pushStack(slice$1.apply(this, arguments)) }, first () { return this.eq(0) }, last () { return this.eq(-1) }, eq (i) { const len = this.length const j = +i + (i < 0 ? len : 0) return this.pushStack(j >= 0 && j < len ? [this[j]] : []) }, end () { return this.prevObject || this.constructor() }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push, sort: arr.sort, splice: arr.splice, } jQuery.extend = jQuery.fn.extend = function () { let options; let name; let src; let copy; let copyIsArray; let clone let target = arguments[0] || {} let i = 1 const { length } = arguments let deep = false // Handle a deep copy situation if (typeof target === 'boolean') { deep = target // Skip the boolean and the target target = arguments[i] || {} i++ } // Handle case when target is a string or something (possible in deep copy) if (typeof target !== 'object' && !isFunction(target)) { target = {} } // Extend jQuery itself if only one argument is passed if (i === length) { target = this i-- } for (; i < length; i++) { // Only deal with non-null/undefined values if ((options = arguments[i]) != null) { // Extend the base object for (name in options) { copy = options[name] // Prevent Object.prototype pollution // Prevent never-ending loop if (name === '__proto__' || target === copy) { continue } // Recurse if we're merging plain objects or arrays if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) { src = target[name] // Ensure proper type for the source value if (copyIsArray && !Array.isArray(src)) { clone = [] } else if (!copyIsArray && !jQuery.isPlainObject(src)) { clone = {} } else { clone = src } copyIsArray = false // Never move original objects, clone them target[name] = jQuery.extend(deep, clone, copy) // Don't bring in undefined values } else if (copy !== undefined) { target[name] = copy } } } } // Return the modified object return target } jQuery.extend({ // Unique for each copy of jQuery on the page expando: `jQuery${(version + Math.random()).replace(/\D/g, '')}`, // Assume jQuery is ready without the ready module isReady: true, error (msg) { throw new Error(msg) }, noop () { }, isPlainObject (obj) { let proto; let Ctor // Detect obvious negatives // Use toString instead of jQuery.type to catch host objects if (!obj || toString$2.call(obj) !== '[object Object]') { return false } proto = getProto(obj) // Objects with no prototype (e.g., `Object.create( null )`) are plain if (!proto) { return true } // Objects with prototype are plain iff they were constructed by a global Object function Ctor = hasOwn.call(proto, 'constructor') && proto.constructor return typeof Ctor === 'function' && fnToString.call(Ctor) === ObjectFunctionString }, isEmptyObject (obj) { let name for (name in obj) { return false } return true }, // Evaluates a script in a global context globalEval (code, options) { DOMEval(code, { nonce: options && options.nonce }) }, each (obj, callback) { let length; let i = 0 if (isArrayLike(obj)) { length = obj.length for (; i < length; i++) { if (callback.call(obj[i], i, obj[i]) === false) { break } } } else { for (i in obj) { if (callback.call(obj[i], i, obj[i]) === false) { break } } } return obj }, // Support: Android <=4.0 only trim (text) { return text == null ? '' : (`${text}`).replace(rtrim, '') }, // results is for internal usage only makeArray (arr, results) { const ret = results || [] if (arr != null) { if (isArrayLike(Object(arr))) { jQuery.merge(ret, typeof arr === 'string' ? [arr] : arr) } else { push.call(ret, arr) } } return ret }, inArray (elem, arr, i) { return arr == null ? -1 : indexOf.call(arr, elem, i) }, // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit merge (first, second) { const len = +second.length let j = 0 let i = first.length for (; j < len; j++) { first[i++] = second[j] } first.length = i return first }, grep (elems, callback, invert) { let callbackInverse const matches = [] let i = 0 const { length } = elems const callbackExpect = !invert // Go through the array, only saving the items // that pass the validator function for (; i < length; i++) { callbackInverse = !callback(elems[i], i) if (callbackInverse !== callbackExpect) { matches.push(elems[i]) } } return matches }, // arg is for internal usage only map (elems, callback, arg) { let length; let value let i = 0 const ret = [] // Go through the array, translating each of the items to their new values if (isArrayLike(elems)) { length = elems.length for (; i < length; i++) { value = callback(elems[i], i, arg) if (value != null) { ret.push(value) } } // Go through every key on the object, } else { for (i in elems) { value = callback(elems[i], i, arg) if (value != null) { ret.push(value) } } } // Flatten any nested arrays return concat$2.apply([], ret) }, // A global GUID counter for objects guid: 1, // jQuery.support is not used in Core but other projects attach their // properties to it so it needs to exist. support, }) if (typeof Symbol === 'function') { jQuery.fn[Symbol.iterator] = arr[Symbol.iterator] } // Populate the class2type map jQuery.each('Boolean Number String Function Array Date RegExp Object Error Symbol'.split(' '), (i, name) => { class2type[`[object ${name}]`] = name.toLowerCase() }) function isArrayLike (obj) { // Support: real iOS 8.2 only (not reproducible in simulator) // `in` check used to prevent JIT error (gh-2145) // hasOwn isn't used here due to false negatives // regarding Nodelist length in IE const length = !!obj && 'length' in obj && obj.length const type = toType(obj) if (isFunction(obj) || isWindow(obj)) { return false } return type === 'array' || length === 0 || typeof length === 'number' && length > 0 && (length - 1) in obj } const Sizzle = /*! * Sizzle CSS Selector Engine v2.3.4 * https://sizzlejs.com/ * * Copyright JS Foundation and other contributors * Released under the MIT license * https://js.foundation/ * * Date: 2019-04-08 */ (function (window) { let i let support let Expr let getText let isXML let tokenize let compile let select let outermostContext let sortInput let hasDuplicate // Local document vars let setDocument let document let docElem let documentIsHTML let rbuggyQSA let rbuggyMatches let matches let contains // Instance-specific data const expando = `sizzle${1 * new Date()}` const preferredDoc = window.document let dirruns = 0 let done = 0 const classCache = createCache() const tokenCache = createCache() const compilerCache = createCache() const nonnativeSelectorCache = createCache() let sortOrder = function (a, b) { if (a === b) { hasDuplicate = true } return 0 } // Instance methods const hasOwn = ({}).hasOwnProperty let arr = [] const { pop } = arr const push_native = arr.push let { push } = arr const { slice } = arr // Use a stripped-down indexOf as it's faster than native // https://jsperf.com/thor-indexof-vs-for/5 const indexOf = function (list, elem) { let i = 0 const len = list.length for (; i < len; i++) { if (list[i] === elem) { return i } } return -1 } const booleans = 'checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped' // Regular expressions // http://www.w3.org/TR/css3-selectors/#whitespace const whitespace = '[\\x20\\t\\r\\n\\f]' // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier const identifier = '(?:\\\\.|[\\w-]|[^\0-\\xa0])+' // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors const attributes = `\\[${whitespace}*(${identifier})(?:${whitespace // Operator (capture 2) }*([*^$|!~]?=)${whitespace // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" }*(?:'((?:\\\\.|[^\\\\'])*)'|"((?:\\\\.|[^\\\\"])*)"|(${identifier}))|)${whitespace }*\\]` const pseudos = `:(${identifier})(?:\\((` // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: // 1. quoted (capture 3; capture 4 or capture 5) + '(\'((?:\\\\.|[^\\\\\'])*)\'|"((?:\\\\.|[^\\\\"])*)")|' // 2. simple (capture 6) + `((?:\\\\.|[^\\\\()[\\]]|${attributes})*)|` // 3. anything else (capture 2) + '.*' + ')\\)|)' // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter const rwhitespace = new RegExp(`${whitespace}+`, 'g') const rtrim = new RegExp(`^${whitespace}+|((?:^|[^\\\\])(?:\\\\.)*)${whitespace}+$`, 'g') const rcomma = new RegExp(`^${whitespace}*,${whitespace}*`) const rcombinators = new RegExp(`^${whitespace}*([>+~]|${whitespace})${whitespace}*`) const rdescend = new RegExp(`${whitespace}|>`) const rpseudo = new RegExp(pseudos) const ridentifier = new RegExp(`^${identifier}$`) const matchExpr = { ID: new RegExp(`^#(${identifier})`), CLASS: new RegExp(`^\\.(${identifier})`), TAG: new RegExp(`^(${identifier}|[*])`), ATTR: new RegExp(`^${attributes}`), PSEUDO: new RegExp(`^${pseudos}`), CHILD: new RegExp(`^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(${whitespace }*(even|odd|(([+-]|)(\\d*)n|)${whitespace}*(?:([+-]|)${whitespace }*(\\d+)|))${whitespace}*\\)|)`, 'i'), bool: new RegExp(`^(?:${booleans})$`, 'i'), // For use in libraries implementing .is() // We use this for POS matching in `select` needsContext: new RegExp(`^${whitespace}*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(${whitespace}*((?:-\\d)?\\d*)${whitespace}*\\)|)(?=[^-]|$)`, 'i'), } const rhtml = /HTML$/i const rinputs = /^(?:input|select|textarea|button)$/i const rheader = /^h\d$/i const rnative = /^[^{]+\{\s*\[native \w/ // Easily-parseable/retrievable ID or TAG or CLASS selectors const rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/ const rsibling = /[+~]/ // CSS escapes // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters const runescape = new RegExp(`\\\\([\\da-f]{1,6}${whitespace}?|(${whitespace})|.)`, 'ig') const funescape = function (_, escaped, escapedWhitespace) { const high = `0x${escaped}` - 0x10000 // NaN means non-codepoint // Support: Firefox<24 // Workaround erroneous numeric interpretation of +"0x" return high !== high || escapedWhitespace ? escaped : high < 0 // BMP codepoint ? String.fromCharCode(high + 0x10000) // Supplemental Plane codepoint (surrogate pair) : String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00) } // CSS string/identifier serialization // https://drafts.csswg.org/cssom/#common-serializing-idioms const rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g const fcssescape = function (ch, asCodePoint) { if (asCodePoint) { // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER if (ch === '\0') { return '\uFFFD' } // Control characters and (dependent upon position) numbers get escaped as code points return `${ch.slice(0, -1)}\\${ch.charCodeAt(ch.length - 1).toString(16)} ` } // Other potentially-special ASCII characters get backslash-escaped return `\\${ch}` } // Used for iframes // See setDocument() // Removing the function wrapper causes a "Permission Denied" // error in IE const unloadHandler = function () { setDocument() } const inDisabledFieldset = addCombinator( (elem) => elem.disabled === true && elem.nodeName.toLowerCase() === 'fieldset', { dir: 'parentNode', next: 'legend' }, ) // Optimize for push.apply( _, NodeList ) try { push.apply( (arr = slice.call(preferredDoc.childNodes)), preferredDoc.childNodes, ) // Support: Android<4.0 // Detect silently failing push.apply arr[preferredDoc.childNodes.length].nodeType } catch (e) { push = { apply: arr.length // Leverage slice if possible ? function (target, els) { push_native.apply(target, slice.call(els)) } // Support: IE<9 // Otherwise append directly : function (target, els) { let j = target.length let i = 0 // Can't trust NodeList.length while ((target[j++] = els[i++])) { } target.length = j - 1 }, } } function Sizzle (selector, context, results, seed) { let m; let i; let elem; let nid; let match; let groups; let newSelector let newContext = context && context.ownerDocument // nodeType defaults to 9, since context defaults to document const nodeType = context ? context.nodeType : 9 results = results || [] // Return early from calls with invalid selector or context if (typeof selector !== 'string' || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11) { return results } // Try to shortcut find operations (as opposed to filters) in HTML documents if (!seed) { if ((context ? context.ownerDocument || context : preferredDoc) !== document) { setDocument(context) } context = context || document if (documentIsHTML) { // If the selector is sufficiently simple, try using a "get*By*" DOM method // (excepting DocumentFragment context, where the methods don't exist) if (nodeType !== 11 && (match = rquickExpr.exec(selector))) { // ID selector if ((m = match[1])) { // Document context if (nodeType === 9) { if ((elem = context.getElementById(m))) { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if (elem.id === m) { results.push(elem) return results } } else { return results } // Element context } else { // Support: IE, Opera, Webkit // TODO: identify versions // getElementById can match elements by name instead of ID if (newContext && (elem = newContext.getElementById(m)) && contains(context, elem) && elem.id === m) { results.push(elem) return results } } // Type selector } else if (match[2]) { push.apply(results, context.getElementsByTagName(selector)) return results // Class selector } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) { push.apply(results, context.getElementsByClassName(m)) return results } } // Take advantage of querySelectorAll if (support.qsa && !nonnativeSelectorCache[`${selector} `] && (!rbuggyQSA || !rbuggyQSA.test(selector)) // Support: IE 8 only // Exclude object elements && (nodeType !== 1 || context.nodeName.toLowerCase() !== 'object')) { newSelector = selector newContext = context // qSA considers elements outside a scoping root when evaluating child or // descendant combinators, which is not what we want. // In such cases, we work around the behavior by prefixing every selector in the // list with an ID selector referencing the scope context. // Thanks to Andrew Dupont for this technique. if (nodeType === 1 && rdescend.test(selector)) { // Capture the context ID, setting it first if necessary if ((nid = context.getAttribute('id'))) { nid = nid.replace(rcssescape, fcssescape) } else { context.setAttribute('id', (nid = expando)) } // Prefix every selector in the list groups = tokenize(selector) i = groups.length while (i--) { groups[i] = `#${nid} ${toSelector(groups[i])}` } newSelector = groups.join(',') // Expand context for sibling selectors newContext = rsibling.test(selector) && testContext(context.parentNode) || context } try { push.apply(results, newContext.querySelectorAll(newSelector)) return results } catch (qsaError) { nonnativeSelectorCache(selector, true) } finally { if (nid === expando) { context.removeAttribute('id') } } } } } // All others return select(selector.replace(rtrim, '$1'), context, results, seed) } /** * Create key-value caches of limited size * @returns {function(string, object)} Returns the Object data after storing it on itself with * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) * deleting the oldest entry */ function createCache () { const keys = [] function cache (key, value) { // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) if (keys.push(`${key} `) > Expr.cacheLength) { // Only keep the most recent entries delete cache[keys.shift()] } return (cache[`${key} `] = value) } return cache } /** * Mark a function for special use by Sizzle * @param {Function} fn The function to mark */ function markFunction (fn) { fn[expando] = true return fn } /** * Support testing using an element * @param {Function} fn Passed the created element and returns a boolean result */ function assert (fn) { let el = document.createElement('fieldset') try { return !!fn(el) } catch (e) { return false } finally { // Remove from its parent by default if (el.parentNode) { el.parentNode.removeChild(el) } // release memory in IE el = null } } /** * Adds the same handler for all of the specified attrs * @param {String} attrs Pipe-separated list of attributes * @param {Function} handler The method that will be applied */ function addHandle (attrs, handler) { const arr = attrs.split('|') let i = arr.length while (i--) { Expr.attrHandle[arr[i]] = handler } } /** * Checks document order of two siblings * @param {Element} a * @param {Element} b * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b */ function siblingCheck (a, b) { let cur = b && a const diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex // Use IE sourceIndex if available on both nodes if (diff) { return diff } // Check if b follows a if (cur) { while ((cur = cur.nextSibling)) { if (cur === b) { return -1 } } } return a ? 1 : -1 } /** * Returns a function to use in pseudos for input types * @param {String} type */ function createInputPseudo (type) { return function (elem) { const name = elem.nodeName.toLowerCase() return name === 'input' && elem.type === type } } /** * Returns a function to use in pseudos for buttons * @param {String} type */ function createButtonPseudo (type) { return function (elem) { const name = elem.nodeName.toLowerCase() return (name === 'input' || name === 'button') && elem.type === type } } /** * Returns a function to use in pseudos for :enabled/:disabled * @param {Boolean} disabled true for :disabled; false for :enabled */ function createDisabledPseudo (disabled) { // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable return function (elem) { // Only certain elements can match :enabled or :disabled // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled if ('form' in elem) { // Check for inherited disabledness on relevant non-disabled elements: // * listed form-associated elements in a disabled fieldset // https://html.spec.whatwg.org/multipage/forms.html#category-listed // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled // * option elements in a disabled optgroup // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled // All such elements have a "form" property. if (elem.parentNode && elem.disabled === false) { // Option elements defer to a parent optgroup if present if ('label' in elem) { if ('label' in elem.parentNode) { return elem.parentNode.disabled === disabled } return elem.disabled === disabled } // Support: IE 6 - 11 // Use the isDisabled shortcut property to check for disabled fieldset ancestors return elem.isDisabled === disabled // Where there is no isDisabled, check manually /* jshint -W018 */ || elem.isDisabled !== !disabled && inDisabledFieldset(elem) === disabled } return elem.disabled === disabled // Try to winnow out elements that can't be disabled before trusting the disabled property. // Some victims get caught in our net (label, legend, menu, track), but it shouldn't // even exist on them, let alone have a boolean value. } if ('label' in elem) { return elem.disabled === disabled } // Remaining elements are neither :enabled nor :disabled return false } } /** * Returns a function to use in pseudos for positionals * @param {Function} fn */ function createPositionalPseudo (fn) { return markFunction((argument) => { argument = +argument return markFunction((seed, matches) => { let j const matchIndexes = fn([], seed.length, argument) let i = matchIndexes.length // Match elements found at the specified indexes while (i--) { if (seed[(j = matchIndexes[i])]) { seed[j] = !(matches[j] = seed[j]) } } }) }) } /** * Checks a node for validity as a Sizzle context * @param {Element|Object=} context * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext (context) { return context && typeof context.getElementsByTagName !== 'undefined' && context } // Expose support vars for convenience support = Sizzle.support = {} /** * Detects XML nodes * @param {Element|Object} elem An element or a document * @returns {Boolean} True iff elem is a non-HTML XML node */ isXML = Sizzle.isXML = function (elem) { const namespace = elem.namespaceURI const docElem = (elem.ownerDocument || elem).documentElement // Support: IE <=8 // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes // https://bugs.jquery.com/ticket/4833 return !rhtml.test(namespace || docElem && docElem.nodeName || 'HTML') } /** * Sets document-related variables once based on the current document * @param {Element|Object} [doc] An element or document object to use to set the document * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function (node) { let hasCompare; let subWindow const doc = node ? node.ownerDocument || node : preferredDoc // Return early if doc is invalid or already selected if (doc === document || doc.nodeType !== 9 || !doc.documentElement) { return document } // Update global variables document = doc docElem = document.documentElement documentIsHTML = !isXML(document) // Support: IE 9-11, Edge // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) if (preferredDoc !== document && (subWindow = document.defaultView) && subWindow.top !== subWindow) { // Support: IE 11, Edge if (subWindow.addEventListener) { subWindow.addEventListener('unload', unloadHandler, false) // Support: IE 9 - 10 only } else if (subWindow.attachEvent) { subWindow.attachEvent('onunload', unloadHandler) } } /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 // Verify that getAttribute really returns attributes and not properties // (excepting IE8 booleans) support.attributes = assert((el) => { el.className = 'i' return !el.getAttribute('className') }) /* getElement(s)By* ---------------------------------------------------------------------- */ // Check if getElementsByTagName("*") returns only elements support.getElementsByTagName = assert((el) => { el.appendChild(document.createComment('')) return !el.getElementsByTagName('*').length }) // Support: IE<9 support.getElementsByClassName = rnative.test(document.getElementsByClassName) // Support: IE<10 // Check if getElementById returns elements by name // The broken getElementById methods don't pick up programmatically-set names, // so use a roundabout getElementsByName test support.getById = assert((el) => { docElem.appendChild(el).id = expando return !document.getElementsByName || !document.getElementsByName(expando).length }) // ID filter and find if (support.getById) { Expr.filter.ID = function (id) { const attrId = id.replace(runescape, funescape) return function (elem) { return elem.getAttribute('id') === attrId } } Expr.find.ID = function (id, context) { if (typeof context.getElementById !== 'undefined' && documentIsHTML) { const elem = context.getElementById(id) return elem ? [elem] : [] } } } else { Expr.filter.ID = function (id) { const attrId = id.replace(runescape, funescape) return function (elem) { const node = typeof elem.getAttributeNode !== 'undefined' && elem.getAttributeNode('id') return node && node.value === attrId } } // Support: IE 6 - 7 only // getElementById is not reliable as a find shortcut Expr.find.ID = function (id, context) { if (typeof context.getElementById !== 'undefined' && documentIsHTML) { let node; let i; let elems let elem = context.getElementById(id) if (elem) { // Verify the id attribute node = elem.getAttributeNode('id') if (node && node.value === id) { return [elem] } // Fall back on getElementsByName elems = context.getElementsByName(id) i = 0 while ((elem = elems[i++])) { node = elem.getAttributeNode('id') if (node && node.value === id) { return [elem] } } } return [] } } } // Tag Expr.find.TAG = support.getElementsByTagName ? function (tag, context) { if (typeof context.getElementsByTagName !== 'undefined') { return context.getElementsByTagName(tag) // DocumentFragment nodes don't have gEBTN } if (support.qsa) { return context.querySelectorAll(tag) } } : function (tag, context) { let elem const tmp = [] let i = 0 // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too const results = context.getElementsByTagName(tag) // Filter out possible comments if (tag === '*') { while ((elem = results[i++])) { if (elem.nodeType === 1) { tmp.push(elem) } } return tmp } return results } // Class Expr.find.CLASS = support.getElementsByClassName && function (className, context) { if (typeof context.getElementsByClassName !== 'undefined' && documentIsHTML) { return context.getElementsByClassName(className) } } /* QSA/matchesSelector ---------------------------------------------------------------------- */ // QSA and matchesSelector support // matchesSelector(:active) reports false when true (IE9/Opera 11.5) rbuggyMatches = [] // qSa(:focus) reports false when true (Chrome 21) // We allow this because of a bug in IE8/9 that throws an error // whenever `document.activeElement` is accessed on an iframe // So, we allow :focus to pass through QSA all the time to avoid the IE error // See https://bugs.jquery.com/ticket/13378 rbuggyQSA = [] if ((support.qsa = rnative.test(document.querySelectorAll))) { // Build QSA regex // Regex strategy adopted from Diego Perini assert((el) => { // Select is set to empty string on purpose // This is to test IE's treatment of not explicitly // setting a boolean content attribute, // since its presence should be enough // https://bugs.jquery.com/ticket/12359 docElem.appendChild(el).innerHTML = `` + `' // Support: IE8, Opera 11-12.16 // Nothing should be selected when empty strings follow ^= or $= or *= // The test attribute must be unknown in Opera but "safe" for WinRT // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section if (el.querySelectorAll("[msallowcapture^='']").length) { rbuggyQSA.push(`[*^$]=${whitespace}*(?:''|"")`) } // Support: IE8 // Boolean attributes and "value" are not treated correctly if (!el.querySelectorAll('[selected]').length) { rbuggyQSA.push(`\\[${whitespace}*(?:value|${booleans})`) } // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ if (!el.querySelectorAll(`[id~=${expando}-]`).length) { rbuggyQSA.push('~=') } // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests if (!el.querySelectorAll(':checked').length) { rbuggyQSA.push(':checked') } // Support: Safari 8+, iOS 8+ // https://bugs.webkit.org/show_bug.cgi?id=136851 // In-page `selector#id sibling-combinator selector` fails if (!el.querySelectorAll(`a#${expando}+*`).length) { rbuggyQSA.push('.#.+[+~]') } }) assert((el) => { el.innerHTML = "" + "" // Support: Windows 8 Native Apps // The type and name attributes are restricted during .innerHTML assignment const input = document.createElement('input') input.setAttribute('type', 'hidden') el.appendChild(input).setAttribute('name', 'D') // Support: IE8 // Enforce case-sensitivity of name attribute if (el.querySelectorAll('[name=d]').length) { rbuggyQSA.push(`name${whitespace}*[*^$|!~]?=`) } // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) // IE8 throws error here and will not see later tests if (el.querySelectorAll(':enabled').length !== 2) { rbuggyQSA.push(':enabled', ':disabled') } // Support: IE9-11+ // IE's :disabled selector does not pick up the children of disabled fieldsets docElem.appendChild(el).disabled = true if (el.querySelectorAll(':disabled').length !== 2) { rbuggyQSA.push(':enabled', ':disabled') } // Opera 10-11 does not throw on post-comma invalid pseudos el.querySelectorAll('*,:x') rbuggyQSA.push(',.*:') }) } if ((support.matchesSelector = rnative.test((matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector)))) { assert((el) => { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9) support.disconnectedMatch = matches.call(el, '*') // This should fail with an exception // Gecko does not error, returns false instead matches.call(el, "[s!='']:x") rbuggyMatches.push('!=', pseudos) }) } rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join('|')) rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join('|')) /* Contains ---------------------------------------------------------------------- */ hasCompare = rnative.test(docElem.compareDocumentPosition) // Element contains another // Purposefully self-exclusive // As in, an element does not contain itself contains = hasCompare || rnative.test(docElem.contains) ? function (a, b) { const adown = a.nodeType === 9 ? a.documentElement : a const bup = b && b.parentNode return a === bup || !!(bup && bup.nodeType === 1 && ( adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16 )) } : function (a, b) { if (b) { while ((b = b.parentNode)) { if (b === a) { return true } } } return false } /* Sorting ---------------------------------------------------------------------- */ // Document order sorting sortOrder = hasCompare ? function (a, b) { // Flag for duplicate removal if (a === b) { hasDuplicate = true return 0 } // Sort on method existence if only one input has compareDocumentPosition let compare = !a.compareDocumentPosition - !b.compareDocumentPosition if (compare) { return compare } // Calculate position if both inputs belong to the same document compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) // Otherwise we know they are disconnected : 1 // Disconnected nodes if (compare & 1 || (!support.sortDetached && b.compareDocumentPosition(a) === compare)) { // Choose the first element that is related to our preferred document if (a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) { return -1 } if (b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b)) { return 1 } // Maintain original order return sortInput ? (indexOf(sortInput, a) - indexOf(sortInput, b)) : 0 } return compare & 4 ? -1 : 1 } : function (a, b) { // Exit early if the nodes are identical if (a === b) { hasDuplicate = true return 0 } let cur let i = 0 const aup = a.parentNode const bup = b.parentNode const ap = [a] const bp = [b] // Parentless nodes are either documents or disconnected if (!aup || !bup) { return a === document ? -1 : b === document ? 1 : aup ? -1 : bup ? 1 : sortInput ? (indexOf(sortInput, a) - indexOf(sortInput, b)) : 0 // If the nodes are siblings, we can do a quick check } if (aup === bup) { return siblingCheck(a, b) } // Otherwise we need full lists of their ancestors for comparison cur = a while ((cur = cur.parentNode)) { ap.unshift(cur) } cur = b while ((cur = cur.parentNode)) { bp.unshift(cur) } // Walk down the tree looking for a discrepancy while (ap[i] === bp[i]) { i++ } return i // Do a sibling check if the nodes have a common ancestor ? siblingCheck(ap[i], bp[i]) // Otherwise nodes in our document sort first : ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0 } return document } Sizzle.matches = function (expr, elements) { return Sizzle(expr, null, null, elements) } Sizzle.matchesSelector = function (elem, expr) { // Set document vars if needed if ((elem.ownerDocument || elem) !== document) { setDocument(elem) } if (support.matchesSelector && documentIsHTML && !nonnativeSelectorCache[`${expr} `] && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) { try { const ret = matches.call(elem, expr) // IE 9's matchesSelector returns false on disconnected nodes if (ret || support.disconnectedMatch // As well, disconnected nodes are said to be in a document // fragment in IE 9 || elem.document && elem.document.nodeType !== 11) { return ret } } catch (e) { nonnativeSelectorCache(expr, true) } } return Sizzle(expr, document, null, [elem]).length > 0 } Sizzle.contains = function (context, elem) { // Set document vars if needed if ((context.ownerDocument || context) !== document) { setDocument(context) } return contains(context, elem) } Sizzle.attr = function (elem, name) { // Set document vars if needed if ((elem.ownerDocument || elem) !== document) { setDocument(elem) } const fn = Expr.attrHandle[name.toLowerCase()] // Don't get fooled by Object.prototype properties (jQuery #13807) let val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null } Sizzle.escape = function (sel) { return (`${sel}`).replace(rcssescape, fcssescape) } Sizzle.error = function (msg) { throw new Error(`Syntax error, unrecognized expression: ${msg}`) } /** * Document sorting and removing duplicates * @param {ArrayLike} results */ Sizzle.uniqueSort = function (results) { let elem const duplicates = [] let j = 0 let i = 0 // Unless we *know* we can detect duplicates, assume their presence hasDuplicate = !support.detectDuplicates sortInput = !support.sortStable && results.slice(0) results.sort(sortOrder) if (hasDuplicate) { while ((elem = results[i++])) { if (elem === results[i]) { j = duplicates.push(i) } } while (j--) { results.splice(duplicates[j], 1) } } // Clear input after sorting to release objects // See https://github.com/jquery/sizzle/pull/225 sortInput = null return results } /** * Utility function for retrieving the text value of an array of DOM nodes * @param {Array|Element} elem */ getText = Sizzle.getText = function (elem) { let node let ret = '' let i = 0 const { nodeType } = elem if (!nodeType) { // If no nodeType, this is expected to be an array while ((node = elem[i++])) { // Do not traverse comment nodes ret += getText(node) } } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) { // Use textContent for elements // innerText usage removed for consistency of new lines (jQuery #11153) if (typeof elem.textContent === 'string') { return elem.textContent } // Traverse its children for (elem = elem.firstChild; elem; elem = elem.nextSibling) { ret += getText(elem) } } else if (nodeType === 3 || nodeType === 4) { return elem.nodeValue } // Do not include comment or processing instruction nodes return ret } Expr = Sizzle.selectors = { // Can be adjusted by the user cacheLength: 50, createPseudo: markFunction, match: matchExpr, attrHandle: {}, find: {}, relative: { '>': { dir: 'parentNode', first: true }, ' ': { dir: 'parentNode' }, '+': { dir: 'previousSibling', first: true }, '~': { dir: 'previousSibling' }, }, preFilter: { ATTR (match) { match[1] = match[1].replace(runescape, funescape) // Move the given value to match[3] whether quoted or unquoted match[3] = (match[3] || match[4] || match[5] || '').replace(runescape, funescape) if (match[2] === '~=') { match[3] = ` ${match[3]} ` } return match.slice(0, 4) }, CHILD (match) { /* matches from matchExpr["CHILD"] 1 type (only|nth|...) 2 what (child|of-type) 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) 4 xn-component of xn+y argument ([+-]?\d*n|) 5 sign of xn-component 6 x of xn-component 7 sign of y-component 8 y of y-component */ match[1] = match[1].toLowerCase() if (match[1].slice(0, 3) === 'nth') { // nth-* requires argument if (!match[3]) { Sizzle.error(match[0]) } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === 'even' || match[3] === 'odd')) match[5] = +((match[7] + match[8]) || match[3] === 'odd') // other types prohibit arguments } else if (match[3]) { Sizzle.error(match[0]) } return match }, PSEUDO (match) { let excess const unquoted = !match[6] && match[2] if (matchExpr.CHILD.test(match[0])) { return null } // Accept quoted arguments as-is if (match[3]) { match[2] = match[4] || match[5] || '' // Strip excess characters from unquoted arguments } else if (unquoted && rpseudo.test(unquoted) // Get excess from tokenize (recursively) && (excess = tokenize(unquoted, true)) // advance to the next closing parenthesis && (excess = unquoted.indexOf(')', unquoted.length - excess) - unquoted.length)) { // excess is a negative index match[0] = match[0].slice(0, excess) match[2] = unquoted.slice(0, excess) } // Return only captures needed by the pseudo filter method (type and argument) return match.slice(0, 3) }, }, filter: { TAG (nodeNameSelector) { const nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase() return nodeNameSelector === '*' ? function () { return true } : function (elem) { return elem.nodeName && elem.nodeName.toLowerCase() === nodeName } }, CLASS (className) { let pattern = classCache[`${className} `] return pattern || (pattern = new RegExp(`(^|${whitespace})${className}(${whitespace}|$)`)) && classCache(className, (elem) => pattern.test(typeof elem.className === 'string' && elem.className || typeof elem.getAttribute !== 'undefined' && elem.getAttribute('class') || '')) }, ATTR (name, operator, check) { return function (elem) { let result = Sizzle.attr(elem, name) if (result == null) { return operator === '!=' } if (!operator) { return true } result += '' return operator === '=' ? result === check : operator === '!=' ? result !== check : operator === '^=' ? check && result.indexOf(check) === 0 : operator === '*=' ? check && result.indexOf(check) > -1 : operator === '$=' ? check && result.slice(-check.length) === check : operator === '~=' ? (` ${result.replace(rwhitespace, ' ')} `).indexOf(check) > -1 : operator === '|=' ? result === check || result.slice(0, check.length + 1) === `${check}-` : false } }, CHILD (type, what, argument, first, last) { const simple = type.slice(0, 3) !== 'nth' const forward = type.slice(-4) !== 'last' const ofType = what === 'of-type' return first === 1 && last === 0 // Shortcut for :nth-*(n) ? function (elem) { return !!elem.parentNode } : function (elem, context, xml) { let cache; let uniqueCache; let outerCache; let node; let nodeIndex; let start let dir = simple !== forward ? 'nextSibling' : 'previousSibling' const parent = elem.parentNode const name = ofType && elem.nodeName.toLowerCase() const useCache = !xml && !ofType let diff = false if (parent) { // :(first|last|only)-(child|of-type) if (simple) { while (dir) { node = elem while ((node = node[dir])) { if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) { return false } } // Reverse direction for :only-* (if we haven't yet done so) start = dir = type === 'only' && !start && 'nextSibling' } return true } start = [forward ? parent.firstChild : parent.lastChild] // non-xml :nth-child(...) stores cache data on `parent` if (forward && useCache) { // Seek `elem` from a previously-cached index // ...in a gzip-friendly way node = parent outerCache = node[expando] || (node[expando] = {}) // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}) cache = uniqueCache[type] || [] nodeIndex = cache[0] === dirruns && cache[1] diff = nodeIndex && cache[2] node = nodeIndex && parent.childNodes[nodeIndex] while ((node = ++nodeIndex && node && node[dir] // Fallback to seeking `elem` from the start || (diff = nodeIndex = 0) || start.pop())) { // When found, cache indexes on `parent` and break if (node.nodeType === 1 && ++diff && node === elem) { uniqueCache[type] = [dirruns, nodeIndex, diff] break } } } else { // Use previously-cached element index if available if (useCache) { // ...in a gzip-friendly way node = elem outerCache = node[expando] || (node[expando] = {}) // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}) cache = uniqueCache[type] || [] nodeIndex = cache[0] === dirruns && cache[1] diff = nodeIndex } // xml :nth-child(...) // or :nth-last-child(...) or :nth(-last)?-of-type(...) if (diff === false) { // Use the same loop as above to seek `elem` from the start while ((node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop())) { if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) { // Cache the index of each encountered element if (useCache) { outerCache = node[expando] || (node[expando] = {}) // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {}) uniqueCache[type] = [dirruns, diff] } if (node === elem) { break } } } } } // Incorporate the offset, then check against cycle size diff -= last return diff === first || (diff % first === 0 && diff / first >= 0) } } }, PSEUDO (pseudo, argument) { // pseudo-class names are case-insensitive // http://www.w3.org/TR/selectors/#pseudo-classes // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters // Remember that setFilters inherits from pseudos let args const fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error(`unsupported pseudo: ${pseudo}`) // The user may use createPseudo to indicate that // arguments are needed to create the filter function // just as Sizzle does if (fn[expando]) { return fn(argument) } // But maintain support for old signatures if (fn.length > 1) { args = [pseudo, pseudo, '', argument] return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction((seed, matches) => { let idx const matched = fn(seed, argument) let i = matched.length while (i--) { idx = indexOf(seed, matched[i]) seed[idx] = !(matches[idx] = matched[i]) } }) : function (elem) { return fn(elem, 0, args) } } return fn }, }, pseudos: { // Potentially complex pseudos not: markFunction((selector) => { // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators const input = [] const results = [] const matcher = compile(selector.replace(rtrim, '$1')) return matcher[expando] ? markFunction((seed, matches, context, xml) => { let elem const unmatched = matcher(seed, null, xml, []) let i = seed.length // Match elements unmatched by `matcher` while (i--) { if ((elem = unmatched[i])) { seed[i] = !(matches[i] = elem) } } }) : function (elem, context, xml) { input[0] = elem matcher(input, null, xml, results) // Don't keep the element (issue #299) input[0] = null return !results.pop() } }), has: markFunction((selector) => function (elem) { return Sizzle(selector, elem).length > 0 }), contains: markFunction((text) => { text = text.replace(runescape, funescape) return function (elem) { return (elem.textContent || getText(elem)).indexOf(text) > -1 } }), // "Whether an element is represented by a :lang() selector // is based solely on the element's language value // being equal to the identifier C, // or beginning with the identifier C immediately followed by "-". // The matching of C against the element's language value is performed case-insensitively. // The identifier C does not have to be a valid language name." // http://www.w3.org/TR/selectors/#lang-pseudo lang: markFunction((lang) => { // lang value must be a valid identifier if (!ridentifier.test(lang || '')) { Sizzle.error(`unsupported lang: ${lang}`) } lang = lang.replace(runescape, funescape).toLowerCase() return function (elem) { let elemLang do { if ((elemLang = documentIsHTML ? elem.lang : elem.getAttribute('xml:lang') || elem.getAttribute('lang'))) { elemLang = elemLang.toLowerCase() return elemLang === lang || elemLang.indexOf(`${lang}-`) === 0 } } while ((elem = elem.parentNode) && elem.nodeType === 1) return false } }), // Miscellaneous target (elem) { const hash = window.location && window.location.hash return hash && hash.slice(1) === elem.id }, root (elem) { return elem === docElem }, focus (elem) { return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex) }, // Boolean properties enabled: createDisabledPseudo(false), disabled: createDisabledPseudo(true), checked (elem) { // In CSS3, :checked should return both checked and selected elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked const nodeName = elem.nodeName.toLowerCase() return (nodeName === 'input' && !!elem.checked) || (nodeName === 'option' && !!elem.selected) }, selected (elem) { // Accessing this property makes selected-by-default // options in Safari work properly if (elem.parentNode) { elem.parentNode.selectedIndex } return elem.selected === true }, // Contents empty (elem) { // http://www.w3.org/TR/selectors/#empty-pseudo // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), // but not by others (comment: 8; processing instruction: 7; etc.) // nodeType < 6 works because attributes (2) do not appear as children for (elem = elem.firstChild; elem; elem = elem.nextSibling) { if (elem.nodeType < 6) { return false } } return true }, parent (elem) { return !Expr.pseudos.empty(elem) }, // Element/input types header (elem) { return rheader.test(elem.nodeName) }, input (elem) { return rinputs.test(elem.nodeName) }, button (elem) { const name = elem.nodeName.toLowerCase() return name === 'input' && elem.type === 'button' || name === 'button' }, text (elem) { let attr return elem.nodeName.toLowerCase() === 'input' && elem.type === 'text' // Support: IE<8 // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" && ((attr = elem.getAttribute('type')) == null || attr.toLowerCase() === 'text') }, // Position-in-collection first: createPositionalPseudo(() => [0]), last: createPositionalPseudo((matchIndexes, length) => [length - 1]), eq: createPositionalPseudo((matchIndexes, length, argument) => [argument < 0 ? argument + length : argument]), even: createPositionalPseudo((matchIndexes, length) => { let i = 0 for (; i < length; i += 2) { matchIndexes.push(i) } return matchIndexes }), odd: createPositionalPseudo((matchIndexes, length) => { let i = 1 for (; i < length; i += 2) { matchIndexes.push(i) } return matchIndexes }), lt: createPositionalPseudo((matchIndexes, length, argument) => { let i = argument < 0 ? argument + length : argument > length ? length : argument for (; --i >= 0;) { matchIndexes.push(i) } return matchIndexes }), gt: createPositionalPseudo((matchIndexes, length, argument) => { let i = argument < 0 ? argument + length : argument for (; ++i < length;) { matchIndexes.push(i) } return matchIndexes }), }, } Expr.pseudos.nth = Expr.pseudos.eq // Add button/input type pseudos for (i in { radio: true, checkbox: true, file: true, password: true, image: true, }) { Expr.pseudos[i] = createInputPseudo(i) } for (i in { submit: true, reset: true }) { Expr.pseudos[i] = createButtonPseudo(i) } // Easy API for creating new setFilters function setFilters () { } setFilters.prototype = Expr.filters = Expr.pseudos Expr.setFilters = new setFilters() tokenize = Sizzle.tokenize = function (selector, parseOnly) { let matched; let match; let tokens; let type let soFar; let groups; let preFilters const cached = tokenCache[`${selector} `] if (cached) { return parseOnly ? 0 : cached.slice(0) } soFar = selector groups = [] preFilters = Expr.preFilter while (soFar) { // Comma and first run if (!matched || (match = rcomma.exec(soFar))) { if (match) { // Don't consume trailing commas as valid soFar = soFar.slice(match[0].length) || soFar } groups.push((tokens = [])) } matched = false // Combinators if ((match = rcombinators.exec(soFar))) { matched = match.shift() tokens.push({ value: matched, // Cast descendant combinators to space type: match[0].replace(rtrim, ' '), }) soFar = soFar.slice(matched.length) } // Filters for (type in Expr.filter) { if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) { matched = match.shift() tokens.push({ value: matched, type, matches: match, }) soFar = soFar.slice(matched.length) } } if (!matched) { break } } // Return the length of the invalid excess // if we're just parsing // Otherwise, throw an error or return tokens return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) // Cache the tokens : tokenCache(selector, groups).slice(0) } function toSelector (tokens) { let i = 0 const len = tokens.length let selector = '' for (; i < len; i++) { selector += tokens[i].value } return selector } function addCombinator (matcher, combinator, base) { const { dir } = combinator const skip = combinator.next const key = skip || dir const checkNonElements = base && key === 'parentNode' const doneName = done++ return combinator.first // Check against closest ancestor/preceding element ? function (elem, context, xml) { while ((elem = elem[dir])) { if (elem.nodeType === 1 || checkNonElements) { return matcher(elem, context, xml) } } return false } // Check against all ancestor/preceding elements : function (elem, context, xml) { let oldCache; let uniqueCache; let outerCache const newCache = [dirruns, doneName] // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching if (xml) { while ((elem = elem[dir])) { if (elem.nodeType === 1 || checkNonElements) { if (matcher(elem, context, xml)) { return true } } } } else { while ((elem = elem[dir])) { if (elem.nodeType === 1 || checkNonElements) { outerCache = elem[expando] || (elem[expando] = {}) // Support: IE <9 only // Defend against cloned attroperties (jQuery gh-1709) uniqueCache = outerCache[elem.uniqueID] || (outerCache[elem.uniqueID] = {}) if (skip && skip === elem.nodeName.toLowerCase()) { elem = elem[dir] || elem } else if ((oldCache = uniqueCache[key]) && oldCache[0] === dirruns && oldCache[1] === doneName) { // Assign to newCache so results back-propagate to previous elements return (newCache[2] = oldCache[2]) } else { // Reuse newcache so results back-propagate to previous elements uniqueCache[key] = newCache // A match means we're done; a fail means we have to keep checking if ((newCache[2] = matcher(elem, context, xml))) { return true } } } } } return false } } function elementMatcher (matchers) { return matchers.length > 1 ? function (elem, context, xml) { let i = matchers.length while (i--) { if (!matchers[i](elem, context, xml)) { return false } } return true } : matchers[0] } function multipleContexts (selector, contexts, results) { let i = 0 const len = contexts.length for (; i < len; i++) { Sizzle(selector, contexts[i], results) } return results } function condense (unmatched, map, filter, context, xml) { let elem const newUnmatched = [] let i = 0 const len = unmatched.length const mapped = map != null for (; i < len; i++) { if ((elem = unmatched[i])) { if (!filter || filter(elem, context, xml)) { newUnmatched.push(elem) if (mapped) { map.push(i) } } } } return newUnmatched } function setMatcher (preFilter, selector, matcher, postFilter, postFinder, postSelector) { if (postFilter && !postFilter[expando]) { postFilter = setMatcher(postFilter) } if (postFinder && !postFinder[expando]) { postFinder = setMatcher(postFinder, postSelector) } return markFunction((seed, results, context, xml) => { let temp; let i; let elem const preMap = [] const postMap = [] const preexisting = results.length // Get initial elements from seed or context const elems = seed || multipleContexts(selector || '*', context.nodeType ? [context] : context, []) // Prefilter to get matcher input, preserving a map for seed-results synchronization const matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems let matcherOut = matcher // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, ? postFinder || (seed ? preFilter : preexisting || postFilter) // ...intermediate processing is necessary ? [] // ...otherwise use results directly : results : matcherIn // Find primary matches if (matcher) { matcher(matcherIn, matcherOut, context, xml) } // Apply postFilter if (postFilter) { temp = condense(matcherOut, postMap) postFilter(temp, [], context, xml) // Un-match failing elements by moving them back to matcherIn i = temp.length while (i--) { if ((elem = temp[i])) { matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem) } } } if (seed) { if (postFinder || preFilter) { if (postFinder) { // Get the final matcherOut by condensing this intermediate into postFinder contexts temp = [] i = matcherOut.length while (i--) { if ((elem = matcherOut[i])) { // Restore matcherIn since elem is not yet a final match temp.push((matcherIn[i] = elem)) } } postFinder(null, (matcherOut = []), temp, xml) } // Move matched elements from seed to results to keep them synchronized i = matcherOut.length while (i--) { if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf(seed, elem) : preMap[i]) > -1) { seed[temp] = !(results[temp] = elem) } } } // Add elements to results, through postFinder if defined } else { matcherOut = condense( matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut, ) if (postFinder) { postFinder(null, results, matcherOut, xml) } else { push.apply(results, matcherOut) } } }) } function matcherFromTokens (tokens) { let checkContext; let matcher; let j const len = tokens.length const leadingRelative = Expr.relative[tokens[0].type] const implicitRelative = leadingRelative || Expr.relative[' '] let i = leadingRelative ? 1 : 0 // The foundational matcher ensures that elements are reachable from top-level context(s) const matchContext = addCombinator((elem) => elem === checkContext, implicitRelative, true) const matchAnyContext = addCombinator((elem) => indexOf(checkContext, elem) > -1, implicitRelative, true) let matchers = [function (elem, context, xml) { const ret = (!leadingRelative && (xml || context !== outermostContext)) || ( (checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml)) // Avoid hanging onto element (issue #299) checkContext = null return ret }] for (; i < len; i++) { if ((matcher = Expr.relative[tokens[i].type])) { matchers = [addCombinator(elementMatcher(matchers), matcher)] } else { matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches) // Return special upon seeing a positional matcher if (matcher[expando]) { // Find the next relative operator (if any) for proper handling j = ++i for (; j < len; j++) { if (Expr.relative[tokens[j].type]) { break } } return setMatcher( i > 1 && elementMatcher(matchers), i > 1 && toSelector( // If the preceding token was a descendant combinator, insert an implicit any-element `*` tokens.slice(0, i - 1).concat({ value: tokens[i - 2].type === ' ' ? '*' : '' }), ).replace(rtrim, '$1'), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens((tokens = tokens.slice(j))), j < len && toSelector(tokens), ) } matchers.push(matcher) } } return elementMatcher(matchers) } function matcherFromGroupMatchers (elementMatchers, setMatchers) { const bySet = setMatchers.length > 0 const byElement = elementMatchers.length > 0 const superMatcher = function (seed, context, xml, results, outermost) { let elem; let j; let matcher let matchedCount = 0 let i = '0' const unmatched = seed && [] let setMatched = [] const contextBackup = outermostContext // We must always have either seed elements or outermost context const elems = seed || byElement && Expr.find.TAG('*', outermost) // Use integer dirruns iff this is the outermost matcher const dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1) const len = elems.length if (outermost) { outermostContext = context === document || context || outermost } // Add elements passing elementMatchers directly to results // Support: IE<9, Safari // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id for (; i !== len && (elem = elems[i]) != null; i++) { if (byElement && elem) { j = 0 if (!context && elem.ownerDocument !== document) { setDocument(elem) xml = !documentIsHTML } while ((matcher = elementMatchers[j++])) { if (matcher(elem, context || document, xml)) { results.push(elem) break } } if (outermost) { dirruns = dirrunsUnique } } // Track unmatched elements for set filters if (bySet) { // They will have gone through all possible matchers if ((elem = !matcher && elem)) { matchedCount-- } // Lengthen the array for every element, matched or not if (seed) { unmatched.push(elem) } } } // `i` is now the count of elements visited above, and adding it to `matchedCount` // makes the latter nonnegative. matchedCount += i // Apply set filters to unmatched elements // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` // equals `i`), unless we didn't visit _any_ elements in the above loop because we have // no element matchers and no seed. // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that // case, which will result in a "00" `matchedCount` that differs from `i` but is also // numerically zero. if (bySet && i !== matchedCount) { j = 0 while ((matcher = setMatchers[j++])) { matcher(unmatched, setMatched, context, xml) } if (seed) { // Reintegrate element matches to eliminate the need for sorting if (matchedCount > 0) { while (i--) { if (!(unmatched[i] || setMatched[i])) { setMatched[i] = pop.call(results) } } } // Discard index placeholder values to get only actual matches setMatched = condense(setMatched) } // Add matches to results push.apply(results, setMatched) // Seedless set matches succeeding multiple successful matchers stipulate sorting if (outermost && !seed && setMatched.length > 0 && (matchedCount + setMatchers.length) > 1) { Sizzle.uniqueSort(results) } } // Override manipulation of globals by nested matchers if (outermost) { dirruns = dirrunsUnique outermostContext = contextBackup } return unmatched } return bySet ? markFunction(superMatcher) : superMatcher } compile = Sizzle.compile = function (selector, match /* Internal Use Only */) { let i const setMatchers = [] const elementMatchers = [] let cached = compilerCache[`${selector} `] if (!cached) { // Generate a function of recursive functions that can be used to check each element if (!match) { match = tokenize(selector) } i = match.length while (i--) { cached = matcherFromTokens(match[i]) if (cached[expando]) { setMatchers.push(cached) } else { elementMatchers.push(cached) } } // Cache the compiled function cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers)) // Save selector and tokenization cached.selector = selector } return cached } /** * A low-level selection function that works with Sizzle's compiled * selector functions * @param {String|Function} selector A selector or a pre-compiled * selector function built with Sizzle.compile * @param {Element} context * @param {Array} [results] * @param {Array} [seed] A set of elements to match against */ select = Sizzle.select = function (selector, context, results, seed) { let i; let tokens; let token; let type; let find const compiled = typeof selector === 'function' && selector const match = !seed && tokenize((selector = compiled.selector || selector)) results = results || [] // Try to minimize operations if there is only one selector in the list and no seed // (the latter of which guarantees us context) if (match.length === 1) { // Reduce context if the leading compound selector is an ID tokens = match[0] = match[0].slice(0) if (tokens.length > 2 && (token = tokens[0]).type === 'ID' && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) { context = (Expr.find.ID(token.matches[0].replace(runescape, funescape), context) || [])[0] if (!context) { return results // Precompiled matchers will still verify ancestry, so step up a level } if (compiled) { context = context.parentNode } selector = selector.slice(tokens.shift().value.length) } // Fetch a seed set for right-to-left matching i = matchExpr.needsContext.test(selector) ? 0 : tokens.length while (i--) { token = tokens[i] // Abort if we hit a combinator if (Expr.relative[(type = token.type)]) { break } if ((find = Expr.find[type])) { // Search, expanding context for leading sibling combinators if ((seed = find( token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testContext(context.parentNode) || context, ))) { // If seed is empty or no tokens remain, we can return early tokens.splice(i, 1) selector = seed.length && toSelector(tokens) if (!selector) { push.apply(results, seed) return results } break } } } } // Compile and execute a filtering function if one is not provided // Provide `match` to avoid retokenization if we modified the selector above (compiled || compile(selector, match))( seed, context, !documentIsHTML, results, !context || rsibling.test(selector) && testContext(context.parentNode) || context, ) return results } // One-time assignments // Sort stability support.sortStable = expando.split('').sort(sortOrder).join('') === expando // Support: Chrome 14-35+ // Always assume duplicates if they aren't passed to the comparison function support.detectDuplicates = !!hasDuplicate // Initialize against the default document setDocument() // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) // Detached nodes confoundingly follow *each other* support.sortDetached = assert((el) => // Should return 1, but returns 4 (following) el.compareDocumentPosition(document.createElement('fieldset')) & 1) // Support: IE<8 // Prevent attribute/property "interpolation" // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx if (!assert((el) => { el.innerHTML = "" return el.firstChild.getAttribute('href') === '#' })) { addHandle('type|href|height|width', (elem, name, isXML) => { if (!isXML) { return elem.getAttribute(name, name.toLowerCase() === 'type' ? 1 : 2) } }) } // Support: IE<9 // Use defaultValue in place of getAttribute("value") if (!support.attributes || !assert((el) => { el.innerHTML = '' el.firstChild.setAttribute('value', '') return el.firstChild.getAttribute('value') === '' })) { addHandle('value', (elem, name, isXML) => { if (!isXML && elem.nodeName.toLowerCase() === 'input') { return elem.defaultValue } }) } // Support: IE<9 // Use getAttributeNode to fetch booleans when getAttribute lies if (!assert((el) => el.getAttribute('disabled') == null)) { addHandle(booleans, (elem, name, isXML) => { let val if (!isXML) { return elem[name] === true ? name.toLowerCase() : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null } }) } return Sizzle }(window)) jQuery.find = Sizzle jQuery.expr = Sizzle.selectors // Deprecated jQuery.expr[':'] = jQuery.expr.pseudos jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort jQuery.text = Sizzle.getText jQuery.isXMLDoc = Sizzle.isXML jQuery.contains = Sizzle.contains jQuery.escapeSelector = Sizzle.escape const dir = function (elem, dir, until) { const matched = [] const truncate = until !== undefined while ((elem = elem[dir]) && elem.nodeType !== 9) { if (elem.nodeType === 1) { if (truncate && jQuery(elem).is(until)) { break } matched.push(elem) } } return matched } const siblings = function (n, elem) { const matched = [] for (; n; n = n.nextSibling) { if (n.nodeType === 1 && n !== elem) { matched.push(n) } } return matched } const rneedsContext = jQuery.expr.match.needsContext function nodeName (elem, name) { return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase() } const rsingleTag = (/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i) // Implement the identical functionality for filter and not function winnow (elements, qualifier, not) { if (isFunction(qualifier)) { return jQuery.grep(elements, (elem, i) => !!qualifier.call(elem, i, elem) !== not) } // Single element if (qualifier.nodeType) { return jQuery.grep(elements, (elem) => (elem === qualifier) !== not) } // Arraylike of elements (jQuery, arguments, Array) if (typeof qualifier !== 'string') { return jQuery.grep(elements, (elem) => (indexOf.call(qualifier, elem) > -1) !== not) } // Filtered directly for both simple and complex selectors return jQuery.filter(qualifier, elements, not) } jQuery.filter = function (expr, elems, not) { const elem = elems[0] if (not) { expr = `:not(${expr})` } if (elems.length === 1 && elem.nodeType === 1) { return jQuery.find.matchesSelector(elem, expr) ? [elem] : [] } return jQuery.find.matches(expr, jQuery.grep(elems, (elem) => elem.nodeType === 1)) } jQuery.fn.extend({ find (selector) { let i; let ret const len = this.length const self = this if (typeof selector !== 'string') { return this.pushStack(jQuery(selector).filter(function () { for (i = 0; i < len; i++) { if (jQuery.contains(self[i], this)) { return true } } })) } ret = this.pushStack([]) for (i = 0; i < len; i++) { jQuery.find(selector, self[i], ret) } return len > 1 ? jQuery.uniqueSort(ret) : ret }, filter (selector) { return this.pushStack(winnow(this, selector || [], false)) }, not (selector) { return this.pushStack(winnow(this, selector || [], true)) }, is (selector) { return !!winnow( this, // If this is a positional/relative selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". typeof selector === 'string' && rneedsContext.test(selector) ? jQuery(selector) : selector || [], false, ).length }, }) // Initialize a jQuery object // A central reference to the root jQuery(document) let rootjQuery // A simple way to check for HTML strings // Prioritize #id over to avoid XSS via location.hash (#9521) // Strict HTML recognition (#11290: must start with <) // Shortcut simple #id case for speed const rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/ const init = jQuery.fn.init = function (selector, context, root) { let match; let elem // HANDLE: $(""), $(null), $(undefined), $(false) if (!selector) { return this } // Method init() accepts an alternate rootjQuery // so migrate can support jQuery.sub (gh-2101) root = root || rootjQuery // Handle HTML strings if (typeof selector === 'string') { if (selector[0] === '<' && selector[selector.length - 1] === '>' && selector.length >= 3) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [null, selector, null] } else { match = rquickExpr.exec(selector) } // Match html or make sure no context is specified for #id if (match && (match[1] || !context)) { // HANDLE: $(html) -> $(array) if (match[1]) { context = context instanceof jQuery ? context[0] : context // Option to run scripts is true for back-compat // Intentionally let the error be thrown if parseHTML is not present jQuery.merge(this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document$1, true, )) // HANDLE: $(html, props) if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) { for (match in context) { // Properties of context are called as methods if possible if (isFunction(this[match])) { this[match](context[match]) // ...and otherwise set as attributes } else { this.attr(match, context[match]) } } } return this // HANDLE: $(#id) } elem = document$1.getElementById(match[2]) if (elem) { // Inject the element directly into the jQuery object this[0] = elem this.length = 1 } return this // HANDLE: $(expr, $(...)) } if (!context || context.jquery) { return (context || root).find(selector) // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } return this.constructor(context).find(selector) // HANDLE: $(DOMElement) } if (selector.nodeType) { this[0] = selector this.length = 1 return this // HANDLE: $(function) // Shortcut for document ready } if (isFunction(selector)) { return root.ready !== undefined ? root.ready(selector) // Execute immediately if ready is not present : selector(jQuery) } return jQuery.makeArray(selector, this) } // Give the init function the jQuery prototype for later instantiation init.prototype = jQuery.fn // Initialize central reference rootjQuery = jQuery(document$1) const rparentsprev = /^(?:parents|prev(?:Until|All))/ // Methods guaranteed to produce a unique set when starting from a unique set const guaranteedUnique = { children: true, contents: true, next: true, prev: true, } jQuery.fn.extend({ has (target) { const targets = jQuery(target, this) const l = targets.length return this.filter(function () { let i = 0 for (; i < l; i++) { if (jQuery.contains(this, targets[i])) { return true } } }) }, closest (selectors, context) { let cur let i = 0 const l = this.length const matched = [] const targets = typeof selectors !== 'string' && jQuery(selectors) // Positional selectors never match, since there's no _selection_ context if (!rneedsContext.test(selectors)) { for (; i < l; i++) { for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) { // Always skip document fragments if (cur.nodeType < 11 && (targets ? targets.index(cur) > -1 // Don't pass non-elements to Sizzle : cur.nodeType === 1 && jQuery.find.matchesSelector(cur, selectors))) { matched.push(cur) break } } } } return this.pushStack(matched.length > 1 ? jQuery.uniqueSort(matched) : matched) }, // Determine the position of an element within the set index (elem) { // No argument, return index in parent if (!elem) { return (this[0] && this[0].parentNode) ? this.first().prevAll().length : -1 } // Index in selector if (typeof elem === 'string') { return indexOf.call(jQuery(elem), this[0]) } // Locate the position of the desired element return indexOf.call(this, // If it receives a jQuery object, the first element is used elem.jquery ? elem[0] : elem) }, add (selector, context) { return this.pushStack( jQuery.uniqueSort( jQuery.merge(this.get(), jQuery(selector, context)), ), ) }, addBack (selector) { return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector)) }, }) function sibling (cur, dir) { while ((cur = cur[dir]) && cur.nodeType !== 1) { } return cur } jQuery.each({ parent (elem) { const parent = elem.parentNode return parent && parent.nodeType !== 11 ? parent : null }, parents (elem) { return dir(elem, 'parentNode') }, parentsUntil (elem, i, until) { return dir(elem, 'parentNode', until) }, next (elem) { return sibling(elem, 'nextSibling') }, prev (elem) { return sibling(elem, 'previousSibling') }, nextAll (elem) { return dir(elem, 'nextSibling') }, prevAll (elem) { return dir(elem, 'previousSibling') }, nextUntil (elem, i, until) { return dir(elem, 'nextSibling', until) }, prevUntil (elem, i, until) { return dir(elem, 'previousSibling', until) }, siblings (elem) { return siblings((elem.parentNode || {}).firstChild, elem) }, children (elem) { return siblings(elem.firstChild) }, contents (elem) { if (typeof elem.contentDocument !== 'undefined') { return elem.contentDocument } // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only // Treat the template element as a regular one in browsers that // don't support it. if (nodeName(elem, 'template')) { elem = elem.content || elem } return jQuery.merge([], elem.childNodes) }, }, (name, fn) => { jQuery.fn[name] = function (until, selector) { let matched = jQuery.map(this, fn, until) if (name.slice(-5) !== 'Until') { selector = until } if (selector && typeof selector === 'string') { matched = jQuery.filter(selector, matched) } if (this.length > 1) { // Remove duplicates if (!guaranteedUnique[name]) { jQuery.uniqueSort(matched) } // Reverse order for parents* and prev-derivatives if (rparentsprev.test(name)) { matched.reverse() } } return this.pushStack(matched) } }) const rnothtmlwhite = (/[^\x20\t\r\n\f]+/g) // Convert String-formatted options into Object-formatted ones function createOptions (options) { const object = {} jQuery.each(options.match(rnothtmlwhite) || [], (_, flag) => { object[flag] = true }) return object } /* * Create a callback list using the following parameters: * * options: an optional list of space-separated options that will change how * the callback list behaves or a more traditional option object * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible options: * * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function (options) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof options === 'string' ? createOptions(options) : jQuery.extend({}, options) let // Flag to know if list is currently firing firing // Last fire value for non-forgettable lists let memory // Flag to know if list was already fired let fired // Flag to prevent firing let locked // Actual callback list let list = [] // Queue of execution data for repeatable lists let queue = [] // Index of currently firing callback (modified by add/remove as needed) let firingIndex = -1 // Fire callbacks const fire = function () { // Enforce single-firing locked = locked || options.once // Execute callbacks for all pending executions, // respecting firingIndex overrides and runtime changes fired = firing = true for (; queue.length; firingIndex = -1) { memory = queue.shift() while (++firingIndex < list.length) { // Run callback and check for early termination if (list[firingIndex].apply(memory[0], memory[1]) === false && options.stopOnFalse) { // Jump to end and forget the data so .add doesn't re-fire firingIndex = list.length memory = false } } } // Forget the data if we're done with it if (!options.memory) { memory = false } firing = false // Clean up if we're done firing for good if (locked) { // Keep an empty list if we have data for future add calls if (memory) { list = [] // Otherwise, this object is spent } else { list = '' } } } // Actual Callbacks object var self = { // Add a callback or a collection of callbacks to the list add () { if (list) { // If we have memory from a past run, we should fire after adding if (memory && !firing) { firingIndex = list.length - 1 queue.push(memory) } (function add (args) { jQuery.each(args, (_, arg) => { if (isFunction(arg)) { if (!options.unique || !self.has(arg)) { list.push(arg) } } else if (arg && arg.length && toType(arg) !== 'string') { // Inspect recursively add(arg) } }) }(arguments)) if (memory && !firing) { fire() } } return this }, // Remove a callback from the list remove () { jQuery.each(arguments, (_, arg) => { let index while ((index = jQuery.inArray(arg, list, index)) > -1) { list.splice(index, 1) // Handle firing indexes if (index <= firingIndex) { firingIndex-- } } }) return this }, // Check if a given callback is in the list. // If no argument is given, return whether or not list has callbacks attached. has (fn) { return fn ? jQuery.inArray(fn, list) > -1 : list.length > 0 }, // Remove all callbacks from the list empty () { if (list) { list = [] } return this }, // Disable .fire and .add // Abort any current/pending executions // Clear all callbacks and values disable () { locked = queue = [] list = memory = '' return this }, disabled () { return !list }, // Disable .fire // Also disable .add unless we have memory (since it would have no effect) // Abort any pending executions lock () { locked = queue = [] if (!memory && !firing) { list = memory = '' } return this }, locked () { return !!locked }, // Call all callbacks with the given context and arguments fireWith (context, args) { if (!locked) { args = args || [] args = [context, args.slice ? args.slice() : args] queue.push(args) if (!firing) { fire() } } return this }, // Call all the callbacks with the given arguments fire () { self.fireWith(this, arguments) return this }, // To know if the callbacks have already been called at least once fired () { return !!fired }, } return self } function Identity (v) { return v } function Thrower (ex) { throw ex } function adoptValue (value, resolve, reject, noValue) { let method try { // Check for promise aspect first to privilege synchronous behavior if (value && isFunction((method = value.promise))) { method.call(value).done(resolve).fail(reject) // Other thenables } else if (value && isFunction((method = value.then))) { method.call(value, resolve, reject) // Other non-thenables } else { // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: // * false: [ value ].slice( 0 ) => resolve( value ) // * true: [ value ].slice( 1 ) => resolve() resolve.apply(undefined, [value].slice(noValue)) } // For Promises/A+, convert exceptions into rejections // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in // Deferred#then to conditionally suppress rejection. } catch (value) { // Support: Android 4.0 only // Strict mode functions invoked without .call/.apply get global-object context reject.apply(undefined, [value]) } } jQuery.extend({ Deferred (func) { const tuples = [ // action, add listener, callbacks, // ... .then handlers, argument index, [final state] ['notify', 'progress', jQuery.Callbacks('memory'), jQuery.Callbacks('memory'), 2], ['resolve', 'done', jQuery.Callbacks('once memory'), jQuery.Callbacks('once memory'), 0, 'resolved'], ['reject', 'fail', jQuery.Callbacks('once memory'), jQuery.Callbacks('once memory'), 1, 'rejected'], ] let state = 'pending' var promise = { state () { return state }, always () { deferred.done(arguments).fail(arguments) return this }, catch (fn) { return promise.then(null, fn) }, // Keep pipe for back-compat pipe (/* fnDone, fnFail, fnProgress */) { let fns = arguments return jQuery.Deferred((newDefer) => { jQuery.each(tuples, (i, tuple) => { // Map tuples (progress, done, fail) to arguments (done, fail, progress) const fn = isFunction(fns[tuple[4]]) && fns[tuple[4]] // deferred.progress(function() { bind to newDefer or newDefer.notify }) // deferred.done(function() { bind to newDefer or newDefer.resolve }) // deferred.fail(function() { bind to newDefer or newDefer.reject }) deferred[tuple[1]](function () { const returned = fn && fn.apply(this, arguments) if (returned && isFunction(returned.promise)) { returned.promise() .progress(newDefer.notify) .done(newDefer.resolve) .fail(newDefer.reject) } else { newDefer[`${tuple[0]}With`]( this, fn ? [returned] : arguments, ) } }) }) fns = null }).promise() }, then (onFulfilled, onRejected, onProgress) { let maxDepth = 0 function resolve (depth, deferred, handler, special) { return function () { let that = this let args = arguments const mightThrow = function () { let returned; let then // Support: Promises/A+ section 2.3.3.3.3 // https://promisesaplus.com/#point-59 // Ignore double-resolution attempts if (depth < maxDepth) { return } returned = handler.apply(that, args) // Support: Promises/A+ section 2.3.1 // https://promisesaplus.com/#point-48 if (returned === deferred.promise()) { throw new TypeError('Thenable self-resolution') } // Support: Promises/A+ sections 2.3.3.1, 3.5 // https://promisesaplus.com/#point-54 // https://promisesaplus.com/#point-75 // Retrieve `then` only once then = returned // Support: Promises/A+ section 2.3.4 // https://promisesaplus.com/#point-64 // Only check objects and functions for thenability && (typeof returned === 'object' || typeof returned === 'function') && returned.then // Handle a returned thenable if (isFunction(then)) { // Special processors (notify) just wait for resolution if (special) { then.call( returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special), ) // Normal processors (resolve) also hook into progress } else { // ...and disregard older resolution values maxDepth++ then.call( returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special), resolve(maxDepth, deferred, Identity, deferred.notifyWith), ) } // Handle all other returned values } else { // Only substitute handlers pass on context // and multiple values (non-spec behavior) if (handler !== Identity) { that = undefined args = [returned] } // Process the value(s) // Default process is resolve (special || deferred.resolveWith)(that, args) } } // Only normal processors (resolve) catch and reject exceptions var process = special ? mightThrow : function () { try { mightThrow() } catch (e) { if (jQuery.Deferred.exceptionHook) { jQuery.Deferred.exceptionHook(e, process.stackTrace) } // Support: Promises/A+ section 2.3.3.3.4.1 // https://promisesaplus.com/#point-61 // Ignore post-resolution exceptions if (depth + 1 >= maxDepth) { // Only substitute handlers pass on context // and multiple values (non-spec behavior) if (handler !== Thrower) { that = undefined args = [e] } deferred.rejectWith(that, args) } } } // Support: Promises/A+ section 2.3.3.3.1 // https://promisesaplus.com/#point-57 // Re-resolve promises immediately to dodge false rejection from // subsequent errors if (depth) { process() } else { // Call an optional hook to record the stack, in case of exception // since it's otherwise lost when execution goes async if (jQuery.Deferred.getStackHook) { process.stackTrace = jQuery.Deferred.getStackHook() } window.setTimeout(process) } } } return jQuery.Deferred((newDefer) => { // progress_handlers.add( ... ) tuples[0][3].add( resolve( 0, newDefer, isFunction(onProgress) ? onProgress : Identity, newDefer.notifyWith, ), ) // fulfilled_handlers.add( ... ) tuples[1][3].add( resolve( 0, newDefer, isFunction(onFulfilled) ? onFulfilled : Identity, ), ) // rejected_handlers.add( ... ) tuples[2][3].add( resolve( 0, newDefer, isFunction(onRejected) ? onRejected : Thrower, ), ) }).promise() }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise (obj) { return obj != null ? jQuery.extend(obj, promise) : promise }, } var deferred = {} // Add list-specific methods jQuery.each(tuples, (i, tuple) => { const list = tuple[2] const stateString = tuple[5] // promise.progress = list.add // promise.done = list.add // promise.fail = list.add promise[tuple[1]] = list.add // Handle state if (stateString) { list.add( () => { // state = "resolved" (i.e., fulfilled) // state = "rejected" state = stateString }, // rejected_callbacks.disable // fulfilled_callbacks.disable tuples[3 - i][2].disable, // rejected_handlers.disable // fulfilled_handlers.disable tuples[3 - i][3].disable, // progress_callbacks.lock tuples[0][2].lock, // progress_handlers.lock tuples[0][3].lock, ) } // progress_handlers.fire // fulfilled_handlers.fire // rejected_handlers.fire list.add(tuple[3].fire) // deferred.notify = function() { deferred.notifyWith(...) } // deferred.resolve = function() { deferred.resolveWith(...) } // deferred.reject = function() { deferred.rejectWith(...) } deferred[tuple[0]] = function () { deferred[`${tuple[0]}With`](this === deferred ? undefined : this, arguments) return this } // deferred.notifyWith = list.fireWith // deferred.resolveWith = list.fireWith // deferred.rejectWith = list.fireWith deferred[`${tuple[0]}With`] = list.fireWith }) // Make the deferred a promise promise.promise(deferred) // Call given func if any if (func) { func.call(deferred, deferred) } // All done! return deferred }, // Deferred helper when (singleValue) { let // count of uncompleted subordinates remaining = arguments.length // count of unprocessed arguments let i = remaining // subordinate fulfillment data const resolveContexts = Array(i) const resolveValues = slice$1.call(arguments) // the master Deferred const master = jQuery.Deferred() // subordinate callback factory const updateFunc = function (i) { return function (value) { resolveContexts[i] = this resolveValues[i] = arguments.length > 1 ? slice$1.call(arguments) : value if (!(--remaining)) { master.resolveWith(resolveContexts, resolveValues) } } } // Single- and empty arguments are adopted like Promise.resolve if (remaining <= 1) { adoptValue(singleValue, master.done(updateFunc(i)).resolve, master.reject, !remaining) // Use .then() to unwrap secondary thenables (cf. gh-3000) if (master.state() === 'pending' || isFunction(resolveValues[i] && resolveValues[i].then)) { return master.then() } } // Multiple arguments are aggregated like Promise.all array elements while (i--) { adoptValue(resolveValues[i], updateFunc(i), master.reject) } return master.promise() }, }) // These usually indicate a programmer mistake during development, // warn about them ASAP rather than swallowing them by default. const rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/ jQuery.Deferred.exceptionHook = function (error, stack) { // Support: IE 8 - 9 only // Console exists when dev tools are open, which can happen at any time if (window.console && window.console.warn && error && rerrorNames.test(error.name)) { window.console.warn(`jQuery.Deferred exception: ${error.message}`, error.stack, stack) } } jQuery.readyException = function (error) { window.setTimeout(() => { throw error }) } // The deferred used on DOM ready const readyList = jQuery.Deferred() jQuery.fn.ready = function (fn) { readyList .then(fn) // Wrap jQuery.readyException in a function so that the lookup // happens at the time of error handling instead of callback // registration. .catch((error) => { jQuery.readyException(error) }) return this } jQuery.extend({ // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Handle when the DOM is ready ready (wait) { // Abort if there are pending holds or we're already ready if (wait === true ? --jQuery.readyWait : jQuery.isReady) { return } // Remember that the DOM is ready jQuery.isReady = true // If a normal DOM Ready event fired, decrement, and wait if need be if (wait !== true && --jQuery.readyWait > 0) { return } // If there are functions bound, to execute readyList.resolveWith(document$1, [jQuery]) }, }) jQuery.ready.then = readyList.then // The ready event handler and self cleanup method function completed () { document$1.removeEventListener('DOMContentLoaded', completed) window.removeEventListener('load', completed) jQuery.ready() } // Catch cases where $(document).ready() is called // after the browser event has already occurred. // Support: IE <=9 - 10 only // Older IE sometimes signals "interactive" too soon if (document$1.readyState === 'complete' || (document$1.readyState !== 'loading' && !document$1.documentElement.doScroll)) { // Handle it asynchronously to allow scripts the opportunity to delay ready window.setTimeout(jQuery.ready) } else { // Use the handy event callback document$1.addEventListener('DOMContentLoaded', completed) // A fallback to window.onload, that will always work window.addEventListener('load', completed) } // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function var access = function (elems, fn, key, value, chainable, emptyGet, raw) { let i = 0 const len = elems.length let bulk = key == null // Sets many values if (toType(key) === 'object') { chainable = true for (i in key) { access(elems, fn, i, key[i], true, emptyGet, raw) } // Sets one value } else if (value !== undefined) { chainable = true if (!isFunction(value)) { raw = true } if (bulk) { // Bulk operations run against the entire set if (raw) { fn.call(elems, value) fn = null // ...except when executing function values } else { bulk = fn fn = function (elem, key, value) { return bulk.call(jQuery(elem), value) } } } if (fn) { for (; i < len; i++) { fn( elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key)), ) } } } if (chainable) { return elems } // Gets if (bulk) { return fn.call(elems) } return len ? fn(elems[0], key) : emptyGet } // Matches dashed string for camelizing const rmsPrefix = /^-ms-/ const rdashAlpha = /-([a-z])/g // Used by camelCase as callback to replace() function fcamelCase (all, letter) { return letter.toUpperCase() } // Convert dashed to camelCase; used by the css and data modules // Support: IE <=9 - 11, Edge 12 - 15 // Microsoft forgot to hump their vendor prefix (#9572) function camelCase (string) { return string.replace(rmsPrefix, 'ms-').replace(rdashAlpha, fcamelCase) } const acceptData = function (owner) { // Accepts only: // - Node // - Node.ELEMENT_NODE // - Node.DOCUMENT_NODE // - Object // - Any return owner.nodeType === 1 || owner.nodeType === 9 || !(+owner.nodeType) } function Data () { this.expando = jQuery.expando + Data.uid++ } Data.uid = 1 Data.prototype = { cache (owner) { // Check if the owner object already has a cache let value = owner[this.expando] // If not, create one if (!value) { value = {} // We can accept data for non-element nodes in modern browsers, // but we should not, see #8335. // Always return an empty object. if (acceptData(owner)) { // If it is a node unlikely to be stringify-ed or looped over // use plain assignment if (owner.nodeType) { owner[this.expando] = value // Otherwise secure it in a non-enumerable property // configurable must be true to allow the property to be // deleted when data is removed } else { Object.defineProperty(owner, this.expando, { value, configurable: true, }) } } } return value }, set (owner, data, value) { let prop const cache = this.cache(owner) // Handle: [ owner, key, value ] args // Always use camelCase key (gh-2257) if (typeof data === 'string') { cache[camelCase(data)] = value // Handle: [ owner, { properties } ] args } else { // Copy the properties one-by-one to the cache object for (prop in data) { cache[camelCase(prop)] = data[prop] } } return cache }, get (owner, key) { return key === undefined ? this.cache(owner) // Always use camelCase key (gh-2257) : owner[this.expando] && owner[this.expando][camelCase(key)] }, access (owner, key, value) { // In cases where either: // // 1. No key was specified // 2. A string key was specified, but no value provided // // Take the "read" path and allow the get method to determine // which value to return, respectively either: // // 1. The entire cache object // 2. The data stored at the key // if (key === undefined || ((key && typeof key === 'string') && value === undefined)) { return this.get(owner, key) } // When the key is not a string, or both a key and value // are specified, set or extend (existing objects) with either: // // 1. An object of properties // 2. A key and value // this.set(owner, key, value) // Since the "set" path can have two possible entry points // return the expected data based on which path was taken[*] return value !== undefined ? value : key }, remove (owner, key) { let i const cache = owner[this.expando] if (cache === undefined) { return } if (key !== undefined) { // Support array or space separated string of keys if (Array.isArray(key)) { // If key is an array of keys... // We always set camelCase keys, so remove that. key = key.map(camelCase) } else { key = camelCase(key) // If a key with the spaces exists, use it. // Otherwise, create an array by matching non-whitespace key = key in cache ? [key] : (key.match(rnothtmlwhite) || []) } i = key.length while (i--) { delete cache[key[i]] } } // Remove the expando if there's no more data if (key === undefined || jQuery.isEmptyObject(cache)) { // Support: Chrome <=35 - 45 // Webkit & Blink performance suffers when deleting properties // from DOM nodes, so set to undefined instead // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) if (owner.nodeType) { owner[this.expando] = undefined } else { delete owner[this.expando] } } }, hasData (owner) { const cache = owner[this.expando] return cache !== undefined && !jQuery.isEmptyObject(cache) }, } const dataPriv = new Data() const dataUser = new Data() // Implementation Summary // // 1. Enforce API surface and semantic compatibility with 1.9.x branch // 2. Improve the module's maintainability by reducing the storage // paths to a single mechanism. // 3. Use the same single mechanism to support "private" and "user" data. // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) // 5. Avoid exposing implementation details on user objects (eg. expando properties) // 6. Provide a clear path for implementation upgrade to WeakMap in 2014 const rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/ const rmultiDash = /[A-Z]/g function getData (data) { if (data === 'true') { return true } if (data === 'false') { return false } if (data === 'null') { return null } // Only convert to a number if it doesn't change the string if (data === `${+data}`) { return +data } if (rbrace.test(data)) { return JSON.parse(data) } return data } function dataAttr (elem, key, data) { let name // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if (data === undefined && elem.nodeType === 1) { name = `data-${key.replace(rmultiDash, '-$&').toLowerCase()}` data = elem.getAttribute(name) if (typeof data === 'string') { try { data = getData(data) } catch (e) { } // Make sure we set the data so it isn't changed later dataUser.set(elem, key, data) } else { data = undefined } } return data } jQuery.extend({ hasData (elem) { return dataUser.hasData(elem) || dataPriv.hasData(elem) }, data (elem, name, data) { return dataUser.access(elem, name, data) }, removeData (elem, name) { dataUser.remove(elem, name) }, // TODO: Now that all calls to _data and _removeData have been replaced // with direct calls to dataPriv methods, these can be deprecated. _data (elem, name, data) { return dataPriv.access(elem, name, data) }, _removeData (elem, name) { dataPriv.remove(elem, name) }, }) jQuery.fn.extend({ data (key, value) { let i; let name; let data const elem = this[0] const attrs = elem && elem.attributes // Gets all values if (key === undefined) { if (this.length) { data = dataUser.get(elem) if (elem.nodeType === 1 && !dataPriv.get(elem, 'hasDataAttrs')) { i = attrs.length while (i--) { // Support: IE 11 only // The attrs elements can be null (#14894) if (attrs[i]) { name = attrs[i].name if (name.indexOf('data-') === 0) { name = camelCase(name.slice(5)) dataAttr(elem, name, data[name]) } } } dataPriv.set(elem, 'hasDataAttrs', true) } } return data } // Sets multiple values if (typeof key === 'object') { return this.each(function () { dataUser.set(this, key) }) } return access(this, function (value) { let data // The calling jQuery object (element matches) is not empty // (and therefore has an element appears at this[ 0 ]) and the // `value` parameter was not undefined. An empty jQuery object // will result in `undefined` for elem = this[ 0 ] which will // throw an exception if an attempt to read a data cache is made. if (elem && value === undefined) { // Attempt to get data from the cache // The key will always be camelCased in Data data = dataUser.get(elem, key) if (data !== undefined) { return data } // Attempt to "discover" the data in // HTML5 custom data-* attrs data = dataAttr(elem, key) if (data !== undefined) { return data } // We tried really hard, but the data doesn't exist. return } // Set the data... this.each(function () { // We always store the camelCased key dataUser.set(this, key, value) }) }, null, value, arguments.length > 1, null, true) }, removeData (key) { return this.each(function () { dataUser.remove(this, key) }) }, }) jQuery.extend({ queue (elem, type, data) { let queue if (elem) { type = `${type || 'fx'}queue` queue = dataPriv.get(elem, type) // Speed up dequeue by getting out quickly if this is just a lookup if (data) { if (!queue || Array.isArray(data)) { queue = dataPriv.access(elem, type, jQuery.makeArray(data)) } else { queue.push(data) } } return queue || [] } }, dequeue (elem, type) { type = type || 'fx' const queue = jQuery.queue(elem, type) let startLength = queue.length let fn = queue.shift() const hooks = jQuery._queueHooks(elem, type) const next = function () { jQuery.dequeue(elem, type) } // If the fx queue is dequeued, always remove the progress sentinel if (fn === 'inprogress') { fn = queue.shift() startLength-- } if (fn) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if (type === 'fx') { queue.unshift('inprogress') } // Clear up the last queue stop function delete hooks.stop fn.call(elem, next, hooks) } if (!startLength && hooks) { hooks.empty.fire() } }, // Not public - generate a queueHooks object, or return the current one _queueHooks (elem, type) { const key = `${type}queueHooks` return dataPriv.get(elem, key) || dataPriv.access(elem, key, { empty: jQuery.Callbacks('once memory').add(() => { dataPriv.remove(elem, [`${type}queue`, key]) }), }) }, }) jQuery.fn.extend({ queue (type, data) { let setter = 2 if (typeof type !== 'string') { data = type type = 'fx' setter-- } if (arguments.length < setter) { return jQuery.queue(this[0], type) } return data === undefined ? this : this.each(function () { const queue = jQuery.queue(this, type, data) // Ensure a hooks for this queue jQuery._queueHooks(this, type) if (type === 'fx' && queue[0] !== 'inprogress') { jQuery.dequeue(this, type) } }) }, dequeue (type) { return this.each(function () { jQuery.dequeue(this, type) }) }, clearQueue (type) { return this.queue(type || 'fx', []) }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise (type, obj) { let tmp let count = 1 const defer = jQuery.Deferred() const elements = this let i = this.length const resolve = function () { if (!(--count)) { defer.resolveWith(elements, [elements]) } } if (typeof type !== 'string') { obj = type type = undefined } type = type || 'fx' while (i--) { tmp = dataPriv.get(elements[i], `${type}queueHooks`) if (tmp && tmp.empty) { count++ tmp.empty.add(resolve) } } resolve() return defer.promise(obj) }, }) const pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source const rcssNum = new RegExp(`^(?:([+-])=|)(${pnum})([a-z%]*)$`, 'i') const cssExpand = ['Top', 'Right', 'Bottom', 'Left'] const { documentElement } = document$1 let isAttached = function (elem) { return jQuery.contains(elem.ownerDocument, elem) } const composed = { composed: true } // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only // Check attachment across shadow DOM boundaries when possible (gh-3504) // Support: iOS 10.0-10.2 only // Early iOS 10 versions support `attachShadow` but not `getRootNode`, // leading to errors. We need to check for `getRootNode`. if (documentElement.getRootNode) { isAttached = function (elem) { return jQuery.contains(elem.ownerDocument, elem) || elem.getRootNode(composed) === elem.ownerDocument } } const isHiddenWithinTree = function (elem, el) { // isHiddenWithinTree might be called from jQuery#filter function; // in that case, element will be second argument elem = el || elem // Inline style trumps all return elem.style.display === 'none' || elem.style.display === '' // Otherwise, check computed style // Support: Firefox <=43 - 45 // Disconnected elements can have computed display: none, so first confirm that elem is // in the document. && isAttached(elem) && jQuery.css(elem, 'display') === 'none' } const swap = function (elem, options, callback, args) { let ret; let name const old = {} // Remember the old values, and insert the new ones for (name in options) { old[name] = elem.style[name] elem.style[name] = options[name] } ret = callback.apply(elem, args || []) // Revert the old values for (name in options) { elem.style[name] = old[name] } return ret } function adjustCSS (elem, prop, valueParts, tween) { let adjusted; let scale let maxIterations = 20 const currentValue = tween ? function () { return tween.cur() } : function () { return jQuery.css(elem, prop, '') } let initial = currentValue() let unit = valueParts && valueParts[3] || (jQuery.cssNumber[prop] ? '' : 'px') // Starting value computation is required for potential unit mismatches let initialInUnit = elem.nodeType && (jQuery.cssNumber[prop] || unit !== 'px' && +initial) && rcssNum.exec(jQuery.css(elem, prop)) if (initialInUnit && initialInUnit[3] !== unit) { // Support: Firefox <=54 // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) initial /= 2 // Trust units reported by jQuery.css unit = unit || initialInUnit[3] // Iteratively approximate from a nonzero starting point initialInUnit = +initial || 1 while (maxIterations--) { // Evaluate and update our best guess (doubling guesses that zero out). // Finish if the scale equals or crosses 1 (making the old*new product non-positive). jQuery.style(elem, prop, initialInUnit + unit) if ((1 - scale) * (1 - (scale = currentValue() / initial || 0.5)) <= 0) { maxIterations = 0 } initialInUnit /= scale } initialInUnit *= 2 jQuery.style(elem, prop, initialInUnit + unit) // Make sure we update the tween properties later on valueParts = valueParts || [] } if (valueParts) { initialInUnit = +initialInUnit || +initial || 0 // Apply relative offset (+=/-=) if specified adjusted = valueParts[1] ? initialInUnit + (valueParts[1] + 1) * valueParts[2] : +valueParts[2] if (tween) { tween.unit = unit tween.start = initialInUnit tween.end = adjusted } } return adjusted } const defaultDisplayMap = {} function getDefaultDisplay (elem) { let temp const doc = elem.ownerDocument const { nodeName } = elem let display = defaultDisplayMap[nodeName] if (display) { return display } temp = doc.body.appendChild(doc.createElement(nodeName)) display = jQuery.css(temp, 'display') temp.parentNode.removeChild(temp) if (display === 'none') { display = 'block' } defaultDisplayMap[nodeName] = display return display } function showHide (elements, show) { let display; let elem const values = [] let index = 0 const { length } = elements // Determine new display value for elements that need to change for (; index < length; index++) { elem = elements[index] if (!elem.style) { continue } display = elem.style.display if (show) { // Since we force visibility upon cascade-hidden elements, an immediate (and slow) // check is required in this first loop unless we have a nonempty display value (either // inline or about-to-be-restored) if (display === 'none') { values[index] = dataPriv.get(elem, 'display') || null if (!values[index]) { elem.style.display = '' } } if (elem.style.display === '' && isHiddenWithinTree(elem)) { values[index] = getDefaultDisplay(elem) } } else if (display !== 'none') { values[index] = 'none' // Remember what we're overwriting dataPriv.set(elem, 'display', display) } } // Set the display of the elements in a second loop to avoid constant reflow for (index = 0; index < length; index++) { if (values[index] != null) { elements[index].style.display = values[index] } } return elements } jQuery.fn.extend({ show () { return showHide(this, true) }, hide () { return showHide(this) }, toggle (state) { if (typeof state === 'boolean') { return state ? this.show() : this.hide() } return this.each(function () { if (isHiddenWithinTree(this)) { jQuery(this).show() } else { jQuery(this).hide() } }) }, }) const rcheckableType = (/^(?:checkbox|radio)$/i) const rtagName = (/<([a-z][^\/\0>\x20\t\r\n\f]*)/i) const rscriptType = (/^$|^module$|\/(?:java|ecma)script/i) // We have to close these tags to support XHTML (#13200) const wrapMap = { // Support: IE <=9 only option: [1, "'], // XHTML parsers do not magically insert elements in the // same way that tag soup parsers do. So we cannot shorten // this by omitting or other required elements. thead: [1, '', '
'], col: [2, '', '
'], tr: [2, '', '
'], td: [3, '', '
'], _default: [0, '', ''], } // Support: IE <=9 only wrapMap.optgroup = wrapMap.option wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead wrapMap.th = wrapMap.td function getAll (context, tag) { // Support: IE <=9 - 11 only // Use typeof to avoid zero-argument method invocation on host objects (#15151) let ret if (typeof context.getElementsByTagName !== 'undefined') { ret = context.getElementsByTagName(tag || '*') } else if (typeof context.querySelectorAll !== 'undefined') { ret = context.querySelectorAll(tag || '*') } else { ret = [] } if (tag === undefined || tag && nodeName(context, tag)) { return jQuery.merge([context], ret) } return ret } // Mark scripts as having already been evaluated function setGlobalEval (elems, refElements) { let i = 0 const l = elems.length for (; i < l; i++) { dataPriv.set( elems[i], 'globalEval', !refElements || dataPriv.get(refElements[i], 'globalEval'), ) } } const rhtml = /<|&#?\w+;/ function buildFragment (elems, context, scripts, selection, ignored) { let elem; let tmp; let tag; let wrap; let attached; let j const fragment = context.createDocumentFragment() const nodes = [] let i = 0 const l = elems.length for (; i < l; i++) { elem = elems[i] if (elem || elem === 0) { // Add nodes directly if (toType(elem) === 'object') { // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge(nodes, elem.nodeType ? [elem] : elem) // Convert non-html into a text node } else if (!rhtml.test(elem)) { nodes.push(context.createTextNode(elem)) // Convert html into DOM nodes } else { tmp = tmp || fragment.appendChild(context.createElement('div')) // Deserialize a standard representation tag = (rtagName.exec(elem) || ['', ''])[1].toLowerCase() wrap = wrapMap[tag] || wrapMap._default tmp.innerHTML = wrap[1] + jQuery.htmlPrefilter(elem) + wrap[2] // Descend through wrappers to the right content j = wrap[0] while (j--) { tmp = tmp.lastChild } // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge(nodes, tmp.childNodes) // Remember the top-level container tmp = fragment.firstChild // Ensure the created nodes are orphaned (#12392) tmp.textContent = '' } } } // Remove wrapper from fragment fragment.textContent = '' i = 0 while ((elem = nodes[i++])) { // Skip elements already in the context collection (trac-4087) if (selection && jQuery.inArray(elem, selection) > -1) { if (ignored) { ignored.push(elem) } continue } attached = isAttached(elem) // Append to fragment tmp = getAll(fragment.appendChild(elem), 'script') // Preserve script evaluation history if (attached) { setGlobalEval(tmp) } // Capture executables if (scripts) { j = 0 while ((elem = tmp[j++])) { if (rscriptType.test(elem.type || '')) { scripts.push(elem) } } } } return fragment } (function () { const fragment = document$1.createDocumentFragment() const div = fragment.appendChild(document$1.createElement('div')) const input = document$1.createElement('input') // Support: Android 4.0 - 4.3 only // Check state lost if the name is set (#11217) // Support: Windows Web Apps (WWA) // `name` and `type` must use .setAttribute for WWA (#14901) input.setAttribute('type', 'radio') input.setAttribute('checked', 'checked') input.setAttribute('name', 't') div.appendChild(input) // Support: Android <=4.1 only // Older WebKit doesn't clone checked state correctly in fragments support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked // Support: IE <=11 only // Make sure textarea (and checkbox) defaultValue is properly cloned div.innerHTML = '' support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue }()) const rkeyEvent = /^key/ const rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/ const rtypenamespace = /^([^.]*)(?:\.(.+)|)/ function returnTrue () { return true } function returnFalse () { return false } // Support: IE <=9 - 11+ // focus() and blur() are asynchronous, except when they are no-op. // So expect focus to be synchronous when the element is already active, // and blur to be synchronous when the element is not already active. // (focus and blur are always synchronous in other supported browsers, // this just defines when we can count on it). function expectSync (elem, type) { return (elem === safeActiveElement()) === (type === 'focus') } // Support: IE <=9 only // Accessing document.activeElement can throw unexpectedly // https://bugs.jquery.com/ticket/13393 function safeActiveElement () { try { return document$1.activeElement } catch (err) { } } function on (elem, types, selector, data, fn, one) { let origFn; let type // Types can be a map of types/handlers if (typeof types === 'object') { // ( types-Object, selector, data ) if (typeof selector !== 'string') { // ( types-Object, data ) data = data || selector selector = undefined } for (type in types) { on(elem, type, selector, data, types[type], one) } return elem } if (data == null && fn == null) { // ( types, fn ) fn = selector data = selector = undefined } else if (fn == null) { if (typeof selector === 'string') { // ( types, selector, fn ) fn = data data = undefined } else { // ( types, data, fn ) fn = data data = selector selector = undefined } } if (fn === false) { fn = returnFalse } else if (!fn) { return elem } if (one === 1) { origFn = fn fn = function (event) { // Can use an empty set, since event contains the info jQuery().off(event) return origFn.apply(this, arguments) } // Use same guid so caller can remove using origFn fn.guid = origFn.guid || (origFn.guid = jQuery.guid++) } return elem.each(function () { jQuery.event.add(this, types, fn, data, selector) }) } /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = { global: {}, add (elem, types, handler, data, selector) { let handleObjIn; let eventHandle; let tmp let events; let t; let handleObj let special; let handlers; let type; let namespaces; let origType const elemData = dataPriv.get(elem) // Don't attach events to noData or text/comment nodes (but allow plain objects) if (!elemData) { return } // Caller can pass in an object of custom data in lieu of the handler if (handler.handler) { handleObjIn = handler handler = handleObjIn.handler selector = handleObjIn.selector } // Ensure that invalid selectors throw exceptions at attach time // Evaluate against documentElement in case elem is a non-element node (e.g., document) if (selector) { jQuery.find.matchesSelector(documentElement, selector) } // Make sure that the handler has a unique ID, used to find/remove it later if (!handler.guid) { handler.guid = jQuery.guid++ } // Init the element's event structure and main handler, if this is the first if (!(events = elemData.events)) { events = elemData.events = {} } if (!(eventHandle = elemData.handle)) { eventHandle = elemData.handle = function (e) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== 'undefined' && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply(elem, arguments) : undefined } } // Handle multiple events separated by a space types = (types || '').match(rnothtmlwhite) || [''] t = types.length while (t--) { tmp = rtypenamespace.exec(types[t]) || [] type = origType = tmp[1] namespaces = (tmp[2] || '').split('.').sort() // There *must* be a type, no attaching namespace-only handlers if (!type) { continue } // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[type] || {} // If selector defined, determine special event api type, otherwise given type type = (selector ? special.delegateType : special.bindType) || type // Update special based on newly reset type special = jQuery.event.special[type] || {} // handleObj is passed to all event handlers handleObj = jQuery.extend({ type, origType, data, handler, guid: handler.guid, selector, needsContext: selector && jQuery.expr.match.needsContext.test(selector), namespace: namespaces.join('.'), }, handleObjIn) // Init the event handler queue if we're the first if (!(handlers = events[type])) { handlers = events[type] = [] handlers.delegateCount = 0 // Only use addEventListener if the special events handler returns false if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) { if (elem.addEventListener) { elem.addEventListener(type, eventHandle) } } } if (special.add) { special.add.call(elem, handleObj) if (!handleObj.handler.guid) { handleObj.handler.guid = handler.guid } } // Add to the element's handler list, delegates in front if (selector) { handlers.splice(handlers.delegateCount++, 0, handleObj) } else { handlers.push(handleObj) } // Keep track of which events have ever been used, for event optimization jQuery.event.global[type] = true } }, // Detach an event or set of events from an element remove (elem, types, handler, selector, mappedTypes) { let j; let origCount; let tmp let events; let t; let handleObj let special; let handlers; let type; let namespaces; let origType const elemData = dataPriv.hasData(elem) && dataPriv.get(elem) if (!elemData || !(events = elemData.events)) { return } // Once for each type.namespace in types; type may be omitted types = (types || '').match(rnothtmlwhite) || [''] t = types.length while (t--) { tmp = rtypenamespace.exec(types[t]) || [] type = origType = tmp[1] namespaces = (tmp[2] || '').split('.').sort() // Unbind all events (on this namespace, if provided) for the element if (!type) { for (type in events) { jQuery.event.remove(elem, type + types[t], handler, selector, true) } continue } special = jQuery.event.special[type] || {} type = (selector ? special.delegateType : special.bindType) || type handlers = events[type] || [] tmp = tmp[2] && new RegExp(`(^|\\.)${namespaces.join('\\.(?:.*\\.|)')}(\\.|$)`) // Remove matching events origCount = j = handlers.length while (j--) { handleObj = handlers[j] if ((mappedTypes || origType === handleObj.origType) && (!handler || handler.guid === handleObj.guid) && (!tmp || tmp.test(handleObj.namespace)) && (!selector || selector === handleObj.selector || selector === '**' && handleObj.selector)) { handlers.splice(j, 1) if (handleObj.selector) { handlers.delegateCount-- } if (special.remove) { special.remove.call(elem, handleObj) } } } // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if (origCount && !handlers.length) { if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) { jQuery.removeEvent(elem, type, elemData.handle) } delete events[type] } } // Remove data and the expando if it's no longer used if (jQuery.isEmptyObject(events)) { dataPriv.remove(elem, 'handle events') } }, dispatch (nativeEvent) { // Make a writable jQuery.Event from the native event object const event = jQuery.event.fix(nativeEvent) let i; let j; let ret; let matched; let handleObj; let handlerQueue const args = new Array(arguments.length) const handlers = (dataPriv.get(this, 'events') || {})[event.type] || [] const special = jQuery.event.special[event.type] || {} // Use the fix-ed jQuery.Event rather than the (read-only) native event args[0] = event for (i = 1; i < arguments.length; i++) { args[i] = arguments[i] } event.delegateTarget = this // Call the preDispatch hook for the mapped type, and let it bail if desired if (special.preDispatch && special.preDispatch.call(this, event) === false) { return } // Determine handlers handlerQueue = jQuery.event.handlers.call(this, event, handlers) // Run delegates first; they may want to stop propagation beneath us i = 0 while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) { event.currentTarget = matched.elem j = 0 while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) { // If the event is namespaced, then each handler is only invoked if it is // specially universal or its namespaces are a superset of the event's. if (!event.rnamespace || handleObj.namespace === false || event.rnamespace.test(handleObj.namespace)) { event.handleObj = handleObj event.data = handleObj.data ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler).apply(matched.elem, args) if (ret !== undefined) { if ((event.result = ret) === false) { event.preventDefault() event.stopPropagation() } } } } } // Call the postDispatch hook for the mapped type if (special.postDispatch) { special.postDispatch.call(this, event) } return event.result }, handlers (event, handlers) { let i; let handleObj; let sel; let matchedHandlers; let matchedSelectors const handlerQueue = [] const { delegateCount } = handlers let cur = event.target // Find delegate handlers if (delegateCount // Support: IE <=9 // Black-hole SVG instance trees (trac-13180) && cur.nodeType // Support: Firefox <=42 // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click // Support: IE 11 only // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) && !(event.type === 'click' && event.button >= 1)) { for (; cur !== this; cur = cur.parentNode || this) { // Don't check non-elements (#13208) // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) if (cur.nodeType === 1 && !(event.type === 'click' && cur.disabled === true)) { matchedHandlers = [] matchedSelectors = {} for (i = 0; i < delegateCount; i++) { handleObj = handlers[i] // Don't conflict with Object.prototype properties (#13203) sel = `${handleObj.selector} ` if (matchedSelectors[sel] === undefined) { matchedSelectors[sel] = handleObj.needsContext ? jQuery(sel, this).index(cur) > -1 : jQuery.find(sel, this, null, [cur]).length } if (matchedSelectors[sel]) { matchedHandlers.push(handleObj) } } if (matchedHandlers.length) { handlerQueue.push({ elem: cur, handlers: matchedHandlers }) } } } } // Add the remaining (directly-bound) handlers cur = this if (delegateCount < handlers.length) { handlerQueue.push({ elem: cur, handlers: handlers.slice(delegateCount) }) } return handlerQueue }, addProp (name, hook) { Object.defineProperty(jQuery.Event.prototype, name, { enumerable: true, configurable: true, get: isFunction(hook) ? function () { if (this.originalEvent) { return hook(this.originalEvent) } } : function () { if (this.originalEvent) { return this.originalEvent[name] } }, set (value) { Object.defineProperty(this, name, { enumerable: true, configurable: true, writable: true, value, }) }, }) }, fix (originalEvent) { return originalEvent[jQuery.expando] ? originalEvent : new jQuery.Event(originalEvent) }, special: { load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true, }, click: { // Utilize native event to ensure correct state for checkable inputs setup (data) { // For mutual compressibility with _default, replace `this` access with a local var. // `|| data` is dead code meant only to preserve the variable through minification. const el = this || data // Claim the first handler if (rcheckableType.test(el.type) && el.click && nodeName(el, 'input')) { // dataPriv.set( el, "click", ... ) leverageNative(el, 'click', returnTrue) } // Return false to allow normal processing in the caller return false }, trigger (data) { // For mutual compressibility with _default, replace `this` access with a local var. // `|| data` is dead code meant only to preserve the variable through minification. const el = this || data // Force setup before triggering a click if (rcheckableType.test(el.type) && el.click && nodeName(el, 'input')) { leverageNative(el, 'click') } // Return non-false to allow normal event-path propagation return true }, // For cross-browser consistency, suppress native .click() on links // Also prevent it if we're currently inside a leveraged native-event stack _default (event) { const { target } = event return rcheckableType.test(target.type) && target.click && nodeName(target, 'input') && dataPriv.get(target, 'click') || nodeName(target, 'a') }, }, beforeunload: { postDispatch (event) { // Support: Firefox 20+ // Firefox doesn't alert if the returnValue field is not set. if (event.result !== undefined && event.originalEvent) { event.originalEvent.returnValue = event.result } }, }, }, } // Ensure the presence of an event listener that handles manually-triggered // synthetic events by interrupting progress until reinvoked in response to // *native* events that it fires directly, ensuring that state changes have // already occurred before other listeners are invoked. function leverageNative (el, type, expectSync) { // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add if (!expectSync) { if (dataPriv.get(el, type) === undefined) { jQuery.event.add(el, type, returnTrue) } return } // Register the controller as a special universal handler for all event namespaces dataPriv.set(el, type, false) jQuery.event.add(el, type, { namespace: false, handler (event) { let notAsync; let result let saved = dataPriv.get(this, type) if ((event.isTrigger & 1) && this[type]) { // Interrupt processing of the outer synthetic .trigger()ed event // Saved data should be false in such cases, but might be a leftover capture object // from an async native handler (gh-4350) if (!saved.length) { // Store arguments for use when handling the inner native event // There will always be at least one argument (an event object), so this array // will not be confused with a leftover capture object. saved = slice$1.call(arguments) dataPriv.set(this, type, saved) // Trigger the native event and capture its result // Support: IE <=9 - 11+ // focus() and blur() are asynchronous notAsync = expectSync(this, type) this[type]() result = dataPriv.get(this, type) if (saved !== result || notAsync) { dataPriv.set(this, type, false) } else { result = {} } if (saved !== result) { // Cancel the outer synthetic event event.stopImmediatePropagation() event.preventDefault() return result.value } // If this is an inner synthetic event for an event with a bubbling surrogate // (focus or blur), assume that the surrogate already propagated from triggering the // native event and prevent that from happening again here. // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the // bubbling surrogate propagates *after* the non-bubbling base), but that seems // less bad than duplication. } else if ((jQuery.event.special[type] || {}).delegateType) { event.stopPropagation() } // If this is a native event triggered above, everything is now in order // Fire an inner synthetic event with the original arguments } else if (saved.length) { // ...and capture the result dataPriv.set(this, type, { value: jQuery.event.trigger( // Support: IE <=9 - 11+ // Extend with the prototype to reset the above stopImmediatePropagation() jQuery.extend(saved[0], jQuery.Event.prototype), saved.slice(1), this, ), }) // Abort handling of the native event event.stopImmediatePropagation() } }, }) } jQuery.removeEvent = function (elem, type, handle) { // This "if" is needed for plain objects if (elem.removeEventListener) { elem.removeEventListener(type, handle) } } jQuery.Event = function (src, props) { // Allow instantiation without the 'new' keyword if (!(this instanceof jQuery.Event)) { return new jQuery.Event(src, props) } // Event object if (src && src.type) { this.originalEvent = src this.type = src.type // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined // Support: Android <=2.3 only && src.returnValue === false ? returnTrue : returnFalse // Create target properties // Support: Safari <=6 - 7 only // Target should not be a text node (#504, #13143) this.target = (src.target && src.target.nodeType === 3) ? src.target.parentNode : src.target this.currentTarget = src.currentTarget this.relatedTarget = src.relatedTarget // Event type } else { this.type = src } // Put explicitly provided properties onto the event object if (props) { jQuery.extend(this, props) } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || Date.now() // Mark it as fixed this[jQuery.expando] = true } // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { constructor: jQuery.Event, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse, isSimulated: false, preventDefault () { const e = this.originalEvent this.isDefaultPrevented = returnTrue if (e && !this.isSimulated) { e.preventDefault() } }, stopPropagation () { const e = this.originalEvent this.isPropagationStopped = returnTrue if (e && !this.isSimulated) { e.stopPropagation() } }, stopImmediatePropagation () { const e = this.originalEvent this.isImmediatePropagationStopped = returnTrue if (e && !this.isSimulated) { e.stopImmediatePropagation() } this.stopPropagation() }, } // Includes all common event props including KeyEvent and MouseEvent specific props jQuery.each({ altKey: true, bubbles: true, cancelable: true, changedTouches: true, ctrlKey: true, detail: true, eventPhase: true, metaKey: true, pageX: true, pageY: true, shiftKey: true, view: true, char: true, code: true, charCode: true, key: true, keyCode: true, button: true, buttons: true, clientX: true, clientY: true, offsetX: true, offsetY: true, pointerId: true, pointerType: true, screenX: true, screenY: true, targetTouches: true, toElement: true, touches: true, which (event) { const { button } = event // Add which for key events if (event.which == null && rkeyEvent.test(event.type)) { return event.charCode != null ? event.charCode : event.keyCode } // Add which for click: 1 === left; 2 === middle; 3 === right if (!event.which && button !== undefined && rmouseEvent.test(event.type)) { if (button & 1) { return 1 } if (button & 2) { return 3 } if (button & 4) { return 2 } return 0 } return event.which }, }, jQuery.event.addProp) jQuery.each({ focus: 'focusin', blur: 'focusout' }, (type, delegateType) => { jQuery.event.special[type] = { // Utilize native event if possible so blur/focus sequence is correct setup () { // Claim the first handler // dataPriv.set( this, "focus", ... ) // dataPriv.set( this, "blur", ... ) leverageNative(this, type, expectSync) // Return false to allow normal processing in the caller return false }, trigger () { // Force setup before trigger leverageNative(this, type) // Return non-false to allow normal event-path propagation return true }, delegateType, } }) // Create mouseenter/leave events using mouseover/out and event-time checks // so that event delegation works in jQuery. // Do the same for pointerenter/pointerleave and pointerover/pointerout // // Support: Safari 7 only // Safari sends mouseenter too often; see: // https://bugs.chromium.org/p/chromium/issues/detail?id=470258 // for the description of the bug (it existed in older Chrome versions as well). jQuery.each({ mouseenter: 'mouseover', mouseleave: 'mouseout', pointerenter: 'pointerover', pointerleave: 'pointerout', }, (orig, fix) => { jQuery.event.special[orig] = { delegateType: fix, bindType: fix, handle (event) { let ret const target = this const related = event.relatedTarget const { handleObj } = event // For mouseenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window if (!related || (related !== target && !jQuery.contains(target, related))) { event.type = handleObj.origType ret = handleObj.handler.apply(this, arguments) event.type = fix } return ret }, } }) jQuery.fn.extend({ on (types, selector, data, fn) { return on(this, types, selector, data, fn) }, one (types, selector, data, fn) { return on(this, types, selector, data, fn, 1) }, off (types, selector, fn) { let handleObj; let type if (types && types.preventDefault && types.handleObj) { // ( event ) dispatched jQuery.Event handleObj = types.handleObj jQuery(types.delegateTarget).off( handleObj.namespace ? `${handleObj.origType}.${handleObj.namespace}` : handleObj.origType, handleObj.selector, handleObj.handler, ) return this } if (typeof types === 'object') { // ( types-object [, selector] ) for (type in types) { this.off(type, selector, types[type]) } return this } if (selector === false || typeof selector === 'function') { // ( types [, fn] ) fn = selector selector = undefined } if (fn === false) { fn = returnFalse } return this.each(function () { jQuery.event.remove(this, types, fn, selector) }) }, }) const /* eslint-disable max-len */ // See https://github.com/eslint/eslint/issues/3229 rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi /* eslint-enable */ // Support: IE <=10 - 11, Edge 12 - 13 only // In IE/Edge using regex groups here causes severe slowdowns. // See https://connect.microsoft.com/IE/feedback/details/1736512/ const rnoInnerhtml = /\s*$/g // Prefer a tbody over its parent table for containing new rows function manipulationTarget (elem, content) { if (nodeName(elem, 'table') && nodeName(content.nodeType !== 11 ? content : content.firstChild, 'tr')) { return jQuery(elem).children('tbody')[0] || elem } return elem } // Replace/restore the type attribute of script elements for safe DOM manipulation function disableScript (elem) { elem.type = `${elem.getAttribute('type') !== null}/${elem.type}` return elem } function restoreScript (elem) { if ((elem.type || '').slice(0, 5) === 'true/') { elem.type = elem.type.slice(5) } else { elem.removeAttribute('type') } return elem } function cloneCopyEvent (src, dest) { let i; let l; let type; let pdataOld; let pdataCur; let udataOld; let udataCur; let events if (dest.nodeType !== 1) { return } // 1. Copy private data: events, handlers, etc. if (dataPriv.hasData(src)) { pdataOld = dataPriv.access(src) pdataCur = dataPriv.set(dest, pdataOld) events = pdataOld.events if (events) { delete pdataCur.handle pdataCur.events = {} for (type in events) { for (i = 0, l = events[type].length; i < l; i++) { jQuery.event.add(dest, type, events[type][i]) } } } } // 2. Copy user data if (dataUser.hasData(src)) { udataOld = dataUser.access(src) udataCur = jQuery.extend({}, udataOld) dataUser.set(dest, udataCur) } } // Fix IE bugs, see support tests function fixInput (src, dest) { const nodeName = dest.nodeName.toLowerCase() // Fails to persist the checked state of a cloned checkbox or radio button. if (nodeName === 'input' && rcheckableType.test(src.type)) { dest.checked = src.checked // Fails to return the selected option to the default selected state when cloning options } else if (nodeName === 'input' || nodeName === 'textarea') { dest.defaultValue = src.defaultValue } } function domManip (collection, args, callback, ignored) { // Flatten any nested arrays args = concat$2.apply([], args) let fragment; let first; let scripts; let hasScripts; let node; let doc let i = 0 const l = collection.length const iNoClone = l - 1 const value = args[0] const valueIsFunction = isFunction(value) // We can't cloneNode fragments that contain checked, in WebKit if (valueIsFunction || (l > 1 && typeof value === 'string' && !support.checkClone && rchecked.test(value))) { return collection.each(function (index) { const self = collection.eq(index) if (valueIsFunction) { args[0] = value.call(this, index, self.html()) } domManip(self, args, callback, ignored) }) } if (l) { fragment = buildFragment(args, collection[0].ownerDocument, false, collection, ignored) first = fragment.firstChild if (fragment.childNodes.length === 1) { fragment = first } // Require either new content or an interest in ignored elements to invoke the callback if (first || ignored) { scripts = jQuery.map(getAll(fragment, 'script'), disableScript) hasScripts = scripts.length // Use the original fragment for the last item // instead of the first because it can end up // being emptied incorrectly in certain situations (#8070). for (; i < l; i++) { node = fragment if (i !== iNoClone) { node = jQuery.clone(node, true, true) // Keep references to cloned scripts for later restoration if (hasScripts) { // Support: Android <=4.0 only, PhantomJS 1 only // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge(scripts, getAll(node, 'script')) } } callback.call(collection[i], node, i) } if (hasScripts) { doc = scripts[scripts.length - 1].ownerDocument // Reenable scripts jQuery.map(scripts, restoreScript) // Evaluate executable scripts on first document insertion for (i = 0; i < hasScripts; i++) { node = scripts[i] if (rscriptType.test(node.type || '') && !dataPriv.access(node, 'globalEval') && jQuery.contains(doc, node)) { if (node.src && (node.type || '').toLowerCase() !== 'module') { // Optional AJAX dependency, but won't run scripts if not present if (jQuery._evalUrl && !node.noModule) { jQuery._evalUrl(node.src, { nonce: node.nonce || node.getAttribute('nonce'), }) } } else { DOMEval(node.textContent.replace(rcleanScript, ''), node, doc) } } } } } } return collection } function remove (elem, selector, keepData) { let node const nodes = selector ? jQuery.filter(selector, elem) : elem let i = 0 for (; (node = nodes[i]) != null; i++) { if (!keepData && node.nodeType === 1) { jQuery.cleanData(getAll(node)) } if (node.parentNode) { if (keepData && isAttached(node)) { setGlobalEval(getAll(node, 'script')) } node.parentNode.removeChild(node) } } return elem } jQuery.extend({ htmlPrefilter (html) { return html.replace(rxhtmlTag, '<$1>') }, clone (elem, dataAndEvents, deepDataAndEvents) { let i; let l; let srcElements; let destElements const clone = elem.cloneNode(true) const inPage = isAttached(elem) // Fix IE cloning issues if (!support.noCloneChecked && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem)) { // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 destElements = getAll(clone) srcElements = getAll(elem) for (i = 0, l = srcElements.length; i < l; i++) { fixInput(srcElements[i], destElements[i]) } } // Copy the events from the original to the clone if (dataAndEvents) { if (deepDataAndEvents) { srcElements = srcElements || getAll(elem) destElements = destElements || getAll(clone) for (i = 0, l = srcElements.length; i < l; i++) { cloneCopyEvent(srcElements[i], destElements[i]) } } else { cloneCopyEvent(elem, clone) } } // Preserve script evaluation history destElements = getAll(clone, 'script') if (destElements.length > 0) { setGlobalEval(destElements, !inPage && getAll(elem, 'script')) } // Return the cloned set return clone }, cleanData (elems) { let data; let elem; let type const { special } = jQuery.event let i = 0 for (; (elem = elems[i]) !== undefined; i++) { if (acceptData(elem)) { if ((data = elem[dataPriv.expando])) { if (data.events) { for (type in data.events) { if (special[type]) { jQuery.event.remove(elem, type) // This is a shortcut to avoid jQuery.event.remove's overhead } else { jQuery.removeEvent(elem, type, data.handle) } } } // Support: Chrome <=35 - 45+ // Assign undefined instead of using delete, see Data#remove elem[dataPriv.expando] = undefined } if (elem[dataUser.expando]) { // Support: Chrome <=35 - 45+ // Assign undefined instead of using delete, see Data#remove elem[dataUser.expando] = undefined } } } }, }) jQuery.fn.extend({ detach (selector) { return remove(this, selector, true) }, remove (selector) { return remove(this, selector) }, text (value) { return access(this, function (value) { return value === undefined ? jQuery.text(this) : this.empty().each(function () { if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { this.textContent = value } }) }, null, value, arguments.length) }, append () { return domManip(this, arguments, function (elem) { if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { const target = manipulationTarget(this, elem) target.appendChild(elem) } }) }, prepend () { return domManip(this, arguments, function (elem) { if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) { const target = manipulationTarget(this, elem) target.insertBefore(elem, target.firstChild) } }) }, before () { return domManip(this, arguments, function (elem) { if (this.parentNode) { this.parentNode.insertBefore(elem, this) } }) }, after () { return domManip(this, arguments, function (elem) { if (this.parentNode) { this.parentNode.insertBefore(elem, this.nextSibling) } }) }, empty () { let elem let i = 0 for (; (elem = this[i]) != null; i++) { if (elem.nodeType === 1) { // Prevent memory leaks jQuery.cleanData(getAll(elem, false)) // Remove any remaining nodes elem.textContent = '' } } return this }, clone (dataAndEvents, deepDataAndEvents) { dataAndEvents = dataAndEvents == null ? false : dataAndEvents deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents return this.map(function () { return jQuery.clone(this, dataAndEvents, deepDataAndEvents) }) }, html (value) { return access(this, function (value) { let elem = this[0] || {} let i = 0 const l = this.length if (value === undefined && elem.nodeType === 1) { return elem.innerHTML } // See if we can take a shortcut and just use innerHTML if (typeof value === 'string' && !rnoInnerhtml.test(value) && !wrapMap[(rtagName.exec(value) || ['', ''])[1].toLowerCase()]) { value = jQuery.htmlPrefilter(value) try { for (; i < l; i++) { elem = this[i] || {} // Remove element nodes and prevent memory leaks if (elem.nodeType === 1) { jQuery.cleanData(getAll(elem, false)) elem.innerHTML = value } } elem = 0 // If using innerHTML throws an exception, use the fallback method } catch (e) { } } if (elem) { this.empty().append(value) } }, null, value, arguments.length) }, replaceWith () { const ignored = [] // Make the changes, replacing each non-ignored context element with the new content return domManip(this, arguments, function (elem) { const parent = this.parentNode if (jQuery.inArray(this, ignored) < 0) { jQuery.cleanData(getAll(this)) if (parent) { parent.replaceChild(elem, this) } } // Force callback invocation }, ignored) }, }) jQuery.each({ appendTo: 'append', prependTo: 'prepend', insertBefore: 'before', insertAfter: 'after', replaceAll: 'replaceWith', }, (name, original) => { jQuery.fn[name] = function (selector) { let elems const ret = [] const insert = jQuery(selector) const last = insert.length - 1 let i = 0 for (; i <= last; i++) { elems = i === last ? this : this.clone(true) jQuery(insert[i])[original](elems) // Support: Android <=4.0 only, PhantomJS 1 only // .get() because push.apply(_, arraylike) throws on ancient WebKit push.apply(ret, elems.get()) } return this.pushStack(ret) } }) const rnumnonpx = new RegExp(`^(${pnum})(?!px)[a-z%]+$`, 'i') const getStyles = function (elem) { // Support: IE <=11 only, Firefox <=30 (#15098, #14150) // IE throws on elements created in popups // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" let view = elem.ownerDocument.defaultView if (!view || !view.opener) { view = window } return view.getComputedStyle(elem) } const rboxStyle = new RegExp(cssExpand.join('|'), 'i'); (function () { // Executing both pixelPosition & boxSizingReliable tests require only one layout // so they're executed at the same time to save the second computation. function computeStyleTests () { // This is a singleton, we need to execute it only once if (!div) { return } container.style.cssText = 'position:absolute;left:-11111px;width:60px;' + 'margin-top:1px;padding:0;border:0' div.style.cssText = 'position:relative;display:block;box-sizing:border-box;overflow:scroll;' + 'margin:auto;border:1px;padding:1px;' + 'width:60%;top:1%' documentElement.appendChild(container).appendChild(div) const divStyle = window.getComputedStyle(div) pixelPositionVal = divStyle.top !== '1%' // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 reliableMarginLeftVal = roundPixelMeasures(divStyle.marginLeft) === 12 // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 // Some styles come back with percentage values, even though they shouldn't div.style.right = '60%' pixelBoxStylesVal = roundPixelMeasures(divStyle.right) === 36 // Support: IE 9 - 11 only // Detect misreporting of content dimensions for box-sizing:border-box elements boxSizingReliableVal = roundPixelMeasures(divStyle.width) === 36 // Support: IE 9 only // Detect overflow:scroll screwiness (gh-3699) // Support: Chrome <=64 // Don't get tricked when zoom affects offsetWidth (gh-4029) div.style.position = 'absolute' scrollboxSizeVal = roundPixelMeasures(div.offsetWidth / 3) === 12 documentElement.removeChild(container) // Nullify the div so it wouldn't be stored in the memory and // it will also be a sign that checks already performed div = null } function roundPixelMeasures (measure) { return Math.round(parseFloat(measure)) } let pixelPositionVal; let boxSizingReliableVal; let scrollboxSizeVal; let pixelBoxStylesVal let reliableMarginLeftVal var container = document$1.createElement('div') var div = document$1.createElement('div') // Finish early in limited (non-browser) environments if (!div.style) { return } // Support: IE <=9 - 11 only // Style of cloned element affects source element cloned (#8908) div.style.backgroundClip = 'content-box' div.cloneNode(true).style.backgroundClip = '' support.clearCloneStyle = div.style.backgroundClip === 'content-box' jQuery.extend(support, { boxSizingReliable () { computeStyleTests() return boxSizingReliableVal }, pixelBoxStyles () { computeStyleTests() return pixelBoxStylesVal }, pixelPosition () { computeStyleTests() return pixelPositionVal }, reliableMarginLeft () { computeStyleTests() return reliableMarginLeftVal }, scrollboxSize () { computeStyleTests() return scrollboxSizeVal }, }) }()) function curCSS (elem, name, computed) { let width; let minWidth; let maxWidth; let ret // Support: Firefox 51+ // Retrieving style before computed somehow // fixes an issue with getting wrong values // on detached elements const { style } = elem computed = computed || getStyles(elem) // getPropertyValue is needed for: // .css('filter') (IE 9 only, #12537) // .css('--customProperty) (#3144) if (computed) { ret = computed.getPropertyValue(name) || computed[name] if (ret === '' && !isAttached(elem)) { ret = jQuery.style(elem, name) } // A tribute to the "awesome hack by Dean Edwards" // Android Browser returns percentage for some values, // but width seems to be reliably pixels. // This is against the CSSOM draft spec: // https://drafts.csswg.org/cssom/#resolved-values if (!support.pixelBoxStyles() && rnumnonpx.test(ret) && rboxStyle.test(name)) { // Remember the original values width = style.width minWidth = style.minWidth maxWidth = style.maxWidth // Put in the new values to get a computed value out style.minWidth = style.maxWidth = style.width = ret ret = computed.width // Revert the changed values style.width = width style.minWidth = minWidth style.maxWidth = maxWidth } } return ret !== undefined // Support: IE <=9 - 11 only // IE returns zIndex value as an integer. ? `${ret}` : ret } function addGetHookIf (conditionFn, hookFn) { // Define the hook, we'll check on the first run if it's really needed. return { get () { if (conditionFn()) { // Hook not needed (or it's not possible to use it due // to missing dependency), remove it. delete this.get return } // Hook needed; redefine it so that the support test is not executed again. return (this.get = hookFn).apply(this, arguments) }, } } const cssPrefixes = ['Webkit', 'Moz', 'ms'] const emptyStyle = document$1.createElement('div').style const vendorProps = {} // Return a vendor-prefixed property or undefined function vendorPropName (name) { // Check for vendor prefixed names const capName = name[0].toUpperCase() + name.slice(1) let i = cssPrefixes.length while (i--) { name = cssPrefixes[i] + capName if (name in emptyStyle) { return name } } } // Return a potentially-mapped jQuery.cssProps or vendor prefixed property function finalPropName (name) { const final = jQuery.cssProps[name] || vendorProps[name] if (final) { return final } if (name in emptyStyle) { return name } return vendorProps[name] = vendorPropName(name) || name } const // Swappable if display is none or starts with table // except "table", "table-cell", or "table-caption" // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display rdisplayswap = /^(none|table(?!-c[ea]).+)/ const rcustomProp = /^--/ const cssShow = { position: 'absolute', visibility: 'hidden', display: 'block' } const cssNormalTransform = { letterSpacing: '0', fontWeight: '400', } function setPositiveNumber (elem, value, subtract) { // Any relative (+/-) values have already been // normalized at this point const matches = rcssNum.exec(value) return matches // Guard against undefined "subtract", e.g., when used as in cssHooks ? Math.max(0, matches[2] - (subtract || 0)) + (matches[3] || 'px') : value } function boxModelAdjustment (elem, dimension, box, isBorderBox, styles, computedVal) { let i = dimension === 'width' ? 1 : 0 let extra = 0 let delta = 0 // Adjustment may not be necessary if (box === (isBorderBox ? 'border' : 'content')) { return 0 } for (; i < 4; i += 2) { // Both box models exclude margin if (box === 'margin') { delta += jQuery.css(elem, box + cssExpand[i], true, styles) } // If we get here with a content-box, we're seeking "padding" or "border" or "margin" if (!isBorderBox) { // Add padding delta += jQuery.css(elem, `padding${cssExpand[i]}`, true, styles) // For "border" or "margin", add border if (box !== 'padding') { delta += jQuery.css(elem, `border${cssExpand[i]}Width`, true, styles) // But still keep track of it otherwise } else { extra += jQuery.css(elem, `border${cssExpand[i]}Width`, true, styles) } // If we get here with a border-box (content + padding + border), we're seeking "content" or // "padding" or "margin" } else { // For "content", subtract padding if (box === 'content') { delta -= jQuery.css(elem, `padding${cssExpand[i]}`, true, styles) } // For "content" or "padding", subtract border if (box !== 'margin') { delta -= jQuery.css(elem, `border${cssExpand[i]}Width`, true, styles) } } } // Account for positive content-box scroll gutter when requested by providing computedVal if (!isBorderBox && computedVal >= 0) { // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border // Assuming integer scroll gutter, subtract the rest and round down delta += Math.max(0, Math.ceil( elem[`offset${dimension[0].toUpperCase()}${dimension.slice(1)}`] - computedVal - delta - extra - 0.5, // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter // Use an explicit zero to avoid NaN (gh-3964) )) || 0 } return delta } function getWidthOrHeight (elem, dimension, extra) { // Start with computed style const styles = getStyles(elem) // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). // Fake content-box until we know it's needed to know the true value. const boxSizingNeeded = !support.boxSizingReliable() || extra let isBorderBox = boxSizingNeeded && jQuery.css(elem, 'boxSizing', false, styles) === 'border-box' let valueIsBorderBox = isBorderBox let val = curCSS(elem, dimension, styles) const offsetProp = `offset${dimension[0].toUpperCase()}${dimension.slice(1)}` // Support: Firefox <=54 // Return a confounding non-pixel value or feign ignorance, as appropriate. if (rnumnonpx.test(val)) { if (!extra) { return val } val = 'auto' } // Fall back to offsetWidth/offsetHeight when value is "auto" // This happens for inline elements with no explicit setting (gh-3571) // Support: Android <=4.1 - 4.3 only // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) // Support: IE 9-11 only // Also use offsetWidth/offsetHeight for when box sizing is unreliable // We use getClientRects() to check for hidden/disconnected. // In those cases, the computed value can be trusted to be border-box if ((!support.boxSizingReliable() && isBorderBox || val === 'auto' || !parseFloat(val) && jQuery.css(elem, 'display', false, styles) === 'inline') && elem.getClientRects().length) { isBorderBox = jQuery.css(elem, 'boxSizing', false, styles) === 'border-box' // Where available, offsetWidth/offsetHeight approximate border box dimensions. // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the // retrieved value as a content box dimension. valueIsBorderBox = offsetProp in elem if (valueIsBorderBox) { val = elem[offsetProp] } } // Normalize "" and auto val = parseFloat(val) || 0 // Adjust for the element's box model return `${val + boxModelAdjustment( elem, dimension, extra || (isBorderBox ? 'border' : 'content'), valueIsBorderBox, styles, // Provide the current computed size to request scroll gutter calculation (gh-3589) val, ) }px` } jQuery.extend({ // Add in style property hooks for overriding the default // behavior of getting and setting a style property cssHooks: { opacity: { get (elem, computed) { if (computed) { // We should always get a number back from opacity const ret = curCSS(elem, 'opacity') return ret === '' ? '1' : ret } }, }, }, // Don't automatically add "px" to these possibly-unitless properties cssNumber: { animationIterationCount: true, columnCount: true, fillOpacity: true, flexGrow: true, flexShrink: true, fontWeight: true, gridArea: true, gridColumn: true, gridColumnEnd: true, gridColumnStart: true, gridRow: true, gridRowEnd: true, gridRowStart: true, lineHeight: true, opacity: true, order: true, orphans: true, widows: true, zIndex: true, zoom: true, }, // Add in properties whose names you wish to fix before // setting or getting the value cssProps: {}, // Get and set the style property on a DOM Node style (elem, name, value, extra) { // Don't set styles on text and comment nodes if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style) { return } // Make sure that we're working with the right name let ret; let type; let hooks const origName = camelCase(name) const isCustomProp = rcustomProp.test(name) const { style } = elem // Make sure that we're working with the right name. We don't // want to query the value if it is a CSS custom property // since they are user-defined. if (!isCustomProp) { name = finalPropName(origName) } // Gets hook for the prefixed version, then unprefixed version hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName] // Check if we're setting a value if (value !== undefined) { type = typeof value // Convert "+=" or "-=" to relative numbers (#7345) if (type === 'string' && (ret = rcssNum.exec(value)) && ret[1]) { value = adjustCSS(elem, name, ret) // Fixes bug #9237 type = 'number' } // Make sure that null and NaN values aren't set (#7116) if (value == null || value !== value) { return } // If a number was passed in, add the unit (except for certain CSS properties) // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append // "px" to a few hardcoded values. if (type === 'number' && !isCustomProp) { value += ret && ret[3] || (jQuery.cssNumber[origName] ? '' : 'px') } // background-* props affect original clone's values if (!support.clearCloneStyle && value === '' && name.indexOf('background') === 0) { style[name] = 'inherit' } // If a hook was provided, use that value, otherwise just set the specified value if (!hooks || !('set' in hooks) || (value = hooks.set(elem, value, extra)) !== undefined) { if (isCustomProp) { style.setProperty(name, value) } else { style[name] = value } } } else { // If a hook was provided get the non-computed value from there if (hooks && 'get' in hooks && (ret = hooks.get(elem, false, extra)) !== undefined) { return ret } // Otherwise just get the value from the style object return style[name] } }, css (elem, name, extra, styles) { let val; let num; let hooks const origName = camelCase(name) const isCustomProp = rcustomProp.test(name) // Make sure that we're working with the right name. We don't // want to modify the value if it is a CSS custom property // since they are user-defined. if (!isCustomProp) { name = finalPropName(origName) } // Try prefixed name followed by the unprefixed name hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName] // If a hook was provided get the computed value from there if (hooks && 'get' in hooks) { val = hooks.get(elem, true, extra) } // Otherwise, if a way to get the computed value exists, use that if (val === undefined) { val = curCSS(elem, name, styles) } // Convert "normal" to computed value if (val === 'normal' && name in cssNormalTransform) { val = cssNormalTransform[name] } // Make numeric if forced or a qualifier was provided and val looks numeric if (extra === '' || extra) { num = parseFloat(val) return extra === true || isFinite(num) ? num || 0 : val } return val }, }) jQuery.each(['height', 'width'], (i, dimension) => { jQuery.cssHooks[dimension] = { get (elem, computed, extra) { if (computed) { // Certain elements can have dimension info if we invisibly show them // but it must have a current display style that would benefit return rdisplayswap.test(jQuery.css(elem, 'display')) // Support: Safari 8+ // Table columns in Safari have non-zero offsetWidth & zero // getBoundingClientRect().width unless display is changed. // Support: IE <=11 only // Running getBoundingClientRect on a disconnected node // in IE throws an error. && (!elem.getClientRects().length || !elem.getBoundingClientRect().width) ? swap(elem, cssShow, () => getWidthOrHeight(elem, dimension, extra)) : getWidthOrHeight(elem, dimension, extra) } }, set (elem, value, extra) { let matches const styles = getStyles(elem) // Only read styles.position if the test has a chance to fail // to avoid forcing a reflow. const scrollboxSizeBuggy = !support.scrollboxSize() && styles.position === 'absolute' // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) const boxSizingNeeded = scrollboxSizeBuggy || extra const isBorderBox = boxSizingNeeded && jQuery.css(elem, 'boxSizing', false, styles) === 'border-box' let subtract = extra ? boxModelAdjustment( elem, dimension, extra, isBorderBox, styles, ) : 0 // Account for unreliable border-box dimensions by comparing offset* to computed and // faking a content-box to get border and padding (gh-3699) if (isBorderBox && scrollboxSizeBuggy) { subtract -= Math.ceil( elem[`offset${dimension[0].toUpperCase()}${dimension.slice(1)}`] - parseFloat(styles[dimension]) - boxModelAdjustment(elem, dimension, 'border', false, styles) - 0.5, ) } // Convert to pixels if value adjustment is needed if (subtract && (matches = rcssNum.exec(value)) && (matches[3] || 'px') !== 'px') { elem.style[dimension] = value value = jQuery.css(elem, dimension) } return setPositiveNumber(elem, value, subtract) }, } }) jQuery.cssHooks.marginLeft = addGetHookIf(support.reliableMarginLeft, (elem, computed) => { if (computed) { return `${parseFloat(curCSS(elem, 'marginLeft')) || elem.getBoundingClientRect().left - swap(elem, { marginLeft: 0 }, () => elem.getBoundingClientRect().left) }px` } }) // These hooks are used by animate to expand properties jQuery.each({ margin: '', padding: '', border: 'Width', }, (prefix, suffix) => { jQuery.cssHooks[prefix + suffix] = { expand (value) { let i = 0 const expanded = {} // Assumes a single number if not a string const parts = typeof value === 'string' ? value.split(' ') : [value] for (; i < 4; i++) { expanded[prefix + cssExpand[i] + suffix] = parts[i] || parts[i - 2] || parts[0] } return expanded }, } if (prefix !== 'margin') { jQuery.cssHooks[prefix + suffix].set = setPositiveNumber } }) jQuery.fn.extend({ css (name, value) { return access(this, (elem, name, value) => { let styles; let len const map = {} let i = 0 if (Array.isArray(name)) { styles = getStyles(elem) len = name.length for (; i < len; i++) { map[name[i]] = jQuery.css(elem, name[i], false, styles) } return map } return value !== undefined ? jQuery.style(elem, name, value) : jQuery.css(elem, name) }, name, value, arguments.length > 1) }, }) function Tween (elem, options, prop, end, easing) { return new Tween.prototype.init(elem, options, prop, end, easing) } jQuery.Tween = Tween Tween.prototype = { constructor: Tween, init (elem, options, prop, end, easing, unit) { this.elem = elem this.prop = prop this.easing = easing || jQuery.easing._default this.options = options this.start = this.now = this.cur() this.end = end this.unit = unit || (jQuery.cssNumber[prop] ? '' : 'px') }, cur () { const hooks = Tween.propHooks[this.prop] return hooks && hooks.get ? hooks.get(this) : Tween.propHooks._default.get(this) }, run (percent) { let eased const hooks = Tween.propHooks[this.prop] if (this.options.duration) { this.pos = eased = jQuery.easing[this.easing]( percent, this.options.duration * percent, 0, 1, this.options.duration, ) } else { this.pos = eased = percent } this.now = (this.end - this.start) * eased + this.start if (this.options.step) { this.options.step.call(this.elem, this.now, this) } if (hooks && hooks.set) { hooks.set(this) } else { Tween.propHooks._default.set(this) } return this }, } Tween.prototype.init.prototype = Tween.prototype Tween.propHooks = { _default: { get (tween) { let result // Use a property on the element directly when it is not a DOM element, // or when there is no matching style property that exists. if (tween.elem.nodeType !== 1 || tween.elem[tween.prop] != null && tween.elem.style[tween.prop] == null) { return tween.elem[tween.prop] } // Passing an empty string as a 3rd parameter to .css will automatically // attempt a parseFloat and fallback to a string if the parse fails. // Simple values such as "10px" are parsed to Float; // complex values such as "rotate(1rad)" are returned as-is. result = jQuery.css(tween.elem, tween.prop, '') // Empty strings, null, undefined and "auto" are converted to 0. return !result || result === 'auto' ? 0 : result }, set (tween) { // Use step hook for back compat. // Use cssHook if its there. // Use .style if available and use plain properties where available. if (jQuery.fx.step[tween.prop]) { jQuery.fx.step[tween.prop](tween) } else if (tween.elem.nodeType === 1 && ( jQuery.cssHooks[tween.prop] || tween.elem.style[finalPropName(tween.prop)] != null)) { jQuery.style(tween.elem, tween.prop, tween.now + tween.unit) } else { tween.elem[tween.prop] = tween.now } }, }, } // Support: IE <=9 only // Panic based approach to setting things on disconnected nodes Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { set (tween) { if (tween.elem.nodeType && tween.elem.parentNode) { tween.elem[tween.prop] = tween.now } }, } jQuery.easing = { linear (p) { return p }, swing (p) { return 0.5 - Math.cos(p * Math.PI) / 2 }, _default: 'swing', } jQuery.fx = Tween.prototype.init // Back compat <1.8 extension point jQuery.fx.step = {} let fxNow; let inProgress const rfxtypes = /^(?:toggle|show|hide)$/ const rrun = /queueHooks$/ function schedule () { if (inProgress) { if (document$1.hidden === false && window.requestAnimationFrame) { window.requestAnimationFrame(schedule) } else { window.setTimeout(schedule, jQuery.fx.interval) } jQuery.fx.tick() } } // Animations created synchronously will run synchronously function createFxNow () { window.setTimeout(() => { fxNow = undefined }) return (fxNow = Date.now()) } // Generate parameters to create a standard animation function genFx (type, includeWidth) { let which let i = 0 const attrs = { height: type } // If we include width, step value is 1 to do all cssExpand values, // otherwise step value is 2 to skip over Left and Right includeWidth = includeWidth ? 1 : 0 for (; i < 4; i += 2 - includeWidth) { which = cssExpand[i] attrs[`margin${which}`] = attrs[`padding${which}`] = type } if (includeWidth) { attrs.opacity = attrs.width = type } return attrs } function createTween (value, prop, animation) { let tween const collection = (Animation.tweeners[prop] || []).concat(Animation.tweeners['*']) let index = 0 const { length } = collection for (; index < length; index++) { if ((tween = collection[index].call(animation, prop, value))) { // We're done with this property return tween } } } function defaultPrefilter (elem, props, opts) { let prop; let value; let toggle; let hooks; let oldfire; let propTween; let restoreDisplay; let display const isBox = 'width' in props || 'height' in props const anim = this const orig = {} const { style } = elem let hidden = elem.nodeType && isHiddenWithinTree(elem) let dataShow = dataPriv.get(elem, 'fxshow') // Queue-skipping animations hijack the fx hooks if (!opts.queue) { hooks = jQuery._queueHooks(elem, 'fx') if (hooks.unqueued == null) { hooks.unqueued = 0 oldfire = hooks.empty.fire hooks.empty.fire = function () { if (!hooks.unqueued) { oldfire() } } } hooks.unqueued++ anim.always(() => { // Ensure the complete handler is called before this completes anim.always(() => { hooks.unqueued-- if (!jQuery.queue(elem, 'fx').length) { hooks.empty.fire() } }) }) } // Detect show/hide animations for (prop in props) { value = props[prop] if (rfxtypes.test(value)) { delete props[prop] toggle = toggle || value === 'toggle' if (value === (hidden ? 'hide' : 'show')) { // Pretend to be hidden if this is a "show" and // there is still data from a stopped show/hide if (value === 'show' && dataShow && dataShow[prop] !== undefined) { hidden = true // Ignore all other no-op show/hide data } else { continue } } orig[prop] = dataShow && dataShow[prop] || jQuery.style(elem, prop) } } // Bail out if this is a no-op like .hide().hide() propTween = !jQuery.isEmptyObject(props) if (!propTween && jQuery.isEmptyObject(orig)) { return } // Restrict "overflow" and "display" styles during box animations if (isBox && elem.nodeType === 1) { // Support: IE <=9 - 11, Edge 12 - 15 // Record all 3 overflow attributes because IE does not infer the shorthand // from identically-valued overflowX and overflowY and Edge just mirrors // the overflowX value there. opts.overflow = [style.overflow, style.overflowX, style.overflowY] // Identify a display type, preferring old show/hide data over the CSS cascade restoreDisplay = dataShow && dataShow.display if (restoreDisplay == null) { restoreDisplay = dataPriv.get(elem, 'display') } display = jQuery.css(elem, 'display') if (display === 'none') { if (restoreDisplay) { display = restoreDisplay } else { // Get nonempty value(s) by temporarily forcing visibility showHide([elem], true) restoreDisplay = elem.style.display || restoreDisplay display = jQuery.css(elem, 'display') showHide([elem]) } } // Animate inline elements as inline-block if (display === 'inline' || display === 'inline-block' && restoreDisplay != null) { if (jQuery.css(elem, 'float') === 'none') { // Restore the original display value at the end of pure show/hide animations if (!propTween) { anim.done(() => { style.display = restoreDisplay }) if (restoreDisplay == null) { display = style.display restoreDisplay = display === 'none' ? '' : display } } style.display = 'inline-block' } } } if (opts.overflow) { style.overflow = 'hidden' anim.always(() => { style.overflow = opts.overflow[0] style.overflowX = opts.overflow[1] style.overflowY = opts.overflow[2] }) } // Implement show/hide animations propTween = false for (prop in orig) { // General show/hide setup for this element animation if (!propTween) { if (dataShow) { if ('hidden' in dataShow) { hidden = dataShow.hidden } } else { dataShow = dataPriv.access(elem, 'fxshow', { display: restoreDisplay }) } // Store hidden/visible for toggle so `.stop().toggle()` "reverses" if (toggle) { dataShow.hidden = !hidden } // Show elements before animating them if (hidden) { showHide([elem], true) } /* eslint-disable no-loop-func */ anim.done(() => { /* eslint-enable no-loop-func */ // The final step of a "hide" animation is actually hiding the element if (!hidden) { showHide([elem]) } dataPriv.remove(elem, 'fxshow') for (prop in orig) { jQuery.style(elem, prop, orig[prop]) } }) } // Per-property setup propTween = createTween(hidden ? dataShow[prop] : 0, prop, anim) if (!(prop in dataShow)) { dataShow[prop] = propTween.start if (hidden) { propTween.end = propTween.start propTween.start = 0 } } } } function propFilter (props, specialEasing) { let index; let name; let easing; let value; let hooks // camelCase, specialEasing and expand cssHook pass for (index in props) { name = camelCase(index) easing = specialEasing[name] value = props[index] if (Array.isArray(value)) { easing = value[1] value = props[index] = value[0] } if (index !== name) { props[name] = value delete props[index] } hooks = jQuery.cssHooks[name] if (hooks && 'expand' in hooks) { value = hooks.expand(value) delete props[name] // Not quite $.extend, this won't overwrite existing keys. // Reusing 'index' because we have the correct "name" for (index in value) { if (!(index in props)) { props[index] = value[index] specialEasing[index] = easing } } } else { specialEasing[name] = easing } } } function Animation (elem, properties, options) { let result let stopped let index = 0 const { length } = Animation.prefilters const deferred = jQuery.Deferred().always(() => { // Don't match elem in the :animated selector delete tick.elem }) var tick = function () { if (stopped) { return false } const currentTime = fxNow || createFxNow() const remaining = Math.max(0, animation.startTime + animation.duration - currentTime) // Support: Android 2.3 only // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) const temp = remaining / animation.duration || 0 const percent = 1 - temp let index = 0 const { length } = animation.tweens for (; index < length; index++) { animation.tweens[index].run(percent) } deferred.notifyWith(elem, [animation, percent, remaining]) // If there's more to do, yield if (percent < 1 && length) { return remaining } // If this was an empty animation, synthesize a final progress notification if (!length) { deferred.notifyWith(elem, [animation, 1, 0]) } // Resolve the animation and report its conclusion deferred.resolveWith(elem, [animation]) return false } var animation = deferred.promise({ elem, props: jQuery.extend({}, properties), opts: jQuery.extend(true, { specialEasing: {}, easing: jQuery.easing._default, }, options), originalProperties: properties, originalOptions: options, startTime: fxNow || createFxNow(), duration: options.duration, tweens: [], createTween (prop, end) { const tween = jQuery.Tween(elem, animation.opts, prop, end, animation.opts.specialEasing[prop] || animation.opts.easing) animation.tweens.push(tween) return tween }, stop (gotoEnd) { let index = 0 // If we are going to the end, we want to run all the tweens // otherwise we skip this part const length = gotoEnd ? animation.tweens.length : 0 if (stopped) { return this } stopped = true for (; index < length; index++) { animation.tweens[index].run(1) } // Resolve when we played the last frame; otherwise, reject if (gotoEnd) { deferred.notifyWith(elem, [animation, 1, 0]) deferred.resolveWith(elem, [animation, gotoEnd]) } else { deferred.rejectWith(elem, [animation, gotoEnd]) } return this }, }) const { props } = animation propFilter(props, animation.opts.specialEasing) for (; index < length; index++) { result = Animation.prefilters[index].call(animation, elem, props, animation.opts) if (result) { if (isFunction(result.stop)) { jQuery._queueHooks(animation.elem, animation.opts.queue).stop = result.stop.bind(result) } return result } } jQuery.map(props, createTween, animation) if (isFunction(animation.opts.start)) { animation.opts.start.call(elem, animation) } // Attach callbacks from options animation .progress(animation.opts.progress) .done(animation.opts.done, animation.opts.complete) .fail(animation.opts.fail) .always(animation.opts.always) jQuery.fx.timer( jQuery.extend(tick, { elem, anim: animation, queue: animation.opts.queue, }), ) return animation } jQuery.Animation = jQuery.extend(Animation, { tweeners: { '*': [function (prop, value) { const tween = this.createTween(prop, value) adjustCSS(tween.elem, prop, rcssNum.exec(value), tween) return tween }], }, tweener (props, callback) { if (isFunction(props)) { callback = props props = ['*'] } else { props = props.match(rnothtmlwhite) } let prop let index = 0 const { length } = props for (; index < length; index++) { prop = props[index] Animation.tweeners[prop] = Animation.tweeners[prop] || [] Animation.tweeners[prop].unshift(callback) } }, prefilters: [defaultPrefilter], prefilter (callback, prepend) { if (prepend) { Animation.prefilters.unshift(callback) } else { Animation.prefilters.push(callback) } }, }) jQuery.speed = function (speed, easing, fn) { const opt = speed && typeof speed === 'object' ? jQuery.extend({}, speed) : { complete: fn || !fn && easing || isFunction(speed) && speed, duration: speed, easing: fn && easing || easing && !isFunction(easing) && easing, } // Go to the end state if fx are off if (jQuery.fx.off) { opt.duration = 0 } else if (typeof opt.duration !== 'number') { if (opt.duration in jQuery.fx.speeds) { opt.duration = jQuery.fx.speeds[opt.duration] } else { opt.duration = jQuery.fx.speeds._default } } // Normalize opt.queue - true/undefined/null -> "fx" if (opt.queue == null || opt.queue === true) { opt.queue = 'fx' } // Queueing opt.old = opt.complete opt.complete = function () { if (isFunction(opt.old)) { opt.old.call(this) } if (opt.queue) { jQuery.dequeue(this, opt.queue) } } return opt } jQuery.fn.extend({ fadeTo (speed, to, easing, callback) { // Show any hidden elements after setting opacity to 0 return this.filter(isHiddenWithinTree).css('opacity', 0).show() // Animate to the value specified .end() .animate({ opacity: to }, speed, easing, callback) }, animate (prop, speed, easing, callback) { const empty = jQuery.isEmptyObject(prop) const optall = jQuery.speed(speed, easing, callback) const doAnimation = function () { // Operate on a copy of prop so per-property easing won't be lost const anim = Animation(this, jQuery.extend({}, prop), optall) // Empty animations, or finishing resolves immediately if (empty || dataPriv.get(this, 'finish')) { anim.stop(true) } } doAnimation.finish = doAnimation return empty || optall.queue === false ? this.each(doAnimation) : this.queue(optall.queue, doAnimation) }, stop (type, clearQueue, gotoEnd) { const stopQueue = function (hooks) { const { stop } = hooks delete hooks.stop stop(gotoEnd) } if (typeof type !== 'string') { gotoEnd = clearQueue clearQueue = type type = undefined } if (clearQueue && type !== false) { this.queue(type || 'fx', []) } return this.each(function () { let dequeue = true let index = type != null && `${type}queueHooks` const { timers } = jQuery const data = dataPriv.get(this) if (index) { if (data[index] && data[index].stop) { stopQueue(data[index]) } } else { for (index in data) { if (data[index] && data[index].stop && rrun.test(index)) { stopQueue(data[index]) } } } for (index = timers.length; index--;) { if (timers[index].elem === this && (type == null || timers[index].queue === type)) { timers[index].anim.stop(gotoEnd) dequeue = false timers.splice(index, 1) } } // Start the next in the queue if the last step wasn't forced. // Timers currently will call their complete callbacks, which // will dequeue but only if they were gotoEnd. if (dequeue || !gotoEnd) { jQuery.dequeue(this, type) } }) }, finish (type) { if (type !== false) { type = type || 'fx' } return this.each(function () { let index const data = dataPriv.get(this) const queue = data[`${type}queue`] const hooks = data[`${type}queueHooks`] const { timers } = jQuery const length = queue ? queue.length : 0 // Enable finishing flag on private data data.finish = true // Empty the queue first jQuery.queue(this, type, []) if (hooks && hooks.stop) { hooks.stop.call(this, true) } // Look for any active animations, and finish them for (index = timers.length; index--;) { if (timers[index].elem === this && timers[index].queue === type) { timers[index].anim.stop(true) timers.splice(index, 1) } } // Look for any animations in the old queue and finish them for (index = 0; index < length; index++) { if (queue[index] && queue[index].finish) { queue[index].finish.call(this) } } // Turn off finishing flag delete data.finish }) }, }) jQuery.each(['toggle', 'show', 'hide'], (i, name) => { const cssFn = jQuery.fn[name] jQuery.fn[name] = function (speed, easing, callback) { return speed == null || typeof speed === 'boolean' ? cssFn.apply(this, arguments) : this.animate(genFx(name, true), speed, easing, callback) } }) // Generate shortcuts for custom animations jQuery.each({ slideDown: genFx('show'), slideUp: genFx('hide'), slideToggle: genFx('toggle'), fadeIn: { opacity: 'show' }, fadeOut: { opacity: 'hide' }, fadeToggle: { opacity: 'toggle' }, }, (name, props) => { jQuery.fn[name] = function (speed, easing, callback) { return this.animate(props, speed, easing, callback) } }) jQuery.timers = [] jQuery.fx.tick = function () { let timer let i = 0 const { timers } = jQuery fxNow = Date.now() for (; i < timers.length; i++) { timer = timers[i] // Run the timer and safely remove it when done (allowing for external removal) if (!timer() && timers[i] === timer) { timers.splice(i--, 1) } } if (!timers.length) { jQuery.fx.stop() } fxNow = undefined } jQuery.fx.timer = function (timer) { jQuery.timers.push(timer) jQuery.fx.start() } jQuery.fx.interval = 13 jQuery.fx.start = function () { if (inProgress) { return } inProgress = true schedule() } jQuery.fx.stop = function () { inProgress = null } jQuery.fx.speeds = { slow: 600, fast: 200, // Default speed _default: 400, } // Based off of the plugin by Clint Helfers, with permission. // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ jQuery.fn.delay = function (time, type) { time = jQuery.fx ? jQuery.fx.speeds[time] || time : time type = type || 'fx' return this.queue(type, (next, hooks) => { const timeout = window.setTimeout(next, time) hooks.stop = function () { window.clearTimeout(timeout) } }) }; (function () { let input = document$1.createElement('input') const select = document$1.createElement('select') const opt = select.appendChild(document$1.createElement('option')) input.type = 'checkbox' // Support: Android <=4.3 only // Default value for a checkbox should be "on" support.checkOn = input.value !== '' // Support: IE <=11 only // Must access selectedIndex to make default options select support.optSelected = opt.selected // Support: IE <=11 only // An input loses its value after becoming a radio input = document$1.createElement('input') input.value = 't' input.type = 'radio' support.radioValue = input.value === 't' }()) let boolHook const { attrHandle } = jQuery.expr jQuery.fn.extend({ attr (name, value) { return access(this, jQuery.attr, name, value, arguments.length > 1) }, removeAttr (name) { return this.each(function () { jQuery.removeAttr(this, name) }) }, }) jQuery.extend({ attr (elem, name, value) { let ret; let hooks const nType = elem.nodeType // Don't get/set attributes on text, comment and attribute nodes if (nType === 3 || nType === 8 || nType === 2) { return } // Fallback to prop when attributes are not supported if (typeof elem.getAttribute === 'undefined') { return jQuery.prop(elem, name, value) } // Attribute hooks are determined by the lowercase version // Grab necessary hook if one is defined if (nType !== 1 || !jQuery.isXMLDoc(elem)) { hooks = jQuery.attrHooks[name.toLowerCase()] || (jQuery.expr.match.bool.test(name) ? boolHook : undefined) } if (value !== undefined) { if (value === null) { jQuery.removeAttr(elem, name) return } if (hooks && 'set' in hooks && (ret = hooks.set(elem, value, name)) !== undefined) { return ret } elem.setAttribute(name, `${value}`) return value } if (hooks && 'get' in hooks && (ret = hooks.get(elem, name)) !== null) { return ret } ret = jQuery.find.attr(elem, name) // Non-existent attributes return null, we normalize to undefined return ret == null ? undefined : ret }, attrHooks: { type: { set (elem, value) { if (!support.radioValue && value === 'radio' && nodeName(elem, 'input')) { const val = elem.value elem.setAttribute('type', value) if (val) { elem.value = val } return value } }, }, }, removeAttr (elem, value) { let name let i = 0 // Attribute names can contain non-HTML whitespace characters // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 const attrNames = value && value.match(rnothtmlwhite) if (attrNames && elem.nodeType === 1) { while ((name = attrNames[i++])) { elem.removeAttribute(name) } } }, }) // Hooks for boolean attributes boolHook = { set (elem, value, name) { if (value === false) { // Remove boolean attributes when set to false jQuery.removeAttr(elem, name) } else { elem.setAttribute(name, name) } return name }, } jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g), (i, name) => { const getter = attrHandle[name] || jQuery.find.attr attrHandle[name] = function (elem, name, isXML) { let ret; let handle const lowercaseName = name.toLowerCase() if (!isXML) { // Avoid an infinite loop by temporarily removing this function from the getter handle = attrHandle[lowercaseName] attrHandle[lowercaseName] = ret ret = getter(elem, name, isXML) != null ? lowercaseName : null attrHandle[lowercaseName] = handle } return ret } }) const rfocusable = /^(?:input|select|textarea|button)$/i const rclickable = /^(?:a|area)$/i jQuery.fn.extend({ prop (name, value) { return access(this, jQuery.prop, name, value, arguments.length > 1) }, removeProp (name) { return this.each(function () { delete this[jQuery.propFix[name] || name] }) }, }) jQuery.extend({ prop (elem, name, value) { let ret; let hooks const nType = elem.nodeType // Don't get/set properties on text, comment and attribute nodes if (nType === 3 || nType === 8 || nType === 2) { return } if (nType !== 1 || !jQuery.isXMLDoc(elem)) { // Fix name and attach hooks name = jQuery.propFix[name] || name hooks = jQuery.propHooks[name] } if (value !== undefined) { if (hooks && 'set' in hooks && (ret = hooks.set(elem, value, name)) !== undefined) { return ret } return (elem[name] = value) } if (hooks && 'get' in hooks && (ret = hooks.get(elem, name)) !== null) { return ret } return elem[name] }, propHooks: { tabIndex: { get (elem) { // Support: IE <=9 - 11 only // elem.tabIndex doesn't always return the // correct value when it hasn't been explicitly set // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ // Use proper attribute retrieval(#12072) const tabindex = jQuery.find.attr(elem, 'tabindex') if (tabindex) { return parseInt(tabindex, 10) } if ( rfocusable.test(elem.nodeName) || rclickable.test(elem.nodeName) && elem.href ) { return 0 } return -1 }, }, }, propFix: { for: 'htmlFor', class: 'className', }, }) // Support: IE <=11 only // Accessing the selectedIndex property // forces the browser to respect setting selected // on the option // The getter ensures a default option is selected // when in an optgroup // eslint rule "no-unused-expressions" is disabled for this code // since it considers such accessions noop if (!support.optSelected) { jQuery.propHooks.selected = { get (elem) { /* eslint no-unused-expressions: "off" */ const parent = elem.parentNode if (parent && parent.parentNode) { parent.parentNode.selectedIndex } return null }, set (elem) { /* eslint no-unused-expressions: "off" */ const parent = elem.parentNode if (parent) { parent.selectedIndex if (parent.parentNode) { parent.parentNode.selectedIndex } } }, } } jQuery.each([ 'tabIndex', 'readOnly', 'maxLength', 'cellSpacing', 'cellPadding', 'rowSpan', 'colSpan', 'useMap', 'frameBorder', 'contentEditable', ], function () { jQuery.propFix[this.toLowerCase()] = this }) // Strip and collapse whitespace according to HTML spec // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace function stripAndCollapse (value) { const tokens = value.match(rnothtmlwhite) || [] return tokens.join(' ') } function getClass (elem) { return elem.getAttribute && elem.getAttribute('class') || '' } function classesToArray (value) { if (Array.isArray(value)) { return value } if (typeof value === 'string') { return value.match(rnothtmlwhite) || [] } return [] } jQuery.fn.extend({ addClass (value) { let classes; let elem; let cur; let curValue; let clazz; let j; let finalValue let i = 0 if (isFunction(value)) { return this.each(function (j) { jQuery(this).addClass(value.call(this, j, getClass(this))) }) } classes = classesToArray(value) if (classes.length) { while ((elem = this[i++])) { curValue = getClass(elem) cur = elem.nodeType === 1 && (` ${stripAndCollapse(curValue)} `) if (cur) { j = 0 while ((clazz = classes[j++])) { if (cur.indexOf(` ${clazz} `) < 0) { cur += `${clazz} ` } } // Only assign if different to avoid unneeded rendering. finalValue = stripAndCollapse(cur) if (curValue !== finalValue) { elem.setAttribute('class', finalValue) } } } } return this }, removeClass (value) { let classes; let elem; let cur; let curValue; let clazz; let j; let finalValue let i = 0 if (isFunction(value)) { return this.each(function (j) { jQuery(this).removeClass(value.call(this, j, getClass(this))) }) } if (!arguments.length) { return this.attr('class', '') } classes = classesToArray(value) if (classes.length) { while ((elem = this[i++])) { curValue = getClass(elem) // This expression is here for better compressibility (see addClass) cur = elem.nodeType === 1 && (` ${stripAndCollapse(curValue)} `) if (cur) { j = 0 while ((clazz = classes[j++])) { // Remove *all* instances while (cur.indexOf(` ${clazz} `) > -1) { cur = cur.replace(` ${clazz} `, ' ') } } // Only assign if different to avoid unneeded rendering. finalValue = stripAndCollapse(cur) if (curValue !== finalValue) { elem.setAttribute('class', finalValue) } } } } return this }, toggleClass (value, stateVal) { const type = typeof value const isValidValue = type === 'string' || Array.isArray(value) if (typeof stateVal === 'boolean' && isValidValue) { return stateVal ? this.addClass(value) : this.removeClass(value) } if (isFunction(value)) { return this.each(function (i) { jQuery(this).toggleClass( value.call(this, i, getClass(this), stateVal), stateVal, ) }) } return this.each(function () { let className; let i; let self; let classNames if (isValidValue) { // Toggle individual class names i = 0 self = jQuery(this) classNames = classesToArray(value) while ((className = classNames[i++])) { // Check each className given, space separated list if (self.hasClass(className)) { self.removeClass(className) } else { self.addClass(className) } } // Toggle whole class name } else if (value === undefined || type === 'boolean') { className = getClass(this) if (className) { // Store className if set dataPriv.set(this, '__className__', className) } // If the element has a class name or if we're passed `false`, // then remove the whole classname (if there was one, the above saved it). // Otherwise bring back whatever was previously saved (if anything), // falling back to the empty string if nothing was stored. if (this.setAttribute) { this.setAttribute('class', className || value === false ? '' : dataPriv.get(this, '__className__') || '') } } }) }, hasClass (selector) { let className; let elem let i = 0 className = ` ${selector} ` while ((elem = this[i++])) { if (elem.nodeType === 1 && (` ${stripAndCollapse(getClass(elem))} `).indexOf(className) > -1) { return true } } return false }, }) const rreturn = /\r/g jQuery.fn.extend({ val (value) { let hooks; let ret; let valueIsFunction const elem = this[0] if (!arguments.length) { if (elem) { hooks = jQuery.valHooks[elem.type] || jQuery.valHooks[elem.nodeName.toLowerCase()] if (hooks && 'get' in hooks && (ret = hooks.get(elem, 'value')) !== undefined ) { return ret } ret = elem.value // Handle most common string cases if (typeof ret === 'string') { return ret.replace(rreturn, '') } // Handle cases where value is null/undef or number return ret == null ? '' : ret } return } valueIsFunction = isFunction(value) return this.each(function (i) { let val if (this.nodeType !== 1) { return } if (valueIsFunction) { val = value.call(this, i, jQuery(this).val()) } else { val = value } // Treat null/undefined as ""; convert numbers to string if (val == null) { val = '' } else if (typeof val === 'number') { val += '' } else if (Array.isArray(val)) { val = jQuery.map(val, (value) => (value == null ? '' : `${value}`)) } hooks = jQuery.valHooks[this.type] || jQuery.valHooks[this.nodeName.toLowerCase()] // If set returns undefined, fall back to normal setting if (!hooks || !('set' in hooks) || hooks.set(this, val, 'value') === undefined) { this.value = val } }) }, }) jQuery.extend({ valHooks: { option: { get (elem) { const val = jQuery.find.attr(elem, 'value') return val != null ? val // Support: IE <=10 - 11 only // option.text throws exceptions (#14686, #14858) // Strip and collapse whitespace // https://html.spec.whatwg.org/#strip-and-collapse-whitespace : stripAndCollapse(jQuery.text(elem)) }, }, select: { get (elem) { let value; let option; let i const { options } = elem const index = elem.selectedIndex const one = elem.type === 'select-one' const values = one ? null : [] const max = one ? index + 1 : options.length if (index < 0) { i = max } else { i = one ? index : 0 } // Loop through all the selected options for (; i < max; i++) { option = options[i] // Support: IE <=9 only // IE8-9 doesn't update selected after form reset (#2551) if ((option.selected || i === index) // Don't return options that are disabled or in a disabled optgroup && !option.disabled && (!option.parentNode.disabled || !nodeName(option.parentNode, 'optgroup'))) { // Get the specific value for the option value = jQuery(option).val() // We don't need an array for one selects if (one) { return value } // Multi-Selects return an array values.push(value) } } return values }, set (elem, value) { let optionSet; let option const { options } = elem const values = jQuery.makeArray(value) let i = options.length while (i--) { option = options[i] /* eslint-disable no-cond-assign */ if (option.selected = jQuery.inArray(jQuery.valHooks.option.get(option), values) > -1 ) { optionSet = true } /* eslint-enable no-cond-assign */ } // Force browsers to behave consistently when non-matching value is set if (!optionSet) { elem.selectedIndex = -1 } return values }, }, }, }) // Radios and checkboxes getter/setter jQuery.each(['radio', 'checkbox'], function () { jQuery.valHooks[this] = { set (elem, value) { if (Array.isArray(value)) { return (elem.checked = jQuery.inArray(jQuery(elem).val(), value) > -1) } }, } if (!support.checkOn) { jQuery.valHooks[this].get = function (elem) { return elem.getAttribute('value') === null ? 'on' : elem.value } } }) // Return jQuery for attributes-only inclusion support.focusin = 'onfocusin' in window const rfocusMorph = /^(?:focusinfocus|focusoutblur)$/ const stopPropagationCallback = function (e) { e.stopPropagation() } jQuery.extend(jQuery.event, { trigger (event, data, elem, onlyHandlers) { let i; let cur; let tmp; let bubbleType; let ontype; let handle; let special; let lastElement const eventPath = [elem || document$1] let type = hasOwn.call(event, 'type') ? event.type : event let namespaces = hasOwn.call(event, 'namespace') ? event.namespace.split('.') : [] cur = lastElement = tmp = elem = elem || document$1 // Don't do events on text and comment nodes if (elem.nodeType === 3 || elem.nodeType === 8) { return } // focus/blur morphs to focusin/out; ensure we're not firing them right now if (rfocusMorph.test(type + jQuery.event.triggered)) { return } if (type.indexOf('.') > -1) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split('.') type = namespaces.shift() namespaces.sort() } ontype = type.indexOf(':') < 0 && `on${type}` // Caller can pass in a jQuery.Event object, Object, or just an event type string event = event[jQuery.expando] ? event : new jQuery.Event(type, typeof event === 'object' && event) // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) event.isTrigger = onlyHandlers ? 2 : 3 event.namespace = namespaces.join('.') event.rnamespace = event.namespace ? new RegExp(`(^|\\.)${namespaces.join('\\.(?:.*\\.|)')}(\\.|$)`) : null // Clean up the event in case it is being reused event.result = undefined if (!event.target) { event.target = elem } // Clone any incoming data and prepend the event, creating the handler arg list data = data == null ? [event] : jQuery.makeArray(data, [event]) // Allow special events to draw outside the lines special = jQuery.event.special[type] || {} if (!onlyHandlers && special.trigger && special.trigger.apply(elem, data) === false) { return } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) if (!onlyHandlers && !special.noBubble && !isWindow(elem)) { bubbleType = special.delegateType || type if (!rfocusMorph.test(bubbleType + type)) { cur = cur.parentNode } for (; cur; cur = cur.parentNode) { eventPath.push(cur) tmp = cur } // Only add window if we got to document (e.g., not plain obj or detached DOM) if (tmp === (elem.ownerDocument || document$1)) { eventPath.push(tmp.defaultView || tmp.parentWindow || window) } } // Fire handlers on the event path i = 0 while ((cur = eventPath[i++]) && !event.isPropagationStopped()) { lastElement = cur event.type = i > 1 ? bubbleType : special.bindType || type // jQuery handler handle = (dataPriv.get(cur, 'events') || {})[event.type] && dataPriv.get(cur, 'handle') if (handle) { handle.apply(cur, data) } // Native handler handle = ontype && cur[ontype] if (handle && handle.apply && acceptData(cur)) { event.result = handle.apply(cur, data) if (event.result === false) { event.preventDefault() } } } event.type = type // If nobody prevented the default action, do it now if (!onlyHandlers && !event.isDefaultPrevented()) { if ((!special._default || special._default.apply(eventPath.pop(), data) === false) && acceptData(elem)) { // Call a native DOM method on the target with the same name as the event. // Don't do default actions on window, that's where global variables be (#6170) if (ontype && isFunction(elem[type]) && !isWindow(elem)) { // Don't re-trigger an onFOO event when we call its FOO() method tmp = elem[ontype] if (tmp) { elem[ontype] = null } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type if (event.isPropagationStopped()) { lastElement.addEventListener(type, stopPropagationCallback) } elem[type]() if (event.isPropagationStopped()) { lastElement.removeEventListener(type, stopPropagationCallback) } jQuery.event.triggered = undefined if (tmp) { elem[ontype] = tmp } } } } return event.result }, // Piggyback on a donor event to simulate a different one // Used only for `focus(in | out)` events simulate (type, elem, event) { const e = jQuery.extend( new jQuery.Event(), event, { type, isSimulated: true, }, ) jQuery.event.trigger(e, null, elem) }, }) jQuery.fn.extend({ trigger (type, data) { return this.each(function () { jQuery.event.trigger(type, data, this) }) }, triggerHandler (type, data) { const elem = this[0] if (elem) { return jQuery.event.trigger(type, data, elem, true) } }, }) // Support: Firefox <=44 // Firefox doesn't have focus(in | out) events // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 // // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 // focus(in | out) events fire after focus & blur events, // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 if (!support.focusin) { jQuery.each({ focus: 'focusin', blur: 'focusout' }, (orig, fix) => { // Attach a single capturing handler on the document while someone wants focusin/focusout const handler = function (event) { jQuery.event.simulate(fix, event.target, jQuery.event.fix(event)) } jQuery.event.special[fix] = { setup () { const doc = this.ownerDocument || this const attaches = dataPriv.access(doc, fix) if (!attaches) { doc.addEventListener(orig, handler, true) } dataPriv.access(doc, fix, (attaches || 0) + 1) }, teardown () { const doc = this.ownerDocument || this const attaches = dataPriv.access(doc, fix) - 1 if (!attaches) { doc.removeEventListener(orig, handler, true) dataPriv.remove(doc, fix) } else { dataPriv.access(doc, fix, attaches) } }, } }) } const { location } = window let nonce = Date.now() const rquery = (/\?/) // Cross-browser xml parsing jQuery.parseXML = function (data) { let xml if (!data || typeof data !== 'string') { return null } // Support: IE 9 - 11 only // IE throws on parseFromString with invalid input. try { xml = (new window.DOMParser()).parseFromString(data, 'text/xml') } catch (e) { xml = undefined } if (!xml || xml.getElementsByTagName('parsererror').length) { jQuery.error(`Invalid XML: ${data}`) } return xml } const rbracket = /\[\]$/ const rCRLF = /\r?\n/g const rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i const rsubmittable = /^(?:input|select|textarea|keygen)/i function buildParams (prefix, obj, traditional, add) { let name if (Array.isArray(obj)) { // Serialize array item. jQuery.each(obj, (i, v) => { if (traditional || rbracket.test(prefix)) { // Treat each array item as a scalar. add(prefix, v) } else { // Item is non-scalar (array or object), encode its numeric index. buildParams( `${prefix}[${typeof v === 'object' && v != null ? i : ''}]`, v, traditional, add, ) } }) } else if (!traditional && toType(obj) === 'object') { // Serialize object item. for (name in obj) { buildParams(`${prefix}[${name}]`, obj[name], traditional, add) } } else { // Serialize scalar item. add(prefix, obj) } } // Serialize an array of form elements or a set of // key/values into a query string jQuery.param = function (a, traditional) { let prefix const s = [] const add = function (key, valueOrFunction) { // If value is a function, invoke it and use its return value const value = isFunction(valueOrFunction) ? valueOrFunction() : valueOrFunction s[s.length] = `${encodeURIComponent(key)}=${encodeURIComponent(value == null ? '' : value)}` } if (a == null) { return '' } // If an array was passed in, assume that it is an array of form elements. if (Array.isArray(a) || (a.jquery && !jQuery.isPlainObject(a))) { // Serialize the form elements jQuery.each(a, function () { add(this.name, this.value) }) } else { // If traditional, encode the "old" way (the way 1.3.2 or older // did it), otherwise encode params recursively. for (prefix in a) { buildParams(prefix, a[prefix], traditional, add) } } // Return the resulting serialization return s.join('&') } jQuery.fn.extend({ serialize () { return jQuery.param(this.serializeArray()) }, serializeArray () { return this.map(function () { // Can add propHook for "elements" to filter or add form elements const elements = jQuery.prop(this, 'elements') return elements ? jQuery.makeArray(elements) : this }) .filter(function () { const { type } = this // Use .is( ":disabled" ) so that fieldset[disabled] works return this.name && !jQuery(this).is(':disabled') && rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && (this.checked || !rcheckableType.test(type)) }) .map(function (i, elem) { const val = jQuery(this).val() if (val == null) { return null } if (Array.isArray(val)) { return jQuery.map(val, (val) => ({ name: elem.name, value: val.replace(rCRLF, '\r\n') })) } return { name: elem.name, value: val.replace(rCRLF, '\r\n') } }).get() }, }) const r20 = /%20/g const rhash = /#.*$/ const rantiCache = /([?&])_=[^&]*/ const rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg // #7653, #8125, #8152: local protocol detection const rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/ const rnoContent = /^(?:GET|HEAD)$/ const rprotocol = /^\/\// /* Prefilters * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) * 2) These are called: * - BEFORE asking for a transport * - AFTER param serialization (s.data is a string if s.processData is true) * 3) key is the dataType * 4) the catchall symbol "*" can be used * 5) execution will start with transport dataType and THEN continue down to "*" if needed */ const prefilters = {} /* Transports bindings * 1) key is the dataType * 2) the catchall symbol "*" can be used * 3) selection will start with transport dataType and THEN go to "*" if needed */ const transports = {} // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression const allTypes = '*/'.concat('*') // Anchor tag for parsing the document origin const originAnchor = document$1.createElement('a') originAnchor.href = location.href // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport function addToPrefiltersOrTransports (structure) { // dataTypeExpression is optional and defaults to "*" return function (dataTypeExpression, func) { if (typeof dataTypeExpression !== 'string') { func = dataTypeExpression dataTypeExpression = '*' } let dataType let i = 0 const dataTypes = dataTypeExpression.toLowerCase().match(rnothtmlwhite) || [] if (isFunction(func)) { // For each dataType in the dataTypeExpression while ((dataType = dataTypes[i++])) { // Prepend if requested if (dataType[0] === '+') { dataType = dataType.slice(1) || '*'; (structure[dataType] = structure[dataType] || []).unshift(func) // Otherwise append } else { (structure[dataType] = structure[dataType] || []).push(func) } } } } } // Base inspection function for prefilters and transports function inspectPrefiltersOrTransports (structure, options, originalOptions, jqXHR) { const inspected = {} const seekingTransport = (structure === transports) function inspect (dataType) { let selected inspected[dataType] = true jQuery.each(structure[dataType] || [], (_, prefilterOrFactory) => { const dataTypeOrTransport = prefilterOrFactory(options, originalOptions, jqXHR) if (typeof dataTypeOrTransport === 'string' && !seekingTransport && !inspected[dataTypeOrTransport]) { options.dataTypes.unshift(dataTypeOrTransport) inspect(dataTypeOrTransport) return false } if (seekingTransport) { return !(selected = dataTypeOrTransport) } }) return selected } return inspect(options.dataTypes[0]) || !inspected['*'] && inspect('*') } // A special extend for ajax options // that takes "flat" options (not to be deep extended) // Fixes #9887 function ajaxExtend (target, src) { let key; let deep const flatOptions = jQuery.ajaxSettings.flatOptions || {} for (key in src) { if (src[key] !== undefined) { (flatOptions[key] ? target : (deep || (deep = {})))[key] = src[key] } } if (deep) { jQuery.extend(true, target, deep) } return target } /* Handles responses to an ajax request: * - finds the right dataType (mediates between content-type and expected dataType) * - returns the corresponding response */ function ajaxHandleResponses (s, jqXHR, responses) { let ct; let type; let finalDataType; let firstDataType const { contents } = s const { dataTypes } = s // Remove auto dataType and get content-type in the process while (dataTypes[0] === '*') { dataTypes.shift() if (ct === undefined) { ct = s.mimeType || jqXHR.getResponseHeader('Content-Type') } } // Check if we're dealing with a known content-type if (ct) { for (type in contents) { if (contents[type] && contents[type].test(ct)) { dataTypes.unshift(type) break } } } // Check to see if we have a response for the expected dataType if (dataTypes[0] in responses) { finalDataType = dataTypes[0] } else { // Try convertible dataTypes for (type in responses) { if (!dataTypes[0] || s.converters[`${type} ${dataTypes[0]}`]) { finalDataType = type break } if (!firstDataType) { firstDataType = type } } // Or just use first one finalDataType = finalDataType || firstDataType } // If we found a dataType // We add the dataType to the list if needed // and return the corresponding response if (finalDataType) { if (finalDataType !== dataTypes[0]) { dataTypes.unshift(finalDataType) } return responses[finalDataType] } } /* Chain conversions given the request and the original response * Also sets the responseXXX fields on the jqXHR instance */ function ajaxConvert (s, response, jqXHR, isSuccess) { let conv2; let current; let conv; let tmp; let prev const converters = {} // Work with a copy of dataTypes in case we need to modify it for conversion const dataTypes = s.dataTypes.slice() // Create converters map with lowercased keys if (dataTypes[1]) { for (conv in s.converters) { converters[conv.toLowerCase()] = s.converters[conv] } } current = dataTypes.shift() // Convert to each sequential dataType while (current) { if (s.responseFields[current]) { jqXHR[s.responseFields[current]] = response } // Apply the dataFilter if provided if (!prev && isSuccess && s.dataFilter) { response = s.dataFilter(response, s.dataType) } prev = current current = dataTypes.shift() if (current) { // There's only work to do if current dataType is non-auto if (current === '*') { current = prev // Convert response if prev dataType is non-auto and differs from current } else if (prev !== '*' && prev !== current) { // Seek a direct converter conv = converters[`${prev} ${current}`] || converters[`* ${current}`] // If none found, seek a pair if (!conv) { for (conv2 in converters) { // If conv2 outputs current tmp = conv2.split(' ') if (tmp[1] === current) { // If prev can be converted to accepted input conv = converters[`${prev} ${tmp[0]}`] || converters[`* ${tmp[0]}`] if (conv) { // Condense equivalence converters if (conv === true) { conv = converters[conv2] // Otherwise, insert the intermediate dataType } else if (converters[conv2] !== true) { current = tmp[0] dataTypes.unshift(tmp[1]) } break } } } } // Apply converter (if not an equivalence) if (conv !== true) { // Unless errors are allowed to bubble, catch and return them if (conv && s.throws) { response = conv(response) } else { try { response = conv(response) } catch (e) { return { state: 'parsererror', error: conv ? e : `No conversion from ${prev} to ${current}`, } } } } } } } return { state: 'success', data: response } } jQuery.extend({ // Counter for holding the number of active queries active: 0, // Last-Modified header cache for next request lastModified: {}, etag: {}, ajaxSettings: { url: location.href, type: 'GET', isLocal: rlocalProtocol.test(location.protocol), global: true, processData: true, async: true, contentType: 'application/x-www-form-urlencoded; charset=UTF-8', /* timeout: 0, data: null, dataType: null, username: null, password: null, cache: null, throws: false, traditional: false, headers: {}, */ accepts: { '*': allTypes, text: 'text/plain', html: 'text/html', xml: 'application/xml, text/xml', json: 'application/json, text/javascript', }, contents: { xml: /\bxml\b/, html: /\bhtml/, json: /\bjson\b/, }, responseFields: { xml: 'responseXML', text: 'responseText', json: 'responseJSON', }, // Data converters // Keys separate source (or catchall "*") and destination types with a single space converters: { // Convert anything to text '* text': String, // Text to html (true = no transformation) 'text html': true, // Evaluate text as a json expression 'text json': JSON.parse, // Parse text as xml 'text xml': jQuery.parseXML, }, // For options that shouldn't be deep extended: // you can add your own custom options here if // and when you create one that shouldn't be // deep extended (see ajaxExtend) flatOptions: { url: true, context: true, }, }, // Creates a full fledged settings object into target // with both ajaxSettings and settings fields. // If target is omitted, writes into ajaxSettings. ajaxSetup (target, settings) { return settings // Building a settings object ? ajaxExtend(ajaxExtend(target, jQuery.ajaxSettings), settings) // Extending ajaxSettings : ajaxExtend(jQuery.ajaxSettings, target) }, ajaxPrefilter: addToPrefiltersOrTransports(prefilters), ajaxTransport: addToPrefiltersOrTransports(transports), // Main method ajax (url, options) { // If url is an object, simulate pre-1.5 signature if (typeof url === 'object') { options = url url = undefined } // Force options to be an object options = options || {} let transport // URL without anti-cache param let cacheURL // Response headers let responseHeadersString let responseHeaders // timeout handle let timeoutTimer // Url cleanup var let urlAnchor // Request state (becomes false upon send and true upon completion) let completed // To know if global events are to be dispatched let fireGlobals // Loop variable let i // uncached part of the url let uncached // Create the final options object const s = jQuery.ajaxSetup({}, options) // Callbacks context const callbackContext = s.context || s // Context for global events is callbackContext if it is a DOM node or jQuery collection const globalEventContext = s.context && (callbackContext.nodeType || callbackContext.jquery) ? jQuery(callbackContext) : jQuery.event // Deferreds const deferred = jQuery.Deferred() const completeDeferred = jQuery.Callbacks('once memory') // Status-dependent callbacks let statusCode = s.statusCode || {} // Headers (they are sent all at once) const requestHeaders = {} const requestHeadersNames = {} // Default abort message let strAbort = 'canceled' // Fake xhr var jqXHR = { readyState: 0, // Builds headers hashtable if needed getResponseHeader (key) { let match if (completed) { if (!responseHeaders) { responseHeaders = {} while ((match = rheaders.exec(responseHeadersString))) { responseHeaders[`${match[1].toLowerCase()} `] = (responseHeaders[`${match[1].toLowerCase()} `] || []) .concat(match[2]) } } match = responseHeaders[`${key.toLowerCase()} `] } return match == null ? null : match.join(', ') }, // Raw string getAllResponseHeaders () { return completed ? responseHeadersString : null }, // Caches the header setRequestHeader (name, value) { if (completed == null) { name = requestHeadersNames[name.toLowerCase()] = requestHeadersNames[name.toLowerCase()] || name requestHeaders[name] = value } return this }, // Overrides response content-type header overrideMimeType (type) { if (completed == null) { s.mimeType = type } return this }, // Status-dependent callbacks statusCode (map) { let code if (map) { if (completed) { // Execute the appropriate callbacks jqXHR.always(map[jqXHR.status]) } else { // Lazy-add the new callbacks in a way that preserves old ones for (code in map) { statusCode[code] = [statusCode[code], map[code]] } } } return this }, // Cancel the request abort (statusText) { const finalText = statusText || strAbort if (transport) { transport.abort(finalText) } done(0, finalText) return this }, } // Attach deferreds deferred.promise(jqXHR) // Add protocol if not provided (prefilters might expect it) // Handle falsy url in the settings object (#10093: consistency with old signature) // We also use the url parameter if available s.url = (`${url || s.url || location.href}`) .replace(rprotocol, `${location.protocol}//`) // Alias method option to type as per ticket #12004 s.type = options.method || options.type || s.method || s.type // Extract dataTypes list s.dataTypes = (s.dataType || '*').toLowerCase().match(rnothtmlwhite) || [''] // A cross-domain request is in order when the origin doesn't match the current origin. if (s.crossDomain == null) { urlAnchor = document$1.createElement('a') // Support: IE <=8 - 11, Edge 12 - 15 // IE throws exception on accessing the href property if url is malformed, // e.g. http://example.com:80x/ try { urlAnchor.href = s.url // Support: IE <=8 - 11 only // Anchor's host property isn't correctly set when s.url is relative urlAnchor.href = urlAnchor.href s.crossDomain = `${originAnchor.protocol}//${originAnchor.host}` !== `${urlAnchor.protocol}//${urlAnchor.host}` } catch (e) { // If there is an error parsing the URL, assume it is crossDomain, // it can be rejected by the transport if it is invalid s.crossDomain = true } } // Convert data if not already a string if (s.data && s.processData && typeof s.data !== 'string') { s.data = jQuery.param(s.data, s.traditional) } // Apply prefilters inspectPrefiltersOrTransports(prefilters, s, options, jqXHR) // If request was aborted inside a prefilter, stop there if (completed) { return jqXHR } // We can fire global events as of now if asked to // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) fireGlobals = jQuery.event && s.global // Watch for a new set of requests if (fireGlobals && jQuery.active++ === 0) { jQuery.event.trigger('ajaxStart') } // Uppercase the type s.type = s.type.toUpperCase() // Determine if request has content s.hasContent = !rnoContent.test(s.type) // Save the URL in case we're toying with the If-Modified-Since // and/or If-None-Match header later on // Remove hash to simplify url manipulation cacheURL = s.url.replace(rhash, '') // More options handling for requests with no content if (!s.hasContent) { // Remember the hash so we can put it back uncached = s.url.slice(cacheURL.length) // If data is available and should be processed, append data to url if (s.data && (s.processData || typeof s.data === 'string')) { cacheURL += (rquery.test(cacheURL) ? '&' : '?') + s.data // #9682: remove data so that it's not used in an eventual retry delete s.data } // Add or update anti-cache param if needed if (s.cache === false) { cacheURL = cacheURL.replace(rantiCache, '$1') uncached = `${rquery.test(cacheURL) ? '&' : '?'}_=${nonce++}${uncached}` } // Put hash and anti-cache on the URL that will be requested (gh-1732) s.url = cacheURL + uncached // Change '%20' to '+' if this is encoded form body content (gh-2658) } else if (s.data && s.processData && (s.contentType || '').indexOf('application/x-www-form-urlencoded') === 0) { s.data = s.data.replace(r20, '+') } // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if (s.ifModified) { if (jQuery.lastModified[cacheURL]) { jqXHR.setRequestHeader('If-Modified-Since', jQuery.lastModified[cacheURL]) } if (jQuery.etag[cacheURL]) { jqXHR.setRequestHeader('If-None-Match', jQuery.etag[cacheURL]) } } // Set the correct header, if data is being sent if (s.data && s.hasContent && s.contentType !== false || options.contentType) { jqXHR.setRequestHeader('Content-Type', s.contentType) } // Set the Accepts header for the server, depending on the dataType jqXHR.setRequestHeader( 'Accept', s.dataTypes[0] && s.accepts[s.dataTypes[0]] ? s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== '*' ? `, ${allTypes}; q=0.01` : '') : s.accepts['*'], ) // Check for headers option for (i in s.headers) { jqXHR.setRequestHeader(i, s.headers[i]) } // Allow custom headers/mimetypes and early abort if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || completed)) { // Abort if not done already and return return jqXHR.abort() } // Aborting is no longer a cancellation strAbort = 'abort' // Install callbacks on deferreds completeDeferred.add(s.complete) jqXHR.done(s.success) jqXHR.fail(s.error) // Get transport transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR) // If no transport, we auto-abort if (!transport) { done(-1, 'No Transport') } else { jqXHR.readyState = 1 // Send global event if (fireGlobals) { globalEventContext.trigger('ajaxSend', [jqXHR, s]) } // If request was aborted inside ajaxSend, stop there if (completed) { return jqXHR } // Timeout if (s.async && s.timeout > 0) { timeoutTimer = window.setTimeout(() => { jqXHR.abort('timeout') }, s.timeout) } try { completed = false transport.send(requestHeaders, done) } catch (e) { // Rethrow post-completion exceptions if (completed) { throw e } // Propagate others as results done(-1, e) } } // Callback for when everything is done function done (status, nativeStatusText, responses, headers) { let isSuccess; let success; let error; let response; let modified let statusText = nativeStatusText // Ignore repeat invocations if (completed) { return } completed = true // Clear timeout if it exists if (timeoutTimer) { window.clearTimeout(timeoutTimer) } // Dereference transport for early garbage collection // (no matter how long the jqXHR object will be used) transport = undefined // Cache response headers responseHeadersString = headers || '' // Set readyState jqXHR.readyState = status > 0 ? 4 : 0 // Determine if successful isSuccess = status >= 200 && status < 300 || status === 304 // Get response data if (responses) { response = ajaxHandleResponses(s, jqXHR, responses) } // Convert no matter what (that way responseXXX fields are always set) response = ajaxConvert(s, response, jqXHR, isSuccess) // If successful, handle type chaining if (isSuccess) { // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. if (s.ifModified) { modified = jqXHR.getResponseHeader('Last-Modified') if (modified) { jQuery.lastModified[cacheURL] = modified } modified = jqXHR.getResponseHeader('etag') if (modified) { jQuery.etag[cacheURL] = modified } } // if no content if (status === 204 || s.type === 'HEAD') { statusText = 'nocontent' // if not modified } else if (status === 304) { statusText = 'notmodified' // If we have data, let's convert it } else { statusText = response.state success = response.data error = response.error isSuccess = !error } } else { // Extract error from statusText and normalize for non-aborts error = statusText if (status || !statusText) { statusText = 'error' if (status < 0) { status = 0 } } } // Set data for the fake xhr object jqXHR.status = status jqXHR.statusText = `${nativeStatusText || statusText}` // Success/Error if (isSuccess) { deferred.resolveWith(callbackContext, [success, statusText, jqXHR]) } else { deferred.rejectWith(callbackContext, [jqXHR, statusText, error]) } // Status-dependent callbacks jqXHR.statusCode(statusCode) statusCode = undefined if (fireGlobals) { globalEventContext.trigger(isSuccess ? 'ajaxSuccess' : 'ajaxError', [jqXHR, s, isSuccess ? success : error]) } // Complete completeDeferred.fireWith(callbackContext, [jqXHR, statusText]) if (fireGlobals) { globalEventContext.trigger('ajaxComplete', [jqXHR, s]) // Handle the global AJAX counter if (!(--jQuery.active)) { jQuery.event.trigger('ajaxStop') } } } return jqXHR }, getJSON (url, data, callback) { return jQuery.get(url, data, callback, 'json') }, getScript (url, callback) { return jQuery.get(url, undefined, callback, 'script') }, }) jQuery.each(['get', 'post'], (i, method) => { jQuery[method] = function (url, data, callback, type) { // Shift arguments if data argument was omitted if (isFunction(data)) { type = type || callback callback = data data = undefined } // The url can be an options object (which then must have .url) return jQuery.ajax(jQuery.extend({ url, type: method, dataType: type, data, success: callback, }, jQuery.isPlainObject(url) && url)) } }) jQuery._evalUrl = function (url, options) { return jQuery.ajax({ url, // Make this explicit, since user can override this through ajaxSetup (#11264) type: 'GET', dataType: 'script', cache: true, async: false, global: false, // Only evaluate the response if it is successful (gh-4126) // dataFilter is not invoked for failure responses, so using it instead // of the default converter is kludgy but it works. converters: { 'text script': function () { }, }, dataFilter (response) { jQuery.globalEval(response, options) }, }) } jQuery.fn.extend({ wrapAll (html) { let wrap if (this[0]) { if (isFunction(html)) { html = html.call(this[0]) } // The elements to wrap the target around wrap = jQuery(html, this[0].ownerDocument).eq(0).clone(true) if (this[0].parentNode) { wrap.insertBefore(this[0]) } wrap.map(function () { let elem = this while (elem.firstElementChild) { elem = elem.firstElementChild } return elem }).append(this) } return this }, wrapInner (html) { if (isFunction(html)) { return this.each(function (i) { jQuery(this).wrapInner(html.call(this, i)) }) } return this.each(function () { const self = jQuery(this) const contents = self.contents() if (contents.length) { contents.wrapAll(html) } else { self.append(html) } }) }, wrap (html) { const htmlIsFunction = isFunction(html) return this.each(function (i) { jQuery(this).wrapAll(htmlIsFunction ? html.call(this, i) : html) }) }, unwrap (selector) { this.parent(selector).not('body').each(function () { jQuery(this).replaceWith(this.childNodes) }) return this }, }) jQuery.expr.pseudos.hidden = function (elem) { return !jQuery.expr.pseudos.visible(elem) } jQuery.expr.pseudos.visible = function (elem) { return !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length) } jQuery.ajaxSettings.xhr = function () { try { return new window.XMLHttpRequest() } catch (e) { } } const xhrSuccessStatus = { // File protocol always yields status code 0, assume 200 0: 200, // Support: IE <=9 only // #1450: sometimes IE returns 1223 when it should be 204 1223: 204, } let xhrSupported = jQuery.ajaxSettings.xhr() support.cors = !!xhrSupported && ('withCredentials' in xhrSupported) support.ajax = xhrSupported = !!xhrSupported jQuery.ajaxTransport((options) => { let callback; let errorCallback // Cross domain only allowed if supported through XMLHttpRequest if (support.cors || xhrSupported && !options.crossDomain) { return { send (headers, complete) { let i const xhr = options.xhr() xhr.open( options.type, options.url, options.async, options.username, options.password, ) // Apply custom fields if provided if (options.xhrFields) { for (i in options.xhrFields) { xhr[i] = options.xhrFields[i] } } // Override mime type if needed if (options.mimeType && xhr.overrideMimeType) { xhr.overrideMimeType(options.mimeType) } // X-Requested-With header // For cross-domain requests, seeing as conditions for a preflight are // akin to a jigsaw puzzle, we simply never set it to be sure. // (it can always be set on a per-request basis or even using ajaxSetup) // For same-domain requests, won't change header if already provided. if (!options.crossDomain && !headers['X-Requested-With']) { headers['X-Requested-With'] = 'XMLHttpRequest' } // Set headers for (i in headers) { xhr.setRequestHeader(i, headers[i]) } // Callback callback = function (type) { return function () { if (callback) { callback = errorCallback = xhr.onload = xhr.onerror = xhr.onabort = xhr.ontimeout = xhr.onreadystatechange = null if (type === 'abort') { xhr.abort() } else if (type === 'error') { // Support: IE <=9 only // On a manual native abort, IE9 throws // errors on any property access that is not readyState if (typeof xhr.status !== 'number') { complete(0, 'error') } else { complete( // File: protocol always yields status 0; see #8605, #14207 xhr.status, xhr.statusText, ) } } else { complete( xhrSuccessStatus[xhr.status] || xhr.status, xhr.statusText, // Support: IE <=9 only // IE9 has no XHR2 but throws on binary (trac-11426) // For XHR2 non-text, let the caller handle it (gh-2498) (xhr.responseType || 'text') !== 'text' || typeof xhr.responseText !== 'string' ? { binary: xhr.response } : { text: xhr.responseText }, xhr.getAllResponseHeaders(), ) } } } } // Listen to events xhr.onload = callback() errorCallback = xhr.onerror = xhr.ontimeout = callback('error') // Support: IE 9 only // Use onreadystatechange to replace onabort // to handle uncaught aborts if (xhr.onabort !== undefined) { xhr.onabort = errorCallback } else { xhr.onreadystatechange = function () { // Check readyState before timeout as it changes if (xhr.readyState === 4) { // Allow onerror to be called first, // but that will not handle a native abort // Also, save errorCallback to a variable // as xhr.onerror cannot be accessed window.setTimeout(() => { if (callback) { errorCallback() } }) } } } // Create the abort callback callback = callback('abort') try { // Do send the request (this may raise an exception) xhr.send(options.hasContent && options.data || null) } catch (e) { // #14683: Only rethrow if this hasn't been notified as an error yet if (callback) { throw e } } }, abort () { if (callback) { callback() } }, } } }) // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) jQuery.ajaxPrefilter((s) => { if (s.crossDomain) { s.contents.script = false } }) // Install script dataType jQuery.ajaxSetup({ accepts: { script: 'text/javascript, application/javascript, ' + 'application/ecmascript, application/x-ecmascript', }, contents: { script: /\b(?:java|ecma)script\b/, }, converters: { 'text script': function (text) { jQuery.globalEval(text) return text }, }, }) // Handle cache's special case and crossDomain jQuery.ajaxPrefilter('script', (s) => { if (s.cache === undefined) { s.cache = false } if (s.crossDomain) { s.type = 'GET' } }) // Bind script tag hack transport jQuery.ajaxTransport('script', (s) => { // This transport only deals with cross domain or forced-by-attrs requests if (s.crossDomain || s.scriptAttrs) { let script; let callback return { send (_, complete) { script = jQuery('