diff --git a/src/style-spec/expression/definitions/distance.js b/src/style-spec/expression/definitions/distance.js new file mode 100644 index 00000000000..4cc59de41b1 --- /dev/null +++ b/src/style-spec/expression/definitions/distance.js @@ -0,0 +1,553 @@ +// @flow + +import {isValue} from "../values.js"; +import type {Type} from "../types.js"; +import {NumberType} from "../types.js"; +import type {Expression} from "../expression.js"; +import type ParsingContext from "../parsing_context.js"; +import type EvaluationContext from "../evaluation_context.js"; +import type { + GeoJSON, + GeoJSONPoint, + GeoJSONMultiPoint, + GeoJSONLineString, + GeoJSONMultiLineString, + GeoJSONPolygon, + GeoJSONMultiPolygon +} from "@mapbox/geojson-types"; +import {classifyRings, updateBBox, boxWithinBox, pointWithinPolygon, segmentIntersectSegment, CheapRuler} from '../../util/geometry_util.js'; +import type {GeometryPoint} from '../../util/geometry_util.js'; +import Point from "@mapbox/point-geometry"; +import Queue from "tinyqueue"; + +type DistanceGeometry = + | GeoJSONPoint + | GeoJSONMultiPoint + | GeoJSONLineString + | GeoJSONMultiLineString + | GeoJSONPolygon + | GeoJSONMultiPolygon; + +// Inclusive index range for multipoint or linestring container +type IndexRange = [number, number]; +type DistPair = { dist: number, range1: IndexRange, range2: IndexRange }; + +const EXTENT = 8192; +const MIN_POINT_SIZE = 100; +const MIN_LINE_POINT_SIZE = 50; + +function getRangeSize(range: IndexRange) { + return range[1] - range[0] + 1; +} + +function isRangeSafe(range: IndexRange, threshold: number) { + return range[1] >= range[0] && range[1] < threshold; +} + +// Split the point set(points or linestring) into two halves, using IndexRange to do in-place splitting. +// If geometry is a line, the last point(here is the second index) of range1 needs to be included as the first point(here is the first index) of range2. +// If geometry are points, just split the points equally(if possible) into two new point sets(here are two index ranges). +function splitRange(range: IndexRange, isLine: boolean) { + if (range[0] > range[1]) return [null, null]; + const size = getRangeSize(range); + if (isLine) { + if (size === 2) { + return [range, null]; + } + const size1 = Math.floor(size / 2); + const range1: IndexRange = [range[0], range[0] + size1]; + const range2: IndexRange = [range[0] + size1, range[1]]; + return [range1, range2]; + } else { + if (size === 1) { + return [range, null]; + } + const size1 = Math.floor(size / 2) - 1; + const range1: IndexRange = [range[0], range[0] + size1]; + const range2: IndexRange = [range[0] + size1 + 1, range[1]]; + return [range1, range2]; + } +} + +function getBBox(pointSets: Array, range: IndexRange) { + const bbox = [Infinity, Infinity, -Infinity, -Infinity]; + if (!isRangeSafe(range, pointSets.length)) return bbox; + for (let i = range[0]; i <= range[1]; ++i) { + updateBBox(bbox, pointSets[i]); + } + return bbox; +} + +function getPolygonBBox(polygon: Array>) { + const bbox = [Infinity, Infinity, -Infinity, -Infinity]; + for (let i = 0; i < polygon.length; ++i) { + for (let j = 0; j < polygon[i].length; ++j) { + updateBBox(bbox, polygon[i][j]); + } + } + return bbox; +} + +// Calculate the distance between two bounding boxes. +// Calculate the delta in x and y direction, and use two fake points {0.0, 0.0} and {dx, dy} to calculate the distance. +// Distance will be 0.0 if bounding box are overlapping. +function bboxToBBoxDistance(bbox1, bbox2, ruler) { + let dx = 0.0; + let dy = 0.0; + // bbox1 in left side + if (bbox1[2] < bbox2[0]) { + dx = bbox2[0] - bbox1[2]; + } + // bbox1 in right side + if (bbox1[0] > bbox2[2]) { + dx = bbox1[0] - bbox2[2]; + } + // bbox1 in above side + if (bbox1[1] > bbox2[3]) { + dy = bbox1[1] - bbox2[3]; + } + // bbox1 in down side + if (bbox1[3] < bbox2[1]) { + dy = bbox2[1] - bbox1[3]; + } + return ruler.distance([0.0, 0.0], [dx, dy]); +} + +function lngFromMercatorX(x: number) { + return x * 360 - 180; +} + +function latFromMercatorY(y: number) { + const y2 = 180 - y * 360; + return (360 / Math.PI) * Math.atan(Math.exp((y2 * Math.PI) / 180)) - 90; +} + +function getLngLatPoint(coord: Point, canonical) { + const tilesAtZoom = Math.pow(2, canonical.z); + const x = (coord.x / EXTENT + canonical.x) / tilesAtZoom; + const y = (coord.y / EXTENT + canonical.y) / tilesAtZoom; + return [lngFromMercatorX(x), latFromMercatorY(y)]; +} + +function getLngLatPoints(coordinates, canonical) { + const coords = []; + for (let i = 0; i < coordinates.length; ++i) { + coords.push(getLngLatPoint(coordinates[i], canonical)); + } + return coords; +} + +function pointToLineDistance(point, line, ruler) { + const nearestPoint = ruler.pointOnLine(line, point).point; + return ruler.distance(point, nearestPoint); +} + +function pointsToLineDistance(points, rangeA, line, rangeB, ruler) { + const subLine = line.slice(rangeB[0], rangeB[1] + 1); + let dist = Infinity; + for (let i = rangeA[0]; i <= rangeA[1]; ++i) { + if ((dist = Math.min(dist, pointToLineDistance(points[i], subLine, ruler))) === 0.0) return 0.0; + } + return dist; +} + +// precondition is two segments are not intersecting with each other +function segmentToSegmentDistance(p1, p2, q1, q2, ruler) { + const dist1 = Math.min( + ruler.pointToSegmentDistance(p1, q1, q2), + ruler.pointToSegmentDistance(p2, q1, q2) + ); + const dist2 = Math.min( + ruler.pointToSegmentDistance(q1, p1, p2), + ruler.pointToSegmentDistance(q2, p1, p2) + ); + + return Math.min(dist1, dist2); +} + +function lineToLineDistance(line1, range1, line2, range2, ruler) { + let dist = Infinity; + for (let i = range1[0]; i < range1[1]; ++i) { + for (let j = range2[0]; j < range2[1]; ++j) { + if (segmentIntersectSegment(line1[i], line1[i + 1], line2[j], line2[j + 1])) return 0.0; + dist = Math.min(dist, segmentToSegmentDistance(line1[i], line1[i + 1], line2[j], line2[j + 1], ruler)); + } + } + return dist; +} + +function pointsToPointsDistance(pointSet1, range1, pointSet2, range2, ruler) { + let dist = Infinity; + for (let i = range1[0]; i <= range1[1]; ++i) { + for (let j = range2[0]; j <= range2[1]; ++j) { + if ((dist = Math.min(dist, ruler.distance(pointSet1[i], pointSet2[j]))) === 0.0) return dist; + } + } + return dist; +} + +function pointToPolygonDistance(point, polygon, ruler) { + if (pointWithinPolygon(point, polygon, true /*trueOnBoundary*/)) return 0.0; + let dist = Infinity; + for (const ring of polygon) { + if ((dist = Math.min(dist, pointToLineDistance(point, ring, ruler))) === 0.0) return dist; + } + return dist; +} + +function lineToPolygonDistance(line, range, polygon, ruler) { + for (let i = range[0]; i <= range[1]; ++i) { + if (pointWithinPolygon(line[i], polygon, true /*trueOnBoundary*/)) return 0.0; + } + let dist = Infinity; + for (let i = range[0]; i < range[1]; ++i) { + for (const ring of polygon) { + for (let j = 0, len = ring.length, k = len - 1; j < len; k = j++) { + if (segmentIntersectSegment(line[i], line[i + 1], ring[k], ring[j])) return 0.0; + dist = Math.min(dist, segmentToSegmentDistance(line[i], line[i + 1], ring[k], ring[j], ruler)); + } + } + } + return dist; +} + +function polygonIntersect(polygon1, polygon2) { + for (const ring of polygon1) { + for (let i = 0; i <= ring.length - 1; ++i) { + if (pointWithinPolygon(ring[i], polygon2, true /*trueOnBoundary*/)) return true; + } + } + return false; +} + +function polygonToPolygonDistance(polygon1, polygon2, ruler, currentMiniDist = Infinity) { + const bbox1 = getPolygonBBox(polygon1); + const bbox2 = getPolygonBBox(polygon2); + if (currentMiniDist !== Infinity && bboxToBBoxDistance(bbox1, bbox2, ruler) >= currentMiniDist) { + return currentMiniDist; + } + if (boxWithinBox(bbox1, bbox2)) { + if (polygonIntersect(polygon1, polygon2)) return 0.0; + } else if (polygonIntersect(polygon2, polygon1)) { + return 0.0; + } + let dist = currentMiniDist; + for (const ring1 of polygon1) { + for (let i = 0, len1 = ring1.length, l = len1 - 1; i < len1; l = i++) { + for (const ring2 of polygon2) { + for (let j = 0, len2 = ring2.length, k = len2 - 1; j < len2; k = j++) { + if (segmentIntersectSegment(ring1[l], ring1[i], ring2[k], ring2[j])) return 0.0; + dist = Math.min(dist, segmentToSegmentDistance(ring1[l], ring1[i], ring2[k], ring2[j], ruler)); + } + } + } + } + return dist; +} + +function updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, r1, r2) { + if (r1 === null || r2 === null) return; + const tempDist = bboxToBBoxDistance(getBBox(pointSet1, r1), getBBox(pointSet2, r2), ruler); + // Insert new pair to the queue if the bbox distance is less than miniDist, the pair with biggest distance will be at the top + if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: r1, range2: r2}); +} + +function compareMax(a, b) { + return b.dist - a.dist; +} + +// Divide and conquer, the time complexity is O(n*lgn), faster than Brute force O(n*n) +// Most of the time, use index for in-place processing. +function pointSetToPolygonDistance(pointSets, isLine, polygon, ruler, currentMiniDist = Infinity) { + let miniDist = Math.min(ruler.distance(pointSets[0], polygon[0][0]), currentMiniDist); + if (miniDist === 0.0) return miniDist; + const initialDistPair: DistPair = { + dist: 0, + range1: [0, pointSets.length - 1], + range2: [0, 0] + }; + const distQueue = new Queue([initialDistPair], compareMax); + + const setThreshold = isLine ? MIN_LINE_POINT_SIZE : MIN_POINT_SIZE; + const polyBBox = getPolygonBBox(polygon); + + while (distQueue.length) { + const distPair = distQueue.pop(); + if (distPair.dist >= miniDist) continue; + const range = distPair.range1; + // In case the set size are relatively small, we could use brute-force directly + if (getRangeSize(range) <= setThreshold) { + if (!isRangeSafe(range, pointSets.length)) return NaN; + if (isLine) { + const tempDist = lineToPolygonDistance(pointSets, range, polygon, ruler); + if ((miniDist = Math.min(miniDist, tempDist)) === 0.0) return miniDist; + } else { + for (let i = range[0]; i <= range[1]; ++i) { + const tempDist = pointToPolygonDistance(pointSets[i], polygon, ruler); + if ((miniDist = Math.min(miniDist, tempDist)) === 0.0) return miniDist; + } + } + } else { + const newRanges = splitRange(range, isLine); + if (newRanges[0] !== null) { + const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[0]), polyBBox, ruler); + if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: newRanges[0], range2: [0, 0]}); + } + if (newRanges[1] !== null) { + const tempDist = bboxToBBoxDistance(getBBox(pointSets, newRanges[1]), polyBBox, ruler); + if (tempDist < miniDist) distQueue.push({dist: tempDist, range1: newRanges[1], range2: [0, 0]}); + } + } + } + return miniDist; +} + +function pointSetsDistance(pointSet1: Array, isLine1: boolean, pointSet2: Array, isLine2: boolean, ruler, currentMiniDist = Infinity) { + let miniDist = Math.min(currentMiniDist, ruler.distance(pointSet1[0], pointSet2[0])); + if (miniDist === 0.0) return miniDist; + const initialDistPair: DistPair = { + dist: 0, + range1: [0, pointSet1.length - 1], + range2: [0, pointSet2.length - 1] + }; + const distQueue = new Queue([initialDistPair], compareMax); + + const set1Threshold = isLine1 ? MIN_LINE_POINT_SIZE : MIN_POINT_SIZE; + const set2Threshold = isLine2 ? MIN_LINE_POINT_SIZE : MIN_POINT_SIZE; + + while (distQueue.length) { + const distPair = distQueue.pop(); + if (distPair.dist >= miniDist) continue; + const rangeA = distPair.range1; + const rangeB = distPair.range2; + // In case the set size are relatively small, we could use brute-force directly + if (getRangeSize(rangeA) <= set1Threshold && getRangeSize(rangeB) <= set2Threshold) { + if (!isRangeSafe(rangeA, pointSet1.length) || !isRangeSafe(rangeB, pointSet2.length)) { + return NaN; + } + if (isLine1 && isLine2) { + miniDist = Math.min(miniDist, lineToLineDistance(pointSet1, rangeA, pointSet2, rangeB, ruler)); + } else if (!isLine1 && !isLine2) { + miniDist = Math.min(miniDist, pointsToPointsDistance(pointSet1, rangeA, pointSet2, rangeB, ruler)); + } else if (isLine1 && !isLine2) { + miniDist = Math.min(miniDist, pointsToLineDistance(pointSet2, rangeB, pointSet1, rangeA, ruler)); + } else if (!isLine1 && isLine2) { + miniDist = Math.min(miniDist, pointsToLineDistance(pointSet1, rangeA, pointSet2, rangeB, ruler)); + } + if (miniDist === 0.0) return miniDist; + } else { + const newRangesA = splitRange(rangeA, isLine1); + const newRangesB = splitRange(rangeB, isLine2); + updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, newRangesA[0], newRangesB[0]); + updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, newRangesA[0], newRangesB[1]); + updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, newRangesA[1], newRangesB[0]); + updateQueue(distQueue, miniDist, ruler, pointSet1, pointSet2, newRangesA[1], newRangesB[1]); + } + } + return miniDist; +} + +function pointSetToLinesDistance(pointSet, isLine, lines, ruler, currentMiniDist = Infinity) { + let dist = currentMiniDist; + const bbox1 = getBBox(pointSet, [0, pointSet.length - 1]); + for (const line of lines) { + if (dist !== Infinity && bboxToBBoxDistance(bbox1, getBBox(line, [0, line.length - 1]), ruler) >= dist) continue; + dist = Math.min(dist, pointSetsDistance(pointSet, isLine, line, true /*isLine*/, ruler, dist)); + if (dist === 0.0) return dist; + } + return dist; +} + +function pointSetToPolygonsDistance(points, isLine, polygons, ruler, currentMiniDist = Infinity) { + let dist = currentMiniDist; + const bbox1 = getBBox(points, [0, points.length - 1]); + for (const polygon of polygons) { + if (dist !== Infinity && bboxToBBoxDistance(bbox1, getPolygonBBox(polygon), ruler) >= dist) continue; + const tempDist = pointSetToPolygonDistance(points, isLine, polygon, ruler, dist); + if (isNaN(tempDist)) return tempDist; + if ((dist = Math.min(dist, tempDist)) === 0.0) return dist; + } + return dist; +} + +function polygonsToPolygonsDistance(polygons1, polygons2, ruler) { + let dist = Infinity; + for (const polygon1 of polygons1) { + for (const polygon2 of polygons2) { + const tempDist = polygonToPolygonDistance(polygon1, polygon2, ruler, dist); + if (isNaN(tempDist)) return tempDist; + if ((dist = Math.min(dist, tempDist)) === 0.0) return dist; + } + } + return dist; +} + +function pointsToGeometryDistance(ctx: EvaluationContext, geometry: DistanceGeometry) { + const lngLatPoints = []; + for (const points of ctx.geometry()) { + for (const point of points) { + lngLatPoints.push(getLngLatPoint(point, ctx.canonicalID())); + } + } + const ruler = new CheapRuler(lngLatPoints[0][1], 'meters'); + if (geometry.type === 'Point' || geometry.type === 'MultiPoint' || geometry.type === 'LineString') { + return pointSetsDistance(lngLatPoints, false /*isLine*/, + geometry.type === "Point" ? [geometry.coordinates] : geometry.coordinates, + geometry.type === 'LineString' /*isLine*/, ruler); + } + if (geometry.type === 'MultiLineString') { + return pointSetToLinesDistance(lngLatPoints, false /*isLine*/, geometry.coordinates, ruler); + } + if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') { + return pointSetToPolygonsDistance(lngLatPoints, false /*isLine*/, + geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates, ruler); + } + return null; +} + +function linesToGeometryDistance(ctx: EvaluationContext, geometry: DistanceGeometry) { + const lngLatLines = []; + for (const line of ctx.geometry()) { + const lngLatLine = []; + for (const point of line) { + lngLatLine.push(getLngLatPoint(point, ctx.canonicalID())); + } + lngLatLines.push(lngLatLine); + } + const ruler = new CheapRuler(lngLatLines[0][0][1], 'meters'); + if (geometry.type === 'Point' || geometry.type === 'MultiPoint' || geometry.type === 'LineString') { + return pointSetToLinesDistance( + geometry.type === "Point" ? [geometry.coordinates] : geometry.coordinates, + geometry.type === 'LineString' /*isLine*/, lngLatLines, ruler); + } + if (geometry.type === 'MultiLineString') { + let dist = Infinity; + for (let i = 0; i < geometry.coordinates.length; i++) { + const tempDist = pointSetToLinesDistance(geometry.coordinates[i], true /*isLine*/, lngLatLines, ruler, dist); + if (isNaN(tempDist)) return tempDist; + if ((dist = Math.min(dist, tempDist)) === 0.0) return dist; + } + return dist; + } + if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') { + let dist = Infinity; + for (let i = 0; i < lngLatLines.length; i++) { + const tempDist = pointSetToPolygonsDistance(lngLatLines[i], true /*isLine*/, + geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates, + ruler, dist); + if (isNaN(tempDist)) return tempDist; + if ((dist = Math.min(dist, tempDist)) === 0.0) return dist; + } + return dist; + } + return null; +} + +function polygonsToGeometryDistance(ctx: EvaluationContext, geometry: DistanceGeometry) { + const lngLatPolygons = []; + for (const polygon of classifyRings(ctx.geometry(), 0)) { + const lngLatPolygon = []; + for (let i = 0; i < polygon.length; ++i) { + lngLatPolygon.push(getLngLatPoints(polygon[i], ctx.canonicalID())); + } + lngLatPolygons.push(lngLatPolygon); + } + const ruler = new CheapRuler(lngLatPolygons[0][0][0][1], 'meters'); + if (geometry.type === 'Point' || geometry.type === 'MultiPoint' || geometry.type === 'LineString') { + return pointSetToPolygonsDistance( + geometry.type === "Point" ? [geometry.coordinates] : geometry.coordinates, + geometry.type === 'LineString' /*isLine*/, lngLatPolygons, ruler); + } + if (geometry.type === 'MultiLineString') { + let dist = Infinity; + for (let i = 0; i < geometry.coordinates.length; i++) { + const tempDist = pointSetToPolygonsDistance(geometry.coordinates[i], true /*isLine*/, lngLatPolygons, ruler, dist); + if (isNaN(tempDist)) return tempDist; + if ((dist = Math.min(dist, tempDist)) === 0.0) return dist; + } + return dist; + } + if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') { + return polygonsToPolygonsDistance( + geometry.type === "Polygon" ? [geometry.coordinates] : geometry.coordinates, + lngLatPolygons, ruler); + } + return null; +} + +function isTypeValid(type) { + return ( + type === "Point" || + type === "MultiPoint" || + type === "LineString" || + type === "MultiLineString" || + type === "Polygon" || + type === "MultiPolygon" + ); +} +class Distance implements Expression { + type: Type; + geojson: GeoJSON; + geometries: DistanceGeometry; + + constructor(geojson: GeoJSON, geometries: DistanceGeometry) { + this.type = NumberType; + this.geojson = geojson; + this.geometries = geometries; + } + + static parse(args: $ReadOnlyArray, context: ParsingContext) { + if (args.length !== 2) { + return context.error( + `'distance' expression requires either one argument, but found ' ${args.length - + 1} instead.` + ); + } + if (isValue(args[1])) { + const geojson = (args[1]: Object); + if (geojson.type === 'FeatureCollection') { + for (let i = 0; i < geojson.features.length; ++i) { + if (isTypeValid(geojson.features[i].geometry.type)) { + return new Distance(geojson, geojson.features[i].geometry); + } + } + } else if (geojson.type === 'Feature') { + if (isTypeValid(geojson.geometry.type)) { + return new Distance(geojson, geojson.geometry); + } + } else if (isTypeValid(geojson.type)) { + return new Distance(geojson, geojson); + } + } + return context.error( + "'distance' expression needs to be an array with format [\'Distance\', GeoJSONObj]." + ); + } + + evaluate(ctx: EvaluationContext) { + if (ctx.geometry() !== null && ctx.canonicalID() !== null) { + if (ctx.geometryType() === 'Point') { + return pointsToGeometryDistance(ctx, this.geometries); + } + if (ctx.geometryType() === 'LineString') { + return linesToGeometryDistance(ctx, this.geometries); + } + if (ctx.geometryType() === 'Polygon') { + return polygonsToGeometryDistance(ctx, this.geometries); + } + } + return null; + } + + eachChild() {} + + outputDefined(): boolean { + return true; + } + + serialize(): Array { + return ['distance', this.geojson]; + } +} + +export default Distance; diff --git a/src/style-spec/expression/definitions/index.js b/src/style-spec/expression/definitions/index.js index 434cf776f1f..fc7a44f5b28 100644 --- a/src/style-spec/expression/definitions/index.js +++ b/src/style-spec/expression/definitions/index.js @@ -45,6 +45,7 @@ import FormatExpression from './format.js'; import ImageExpression from './image.js'; import Length from './length.js'; import Within from './within.js'; +import Distance from './distance.js'; import type {Varargs} from '../compound_expression.js'; import type {ExpressionRegistry} from '../expression.js'; @@ -85,7 +86,8 @@ const expressions: ExpressionRegistry = { 'to-number': Coercion, 'to-string': Coercion, 'var': Var, - 'within': Within + 'within': Within, + 'distance': Distance }; function rgba(ctx, [r, g, b, a]) { diff --git a/src/style-spec/expression/definitions/within.js b/src/style-spec/expression/definitions/within.js index c337c974409..4e5610b145c 100644 --- a/src/style-spec/expression/definitions/within.js +++ b/src/style-spec/expression/definitions/within.js @@ -7,22 +7,13 @@ import type {Expression} from '../expression.js'; import type ParsingContext from '../parsing_context.js'; import type EvaluationContext from '../evaluation_context.js'; import type {GeoJSON, GeoJSONPolygon, GeoJSONMultiPolygon} from '@mapbox/geojson-types'; -import Point from '@mapbox/point-geometry'; import type {CanonicalTileID} from '../../../source/tile_id.js'; +import {updateBBox, boxWithinBox, pointWithinPolygon, segmentIntersectSegment} from '../../util/geometry_util.js'; type GeoJSONPolygons =| GeoJSONPolygon | GeoJSONMultiPolygon; -// minX, minY, maxX, maxY -type BBox = [number, number, number, number]; const EXTENT = 8192; -function updateBBox(bbox: BBox, coord: Point) { - bbox[0] = Math.min(bbox[0], coord[0]); - bbox[1] = Math.min(bbox[1], coord[1]); - bbox[2] = Math.max(bbox[2], coord[0]); - bbox[3] = Math.max(bbox[3], coord[1]); -} - function mercatorXfromLng(lng: number) { return (180 + lng) / 360; } @@ -31,14 +22,6 @@ function mercatorYfromLat(lat: number) { return (180 - (180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + lat * Math.PI / 360)))) / 360; } -function boxWithinBox(bbox1: BBox, bbox2: BBox) { - 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; -} - function getTileCoordinates(p, canonical: CanonicalTileID) { const x = mercatorXfromLng(p[0]); const y = mercatorYfromLat(p[1]); @@ -46,31 +29,6 @@ function getTileCoordinates(p, canonical: CanonicalTileID) { return [Math.round(x * tilesAtZoom * EXTENT), Math.round(y * tilesAtZoom * EXTENT)]; } -function onBoundary(p, p1, p2) { - const x1 = p[0] - p1[0]; - const y1 = p[1] - p1[1]; - const x2 = p[0] - p2[0]; - const y2 = p[1] - p2[1]; - return (x1 * y2 - x2 * y1 === 0) && (x1 * x2 <= 0) && (y1 * y2 <= 0); -} - -function rayIntersect(p, p1, p2) { - return ((p1[1] > p[1]) !== (p2[1] > p[1])) && (p[0] < (p2[0] - p1[0]) * (p[1] - p1[1]) / (p2[1] - p1[1]) + p1[0]); -} - -// ray casting algorithm for detecting if point is in polygon -function pointWithinPolygon(point, rings) { - let inside = false; - for (let i = 0, len = rings.length; i < len; i++) { - const ring = rings[i]; - for (let j = 0, len2 = ring.length; j < len2 - 1; j++) { - if (onBoundary(point, ring[j], ring[j + 1])) return false; - if (rayIntersect(point, ring[j], ring[j + 1])) inside = !inside; - } - } - return inside; -} - function pointWithinPolygons(point, polygons) { for (let i = 0; i < polygons.length; i++) { if (pointWithinPolygon(point, polygons[i])) return true; @@ -78,45 +36,13 @@ function pointWithinPolygons(point, polygons) { return false; } -function perp(v1, v2) { - return (v1[0] * v2[1] - v1[1] * v2[0]); -} - -// check if p1 and p2 are in different sides of line segment q1->q2 -function twoSided(p1, p2, q1, q2) { - // q1->p1 (x1, y1), q1->p2 (x2, y2), q1->q2 (x3, y3) - const x1 = p1[0] - q1[0]; - const y1 = p1[1] - q1[1]; - const x2 = p2[0] - q1[0]; - const y2 = p2[1] - q1[1]; - const x3 = q2[0] - q1[0]; - const y3 = q2[1] - q1[1]; - const det1 = (x1 * y3 - x3 * y1); - const det2 = (x2 * y3 - x3 * y2); - if ((det1 > 0 && det2 < 0) || (det1 < 0 && det2 > 0)) return true; - return false; -} -// a, b are end points for line segment1, c and d are end points for line segment2 -function lineIntersectLine(a, b, c, d) { - // check if two segments are parallel or not - // precondition is end point a, b is inside polygon, if line a->b is - // parallel to polygon edge c->d, then a->b won't intersect with c->d - const vectorP = [b[0] - a[0], b[1] - a[1]]; - const vectorQ = [d[0] - c[0], d[1] - c[1]]; - if (perp(vectorQ, vectorP) === 0) return false; - - // If lines are intersecting with each other, the relative location should be: - // a and b lie in different sides of segment c->d - // c and d lie in different sides of segment a->b - if (twoSided(a, b, c, d) && twoSided(c, d, a, b)) return true; - return false; -} - function lineIntersectPolygon(p1, p2, polygon) { for (const ring of polygon) { // loop through every edge of the ring - for (let j = 0; j < ring.length - 1; ++j) { - if (lineIntersectLine(p1, p2, ring[j], ring[j + 1])) { + for (let j = 0, len = ring.length, k = len - 1; j < len; k = j++) { + const q1 = ring[k]; + const q2 = ring[j]; + if (segmentIntersectSegment(p1, p2, q1, q2)) { return true; } } diff --git a/src/style-spec/expression/is_constant.js b/src/style-spec/expression/is_constant.js index 26724122fb6..991c97c3947 100644 --- a/src/style-spec/expression/is_constant.js +++ b/src/style-spec/expression/is_constant.js @@ -2,6 +2,7 @@ import CompoundExpression from './compound_expression.js'; import Within from './definitions/within.js'; +import Distance from './definitions/distance.js'; import type {Expression} from './expression.js'; function isFeatureConstant(e: Expression) { @@ -27,6 +28,10 @@ function isFeatureConstant(e: Expression) { return false; } + if (e instanceof Distance) { + return false; + } + let result = true; e.eachChild(arg => { if (result && !isFeatureConstant(arg)) { result = false; } diff --git a/src/style-spec/expression/parsing_context.js b/src/style-spec/expression/parsing_context.js index 60df487c5ae..1f364144f44 100644 --- a/src/style-spec/expression/parsing_context.js +++ b/src/style-spec/expression/parsing_context.js @@ -10,6 +10,7 @@ import EvaluationContext from './evaluation_context.js'; import CompoundExpression from './compound_expression.js'; import CollatorExpression from './definitions/collator.js'; import Within from './definitions/within.js'; +import Distance from './definitions/distance.js'; import {isGlobalPropertyConstant, isFeatureConstant} from './is_constant.js'; import Var from './definitions/var.js'; @@ -204,6 +205,8 @@ function isConstant(expression: Expression) { return false; } else if (expression instanceof Within) { return false; + } else if (expression instanceof Distance) { + return false; } const isTypeAnnotation = expression instanceof Coercion || diff --git a/src/style-spec/feature_filter/index.js b/src/style-spec/feature_filter/index.js index 9868c32bf09..89da053a363 100644 --- a/src/style-spec/feature_filter/index.js +++ b/src/style-spec/feature_filter/index.js @@ -98,7 +98,7 @@ function compare(a, b) { function geometryNeeded(filter) { if (!Array.isArray(filter)) return false; - if (filter[0] === 'within') return true; + if (filter[0] === 'within' || filter[0] === 'distance') return true; for (let index = 1; index < filter.length; index++) { if (geometryNeeded(filter[index])) return true; } @@ -123,7 +123,6 @@ function convertFilter(filter: ?Array): mixed { op === '!in' ? convertNegation(convertInOp(filter[1], filter.slice(2))) : op === 'has' ? convertHasOp(filter[1]) : op === '!has' ? convertNegation(convertHasOp(filter[1])) : - op === 'within' ? filter : true; return converted; } diff --git a/src/style-spec/package.json b/src/style-spec/package.json index fb53df1a28d..d389871362e 100644 --- a/src/style-spec/package.json +++ b/src/style-spec/package.json @@ -45,7 +45,9 @@ "json-stringify-pretty-compact": "^2.0.0", "minimist": "^1.2.5", "rw": "^1.3.3", - "sort-object": "^0.3.2" + "sort-object": "^0.3.2", + "quickselect": "^2.0.0", + "tinyqueue": "^2.0.3" }, "sideEffects": false } diff --git a/src/style-spec/reference/v8.json b/src/style-spec/reference/v8.json index 7d3fe7e651f..a6ae2bc4b92 100644 --- a/src/style-spec/reference/v8.json +++ b/src/style-spec/reference/v8.json @@ -2541,9 +2541,6 @@ }, "!has": { "doc": "`[\"!has\", key]` `feature[key]` does not exist" - }, - "within": { - "doc": "`[\"within\", object]` feature geometry is within object geometry" } }, "doc": "The filter operator." @@ -3475,6 +3472,7 @@ "group": "Math", "sdk-support": { "basic functionality": { + "js": "2.3.0", "android": "9.2.0", "ios": "5.9.0", "macos": "0.16.0" diff --git a/src/style-spec/util/geometry_util.js b/src/style-spec/util/geometry_util.js new file mode 100644 index 00000000000..5698b378404 --- /dev/null +++ b/src/style-spec/util/geometry_util.js @@ -0,0 +1,322 @@ +// @flow + +import quickselect from 'quickselect'; + +import type Point from '@mapbox/point-geometry'; + +export type GeometryPoint = [number, number] | [number, number, number]; +/** + * Returns the signed area for the polygon ring. Postive areas are exterior rings and + * have a clockwise winding. Negative areas are interior rings and have a counter clockwise + * ordering. + * + * @private + * @param ring Exterior or interior ring + */ +function calculateSignedArea(ring: Array): number { + let sum = 0; + for (let i = 0, len = ring.length, j = len - 1, p1, p2; i < len; j = i++) { + p1 = ring[i]; + p2 = ring[j]; + sum += (p2.x - p1.x) * (p1.y + p2.y); + } + return sum; +} + +function compareAreas(a, b) { + return b.area - a.area; +} + +// classifies an array of rings into polygons with outer rings and holes +export function classifyRings(rings: Array>, maxRings: number) { + const len = rings.length; + + if (len <= 1) return [rings]; + + const polygons = []; + let polygon, + ccw; + + for (let i = 0; i < len; i++) { + const area = calculateSignedArea(rings[i]); + if (area === 0) continue; + + (rings[i]: any).area = Math.abs(area); + + if (ccw === undefined) ccw = area < 0; + + if (ccw === area < 0) { + if (polygon) polygons.push(polygon); + polygon = [rings[i]]; + + } else { + (polygon: any).push(rings[i]); + } + } + if (polygon) polygons.push(polygon); + + // Earcut performance degrades with the # of rings in a polygon. For this + // reason, we limit strip out all but the `maxRings` largest rings. + if (maxRings > 1) { + for (let j = 0; j < polygons.length; j++) { + if (polygons[j].length <= maxRings) continue; + quickselect(polygons[j], maxRings, 1, polygons[j].length - 1, compareAreas); + polygons[j] = polygons[j].slice(0, maxRings); + } + } + + return polygons; +} + +// minX, minY, maxX, maxY +type BBox = [number, number, number, number]; + +export function updateBBox(bbox: BBox, coord: Point) { + bbox[0] = Math.min(bbox[0], coord[0]); + bbox[1] = Math.min(bbox[1], coord[1]); + bbox[2] = Math.max(bbox[2], coord[0]); + bbox[3] = Math.max(bbox[3], coord[1]); +} + +export function boxWithinBox(bbox1: BBox, bbox2: BBox) { + 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; +} + +function onBoundary(p: GeometryPoint, p1: GeometryPoint, p2: GeometryPoint) { + const x1 = p[0] - p1[0]; + const y1 = p[1] - p1[1]; + const x2 = p[0] - p2[0]; + const y2 = p[1] - p2[1]; + return (x1 * y2 - x2 * y1 === 0) && (x1 * x2 <= 0) && (y1 * y2 <= 0); +} + +function rayIntersect(p: GeometryPoint, p1: GeometryPoint, p2: GeometryPoint) { + return ((p1[1] > p[1]) !== (p2[1] > p[1])) && (p[0] < (p2[0] - p1[0]) * (p[1] - p1[1]) / (p2[1] - p1[1]) + p1[0]); +} + +// ray casting algorithm for detecting if point is in polygon +export function pointWithinPolygon(point: GeometryPoint, rings: Array>, trueOnBoundary: boolean = false) { + let inside = false; + for (let i = 0, len = rings.length; i < len; i++) { + const ring = rings[i]; + for (let j = 0, len2 = ring.length, k = len2 - 1; j < len2; k = j++) { + const q1 = ring[k]; + const q2 = ring[j]; + if (onBoundary(point, q1, q2)) return trueOnBoundary; + if (rayIntersect(point, q1, q2)) inside = !inside; + } + } + return inside; +} + +function perp(v1: GeometryPoint, v2: GeometryPoint) { + return v1[0] * v2[1] - v1[1] * v2[0]; +} + +// check if p1 and p2 are in different sides of line segment q1->q2 +function twoSided(p1: GeometryPoint, p2: GeometryPoint, q1: GeometryPoint, q2: GeometryPoint) { + // q1->p1 (x1, y1), q1->p2 (x2, y2), q1->q2 (x3, y3) + const x1 = p1[0] - q1[0]; + const y1 = p1[1] - q1[1]; + const x2 = p2[0] - q1[0]; + const y2 = p2[1] - q1[1]; + const x3 = q2[0] - q1[0]; + const y3 = q2[1] - q1[1]; + const det1 = x1 * y3 - x3 * y1; + const det2 = x2 * y3 - x3 * y2; + if ((det1 > 0 && det2 < 0) || (det1 < 0 && det2 > 0)) return true; + return false; +} +// a, b are end points for line segment1, c and d are end points for line segment2 +export function segmentIntersectSegment(a: GeometryPoint, b: GeometryPoint, c: GeometryPoint, d: GeometryPoint) { + // check if two segments are parallel or not + // precondition is end point a, b is inside polygon, if line a->b is + // parallel to polygon edge c->d, then a->b won't intersect with c->d + const vectorP = [b[0] - a[0], b[1] - a[1]]; + const vectorQ = [d[0] - c[0], d[1] - c[1]]; + if (perp(vectorQ, vectorP) === 0) return false; + + // If lines are intersecting with each other, the relative location should be: + // a and b lie in different sides of segment c->d + // c and d lie in different sides of segment a->b + if (twoSided(a, b, c, d) && twoSided(c, d, a, b)) return true; + return false; +} + +// normalize a degree value into [-180..180] range +function wrap(deg) { + while (deg < -180) deg += 360; + while (deg > 180) deg -= 360; + return deg; +} + +const factors = { + kilometers: 1, + miles: 1000 / 1609.344, + nauticalmiles: 1000 / 1852, + meters: 1000, + metres: 1000, + yards: 1000 / 0.9144, + feet: 1000 / 0.3048, + inches: 1000 / 0.0254 +}; + +// Values that define WGS84 ellipsoid model of the Earth +const RE = 6378.137; // equatorial radius +const FE = 1 / 298.257223563; // flattening + +const E2 = FE * (2 - FE); +const RAD = Math.PI / 180; + +/** + * A collection of very fast approximations to common geodesic measurements. Useful for performance-sensitive code that measures things on a city scale. + * This is the slim version of https://github.com/mapbox/cheap-ruler + * @param {number} lat latitude + * @param {string} [units='kilometers'] + * @returns {CheapRuler} + * @example + * const ruler = cheapRuler(35.05, 'miles'); + * //=ruler + */ +export class CheapRuler { + kx: number; + ky: number; + /** + * Creates a ruler instance for very fast approximations to common geodesic measurements around a certain latitude. + * + * @param {number} lat latitude + * @param {string} [units='kilometers'] + * @returns {CheapRuler} + * @example + * const ruler = cheapRuler(35.05, 'miles'); + * //=ruler + */ + constructor(lat: number, units: string) { + if (lat === undefined) throw new Error('No latitude given.'); + if (units && !factors[units]) throw new Error(`Unknown unit ${units}. Use one of: ${Object.keys(factors).join(', ')}`); + + // Curvature formulas from https://en.wikipedia.org/wiki/Earth_radius#Meridional + const m = RAD * RE * (units ? factors[units] : 1); + const coslat = Math.cos(lat * RAD); + const w2 = 1 / (1 - E2 * (1 - coslat * coslat)); + const w = Math.sqrt(w2); + + // multipliers for converting longitude and latitude degrees into distance + this.kx = m * w * coslat; // based on normal radius of curvature + this.ky = m * w * w2 * (1 - E2); // based on meridonal radius of curvature + } + + /** + * Given two points of the form [longitude, latitude], returns the distance. + * + * @param {GeometryPoint} a point [longitude, latitude] + * @param {GeometryPoint} b point [longitude, latitude] + * @returns {number} distance + * @example + * const distance = ruler.distance([30.5, 50.5], [30.51, 50.49]); + * //=distance + */ + distance(a: GeometryPoint, b: GeometryPoint): number { + const dx = wrap(a[0] - b[0]) * this.kx; + const dy = (a[1] - b[1]) * this.ky; + return Math.sqrt(dx * dx + dy * dy); + } + + /** + * Returns the distance from a point `p` to a line segment `a` to `b`. + * + * @param {GeometryPoint} p point [longitude, latitude] + * @param {GeometryPoint} a segment point 1 [longitude, latitude] + * @param {GeometryPoint} b segment point 2 [longitude, latitude] + * @returns {number} distance + * @example + * const distance = ruler.pointToSegmentDistance([-67.04, 50.5], [-67.05, 50.57], [-67.03, 50.54]); + * //=distance + */ + pointToSegmentDistance(p: GeometryPoint, a: GeometryPoint, b: GeometryPoint): number { + let [x, y] = a; + let dx = wrap(b[0] - x) * this.kx; + let dy = (b[1] - y) * this.ky; + let t = 0; + + if (dx !== 0 || dy !== 0) { + t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy); + + if (t > 1) { + x = b[0]; + y = b[1]; + + } else if (t > 0) { + x += (dx / this.kx) * t; + y += (dy / this.ky) * t; + } + } + + dx = wrap(p[0] - x) * this.kx; + dy = (p[1] - y) * this.ky; + + return Math.sqrt(dx * dx + dy * dy); + } + + /** + * Returns an object of the form {point, index, t}, where point is closest point on the line + * from the given point, index is the start index of the segment with the closest point, + * and t is a parameter from 0 to 1 that indicates where the closest point is on that segment. + * + * @param {Array} line + * @param {GeometryPoint} p point [longitude, latitude] + * @returns {Object} {point, index, t} + * @example + * const point = ruler.pointOnLine(line, [-67.04, 50.5]).point; + * //=point + */ + pointOnLine(line: Array, p: GeometryPoint): Object { + let minDist = Infinity; + let minX = Infinity, minY = Infinity, minI = Infinity, minT = Infinity; + + for (let i = 0; i < line.length - 1; i++) { + + let x = line[i][0]; + let y = line[i][1]; + let dx = wrap(line[i + 1][0] - x) * this.kx; + let dy = (line[i + 1][1] - y) * this.ky; + let t = 0; + + if (dx !== 0 || dy !== 0) { + t = (wrap(p[0] - x) * this.kx * dx + (p[1] - y) * this.ky * dy) / (dx * dx + dy * dy); + + if (t > 1) { + x = line[i + 1][0]; + y = line[i + 1][1]; + + } else if (t > 0) { + x += (dx / this.kx) * t; + y += (dy / this.ky) * t; + } + } + + dx = wrap(p[0] - x) * this.kx; + dy = (p[1] - y) * this.ky; + + const sqDist = dx * dx + dy * dy; + if (sqDist < minDist) { + minDist = sqDist; + minX = x; + minY = y; + minI = i; + minT = t; + } + } + + return { + point: [minX, minY], + index: minI, + t: Math.max(0, Math.min(1, minT)) + }; + } + +} diff --git a/src/style-spec/validate/validate_filter.js b/src/style-spec/validate/validate_filter.js index 3e03f1f984c..3b58bf7a0e5 100644 --- a/src/style-spec/validate/validate_filter.js +++ b/src/style-spec/validate/validate_filter.js @@ -104,14 +104,6 @@ function validateNonExpressionFilter(options) { errors.push(new ValidationError(`${key}[1]`, value[1], `string expected, ${type} found`)); } break; - case 'within': - type = getType(value[1]); - if (value.length !== 2) { - errors.push(new ValidationError(key, value, `filter array for "${value[0]}" operator must have 2 elements`)); - } else if (type !== 'object') { - errors.push(new ValidationError(`${key}[1]`, value[1], `object expected, ${type} found`)); - } - break; } return errors; } diff --git a/test/expression.test.js b/test/expression.test.js index 2c4155d43f6..6fe2481f134 100644 --- a/test/expression.test.js +++ b/test/expression.test.js @@ -62,9 +62,7 @@ function getGeometry(feature, geometry, canonical) { } else if (type === 'MultiPolygon') { feature.type = 'Polygon'; for (let i = 0; i < coords.length; i++) { - const polygon = []; - convertLines(coords[i], canonical, polygon); - feature.geometry.push(polygon); + convertLines(coords[i], canonical, feature.geometry); } } } diff --git a/test/integration/expression-tests/distance/feature-to-line-distance/test.json b/test/integration/expression-tests/distance/feature-to-line-distance/test.json new file mode 100644 index 00000000000..662a2c60857 --- /dev/null +++ b/test/integration/expression-tests/distance/feature-to-line-distance/test.json @@ -0,0 +1,407 @@ +{ + "expression": [ + "distance", + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [103.87667655944823, 1.3198734077978092], + [103.87895107269286, 1.3198305038395004], + [103.88148307800293, 1.320860198634505], + [103.88474464416504, 1.3220186047688565], + [103.88603210449219, 1.322136590548516], + [103.88659000396729, 1.3221794944670042], + [103.8875126838684, 1.322190220446512], + [103.88829588890076, 1.3222974802390177], + [103.88919711112976, 1.3224583699190875], + [103.89040946960449, 1.3228123271785266], + [103.89161109924316, 1.3230912025594925], + [103.89283418655396, 1.3233486259602607], + [103.89425039291382, 1.323606049334287], + [103.89545202255249, 1.3238205687922546], + [103.89678239822388, 1.3240565401745568], + [103.89828443527222, 1.3243568673559298], + [103.90021562576294, 1.3247644541867094], + [103.90227556228638, 1.3251505890171646], + [103.9038634300232, 1.3255152718573335], + [103.90473783016205, 1.3258102358799508], + [103.90523135662079, 1.3259550363872927], + [103.90625596046448, 1.326287541223903], + [103.90744686126709, 1.3265985940951497], + [103.90831589698792, 1.3268989209681998], + [103.9093565940857, 1.3272850554657019], + [103.9100432395935, 1.327714093725527], + [103.91063332557678, 1.3280358723715426], + [103.91147017478943, 1.3285185402619937], + [103.91221046447754, 1.3288724966550625], + [103.91329407691956, 1.3293658903304728], + [103.91475319862366, 1.3300738028229564], + [103.91640543937683, 1.330856796706907], + [103.91727447509766, 1.3312643824659285], + [103.91828298568726, 1.3317041459724615], + [103.91959190368652, 1.3321439094005239] + ] + } + } + ] + } + ], + "inputs": [ + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.92658710479736, 1.3294838757599914] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91602993011475, 1.330642277859313] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91246795654297, 1.3363484728438335] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.8917827606201, 1.3479324368661274] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.88373613357544, 1.3323584281174479], + [103.88704061508179, 1.3331092434795238], + [103.88867139816284, 1.3334739251442105], + [103.88972282409668, 1.3337957030387755], + [103.89111757278441, 1.334331999436213], + [103.89274835586546, 1.3351900734288746], + [103.89476537704466, 1.3366702503621644] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.90201807022095, 1.3571781167763333], + [103.90379905700684, 1.3606103787570532], + [103.90506505966187, 1.363012959238619], + [103.9055585861206, 1.3638924747085996], + [103.90648126602173, 1.365887472021871], + [103.90686750411987, 1.3668527927080132] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.95070552825928, 1.3499059956258364], + [103.95280838012695, 1.3506782573132619], + [103.95396709442139, 1.3515792289717337], + [103.95486831665039, 1.3527376206128572], + [103.95525455474852, 1.3542392385837099], + [103.95538330078125, 1.35514020891972] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.90637397766113, 1.3406817398811268], + [103.90603065490723, 1.334331999436213] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.88373613357544, 1.3323584281174479], + [103.88704061508179, 1.3331092434795238], + [103.88867139816284, 1.3334739251442105], + [103.88972282409668, 1.3337957030387755], + [103.89111757278441, 1.334331999436213], + [103.89274835586546, 1.3351900734288746], + [103.89476537704466, 1.3366702503621644] + ], + [ + [103.90201807022095, 1.3571781167763333], + [103.90379905700684, 1.3606103787570532], + [103.90506505966187, 1.363012959238619], + [103.9055585861206, 1.3638924747085996], + [103.90648126602173, 1.365887472021871], + [103.90686750411987, 1.3668527927080132] + ], + [ + [103.95070552825928, 1.3499059956258364], + [103.95280838012695, 1.3506782573132619], + [103.95396709442139, 1.3515792289717337], + [103.95486831665039, 1.3527376206128572], + [103.95525455474852, 1.3542392385837099], + [103.95538330078125, 1.35514020891972] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.89933586120604, 1.3423549795571295], + [103.90757560729979, 1.3423549795571295], + [103.90757560729979, 1.3493053474771306], + [103.89933586120604, 1.3493053474771306], + [103.89933586120604, 1.3423549795571295] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.88174057006836, 1.33746396806039], + [103.88096809387207, 1.3306851816303256], + [103.89015197753905, 1.3329161766939823], + [103.888521194458, 1.336434280186183], + [103.88671875, 1.3384936555025502], + [103.88431549072266, 1.3378930045471449], + [103.88174057006836, 1.33746396806039] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.92388343811035, 1.3539389150639312], + [103.91633033752441, 1.3341174808912555], + [103.93160820007324, 1.333173599071337], + [103.9368438720703, 1.339437535278059], + [103.92388343811035, 1.3539389150639312] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.90088081359863, 1.3581434409513022], + [103.90474319458008, 1.355740855624212], + [103.91392707824707, 1.3597737653488802], + [103.9098072052002, 1.3628627980287111], + [103.90088081359863, 1.3581434409513022] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.87710571289062, 1.3415827152334823], + [103.87384414672852, 1.3264806085279128], + [103.88362884521484, 1.3247644541867094], + [103.89736175537108, 1.3340316734680562], + [103.89684677124023, 1.3407246434768525], + [103.88809204101562, 1.3448433851623303], + [103.87710571289062, 1.3415827152334823] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.89873504638672, 1.3544537553607754], + [103.89607429504393, 1.3513647119405165], + [103.89856338500977, 1.350935677821201], + [103.90491485595702, 1.3514505187552757], + [103.90491485595702, 1.3531666544136975], + [103.89873504638672, 1.3544537553607754] + ] + ], + [ + [ + [103.89435768127441, 1.3438995074725528], + [103.89358520507812, 1.3407246434768525], + [103.89839172363281, 1.3395233425123458], + [103.89907836914062, 1.3451866133226467], + [103.89521598815918, 1.3480182438020019], + [103.89126777648926, 1.3475892090924009], + [103.8933277130127, 1.3451866133226467], + [103.88972282409668, 1.3451866133226467], + [103.89092445373535, 1.3439853145503564], + [103.89272689819336, 1.3429556294180167], + [103.89435768127441, 1.3438995074725528] + ] + ], + [ + [ + [103.90268325805664, 1.341925943851875], + [103.9083480834961, 1.341925943851875], + [103.9083480834961, 1.3463879115035189], + [103.90268325805664, 1.3463879115035189], + [103.90268325805664, 1.341925943851875] + ] + ], + [ + [ + [103.90294075012206, 1.325279300613958], + [103.9090347290039, 1.325279300613958], + [103.9090347290039, 1.3305135665417978], + [103.90294075012206, 1.3305135665417978], + [103.90294075012206, 1.325279300613958] + ] + ] + ] + } + } + ] + ], + "expected": { + "compiled": { + "result": "success", + "isFeatureConstant": false, + "isZoomConstant": true, + "type": "number" + }, + "outputs": [ + 832.206, + 3.65803, + 736.057, + 2696.57, + 1148.82, + 3315.26, + 3980.83, + 857.267, + 1148.82, + 1570.13, + 1030.16, + 195.578, + 3038.34, + 327.64, + 0 + ], + "serialized": [ + "distance", + { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [103.87667655944823, 1.3198734077978092], + [103.87895107269286, 1.3198305038395004], + [103.88148307800293, 1.320860198634505], + [103.88474464416504, 1.3220186047688565], + [103.88603210449219, 1.322136590548516], + [103.88659000396729, 1.3221794944670042], + [103.8875126838684, 1.322190220446512], + [103.88829588890076, 1.3222974802390177], + [103.88919711112976, 1.3224583699190875], + [103.89040946960449, 1.3228123271785266], + [103.89161109924316, 1.3230912025594925], + [103.89283418655396, 1.3233486259602607], + [103.89425039291382, 1.323606049334287], + [103.89545202255249, 1.3238205687922546], + [103.89678239822388, 1.3240565401745568], + [103.89828443527222, 1.3243568673559298], + [103.90021562576294, 1.3247644541867094], + [103.90227556228638, 1.3251505890171646], + [103.9038634300232, 1.3255152718573335], + [103.90473783016205, 1.3258102358799508], + [103.90523135662079, 1.3259550363872927], + [103.90625596046448, 1.326287541223903], + [103.90744686126709, 1.3265985940951497], + [103.90831589698792, 1.3268989209681998], + [103.9093565940857, 1.3272850554657019], + [103.9100432395935, 1.327714093725527], + [103.91063332557678, 1.3280358723715426], + [103.91147017478943, 1.3285185402619937], + [103.91221046447754, 1.3288724966550625], + [103.91329407691956, 1.3293658903304728], + [103.91475319862366, 1.3300738028229564], + [103.91640543937683, 1.330856796706907], + [103.91727447509766, 1.3312643824659285], + [103.91828298568726, 1.3317041459724615], + [103.91959190368652, 1.3321439094005239] + ] + } + } + ] + } + ] + } +} diff --git a/test/integration/expression-tests/distance/feature-to-lines-distance/test.json b/test/integration/expression-tests/distance/feature-to-lines-distance/test.json new file mode 100644 index 00000000000..093e9c6a555 --- /dev/null +++ b/test/integration/expression-tests/distance/feature-to-lines-distance/test.json @@ -0,0 +1,367 @@ +{ + "expression": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.88373613357544, 1.3323584281174479], + [103.88704061508179, 1.3331092434795238], + [103.88867139816284, 1.3334739251442105], + [103.88972282409668, 1.3337957030387755], + [103.89111757278441, 1.334331999436213], + [103.89274835586546, 1.3351900734288746], + [103.89476537704466, 1.3366702503621644] + ], + [ + [103.90201807022095, 1.3571781167763333], + [103.90379905700684, 1.3606103787570532], + [103.90506505966187, 1.363012959238619], + [103.9055585861206, 1.3638924747085996], + [103.90648126602173, 1.365887472021871], + [103.90686750411987, 1.3668527927080132] + ], + [ + [103.95070552825928, 1.3499059956258364], + [103.95280838012695, 1.3506782573132619], + [103.95396709442139, 1.3515792289717337], + [103.95486831665039, 1.3527376206128572], + [103.95525455474852, 1.3542392385837099], + [103.95538330078125, 1.35514020891972] + ] + ] + } + } + ], + "inputs": [ + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91959190368652, 1.3218898930028449] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.92658710479736, 1.3294838757599914] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91602993011475, 1.330642277859313] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91246795654297, 1.3363484728438335] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.8917827606201, 1.3479324368661274] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.88174057006836, 1.3316290644037232], + [103.88568878173828, 1.330084528768254], + [103.88139724731445, 1.3288832226055889], + [103.88448715209961, 1.3271670699311868], + [103.88156890869139, 1.3263089931473213], + [103.88895034790039, 1.3285399921660488], + [103.91641616821289, 1.360631830379095], + [103.91899108886719, 1.3602886044036286], + [103.91710281372069, 1.3596021523062254], + [103.91435623168945, 1.3620047337924648], + [103.91332626342773, 1.3599453783793345], + [103.95761489868164, 1.351021484651125], + [103.95967483520508, 1.3518795527836271], + [103.95538330078125, 1.3556550489612673], + [103.95418167114258, 1.355483435626243], + [103.95452499389648, 1.353767301607359] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.89315605163574, 1.3430843400832895], + [103.89646053314209, 1.341239486566936], + [103.89864921569824, 1.339909475029482], + [103.90238285064697, 1.3386652700342137], + [103.90551567077637, 1.338021715478541], + [103.90847682952881, 1.337549775363733] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.89341354370116, 1.3396949569719252], + [103.8960313796997, 1.3380646191208425], + [103.8982629776001, 1.3356620139971913] + ], + [ + [103.901309967041, 1.3559982755948157], + [103.89989376068115, 1.3525231036839902] + ], + [ + [103.95074844360352, 1.349755833602559], + [103.95249724388123, 1.3503886592092311] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.92122268676758, 1.3573711816421556], + [103.90766143798828, 1.3462162975139111], + [103.91332626342773, 1.3417543295487024], + [103.9251708984375, 1.3393517280407568], + [103.92740249633789, 1.3467311394464763], + [103.93392562866211, 1.3505066436261501], + [103.92911911010742, 1.3566847287158743], + [103.92122268676758, 1.3573711816421556] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.88809204101562, 1.3621763466641712], + [103.88465881347656, 1.3565131154538628], + [103.8896369934082, 1.3535956881386368], + [103.90422821044922, 1.3575427948432912], + [103.90079498291016, 1.364064087445756], + [103.88809204101562, 1.3621763466641712] + ] + ], + [ + [ + [103.87899398803711, 1.3395233425123458], + [103.87521743774414, 1.330256143886628], + [103.8819122314453, 1.3275103005613949], + [103.88998031616211, 1.3299129136379466], + [103.89392852783203, 1.3369491241772669], + [103.88757705688477, 1.341239486566936], + [103.87899398803711, 1.3395233425123458] + ] + ], + [ + [ + [103.91864776611328, 1.3503350299269141], + [103.91469955444336, 1.3393517280407568], + [103.92414093017578, 1.3324871393386304], + [103.93529891967773, 1.335232977120653], + [103.93667221069336, 1.3432988578436806], + [103.93598556518555, 1.351021484651125], + [103.91864776611328, 1.3503350299269141] + ] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.88809204101562, 1.3621763466641712], + [103.88465881347656, 1.3565131154538628], + [103.8896369934082, 1.3535956881386368], + [103.90422821044922, 1.3575427948432912], + [103.90079498291016, 1.364064087445756], + [103.88809204101562, 1.3621763466641712] + ] + ], + [ + [ + [103.87899398803711, 1.3395233425123458], + [103.87521743774414, 1.330256143886628], + [103.8819122314453, 1.3275103005613949], + [103.88998031616211, 1.3299129136379466], + [103.89392852783203, 1.3369491241772669], + [103.88757705688477, 1.341239486566936], + [103.87899398803711, 1.3395233425123458] + ] + ], + [ + [ + [103.91864776611328, 1.3503350299269141], + [103.91469955444336, 1.3393517280407568], + [103.92414093017578, 1.3324871393386304], + [103.93529891967773, 1.335232977120653], + [103.93667221069336, 1.3432988578436806], + [103.93598556518555, 1.351021484651125], + [103.91864776611328, 1.3503350299269141] + ] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.89873504638672, 1.3544537553607754], + [103.89607429504393, 1.3513647119405165], + [103.89856338500977, 1.350935677821201], + [103.90491485595702, 1.3514505187552757], + [103.90491485595702, 1.3531666544136975], + [103.89873504638672, 1.3544537553607754] + ] + ], + [ + [ + [103.89435768127441, 1.3438995074725528], + [103.89358520507812, 1.3407246434768525], + [103.89839172363281, 1.3395233425123458], + [103.89907836914062, 1.3451866133226467], + [103.89521598815918, 1.3480182438020019], + [103.89126777648926, 1.3475892090924009], + [103.8933277130127, 1.3451866133226467], + [103.88972282409668, 1.3451866133226467], + [103.89092445373535, 1.3439853145503564], + [103.89272689819336, 1.3429556294180167], + [103.89435768127441, 1.3438995074725528] + ] + ], + [ + [ + [103.90268325805664, 1.341925943851875], + [103.9083480834961, 1.341925943851875], + [103.9083480834961, 1.3463879115035189], + [103.90268325805664, 1.3463879115035189], + [103.90268325805664, 1.341925943851875] + ] + ], + [ + [ + [103.90294075012206, 1.325279300613958], + [103.9090347290039, 1.325279300613958], + [103.9090347290039, 1.3305135665417978], + [103.90294075012206, 1.3305135665417978], + [103.90294075012206, 1.325279300613958] + ] + ] + ] + } + } + ] + ], + "expected": { + "compiled": { + "result": "success", + "isFeatureConstant": false, + "isZoomConstant": true, + "type": "number" + }, + "outputs": [ + 3210.12, + 3507.69, + 2458.6, + 1970.43, + 1288.79, + 56.9283, + 530.028, + 17.2408, + 1335.96, + 0, + 0, + 369.035 + ], + "serialized": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.88373613357544, 1.3323584281174479], + [103.88704061508179, 1.3331092434795238], + [103.88867139816284, 1.3334739251442105], + [103.88972282409668, 1.3337957030387755], + [103.89111757278441, 1.334331999436213], + [103.89274835586546, 1.3351900734288746], + [103.89476537704466, 1.3366702503621644] + ], + [ + [103.90201807022095, 1.3571781167763333], + [103.90379905700684, 1.3606103787570532], + [103.90506505966187, 1.363012959238619], + [103.9055585861206, 1.3638924747085996], + [103.90648126602173, 1.365887472021871], + [103.90686750411987, 1.3668527927080132] + ], + [ + [103.95070552825928, 1.3499059956258364], + [103.95280838012695, 1.3506782573132619], + [103.95396709442139, 1.3515792289717337], + [103.95486831665039, 1.3527376206128572], + [103.95525455474852, 1.3542392385837099], + [103.95538330078125, 1.35514020891972] + ] + ] + } + } + ] + } +} diff --git a/test/integration/expression-tests/distance/feature-to-point-distance/test.json b/test/integration/expression-tests/distance/feature-to-point-distance/test.json new file mode 100644 index 00000000000..8e0a34eb333 --- /dev/null +++ b/test/integration/expression-tests/distance/feature-to-point-distance/test.json @@ -0,0 +1,233 @@ +{ + "expression": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [103.91959190368652, 1.3321439094005239] + } + } + ], + "inputs": [ + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91959190368652, 1.3218898930028449] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.92658710479736, 1.3294838757599914] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91602993011475, 1.330642277859313] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91246795654297, 1.3363484728438335] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.8917827606201, 1.3479324368661274] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.91602993011475, 1.330642277859313], + [103.91959190368652, 1.3218898930028449], + [103.92658710479736, 1.3294838757599914], + [103.91246795654297, 1.3363484728438335], + [103.8917827606201, 1.3479324368661274] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.91695261001587, 1.3291406454039345], + [103.9183259010315, 1.3299558174216557], + [103.91987085342407, 1.3304492108805213], + [103.92178058624268, 1.3309855080064967], + [103.922381401062, 1.3323798799881073], + [103.92274618148804, 1.333945866041842], + [103.92476320266724, 1.334932651262518] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.91887843608856, 1.331328738105921], + [103.91953825950623, 1.3313823678046488], + [103.92026782035828, 1.3315110790768092], + [103.92042875289917, 1.3317309608178751], + [103.92087399959564, 1.332079553781803], + [103.9211368560791, 1.3324603245014226] + ], + [ + [103.91826152801514, 1.332841095162202], + [103.91981720924377, 1.3327445617608182], + [103.92054677009581, 1.3322297168895352] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.9174461364746, 1.3344178068489418], + [103.91637325286865, 1.3304277589930558], + [103.92014980316162, 1.3294838757599914], + [103.92457008361816, 1.3323584281174479], + [103.92285346984863, 1.3348039401692318], + [103.9174461364746, 1.3344178068489418] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.9211368560791, 1.3308782485906447], + [103.92289638519287, 1.3308782485906447], + [103.92289638519287, 1.3329054507610252], + [103.9211368560791, 1.3329054507610252], + [103.9211368560791, 1.3308782485906447] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.9211368560791, 1.3308782485906447], + [103.92289638519287, 1.3308782485906447], + [103.92289638519287, 1.3329054507610252], + [103.9211368560791, 1.3329054507610252], + [103.9211368560791, 1.3308782485906447] + ] + ], + [ + [ + [103.91885161399841, 1.3304277589930558], + [103.91833662986755, 1.329805654175455], + [103.91895890235901, 1.3293122605879297], + [103.91988158226012, 1.3292264529974078], + [103.92009615898132, 1.3297842022823918], + [103.91982793807983, 1.3304492108805213], + [103.91885161399841, 1.3304277589930558] + ] + ], + [ + [ + [103.91636252403259, 1.3328839988949333], + [103.91579389572142, 1.3320044722245021], + [103.91642689704895, 1.331650516280731], + [103.9169418811798, 1.332068827845182], + [103.91730666160583, 1.3324120577937464], + [103.91737103462219, 1.3329483544926368], + [103.91636252403259, 1.3328839988949333] + ] + ], + [ + [ + [103.91837418079376, 1.332395968890984], + [103.91827762126923, 1.3317095089415671], + [103.91878724098206, 1.3316880570650556], + [103.91925394535065, 1.3320902797183731], + [103.91905546188353, 1.3324871393386304], + [103.91837418079376, 1.332395968890984] + ] + ] + ] + } + } + ] + ], + "expected": { + "compiled": { + "result": "success", + "isFeatureConstant": false, + "isZoomConstant": true, + "type": "number" + }, + "outputs": [ + 1133.83, + 832.206, + 429.781, + 919.082, + 3553.3, + 429.781, + 188.84, + 67.8341, + 0, + 171.937, + 38.0758 + ], + "serialized": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [103.91959190368652, 1.3321439094005239] + } + } + ] + } +} diff --git a/test/integration/expression-tests/distance/feature-to-points-distance/test.json b/test/integration/expression-tests/distance/feature-to-points-distance/test.json new file mode 100644 index 00000000000..14d612d46f8 --- /dev/null +++ b/test/integration/expression-tests/distance/feature-to-points-distance/test.json @@ -0,0 +1,241 @@ +{ + "expression": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.91959190368652, 1.3321439094005239], + [103.91693115234375, 1.3332808583872813], + [103.92083644866943, 1.3341818364567084] + ] + } + } + ], + "inputs": [ + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91959190368652, 1.3218898930028449] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.92658710479736, 1.3294838757599914] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91602993011475, 1.330642277859313] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91246795654297, 1.3363484728438335] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.8917827606201, 1.3479324368661274] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.91602993011475, 1.330642277859313], + [103.91959190368652, 1.3218898930028449], + [103.92658710479736, 1.3294838757599914], + [103.91246795654297, 1.3363484728438335], + [103.8917827606201, 1.3479324368661274] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.91695261001587, 1.3291406454039345], + [103.9183259010315, 1.3299558174216557], + [103.91987085342407, 1.3304492108805213], + [103.92178058624268, 1.3309855080064967], + [103.922381401062, 1.3323798799881073], + [103.92274618148804, 1.333945866041842], + [103.92476320266724, 1.334932651262518] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.91887843608856, 1.331328738105921], + [103.91953825950623, 1.3313823678046488], + [103.92026782035828, 1.3315110790768092], + [103.92042875289917, 1.3317309608178751], + [103.92087399959564, 1.332079553781803], + [103.9211368560791, 1.3324603245014226] + ], + [ + [103.91826152801514, 1.332841095162202], + [103.91981720924377, 1.3327445617608182], + [103.92054677009581, 1.3322297168895352] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.9174461364746, 1.3344178068489418], + [103.91637325286865, 1.3304277589930558], + [103.92014980316162, 1.3294838757599914], + [103.92457008361816, 1.3323584281174479], + [103.92285346984863, 1.3348039401692318], + [103.9174461364746, 1.3344178068489418] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.9211368560791, 1.3308782485906447], + [103.92289638519287, 1.3308782485906447], + [103.92289638519287, 1.3329054507610252], + [103.9211368560791, 1.3329054507610252], + [103.9211368560791, 1.3308782485906447] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.9211368560791, 1.3308782485906447], + [103.92289638519287, 1.3308782485906447], + [103.92289638519287, 1.3329054507610252], + [103.9211368560791, 1.3329054507610252], + [103.9211368560791, 1.3308782485906447] + ] + ], + [ + [ + [103.91885161399841, 1.3304277589930558], + [103.91833662986755, 1.329805654175455], + [103.91895890235901, 1.3293122605879297], + [103.91988158226012, 1.3292264529974078], + [103.92009615898132, 1.3297842022823918], + [103.91982793807983, 1.3304492108805213], + [103.91885161399841, 1.3304277589930558] + ] + ], + [ + [ + [103.91636252403259, 1.3328839988949333], + [103.91579389572142, 1.3320044722245021], + [103.91642689704895, 1.331650516280731], + [103.9169418811798, 1.332068827845182], + [103.91730666160583, 1.3324120577937464], + [103.91737103462219, 1.3329483544926368], + [103.91636252403259, 1.3328839988949333] + ] + ], + [ + [ + [103.91837418079376, 1.332395968890984], + [103.91827762126923, 1.3317095089415671], + [103.91878724098206, 1.3316880570650556], + [103.91925394535065, 1.3320902797183731], + [103.91905546188353, 1.3324871393386304], + [103.91837418079376, 1.332395968890984] + ] + ] + ] + } + } + ] + ], + "expected": { + "compiled": { + "result": "success", + "isFeatureConstant": false, + "isZoomConstant": true, + "type": "number" + }, + "outputs": [ + 1133.83, + 824.282, + 308.518, + 601.477, + 3233.82, + 308.518, + 188.84, + 67.8341, + 0, + 145.041, + 38.0758 + ], + "serialized": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.91959190368652, 1.3321439094005239], + [103.91693115234375, 1.3332808583872813], + [103.92083644866943, 1.3341818364567084] + ] + } + } + ] + } +} diff --git a/test/integration/expression-tests/distance/feature-to-polygon-distance/test.json b/test/integration/expression-tests/distance/feature-to-polygon-distance/test.json new file mode 100644 index 00000000000..fec71cc881d --- /dev/null +++ b/test/integration/expression-tests/distance/feature-to-polygon-distance/test.json @@ -0,0 +1,442 @@ +{ + "expression": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.91315460205077, 1.3872316939708569], + [103.9031982421875, 1.3738459931841047], + [103.88843536376953, 1.3601169913975755], + [103.87779235839844, 1.3511930983018892], + [103.8698959350586, 1.339180113557158], + [103.875732421875, 1.3336884437452605], + [103.8819122314453, 1.3240779921172874], + [103.90010833740234, 1.3436420862211271], + [103.90800476074219, 1.3566847287158743], + [103.91315460205077, 1.370070525524323], + [103.92448425292969, 1.3731595449619909], + [103.92688751220703, 1.3865452496126591], + [103.92826080322264, 1.3906639127724936], + [103.91315460205077, 1.3872316939708569] + ] + ] + } + } + ], + "inputs": [ + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.89083862304688, 1.3474175951873832] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91212463378906, 1.3481040507348487] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.89710426330566, 1.3539389150639312], + [103.89427185058594, 1.3505924504712263], + [103.8947868347168, 1.3469027533998386], + [103.89315605163574, 1.342011750998951], + [103.89813423156738, 1.33746396806039], + [103.89504432678223, 1.3371207388169672], + [103.89684677124023, 1.3424407866891552], + [103.8907527923584, 1.3466453324652596], + [103.90019416809082, 1.3497343818841974], + [103.90122413635254, 1.346044683512217], + [103.90088081359863, 1.341239486566936] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.9116096496582, 1.3415827152334823], + [103.91263961791992, 1.3388797881819072], + [103.91062259674072, 1.338021715478541], + [103.9130687713623, 1.3377642936089935], + [103.8913106918335, 1.3353616881914718] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.9116096496582, 1.3415827152334823], + [103.91263961791992, 1.3388797881819072], + [103.91062259674072, 1.338021715478541], + [103.9130687713623, 1.3377642936089935], + [103.90126705169678, 1.3432559542931188] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.92019271850586, 1.3529092341423024], + [103.91701698303223, 1.3336884437452605] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.88586044311522, 1.3379788118355014], + [103.88628959655762, 1.3329161766939823] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.88373613357544, 1.3323584281174479], + [103.88704061508179, 1.3331092434795238], + [103.88867139816284, 1.3334739251442105], + [103.88972282409668, 1.3337957030387755], + [103.89111757278441, 1.334331999436213], + [103.89274835586546, 1.3351900734288746], + [103.89476537704466, 1.3366702503621644] + ], + [ + [103.90201807022095, 1.3571781167763333], + [103.90379905700684, 1.3606103787570532], + [103.90506505966187, 1.363012959238619], + [103.9055585861206, 1.3638924747085996], + [103.90648126602173, 1.365887472021871], + [103.90686750411987, 1.3668527927080132] + ], + [ + [103.95070552825928, 1.3499059956258364], + [103.95280838012695, 1.3506782573132619], + [103.95396709442139, 1.3515792289717337], + [103.95486831665039, 1.3527376206128572], + [103.95525455474852, 1.3542392385837099], + [103.95538330078125, 1.35514020891972] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.8906455039978, 1.352630362150803], + [103.89532327651978, 1.3537029465580084] + ], + [ + [103.90356302261353, 1.359130216376035], + [103.90398144721985, 1.3583257799188355] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.89401435852051, 1.3346323253677046], + [103.89573097229002, 1.3361768581501527], + [103.89761924743652, 1.3371207388169672], + [103.90010833740234, 1.3373781607540316], + [103.9009666442871, 1.3390943063108358], + [103.9028549194336, 1.3424407866891552], + [103.90199661254881, 1.3448433851623303], + [103.90294075012206, 1.3459588765068538], + [103.90508651733398, 1.3465595254810407], + [103.90766143798828, 1.3498201887565244], + [103.90843391418457, 1.3511072914780338], + [103.90843391418457, 1.3529092341423024], + [103.90843391418457, 1.3547969821645598], + [103.91139507293701, 1.3600740881441666], + [103.91169548034668, 1.3630344108392747] + ], + [ + [103.9057731628418, 1.344500156953733], + [103.90525817871092, 1.3396091497436304], + [103.90302658081055, 1.3363484728438335] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.89933586120604, 1.3423549795571295], + [103.90757560729979, 1.3423549795571295], + [103.90757560729979, 1.3493053474771306], + [103.89933586120604, 1.3493053474771306], + [103.89933586120604, 1.3423549795571295] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.88174057006836, 1.33746396806039], + [103.88096809387207, 1.3306851816303256], + [103.89015197753905, 1.3329161766939823], + [103.888521194458, 1.336434280186183], + [103.88671875, 1.3384936555025502], + [103.88431549072266, 1.3378930045471449], + [103.88174057006836, 1.33746396806039] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.92388343811035, 1.3539389150639312], + [103.91633033752441, 1.3341174808912555], + [103.93160820007324, 1.333173599071337], + [103.9368438720703, 1.339437535278059], + [103.92388343811035, 1.3539389150639312] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.90088081359863, 1.3581434409513022], + [103.90474319458008, 1.355740855624212], + [103.91392707824707, 1.3597737653488802], + [103.9098072052002, 1.3628627980287111], + [103.90088081359863, 1.3581434409513022] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.87710571289062, 1.3415827152334823], + [103.87384414672852, 1.3264806085279128], + [103.88362884521484, 1.3247644541867094], + [103.89736175537108, 1.3340316734680562], + [103.89684677124023, 1.3407246434768525], + [103.88809204101562, 1.3448433851623303], + [103.87710571289062, 1.3415827152334823] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.88809204101562, 1.3621763466641712], + [103.88465881347656, 1.3565131154538628], + [103.8896369934082, 1.3535956881386368], + [103.90422821044922, 1.3575427948432912], + [103.90079498291016, 1.364064087445756], + [103.88809204101562, 1.3621763466641712] + ] + ], + [ + [ + [103.87899398803711, 1.3395233425123458], + [103.87521743774414, 1.330256143886628], + [103.8819122314453, 1.3275103005613949], + [103.88998031616211, 1.3299129136379466], + [103.89392852783203, 1.3369491241772669], + [103.88757705688477, 1.341239486566936], + [103.87899398803711, 1.3395233425123458] + ] + ], + [ + [ + [103.91864776611328, 1.3503350299269141], + [103.91469955444336, 1.3393517280407568], + [103.92414093017578, 1.3324871393386304], + [103.93529891967773, 1.335232977120653], + [103.93667221069336, 1.3432988578436806], + [103.93598556518555, 1.351021484651125], + [103.91864776611328, 1.3503350299269141] + ] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.90800476074219, 1.3418401367017962], + [103.91229629516602, 1.3418401367017962], + [103.91229629516602, 1.3449291922069289], + [103.90800476074219, 1.3449291922069289], + [103.90800476074219, 1.3418401367017962] + ] + ], + [ + [ + [103.91675949096678, 1.3378930045471449], + [103.91916275024414, 1.3378930045471449], + [103.91916275024414, 1.341239486566936], + [103.91675949096678, 1.341239486566936], + [103.91675949096678, 1.3378930045471449] + ] + ], + [ + [ + [103.90688896179198, 1.331200026824244], + [103.91032218933105, 1.331200026824244], + [103.91032218933105, 1.333774251180444], + [103.90688896179198, 1.333774251180444], + [103.90688896179198, 1.331200026824244] + ] + ], + [ + [ + [103.90439987182617, 1.3465595254810407], + [103.90826225280762, 1.3465595254810407], + [103.90826225280762, 1.3488763129943924], + [103.90439987182617, 1.3488763129943924], + [103.90439987182617, 1.3465595254810407] + ] + ] + ] + } + } + ] + ], + "expected": { + "compiled": { + "result": "success", + "isFeatureConstant": false, + "isZoomConstant": true, + "type": "number" + }, + "outputs": [ + 0, + 885.245, + 0, + 0, + 132.336, + 1415.61, + 0, + 0, + 0, + 110.334, + 0, + 0, + 1757.52, + 0, + 0, + 0, + 106.684 + ], + "serialized": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.91315460205077, 1.3872316939708569], + [103.9031982421875, 1.3738459931841047], + [103.88843536376953, 1.3601169913975755], + [103.87779235839844, 1.3511930983018892], + [103.8698959350586, 1.339180113557158], + [103.875732421875, 1.3336884437452605], + [103.8819122314453, 1.3240779921172874], + [103.90010833740234, 1.3436420862211271], + [103.90800476074219, 1.3566847287158743], + [103.91315460205077, 1.370070525524323], + [103.92448425292969, 1.3731595449619909], + [103.92688751220703, 1.3865452496126591], + [103.92826080322264, 1.3906639127724936], + [103.91315460205077, 1.3872316939708569] + ] + ] + } + } + ] + } +} diff --git a/test/integration/expression-tests/distance/feature-to-polygons-distance/test.json b/test/integration/expression-tests/distance/feature-to-polygons-distance/test.json new file mode 100644 index 00000000000..094272eb938 --- /dev/null +++ b/test/integration/expression-tests/distance/feature-to-polygons-distance/test.json @@ -0,0 +1,467 @@ +{ + "expression": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.88809204101562, 1.3621763466641712], + [103.88465881347656, 1.3565131154538628], + [103.8896369934082, 1.3535956881386368], + [103.90422821044922, 1.3575427948432912], + [103.90079498291016, 1.364064087445756], + [103.88809204101562, 1.3621763466641712] + ] + ], + [ + [ + [103.87899398803711, 1.3395233425123458], + [103.87521743774414, 1.330256143886628], + [103.8819122314453, 1.3275103005613949], + [103.88998031616211, 1.3299129136379466], + [103.89392852783203, 1.3369491241772669], + [103.88757705688477, 1.341239486566936], + [103.87899398803711, 1.3395233425123458] + ] + ], + [ + [ + [103.91864776611328, 1.3503350299269141], + [103.91469955444336, 1.3393517280407568], + [103.92414093017578, 1.3324871393386304], + [103.93529891967773, 1.335232977120653], + [103.93667221069336, 1.3432988578436806], + [103.93598556518555, 1.351021484651125], + [103.91864776611328, 1.3503350299269141] + ] + ] + ] + } + } + ], + "inputs": [ + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.89083862304688, 1.3474175951873832] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Point", + "coordinates": [103.91212463378906, 1.3481040507348487] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.89710426330566, 1.3539389150639312], + [103.89427185058594, 1.3505924504712263], + [103.8947868347168, 1.3469027533998386], + [103.89315605163574, 1.342011750998951], + [103.89813423156738, 1.33746396806039], + [103.89504432678223, 1.3371207388169672], + [103.89684677124023, 1.3424407866891552], + [103.8907527923584, 1.3466453324652596], + [103.90019416809082, 1.3497343818841974], + [103.90122413635254, 1.346044683512217], + [103.90088081359863, 1.341239486566936] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.9116096496582, 1.3415827152334823], + [103.91263961791992, 1.3388797881819072], + [103.91062259674072, 1.338021715478541], + [103.9130687713623, 1.3377642936089935], + [103.8913106918335, 1.3353616881914718] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [103.9116096496582, 1.3415827152334823], + [103.91263961791992, 1.3388797881819072], + [103.91062259674072, 1.338021715478541], + [103.9130687713623, 1.3377642936089935], + [103.90126705169678, 1.3432559542931188] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.92019271850586, 1.3529092341423024], + [103.91701698303223, 1.3336884437452605] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "LineString", + "coordinates": [ + [103.88586044311522, 1.3379788118355014], + [103.88628959655762, 1.3329161766939823] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.88373613357544, 1.3323584281174479], + [103.88704061508179, 1.3331092434795238], + [103.88867139816284, 1.3334739251442105], + [103.88972282409668, 1.3337957030387755], + [103.89111757278441, 1.334331999436213], + [103.89274835586546, 1.3351900734288746], + [103.89476537704466, 1.3366702503621644] + ], + [ + [103.90201807022095, 1.3571781167763333], + [103.90379905700684, 1.3606103787570532], + [103.90506505966187, 1.363012959238619], + [103.9055585861206, 1.3638924747085996], + [103.90648126602173, 1.365887472021871], + [103.90686750411987, 1.3668527927080132] + ], + [ + [103.95070552825928, 1.3499059956258364], + [103.95280838012695, 1.3506782573132619], + [103.95396709442139, 1.3515792289717337], + [103.95486831665039, 1.3527376206128572], + [103.95525455474852, 1.3542392385837099], + [103.95538330078125, 1.35514020891972] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.8906455039978, 1.352630362150803], + [103.89532327651978, 1.3537029465580084] + ], + [ + [103.90356302261353, 1.359130216376035], + [103.90398144721985, 1.3583257799188355] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiLineString", + "coordinates": [ + [ + [103.89401435852051, 1.3346323253677046], + [103.89573097229002, 1.3361768581501527], + [103.89761924743652, 1.3371207388169672], + [103.90010833740234, 1.3373781607540316], + [103.9009666442871, 1.3390943063108358], + [103.9028549194336, 1.3424407866891552], + [103.90199661254881, 1.3448433851623303], + [103.90294075012206, 1.3459588765068538], + [103.90508651733398, 1.3465595254810407], + [103.90766143798828, 1.3498201887565244], + [103.90843391418457, 1.3511072914780338], + [103.90843391418457, 1.3529092341423024], + [103.90843391418457, 1.3547969821645598], + [103.91139507293701, 1.3600740881441666], + [103.91169548034668, 1.3630344108392747] + ], + [ + [103.9057731628418, 1.344500156953733], + [103.90525817871092, 1.3396091497436304], + [103.90302658081055, 1.3363484728438335] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.89933586120604, 1.3423549795571295], + [103.90757560729979, 1.3423549795571295], + [103.90757560729979, 1.3493053474771306], + [103.89933586120604, 1.3493053474771306], + [103.89933586120604, 1.3423549795571295] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.88174057006836, 1.33746396806039], + [103.88096809387207, 1.3306851816303256], + [103.89015197753905, 1.3329161766939823], + [103.888521194458, 1.336434280186183], + [103.88671875, 1.3384936555025502], + [103.88431549072266, 1.3378930045471449], + [103.88174057006836, 1.33746396806039] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.92388343811035, 1.3539389150639312], + [103.91633033752441, 1.3341174808912555], + [103.93160820007324, 1.333173599071337], + [103.9368438720703, 1.339437535278059], + [103.92388343811035, 1.3539389150639312] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.90088081359863, 1.3581434409513022], + [103.90474319458008, 1.355740855624212], + [103.91392707824707, 1.3597737653488802], + [103.9098072052002, 1.3628627980287111], + [103.90088081359863, 1.3581434409513022] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [103.8960313796997, 1.338322040958877], + [103.89495849609375, 1.3363913765153836], + [103.89555931091309, 1.3345465179624436], + [103.8982629776001, 1.3339029623276215], + [103.89929294586182, 1.3351900734288746], + [103.89942169189453, 1.3368633168529194], + [103.89822006225586, 1.338150426403194], + [103.89719009399414, 1.3390084990615112], + [103.8960313796997, 1.338322040958877] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.88809204101562, 1.3621763466641712], + [103.88465881347656, 1.3565131154538628], + [103.8896369934082, 1.3535956881386368], + [103.90422821044922, 1.3575427948432912], + [103.90079498291016, 1.364064087445756], + [103.88809204101562, 1.3621763466641712] + ] + ], + [ + [ + [103.87899398803711, 1.3395233425123458], + [103.87521743774414, 1.330256143886628], + [103.8819122314453, 1.3275103005613949], + [103.88998031616211, 1.3299129136379466], + [103.89392852783203, 1.3369491241772669], + [103.88757705688477, 1.341239486566936], + [103.87899398803711, 1.3395233425123458] + ] + ], + [ + [ + [103.91864776611328, 1.3503350299269141], + [103.91469955444336, 1.3393517280407568], + [103.92414093017578, 1.3324871393386304], + [103.93529891967773, 1.335232977120653], + [103.93667221069336, 1.3432988578436806], + [103.93598556518555, 1.351021484651125], + [103.91864776611328, 1.3503350299269141] + ] + ] + ] + } + } + ], + [ + {"zoom": 13, "canonicalID": {"z": 13, "x": 6460, "y": 4065}}, + { + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.90800476074219, 1.3418401367017962], + [103.91229629516602, 1.3418401367017962], + [103.91229629516602, 1.3449291922069289], + [103.90800476074219, 1.3449291922069289], + [103.90800476074219, 1.3418401367017962] + ] + ], + [ + [ + [103.90688896179198, 1.331200026824244], + [103.91032218933105, 1.331200026824244], + [103.91032218933105, 1.333774251180444], + [103.90688896179198, 1.333774251180444], + [103.90688896179198, 1.331200026824244] + ] + ], + [ + [ + [103.90439987182617, 1.3465595254810407], + [103.90826225280762, 1.3465595254810407], + [103.90826225280762, 1.3488763129943924], + [103.90439987182617, 1.3488763129943924], + [103.90439987182617, 1.3465595254810407] + ] + ] + ] + } + } + ] + ], + "expected": { + "compiled": { + "result": "success", + "isFeatureConstant": false, + "isZoomConstant": true, + "type": "number" + }, + "outputs": [ + 696.107, + 598.72, + 125.617, + 0, + 235.113, + 0, + 0, + 0, + 16.2699, + 134.294, + 738.312, + 0, + 0, + 0, + 130.162, + 0, + 345.114 + ], + "serialized": [ + "distance", + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [103.88809204101562, 1.3621763466641712], + [103.88465881347656, 1.3565131154538628], + [103.8896369934082, 1.3535956881386368], + [103.90422821044922, 1.3575427948432912], + [103.90079498291016, 1.364064087445756], + [103.88809204101562, 1.3621763466641712] + ] + ], + [ + [ + [103.87899398803711, 1.3395233425123458], + [103.87521743774414, 1.330256143886628], + [103.8819122314453, 1.3275103005613949], + [103.88998031616211, 1.3299129136379466], + [103.89392852783203, 1.3369491241772669], + [103.88757705688477, 1.341239486566936], + [103.87899398803711, 1.3395233425123458] + ] + ], + [ + [ + [103.91864776611328, 1.3503350299269141], + [103.91469955444336, 1.3393517280407568], + [103.92414093017578, 1.3324871393386304], + [103.93529891967773, 1.335232977120653], + [103.93667221069336, 1.3432988578436806], + [103.93598556518555, 1.351021484651125], + [103.91864776611328, 1.3503350299269141] + ] + ] + ] + } + } + ] + } +} diff --git a/test/integration/render-tests/distance/filter-with-distance-expression/expected.png b/test/integration/render-tests/distance/filter-with-distance-expression/expected.png new file mode 100644 index 00000000000..4d15441009c Binary files /dev/null and b/test/integration/render-tests/distance/filter-with-distance-expression/expected.png differ diff --git a/test/integration/render-tests/distance/filter-with-distance-expression/style.json b/test/integration/render-tests/distance/filter-with-distance-expression/style.json new file mode 100644 index 00000000000..e974dc4b5fc --- /dev/null +++ b/test/integration/render-tests/distance/filter-with-distance-expression/style.json @@ -0,0 +1,380 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 125, + "height": 125 + } + }, + "zoom": 13, + "center": [ + -73.97850765457153, + 40.75663615846253 + ], + "sources": { + "points": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98010969161987, + 40.75646549167777 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97986292839049, + 40.758009603779705 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97816777229309, + 40.757318821220274 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.9764940738678, + 40.75658739656873 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97747039794922, + 40.75539271899818 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97716999053955, + 40.75848095717076 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97945523262024, + 40.75536021046494 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97729873657227, + 40.75366161748887 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98553848266602, + 40.75793646243674 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97905826568604, + 40.76175595827059 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97186994552612, + 40.76290989043682 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97068977355957, + 40.75575843890192 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98214817047119, + 40.75187357799962 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.9878988265991, + 40.75466940037548 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98674011230469, + 40.76172345284903 + ] + } + } + ] + } + }, + "center": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -73.97860765457153, + 40.75663615846253 + ] + } + } + ] + } + }, + "boundary": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -73.97504593980587, + 40.75663615846253 + ], + [ + -73.9751494367638, + 40.75728181967787 + ], + [ + -73.9754539127706, + 40.75788995167545 + ], + [ + -73.9759416727875, + 40.758425213519445 + ], + [ + -73.97658436997524, + 40.75885649983152 + ], + [ + -73.97734465310938, + 40.75915874804255 + ], + [ + -73.97817833729766, + 40.75931439442866 + ], + [ + -73.9790369718454, + 40.75931439442866 + ], + [ + -73.97987065603368, + 40.75915874804255 + ], + [ + -73.98063093916782, + 40.75885649983152 + ], + [ + -73.98127363635557, + 40.758425213519445 + ], + [ + -73.98176139637246, + 40.75788995167545 + ], + [ + -73.98206587237927, + 40.75728181967787 + ], + [ + -73.9821693693372, + 40.75663615846253 + ], + [ + -73.98206587237927, + 40.75599049097636 + ], + [ + -73.98176139637246, + 40.755382341602825 + ], + [ + -73.98127363635557, + 40.75484705525835 + ], + [ + -73.98063093916782, + 40.7544157429341 + ], + [ + -73.97987065603368, + 40.75411347315821 + ], + [ + -73.9790369718454, + 40.75395781459483 + ], + [ + -73.97817833729766, + 40.75395781459483 + ], + [ + -73.97734465310938, + 40.75411347315821 + ], + [ + -73.97658436997524, + 40.7544157429341 + ], + [ + -73.9759416727875, + 40.75484705525835 + ], + [ + -73.9754539127706, + 40.755382341602825 + ], + [ + -73.9751494367638, + 40.75599049097636 + ], + [ + -73.97504593980587, + 40.75663615846253 + ] + ] + ] + } + } + ] + } + } + }, + "layers": [ + { + "id": "border", + "type": "fill", + "source": "boundary", + "paint": { + "fill-color": "black", + "fill-opacity": 0.5 + } + }, + { + "id": "center", + "type": "circle", + "source": "center", + "paint": { + "circle-radius": 5, + "circle-color": "red" + } + }, + { + "id": "circle", + "type": "circle", + "source": "points", + "filter": [ + "<", + [ + "distance", + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -73.97860765457153, + 40.75663615846253 + ] + } + } + ], + 300 + ], + "paint": { + "circle-radius": 5, + "circle-color": "green" + } + } + ] +} \ No newline at end of file diff --git a/test/integration/render-tests/distance/paint-circle/expected.png b/test/integration/render-tests/distance/paint-circle/expected.png new file mode 100644 index 00000000000..c434f88c2e4 Binary files /dev/null and b/test/integration/render-tests/distance/paint-circle/expected.png differ diff --git a/test/integration/render-tests/distance/paint-circle/style.json b/test/integration/render-tests/distance/paint-circle/style.json new file mode 100644 index 00000000000..15eceda4000 --- /dev/null +++ b/test/integration/render-tests/distance/paint-circle/style.json @@ -0,0 +1,384 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 300, + "height": 300 + } + }, + "zoom": 13, + "center": [ + -73.97860765457153, + 40.75663615846253 + ], + "sources": { + "points": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98010969161987, + 40.75646549167777 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97986292839049, + 40.758009603779705 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97816777229309, + 40.757318821220274 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.9764940738678, + 40.75658739656873 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97747039794922, + 40.75539271899818 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97716999053955, + 40.75848095717076 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97945523262024, + 40.75536021046494 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97729873657227, + 40.75366161748887 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98553848266602, + 40.75793646243674 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97905826568604, + 40.76175595827059 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97186994552612, + 40.76290989043682 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97068977355957, + 40.75575843890192 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98214817047119, + 40.75187357799962 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.99002313613892, + 40.75419801995909 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98674011230469, + 40.76172345284903 + ] + } + } + ] + } + }, + "center": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -73.97860765457153, + 40.75663615846253 + ] + } + } + ] + } + }, + "boundary": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -73.96910974852973, + 40.75663615846253 + ], + [ + -73.96938574041758, + 40.75835790776813 + ], + [ + -73.97019767643575, + 40.75997955448142 + ], + [ + -73.97149836981414, + 40.76140686495245 + ], + [ + -73.97321222898142, + 40.76255690397866 + ], + [ + -73.97523965067244, + 40.76336285128514 + ], + [ + -73.97746280850788, + 40.76377788125359 + ], + [ + -73.97975250063519, + 40.76377788125359 + ], + [ + -73.98197565847063, + 40.76336285128514 + ], + [ + -73.98400308016164, + 40.76255690397866 + ], + [ + -73.98571693932892, + 40.76140686495245 + ], + [ + -73.98701763270732, + 40.75997955448142 + ], + [ + -73.98782956872549, + 40.75835790776813 + ], + [ + -73.98810556061333, + 40.75663615846253 + ], + [ + -73.98782956872549, + 40.75491436456426 + ], + [ + -73.98701763270732, + 40.75329259428858 + ], + [ + -73.98571693932892, + 40.751865109592046 + ], + [ + -73.98400308016164, + 40.75071488559027 + ], + [ + -73.98197565847063, + 40.74990878493372 + ], + [ + -73.97975250063519, + 40.749493668371485 + ], + [ + -73.97746280850788, + 40.749493668371485 + ], + [ + -73.97523965067244, + 40.74990878493372 + ], + [ + -73.97321222898142, + 40.75071488559027 + ], + [ + -73.97149836981414, + 40.751865109592046 + ], + [ + -73.97019767643575, + 40.75329259428858 + ], + [ + -73.96938574041758, + 40.75491436456426 + ], + [ + -73.96910974852973, + 40.75663615846253 + ] + ] + ] + } + } + ] + } + } + }, + "layers": [ + { + "id": "border", + "type": "fill", + "source": "boundary", + "paint": { + "fill-color": "black", + "fill-opacity": 0.5 + } + }, + { + "id": "center", + "type": "circle", + "source": "center", + "paint": { + "circle-radius": 5, + "circle-color": "red" + } + }, + { + "id": "circle", + "type": "circle", + "source": "points", + "paint": { + "circle-radius": 3, + "circle-color": [ + "case", + [ + "<", + [ + "distance", + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [ + -73.97860765457153, + 40.75663615846253 + ] + } + } + ], + 800 + ], + "green", + "blue" + ] + } + } + ] +} \ No newline at end of file diff --git a/test/integration/render-tests/distance/paint-line/expected.png b/test/integration/render-tests/distance/paint-line/expected.png new file mode 100644 index 00000000000..49f65544085 Binary files /dev/null and b/test/integration/render-tests/distance/paint-line/expected.png differ diff --git a/test/integration/render-tests/distance/paint-line/style.json b/test/integration/render-tests/distance/paint-line/style.json new file mode 100644 index 00000000000..69885a5c2dc --- /dev/null +++ b/test/integration/render-tests/distance/paint-line/style.json @@ -0,0 +1,571 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 300, + "height": 300 + } + }, + "zoom": 13, + "center": [ + -73.97882951965332, + 40.75453936473234 + ], + "sources": { + "lines": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.97605419158934, + 40.757887701496706 + ], + [ + -73.9734363555908, + 40.75710752159198 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.9874267578125, + 40.755774693073164 + ], + [ + -73.98828506469727, + 40.75346656097219 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.98270606994629, + 40.75323899431278 + ], + [ + -73.97798538208008, + 40.75353157987466 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.97725582122803, + 40.755742184726685 + ], + [ + -73.97545337677002, + 40.75629482445485 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.97635459899902, + 40.754116747135726 + ], + [ + -73.97502422332764, + 40.75366161748887 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.98519515991211, + 40.75723755221195 + ], + [ + -73.98343563079834, + 40.75674993607564 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.98326396942139, + 40.75486445336327 + ], + [ + -73.98549556732178, + 40.752036129031076 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.97493839263916, + 40.75219867966512 + ], + [ + -73.97433757781982, + 40.7508982634657 + ] + ] + } + } + ] + } + }, + "center": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.9877700805664, + 40.74976037842817 + ], + [ + -73.98648262023926, + 40.75169477140605 + ], + [ + -73.98558139801025, + 40.752913897733926 + ], + [ + -73.98416519165039, + 40.75484819896946 + ], + [ + -73.98319959640503, + 40.75613228383523 + ], + [ + -73.98139715194702, + 40.75868412570509 + ], + [ + -73.97931575775146, + 40.75782268685437 + ], + [ + -73.97824287414551, + 40.757270059827206 + ], + [ + -73.97907972335815, + 40.756051013376364 + ], + [ + -73.97564649581909, + 40.75460438258571 + ], + [ + -73.97423028945923, + 40.75398671041169 + ], + [ + -73.97614002227783, + 40.75143468822972 + ], + [ + -73.97435903549194, + 40.7507357096525 + ] + ] + } + } + ] + } + }, + "boundary": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + -73.980915406985, + 40.757460062068475 + ], + [ + -73.97993559617679, + 40.75705453718075 + ], + [ + -73.97978285721045, + 40.75697586289132 + ], + [ + -73.98013295216039, + 40.7564658767395 + ], + [ + -73.9802661238222, + 40.756019807558545 + ], + [ + -73.98009242653058, + 40.755581806995224 + ], + [ + -73.97965678803773, + 40.7552651674539 + ], + [ + -73.9762311554221, + 40.75382171882893 + ], + [ + -73.97584453587778, + 40.753653094999805 + ], + [ + -73.97717274502423, + 40.75187817755506 + ], + [ + -73.97732688933066, + 40.75141629100844 + ], + [ + -73.97714793303804, + 40.75095956456846 + ], + [ + -73.97668610118902, + 40.750636182251725 + ], + [ + -73.97490511440313, + 40.749937195280495 + ], + [ + -73.97418126210347, + 40.749846537544585 + ], + [ + -73.97352531319592, + 40.750095515074946 + ], + [ + -73.97318781786828, + 40.750589024054165 + ], + [ + -73.97329768786464, + 40.751138557905904 + ], + [ + -73.97381295658076, + 40.75153421443528 + ], + [ + -73.97449936785367, + 40.75180360585742 + ], + [ + -73.97319756671283, + 40.7535432351504 + ], + [ + -73.97304319297578, + 40.7539917982632 + ], + [ + -73.97320425720197, + 40.75443900640337 + ], + [ + -73.97363796104085, + 40.754766027529854 + ], + [ + -73.97505416740071, + 40.75538369246371 + ], + [ + -73.97506943113952, + 40.755390236318846 + ], + [ + -73.97749399824558, + 40.75641184744637 + ], + [ + -73.97718964534327, + 40.75685520148255 + ], + [ + -73.97705577268336, + 40.75727443033833 + ], + [ + -73.97719501885582, + 40.75769265102434 + ], + [ + -73.9775753472124, + 40.758013643518126 + ], + [ + -73.97864823081835, + 40.75856626436385 + ], + [ + -73.97874655265649, + 40.758611784703874 + ], + [ + -73.98082794685205, + 40.7594732133289 + ], + [ + -73.98142855938701, + 40.759583004529844 + ], + [ + -73.98202066406688, + 40.759449302909445 + ], + [ + -73.98244386765893, + 40.75910832520998 + ], + [ + -73.98423886695231, + 40.756567038356934 + ], + [ + -73.98519669908008, + 40.75529328560552 + ], + [ + -73.98520332852566, + 40.7552843514961 + ], + [ + -73.98661831357845, + 40.75335173054083 + ], + [ + -73.9875183856405, + 40.75213416813068 + ], + [ + -73.98754262111453, + 40.75209964365882 + ], + [ + -73.98883008144168, + 40.75016526245955 + ], + [ + -73.98894178359876, + 40.749615932583 + ], + [ + -73.98860593502222, + 40.749121772064484 + ], + [ + -73.98795081845319, + 40.74887153633583 + ], + [ + -73.98722666615446, + 40.748960809814065 + ], + [ + -73.98671007969114, + 40.74935549193148 + ], + [ + -73.98543424256412, + 40.75127243312102 + ], + [ + -73.98454563260901, + 40.752474506162116 + ], + [ + -73.98454326113499, + 40.75247772965659 + ], + [ + -73.98313031781153, + 40.75440758620425 + ], + [ + -73.98216808897534, + 40.75568720281612 + ], + [ + -73.98215288069312, + 40.75570806533946 + ], + [ + -73.980915406985, + 40.757460062068475 + ] + ] + ] + ] + } + } + ] + } + } + }, + "layers": [ + { + "id": "border", + "type": "fill", + "source": "boundary", + "paint": { + "fill-color": "black", + "fill-opacity": 0.5 + } + }, + { + "id": "center", + "type": "line", + "source": "center", + "paint": { + "line-color": "red" + } + }, + { + "id": "circle", + "type": "line", + "source": "lines", + "paint": { + "line-color": [ + "case", + [ + "<", + [ + "distance", + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.9877700805664, + 40.74976037842817 + ], + [ + -73.98648262023926, + 40.75169477140605 + ], + [ + -73.98558139801025, + 40.752913897733926 + ], + [ + -73.98416519165039, + 40.75484819896946 + ], + [ + -73.98319959640503, + 40.75613228383523 + ], + [ + -73.98139715194702, + 40.75868412570509 + ], + [ + -73.97931575775146, + 40.75782268685437 + ], + [ + -73.97824287414551, + 40.757270059827206 + ], + [ + -73.97907972335815, + 40.756051013376364 + ], + [ + -73.97564649581909, + 40.75460438258571 + ], + [ + -73.97423028945923, + 40.75398671041169 + ], + [ + -73.97614002227783, + 40.75143468822972 + ], + [ + -73.97435903549194, + 40.7507357096525 + ] + ] + } + } + ], + 100 + ], + "red", + "blue" + ] + } + } + ] +} \ No newline at end of file diff --git a/test/integration/render-tests/distance/paint-polygon/expected.png b/test/integration/render-tests/distance/paint-polygon/expected.png new file mode 100644 index 00000000000..7da3382254a Binary files /dev/null and b/test/integration/render-tests/distance/paint-polygon/expected.png differ diff --git a/test/integration/render-tests/distance/paint-polygon/style.json b/test/integration/render-tests/distance/paint-polygon/style.json new file mode 100644 index 00000000000..d4d971fa584 --- /dev/null +++ b/test/integration/render-tests/distance/paint-polygon/style.json @@ -0,0 +1,1480 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 500, + "height": 800 + } + }, + "zoom": 15, + "center": [ + -74.0156, 40.7068 + ], + "sources": { + "polygons": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01458144187927, + 40.704993544667936 + ], + [ + -74.01387333869934, + 40.704993544667936 + ], + [ + -74.01387333869934, + 40.70539207464748 + ], + [ + -74.01458144187927, + 40.70539207464748 + ], + [ + -74.01458144187927, + 40.704993544667936 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.0144956111908, + 40.70438354518276 + ], + [ + -74.01401281356812, + 40.70438354518276 + ], + [ + -74.01401281356812, + 40.70445674541596 + ], + [ + -74.0144956111908, + 40.70445674541596 + ], + [ + -74.0144956111908, + 40.70438354518276 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01309013366699, + 40.70529447568931 + ], + [ + -74.01313304901123, + 40.70479834544056 + ], + [ + -74.01241421699523, + 40.704936611619054 + ], + [ + -74.01240348815918, + 40.705400207887536 + ], + [ + -74.01269316673279, + 40.70569300386812 + ], + [ + -74.01309013366699, + 40.70529447568931 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01807904243469, + 40.705969532223364 + ], + [ + -74.0187120437622, + 40.705782469049886 + ], + [ + -74.0179181098938, + 40.70554660603872 + ], + [ + -74.01764988899231, + 40.70579060224226 + ], + [ + -74.01770353317261, + 40.70620539373668 + ], + [ + -74.01807904243469, + 40.705969532223364 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01639461517334, + 40.703594604229664 + ], + [ + -74.01562213897705, + 40.703594604229664 + ], + [ + -74.01562213897705, + 40.70422901109288 + ], + [ + -74.01639461517334, + 40.70422901109288 + ], + [ + -74.01639461517334, + 40.703594604229664 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01465654373169, + 40.703000858998855 + ], + [ + -74.01409864425659, + 40.703000858998855 + ], + [ + -74.01409864425659, + 40.703220464016084 + ], + [ + -74.01465654373169, + 40.703220464016084 + ], + [ + -74.01465654373169, + 40.703000858998855 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01522517204285, + 40.70356207038148 + ], + [ + -74.01349782943726, + 40.70356207038148 + ], + [ + -74.01349782943726, + 40.703895541571974 + ], + [ + -74.01522517204285, + 40.703895541571974 + ], + [ + -74.01522517204285, + 40.70356207038148 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.0171617269516, + 40.70469261228682 + ], + [ + -74.01734948158263, + 40.7043957452272 + ], + [ + -74.01685059070587, + 40.70429814480899 + ], + [ + -74.01658773422241, + 40.70435914508713 + ], + [ + -74.01678085327148, + 40.70465194564456 + ], + [ + -74.0171617269516, + 40.70469261228682 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01637315750122, + 40.708897409073174 + ], + [ + -74.0164589881897, + 40.707953996144724 + ], + [ + -74.013991355896, + 40.70749855063713 + ], + [ + -74.01386260986328, + 40.70798652784752 + ], + [ + -74.01379823684692, + 40.70868595561338 + ], + [ + -74.01596546173096, + 40.70943417253246 + ], + [ + -74.01637315750122, + 40.708897409073174 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01611566543579, + 40.71016611573151 + ], + [ + -74.01568651199341, + 40.71016611573151 + ], + [ + -74.01568651199341, + 40.7107841948341 + ], + [ + -74.01611566543579, + 40.7107841948341 + ], + [ + -74.01611566543579, + 40.71016611573151 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -74.01330471038818, + 40.71062154299493 + ], + [ + -74.01281118392944, + 40.71062154299493 + ], + [ + -74.01281118392944, + 40.7109793765167 + ], + [ + -74.01330471038818, + 40.7109793765167 + ], + [ + -74.01330471038818, + 40.71062154299493 + ] + ] + ] + } + } + + ] + } + }, + "route": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ -74.013841, 40.702449 ], + [ -74.013863, 40.702462 ], + [ -74.013977, 40.702548 ], + [ -74.01404, 40.702595 ], + [ -74.014152, 40.702685 ], + [ -74.014213, 40.702749 ], + [ -74.014284, 40.702835 ], + [ -74.014333, 40.702911 ], + [ -74.014368, 40.702978 ], + [ -74.014407, 40.703066 ], + [ -74.014438, 40.703152 ], + [ -74.014449, 40.703209 ], + [ -74.01445, 40.703263 ], + [ -74.01445, 40.703332 ], + [ -74.014442, 40.703401 ], + [ -74.014404, 40.703614 ], + [ -74.014245, 40.704524 ], + [ -74.01422, 40.704633 ], + [ -74.014329, 40.704667 ], + [ -74.01445, 40.704705 ], + [ -74.014548, 40.704733 ], + [ -74.014641, 40.704756 ], + [ -74.014727, 40.704776 ], + [ -74.014841, 40.704799 ], + [ -74.014977, 40.704827 ], + [ -74.015033, 40.704838 ], + [ -74.015365, 40.704905 ], + [ -74.015454, 40.704921 ], + [ -74.015541, 40.704933 ], + [ -74.015638, 40.704945 ], + [ -74.015699, 40.70495 ], + [ -74.015755, 40.704953 ], + [ -74.01583, 40.704952 ], + [ -74.015909, 40.704949 ], + [ -74.016073, 40.704935 ], + [ -74.016157, 40.704927 ], + [ -74.016224, 40.704921 ], + [ -74.016284, 40.70491 ], + [ -74.016416, 40.704882 ], + [ -74.016424, 40.704918 ], + [ -74.016437, 40.704962 ], + [ -74.016453, 40.705007 ], + [ -74.016462, 40.705041 ], + [ -74.016467, 40.705072 ], + [ -74.016463, 40.705112 ], + [ -74.016457, 40.70515 ], + [ -74.016447, 40.705189 ], + [ -74.016151, 40.705949 ], + [ -74.016121, 40.706032 ], + [ -74.01609, 40.706121 ], + [ -74.01606, 40.706214 ], + [ -74.016037, 40.706296 ], + [ -74.016016, 40.706383 ], + [ -74.016003, 40.70645 ], + [ -74.015986, 40.706549 ], + [ -74.015971, 40.706613 ], + [ -74.015953, 40.706677 ], + [ -74.015888, 40.706844 ], + [ -74.015805, 40.707053 ], + [ -74.015735, 40.707222 ], + [ -74.015697, 40.707307 ], + [ -74.015597, 40.70752 ], + [ -74.015512, 40.707701 ], + [ -74.015476, 40.707784 ], + [ -74.015442, 40.707859 ], + [ -74.015363, 40.708065 ], + [ -74.015197, 40.708495 ], + [ -74.014864, 40.709446 ], + [ -74.01476, 40.709725 ], + [ -74.014744, 40.709777 ], + [ -74.014729, 40.709827 ], + [ -74.01472, 40.709873 ], + [ -74.014712, 40.709925 ], + [ -74.014709, 40.709998 ], + [ -74.014699, 40.710139 ], + [ -74.014689, 40.710215 ], + [ -74.014674, 40.710286 ], + [ -74.014655, 40.710373 ], + [ -74.014631, 40.710477 ], + [ -74.014602, 40.710583 ], + [ -74.014523, 40.710825 ], + [ -74.014492, 40.710899 ], + [ -74.014463, 40.710966 ], + [ -74.014434, 40.711033 ], + [ -74.014406, 40.711098 ], + [ -74.01438, 40.711171 ], + [ -74.01436, 40.71125 ], + [ -74.014147, 40.712245 ] + ] + } + } + ] + } + }, + "boundary": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + -74.0151711019407, + 40.70708248153554 + ], + [ + -74.01513669040085, + 40.70715945454981 + ], + [ + -74.01495320586922, + 40.70755022788697 + ], + [ + -74.01491377266709, + 40.70764071839986 + ], + [ + -74.0148810615757, + 40.707712875375907 + ], + [ + -74.01487264250203, + 40.707732967604218 + ], + [ + -74.01462764250204, + 40.70836896880789 + ], + [ + -74.01462371533762, + 40.70837965125844 + ], + [ + -74.0142919254227, + 40.709327197095749 + ], + [ + -74.01418921264924, + 40.70960274397049 + ], + [ + -74.01418200426355, + 40.709624062706328 + ], + [ + -74.01415100426354, + 40.70972606286091 + ], + [ + -74.01414228154686, + 40.709761040301319 + ], + [ + -74.01413328154685, + 40.70980704034693 + ], + [ + -74.01413085669339, + 40.709820919977548 + ], + [ + -74.0141228566934, + 40.70987292001823 + ], + [ + -74.01411915165584, + 40.70991100075199 + ], + [ + -74.01411636078629, + 40.70997891192715 + ], + [ + -74.014107445332, + 40.710104616078528 + ], + [ + -74.01410062631857, + 40.71015644061677 + ], + [ + -74.01407015652336, + 40.710298038166488 + ], + [ + -74.01404833135662, + 40.71039261400213 + ], + [ + -74.01402352268247, + 40.710483291093428 + ], + [ + -74.01395185417192, + 40.7107028367914 + ], + [ + -74.01392751803896, + 40.71076093110875 + ], + [ + -74.01384233684309, + 40.7109580368456 + ], + [ + -74.01383336576522, + 40.71098081405313 + ], + [ + -74.01380736576523, + 40.71105381418158 + ], + [ + -74.01379749274386, + 40.711086267327718 + ], + [ + -74.01377749274387, + 40.71116526742827 + ], + [ + -74.01377452183337, + 40.71117798717853 + ], + [ + -74.01356152183337, + 40.71217298825462 + ], + [ + -74.01356973267557, + 40.712348300666068 + ], + [ + -74.01366582723498, + 40.712507886077677 + ], + [ + -74.01383517598602, + 40.712627449247438 + ], + [ + -74.0140519971165, + 40.7126887880178 + ], + [ + -74.01428328157479, + 40.712682564282037 + ], + [ + -74.01449381839872, + 40.7126097255296 + ], + [ + -74.01465155526535, + 40.71248136061004 + ], + [ + -74.01473247816664, + 40.712317011667497 + ], + [ + -74.01494411522629, + 40.71132837957097 + ], + [ + -74.01495836129088, + 40.711272105835977 + ], + [ + -74.01497455088455, + 40.71122665051681 + ], + [ + -74.01505566315692, + 40.711038963278529 + ], + [ + -74.01505731843706, + 40.71103507336031 + ], + [ + -74.01508831843704, + 40.71096107351153 + ], + [ + -74.01509877012852, + 40.7109329971876 + ], + [ + -74.01517777012852, + 40.710690997580119 + ], + [ + -74.01518277861777, + 40.710674297126818 + ], + [ + -74.01521177861778, + 40.71056829727215 + ], + [ + -74.01521526423329, + 40.71055447168172 + ], + [ + -74.0152392642333, + 40.710450471802719 + ], + [ + -74.01524039909495, + 40.710445382104499 + ], + [ + -74.01527439909494, + 40.71028738227625 + ], + [ + -74.01527920752534, + 40.71025962213679 + ], + [ + -74.01528920752533, + 40.71018362218774 + ], + [ + -74.01529128065282, + 40.71016313620123 + ], + [ + -74.01530128065282, + 40.71002213625232 + ], + [ + -74.01530406315996, + 40.70995810091367 + ], + [ + -74.0153080756424, + 40.70993202285155 + ], + [ + -74.01531227007016, + 40.7099105846882 + ], + [ + -74.01533474044436, + 40.709836648092849 + ], + [ + -74.01543478735076, + 40.70956825631728 + ], + [ + -74.01543728466237, + 40.709561346894478 + ], + [ + -74.01576840153629, + 40.70861572483216 + ], + [ + -74.01600745770782, + 40.707995155322468 + ], + [ + -74.01603693842432, + 40.70793012446802 + ], + [ + -74.01607320926228, + 40.70784662844005 + ], + [ + -74.01625579413079, + 40.70745777266373 + ], + [ + -74.01625875406399, + 40.70745131375989 + ], + [ + -74.01629675406396, + 40.70736631394408 + ], + [ + -74.01630089636346, + 40.707356693457288 + ], + [ + -74.01637089636347, + 40.707187693799088 + ], + [ + -74.01637295743514, + 40.707182612894317 + ], + [ + -74.01645595743516, + 40.7069736133011 + ], + [ + -74.01645689000667, + 40.70697124138866 + ], + [ + -74.01652189000666, + 40.706804241707718 + ], + [ + -74.01653309799375, + 40.706770755996959 + ], + [ + -74.01655109799376, + 40.706706756087047 + ], + [ + -74.01655499022424, + 40.70669165437923 + ], + [ + -74.01656999022424, + 40.70662765445482 + ], + [ + -74.0165741736369, + 40.70660703985817 + ], + [ + -74.01659054000223, + 40.70651173105705 + ], + [ + -74.01660131513352, + 40.7064561977443 + ], + [ + -74.01661892836694, + 40.70638323119675 + ], + [ + -74.01663829648115, + 40.70631417975625 + ], + [ + -74.01666455846079, + 40.70623276812648 + ], + [ + -74.01672192222928, + 40.70607102529516 + ], + [ + -74.01701585967143, + 40.705316322464629 + ], + [ + -74.0170292385679, + 40.705274794782159 + ], + [ + -74.0170392385679, + 40.70523579483239 + ], + [ + -74.01704593206589, + 40.705203438957628 + ], + [ + -74.01705193206588, + 40.70516543898813 + ], + [ + -74.0170544389246, + 40.70514598878137 + ], + [ + -74.01705843892461, + 40.70510598880179 + ], + [ + -74.01705575132216, + 40.705017428401308 + ], + [ + -74.01705075132216, + 40.70498642837589 + ], + [ + -74.01704354286332, + 40.70495253482977 + ], + [ + -74.01703454286332, + 40.70491853478461 + ], + [ + -74.01702569710665, + 40.70488998001849 + ], + [ + -74.01701301415571, + 40.70485431046822 + ], + [ + -74.01700625809827, + 40.704831440776249 + ], + [ + -74.01700089451123, + 40.70480730460531 + ], + [ + -74.01693588676315, + 40.704665544615099 + ], + [ + -74.0168129594481, + 40.70454789928016 + ], + [ + -74.0166458076577, + 40.704467475393588 + ], + [ + -74.01645305344586, + 40.70443323296857 + ], + [ + -74.0162561711821, + 40.70444898695817 + ], + [ + -74.0161343216639, + 40.70447483386707 + ], + [ + -74.01611792676465, + 40.70447783961842 + ], + [ + -74.01600381100126, + 40.7044884195725 + ], + [ + -74.01586093076117, + 40.70450061679901 + ], + [ + -74.01580996404405, + 40.704502552802697 + ], + [ + -74.01577071796528, + 40.7045030759015 + ], + [ + -74.01571770931192, + 40.70449926797011 + ], + [ + -74.01564186909559, + 40.70448988592864 + ], + [ + -74.01557560970953, + 40.70448074664236 + ], + [ + -74.01550988993013, + 40.70446893195469 + ], + [ + -74.01489045061949, + 40.70434368366864 + ], + [ + -74.01487543241945, + 40.704340191041698 + ], + [ + -74.01499190295306, + 40.70367360138647 + ], + [ + -74.01502978449573, + 40.70346126556211 + ], + [ + -74.01503285796554, + 40.70344037060329 + ], + [ + -74.01504085796553, + 40.703371370644109 + ], + [ + -74.0150431246645, + 40.70332922865779 + ], + [ + -74.01504212466452, + 40.70320622865265 + ], + [ + -74.0150358884247, + 40.70314390850314 + ], + [ + -74.01502488842469, + 40.7030869084474 + ], + [ + -74.01501015744576, + 40.7030334693425 + ], + [ + -74.01497915744578, + 40.70294746918944 + ], + [ + -74.01496925079012, + 40.702922792713739 + ], + [ + -74.0149302507901, + 40.7028347925245 + ], + [ + -74.0149194659434, + 40.70281243589099 + ], + [ + -74.0148844659434, + 40.70274543572444 + ], + [ + -74.01486588776636, + 40.70271354255982 + ], + [ + -74.01481688776636, + 40.702637542334517 + ], + [ + -74.0147867803573, + 40.70259644165009 + ], + [ + -74.01471578035729, + 40.70251044134207 + ], + [ + -74.01469376421812, + 40.702485646223099 + ], + [ + -74.0146327642181, + 40.70242164597008 + ], + [ + -74.01458343847715, + 40.702376430492538 + ], + [ + -74.01447143847715, + 40.70228643007562 + ], + [ + -74.01445754668859, + 40.702275635500829 + ], + [ + -74.01428054668858, + 40.70214263486312 + ], + [ + -74.01422763864254, + 40.702107347156388 + ], + [ + -74.01420563864254, + 40.70209434708718 + ], + [ + -74.01399885793953, + 40.70201555583395 + ], + [ + -74.01376804479618, + 40.70200275269269 + ], + [ + -74.01354833842129, + 40.702057886862238 + ], + [ + -74.01337318711878, + 40.70217256451488 + ], + [ + -74.01326925608669, + 40.702329326768339 + ], + [ + -74.01325236788253, + 40.70250430778853 + ], + [ + -74.0133250935823, + 40.702670868264707 + ], + [ + -74.01344840162615, + 40.70277910857115 + ], + [ + -74.01344545331142, + 40.702781363605627 + ], + [ + -74.01361538926793, + 40.70290905505382 + ], + [ + -74.0136939472981, + 40.70297218137762 + ], + [ + -74.01372069041695, + 40.70300023961846 + ], + [ + -74.0137647430682, + 40.70305359872867 + ], + [ + -74.01379001203522, + 40.70309279310317 + ], + [ + -74.01381075121489, + 40.7031324937183 + ], + [ + -74.01383932636424, + 40.70319696954107 + ], + [ + -74.0138561345278, + 40.703243598562128 + ], + [ + -74.01385670324058, + 40.70331366395001 + ], + [ + -74.01385235754623, + 40.7033511455829 + ], + [ + -74.01381621550429, + 40.703553734576107 + ], + [ + -74.01365857519974, + 40.704455940680109 + ], + [ + -74.01363563146812, + 40.70455597479642 + ], + [ + -74.01363498646063, + 40.70470715797282 + ], + [ + -74.01370047731099, + 40.70484995726059 + ], + [ + -74.01382470026995, + 40.70496822928328 + ], + [ + -74.01399361191557, + 40.70504860353307 + ], + [ + -74.01422361191557, + 40.70512060308374 + ], + [ + -74.01424081586814, + 40.70512575210333 + ], + [ + -74.01433881586815, + 40.70515375192642 + ], + [ + -74.0143640405315, + 40.70516047074901 + ], + [ + -74.01445704053148, + 40.705183470601358 + ], + [ + -74.01446704363791, + 40.70518587047451 + ], + [ + -74.01455304363792, + 40.70520587034545 + ], + [ + -74.01457414286804, + 40.70521045508977 + ], + [ + -74.01521214286805, + 40.70533945424825 + ], + [ + -74.01522813602975, + 40.70534250805011 + ], + [ + -74.01531713602975, + 40.70535850794499 + ], + [ + -74.01534782313047, + 40.70536337910113 + ], + [ + -74.01543482313046, + 40.70537537902143 + ], + [ + -74.01544546939071, + 40.70537677164958 + ], + [ + -74.01554246939071, + 40.70538877156963 + ], + [ + -74.01557423879058, + 40.70539203625961 + ], + [ + -74.01563523879058, + 40.70539703622606 + ], + [ + -74.01565718887346, + 40.705398523240749 + ], + [ + -74.01571318887345, + 40.70540152322056 + ], + [ + -74.01574552677285, + 40.705402172560358 + ], + [ + -74.01558214032856, + 40.70582167874488 + ], + [ + -74.01557820372038, + 40.70583226095144 + ], + [ + -74.0155172037204, + 40.70600426125293 + ], + [ + -74.01551384062543, + 40.706014194530357 + ], + [ + -74.0154838406254, + 40.706107194679507 + ], + [ + -74.01547983388035, + 40.706120485774508 + ], + [ + -74.01545683388037, + 40.706202485889637 + ], + [ + -74.01545355113277, + 40.706215069345748 + ], + [ + -74.01543255113275, + 40.70630206945151 + ], + [ + -74.01542917788899, + 40.70631756891734 + ], + [ + -74.01541617788898, + 40.70638456898317 + ], + [ + -74.01539960315644, + 40.70648061371105 + ], + [ + -74.01538878395782, + 40.7065267756787 + ], + [ + -74.01537765590375, + 40.70656634110651 + ], + [ + -74.01531957658183, + 40.70671555959396 + ], + [ + -74.01523805187868, + 40.70692084518066 + ], + [ + -74.0151711019407, + 40.70708248153554 + ] + ] + ] + ] + } + } + ] + } + } + }, + "layers": [ + { + "id": "border", + "type": "fill", + "source": "boundary", + "paint": { + "fill-color": "black", + "fill-opacity": 0.5 + } + }, + { + "id": "center", + "type": "line", + "source": "route", + "paint": { + "line-color": "red" + } + }, + { + "id": "polygons", + "type": "fill", + "source": "polygons", + "paint": { + "fill-color": [ + "case", + [ + "<", + [ + "distance", + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ -74.013841, 40.702449 ], + [ -74.013863, 40.702462 ], + [ -74.013977, 40.702548 ], + [ -74.01404, 40.702595 ], + [ -74.014152, 40.702685 ], + [ -74.014213, 40.702749 ], + [ -74.014284, 40.702835 ], + [ -74.014333, 40.702911 ], + [ -74.014368, 40.702978 ], + [ -74.014407, 40.703066 ], + [ -74.014438, 40.703152 ], + [ -74.014449, 40.703209 ], + [ -74.01445, 40.703263 ], + [ -74.01445, 40.703332 ], + [ -74.014442, 40.703401 ], + [ -74.014404, 40.703614 ], + [ -74.014245, 40.704524 ], + [ -74.01422, 40.704633 ], + [ -74.014329, 40.704667 ], + [ -74.01445, 40.704705 ], + [ -74.014548, 40.704733 ], + [ -74.014641, 40.704756 ], + [ -74.014727, 40.704776 ], + [ -74.014841, 40.704799 ], + [ -74.014977, 40.704827 ], + [ -74.015033, 40.704838 ], + [ -74.015365, 40.704905 ], + [ -74.015454, 40.704921 ], + [ -74.015541, 40.704933 ], + [ -74.015638, 40.704945 ], + [ -74.015699, 40.70495 ], + [ -74.015755, 40.704953 ], + [ -74.01583, 40.704952 ], + [ -74.015909, 40.704949 ], + [ -74.016073, 40.704935 ], + [ -74.016157, 40.704927 ], + [ -74.016224, 40.704921 ], + [ -74.016284, 40.70491 ], + [ -74.016416, 40.704882 ], + [ -74.016424, 40.704918 ], + [ -74.016437, 40.704962 ], + [ -74.016453, 40.705007 ], + [ -74.016462, 40.705041 ], + [ -74.016467, 40.705072 ], + [ -74.016463, 40.705112 ], + [ -74.016457, 40.70515 ], + [ -74.016447, 40.705189 ], + [ -74.016151, 40.705949 ], + [ -74.016121, 40.706032 ], + [ -74.01609, 40.706121 ], + [ -74.01606, 40.706214 ], + [ -74.016037, 40.706296 ], + [ -74.016016, 40.706383 ], + [ -74.016003, 40.70645 ], + [ -74.015986, 40.706549 ], + [ -74.015971, 40.706613 ], + [ -74.015953, 40.706677 ], + [ -74.015888, 40.706844 ], + [ -74.015805, 40.707053 ], + [ -74.015735, 40.707222 ], + [ -74.015697, 40.707307 ], + [ -74.015597, 40.70752 ], + [ -74.015512, 40.707701 ], + [ -74.015476, 40.707784 ], + [ -74.015442, 40.707859 ], + [ -74.015363, 40.708065 ], + [ -74.015197, 40.708495 ], + [ -74.014864, 40.709446 ], + [ -74.01476, 40.709725 ], + [ -74.014744, 40.709777 ], + [ -74.014729, 40.709827 ], + [ -74.01472, 40.709873 ], + [ -74.014712, 40.709925 ], + [ -74.014709, 40.709998 ], + [ -74.014699, 40.710139 ], + [ -74.014689, 40.710215 ], + [ -74.014674, 40.710286 ], + [ -74.014655, 40.710373 ], + [ -74.014631, 40.710477 ], + [ -74.014602, 40.710583 ], + [ -74.014523, 40.710825 ], + [ -74.014492, 40.710899 ], + [ -74.014463, 40.710966 ], + [ -74.014434, 40.711033 ], + [ -74.014406, 40.711098 ], + [ -74.01438, 40.711171 ], + [ -74.01436, 40.71125 ], + [ -74.014147, 40.712245 ] + ] + } + } + ], + 50 + ], + "red", + "blue" + ] + } + } + ] +} \ No newline at end of file diff --git a/test/integration/render-tests/distance/symbol-style/expected.png b/test/integration/render-tests/distance/symbol-style/expected.png new file mode 100644 index 00000000000..c939751e3a1 Binary files /dev/null and b/test/integration/render-tests/distance/symbol-style/expected.png differ diff --git a/test/integration/render-tests/distance/symbol-style/style.json b/test/integration/render-tests/distance/symbol-style/style.json new file mode 100644 index 00000000000..99ef2e6f070 --- /dev/null +++ b/test/integration/render-tests/distance/symbol-style/style.json @@ -0,0 +1,728 @@ +{ + "version": 8, + "metadata": { + "test": { + "width": 300, + "height": 300 + } + }, + "zoom": 13, + "center": [ + -73.97892951965332, + 40.75452936473234 + ], + "sources": { + "points": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97986292839049, + 40.758009603779705 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97816777229309, + 40.757318821220274 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.9764940738678, + 40.75658739656873 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97747039794922, + 40.75539271899818 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97716999053955, + 40.75848095717076 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97945523262024, + 40.75536021046494 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97729873657227, + 40.75366161748887 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98553848266602, + 40.75793646243674 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97068977355957, + 40.75575843890192 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.99002313613892, + 40.75419801995909 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98244857788086, + 40.75592098043558 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98504495620728, + 40.75418176540237 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98532390594482, + 40.75206863918968 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98150444030762, + 40.758944180522946 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97450923919678, + 40.75254003470314 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.97485256195068, + 40.75382416414898 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.9749813079834, + 40.75058941088087 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98774862289429, + 40.75031306787843 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -73.98122549057007, + 40.75418176540237 + ] + } + } + ] + } + }, + "center": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.9877700805664, + 40.74976037842817 + ], + [ + -73.98648262023926, + 40.75169477140605 + ], + [ + -73.98558139801025, + 40.752913897733926 + ], + [ + -73.98416519165039, + 40.75484819896946 + ], + [ + -73.98319959640503, + 40.75613228383523 + ], + [ + -73.98139715194702, + 40.75868412570509 + ], + [ + -73.97931575775146, + 40.75782268685437 + ], + [ + -73.97824287414551, + 40.757270059827206 + ], + [ + -73.97907972335815, + 40.756051013376364 + ], + [ + -73.97564649581909, + 40.75460438258571 + ], + [ + -73.97423028945923, + 40.75398671041169 + ], + [ + -73.97614002227783, + 40.75143468822972 + ], + [ + -73.97435903549194, + 40.7507357096525 + ] + ] + } + } + ] + } + }, + "boundary": { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [ + -73.980915406985, + 40.757460062068475 + ], + [ + -73.97993559617679, + 40.75705453718075 + ], + [ + -73.97978285721045, + 40.75697586289132 + ], + [ + -73.98013295216039, + 40.7564658767395 + ], + [ + -73.9802661238222, + 40.756019807558545 + ], + [ + -73.98009242653058, + 40.755581806995224 + ], + [ + -73.97965678803773, + 40.7552651674539 + ], + [ + -73.9762311554221, + 40.75382171882893 + ], + [ + -73.97584453587778, + 40.753653094999805 + ], + [ + -73.97717274502423, + 40.75187817755506 + ], + [ + -73.97732688933066, + 40.75141629100844 + ], + [ + -73.97714793303804, + 40.75095956456846 + ], + [ + -73.97668610118902, + 40.750636182251725 + ], + [ + -73.97490511440313, + 40.749937195280495 + ], + [ + -73.97418126210347, + 40.749846537544585 + ], + [ + -73.97352531319592, + 40.750095515074946 + ], + [ + -73.97318781786828, + 40.750589024054165 + ], + [ + -73.97329768786464, + 40.751138557905904 + ], + [ + -73.97381295658076, + 40.75153421443528 + ], + [ + -73.97449936785367, + 40.75180360585742 + ], + [ + -73.97319756671283, + 40.7535432351504 + ], + [ + -73.97304319297578, + 40.7539917982632 + ], + [ + -73.97320425720197, + 40.75443900640337 + ], + [ + -73.97363796104085, + 40.754766027529854 + ], + [ + -73.97505416740071, + 40.75538369246371 + ], + [ + -73.97506943113952, + 40.755390236318846 + ], + [ + -73.97749399824558, + 40.75641184744637 + ], + [ + -73.97718964534327, + 40.75685520148255 + ], + [ + -73.97705577268336, + 40.75727443033833 + ], + [ + -73.97719501885582, + 40.75769265102434 + ], + [ + -73.9775753472124, + 40.758013643518126 + ], + [ + -73.97864823081835, + 40.75856626436385 + ], + [ + -73.97874655265649, + 40.758611784703874 + ], + [ + -73.98082794685205, + 40.7594732133289 + ], + [ + -73.98142855938701, + 40.759583004529844 + ], + [ + -73.98202066406688, + 40.759449302909445 + ], + [ + -73.98244386765893, + 40.75910832520998 + ], + [ + -73.98423886695231, + 40.756567038356934 + ], + [ + -73.98519669908008, + 40.75529328560552 + ], + [ + -73.98520332852566, + 40.7552843514961 + ], + [ + -73.98661831357845, + 40.75335173054083 + ], + [ + -73.9875183856405, + 40.75213416813068 + ], + [ + -73.98754262111453, + 40.75209964365882 + ], + [ + -73.98883008144168, + 40.75016526245955 + ], + [ + -73.98894178359876, + 40.749615932583 + ], + [ + -73.98860593502222, + 40.749121772064484 + ], + [ + -73.98795081845319, + 40.74887153633583 + ], + [ + -73.98722666615446, + 40.748960809814065 + ], + [ + -73.98671007969114, + 40.74935549193148 + ], + [ + -73.98543424256412, + 40.75127243312102 + ], + [ + -73.98454563260901, + 40.752474506162116 + ], + [ + -73.98454326113499, + 40.75247772965659 + ], + [ + -73.98313031781153, + 40.75440758620425 + ], + [ + -73.98216808897534, + 40.75568720281612 + ], + [ + -73.98215288069312, + 40.75570806533946 + ], + [ + -73.980915406985, + 40.757460062068475 + ] + ] + ] + ] + } + } + ] + } + } + }, + "sprite": "local://sprites/sprite", + "glyphs": "local://glyphs/{fontstack}/{range}.pbf", + "layers": [ + { + "id": "border", + "type": "fill", + "source": "boundary", + "paint": { + "fill-color": "black", + "fill-opacity": 0.5 + } + }, + { + "id": "center", + "type": "line", + "source": "center", + "paint": { + "line-color": "red" + } + }, + { + "id": "circle", + "type": "symbol", + "source": "points", + "layout": { + "icon-image": "dot.sdf", + "text-field": [ + "case", + [ + "<", + [ + "distance", + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.9877700805664, + 40.74976037842817 + ], + [ + -73.98648262023926, + 40.75169477140605 + ], + [ + -73.98558139801025, + 40.752913897733926 + ], + [ + -73.98416519165039, + 40.75484819896946 + ], + [ + -73.98319959640503, + 40.75613228383523 + ], + [ + -73.98139715194702, + 40.75868412570509 + ], + [ + -73.97931575775146, + 40.75782268685437 + ], + [ + -73.97824287414551, + 40.757270059827206 + ], + [ + -73.97907972335815, + 40.756051013376364 + ], + [ + -73.97564649581909, + 40.75460438258571 + ], + [ + -73.97423028945923, + 40.75398671041169 + ], + [ + -73.97614002227783, + 40.75143468822972 + ], + [ + -73.97435903549194, + 40.7507357096525 + ] + ] + } + } + ], + 100 + ], + "In", + "Out" + ], + "text-font": [ + "Open Sans Semibold", + "Arial Unicode MS Bold" + ], + "text-size": 10 + }, + "paint": { + "text-color": "red", + "icon-color": "blue", + "icon-opacity": [ + "case", + [ + "<", + [ + "distance", + { + "type": "Feature", + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -73.9877700805664, + 40.74976037842817 + ], + [ + -73.98648262023926, + 40.75169477140605 + ], + [ + -73.98558139801025, + 40.752913897733926 + ], + [ + -73.98416519165039, + 40.75484819896946 + ], + [ + -73.98319959640503, + 40.75613228383523 + ], + [ + -73.98139715194702, + 40.75868412570509 + ], + [ + -73.97931575775146, + 40.75782268685437 + ], + [ + -73.97824287414551, + 40.757270059827206 + ], + [ + -73.97907972335815, + 40.756051013376364 + ], + [ + -73.97564649581909, + 40.75460438258571 + ], + [ + -73.97423028945923, + 40.75398671041169 + ], + [ + -73.97614002227783, + 40.75143468822972 + ], + [ + -73.97435903549194, + 40.7507357096525 + ] + ] + } + } + ], + 100 + ], + 1, + 0.5 + ] + } + } + ] +} \ No newline at end of file