From e82fe5aea0b76e02308f6c3ede5d2260e35b6e60 Mon Sep 17 00:00:00 2001 From: David Manthey Date: Fri, 10 Apr 2020 08:26:30 -0400 Subject: [PATCH] Add a gcs option to pointSearch and polygonSearch. --- src/feature.js | 23 ++++++++++++++--------- src/lineFeature.js | 23 ++++++++++++++--------- src/markerFeature.js | 21 +++++++++++++-------- src/pixelmapFeature.js | 8 +++++--- src/pointFeature.js | 17 ++++++++++------- src/polygonFeature.js | 22 +++++++++++++--------- src/quadFeature.js | 9 ++++++--- 7 files changed, 75 insertions(+), 48 deletions(-) diff --git a/src/feature.js b/src/feature.js index 240f0da186..8985ed4395 100644 --- a/src/feature.js +++ b/src/feature.js @@ -180,11 +180,13 @@ var feature = function (arg) { * Search for features containing the given point. This should be defined in * relevant subclasses. * - * @param {geo.geoPosition} geo Coordinate in interface gcs. + * @param {geo.geoPosition} geo Coordinate. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {geo.feature.searchResult} An object with a list of features and * feature indices that are located at the specified point. */ - this.pointSearch = function (geo) { + this.pointSearch = function (geo, gcs) { // base class method does nothing return { index: [], @@ -195,19 +197,21 @@ var feature = function (arg) { /** * Search for features contained within a rectangular region. * - * @param {geo.geoPosition} lowerLeft Lower-left corner in gcs coordinates. - * @param {geo.geoPosition} upperRight Upper-right corner in gcs coordinates. + * @param {geo.geoPosition} lowerLeft Lower-left corner. + * @param {geo.geoPosition} upperRight Upper-right corner. * @param {object} [opts] Additional search options. * @param {boolean} [opts.partial=false] If truthy, include features that are * partially in the box, otherwise only include features that are fully * within the region. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {geo.feature.searchResult} An object with a list of features and * feature indices that are located at the specified point. */ - this.boxSearch = function (lowerLeft, upperRight, opts) { + this.boxSearch = function (lowerLeft, upperRight, opts, gcs) { return m_this.polygonSearch([ lowerLeft, {x: lowerLeft.x, y: upperRight.y}, - upperRight, {x: upperRight.x, y: lowerLeft.y}], opts); + upperRight, {x: upperRight.x, y: lowerLeft.y}], opts, gcs); }; /** @@ -215,16 +219,17 @@ var feature = function (arg) { * relevant subclasses. * * @param {geo.polygonObject} poly A polygon as an array of coordinates or an - * object with `outer` and optionally `inner` parameters. All coordinates - * are in map interface gcs. + * object with `outer` and optionally `inner` parameters. * @param {object} [opts] Additional search options. * @param {boolean} [opts.partial=false] If truthy, include features that are * partially in the polygon, otherwise only include features that are * fully within the region. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {geo.feature.searchResult} An object with a list of features and * feature indices that are located at the specified point. */ - this.polygonSearch = function (poly, opts) { + this.polygonSearch = function (poly, opts, gcs) { // base class method does nothing return { index: [], diff --git a/src/lineFeature.js b/src/lineFeature.js index f700fc23fe..556f18fdff 100644 --- a/src/lineFeature.js +++ b/src/lineFeature.js @@ -210,13 +210,15 @@ var lineFeature = function (arg) { * width lines will have a greater selection region than their visual size at * the narrow end. * - * @param {geo.geoPosition} p point to search for in map interface gcs. + * @param {geo.geoPosition} p point to search for. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of line indices, `found`: * a list of lines that contain the specified coordinate, and `extra`: an * object with keys that are line indices and values that are the first * segement index for which the line was matched. */ - this.pointSearch = function (p) { + this.pointSearch = function (p, gcs) { var data = m_this.data(), indices = [], found = [], extra = {}; if (!data || !data.length || !m_this.layer()) { return { @@ -226,10 +228,11 @@ var lineFeature = function (arg) { }; } m_this._updatePointSearchInfo(); - var map = m_this.layer().map(), - scale = map.unitsPerPixel(map.zoom()), + var map = m_this.layer().map(); + gcs = (gcs === null ? map.gcs() : (gcs === undefined ? map.ingcs() : gcs)); + var scale = map.unitsPerPixel(map.zoom()), scale2 = scale * scale, - pt = transform.transformCoordinates(map.ingcs(), map.gcs(), p), + pt = transform.transformCoordinates(gcs, map.gcs(), p), strokeWidthFunc = m_this.style.get('strokeWidth'), strokeOpacityFunc = m_this.style.get('strokeOpacity'), lineFunc = m_this.line(), @@ -264,12 +267,13 @@ var lineFeature = function (arg) { * Returns lines that are contained in the given polygon. * * @param {geo.polygonObject} poly A polygon as an array of coordinates or an - * object with `outer` and optionally `inner` parameters. All coordinates - * are in map interface gcs. + * object with `outer` and optionally `inner` parameters. * @param {object} [opts] Additional search options. * @param {boolean} [opts.partial=false] If truthy, include lines that are * partially in the polygon, otherwise only include lines that are fully * within the region. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of line indices, * `found`: a list of lines within the polygon, and `extra`: an object * with index keys containing an object with a `segment` key with a value @@ -277,12 +281,13 @@ var lineFeature = function (arg) { * `partial` key and a boolean value to indicate if the line is on the * polygon's border. */ - this.polygonSearch = function (poly, opts) { + this.polygonSearch = function (poly, opts, gcs) { var data = m_this.data(), indices = [], found = [], extra = {}, min, max, map = m_this.layer().map(), strokeWidthFunc = m_this.style.get('strokeWidth'), strokeOpacityFunc = m_this.style.get('strokeOpacity'), lineFunc = m_this.line(); + gcs = (gcs === null ? map.gcs() : (gcs === undefined ? map.ingcs() : gcs)); if (!poly.outer) { poly = {outer: poly, inner: []}; } @@ -295,7 +300,7 @@ var lineFeature = function (arg) { } opts = opts || {}; opts.partial = opts.partial || false; - poly = {outer: transform.transformCoordinates(map.ingcs(), map.gcs(), poly.outer), inner: (poly.inner || []).map(inner => transform.transformCoordinates(map.ingcs(), map.gcs(), inner))}; + poly = {outer: transform.transformCoordinates(gcs, map.gcs(), poly.outer), inner: (poly.inner || []).map(inner => transform.transformCoordinates(gcs, map.gcs(), inner))}; poly.outer.forEach(p => { if (!min) { min = {x: p.x, y: p.y}; diff --git a/src/markerFeature.js b/src/markerFeature.js index 5f1d36506b..866786f990 100644 --- a/src/markerFeature.js +++ b/src/markerFeature.js @@ -161,11 +161,13 @@ var markerFeature = function (arg) { /** * Returns an array of datum indices that contain the given marker. * - * @param {geo.geoPosition} p marker to search for in map interface gcs. + * @param {geo.geoPosition} p marker to search for. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of marker indices, and * `found`: a list of markers that contain the specified coordinate. */ - this.pointSearch = function (p) { + this.pointSearch = function (p, gcs) { var min, max, data, idx = [], found = [], ifound = [], fgcs = m_this.gcs(), // this feature's gcs corners, @@ -186,8 +188,9 @@ var markerFeature = function (arg) { // determined then m_this._updateRangeTree(); - var map = m_this.layer().map(), - pt = map.gcsToDisplay(p), + var map = m_this.layer().map(); + gcs = (gcs === null ? map.gcs() : (gcs === undefined ? map.ingcs() : gcs)); + var pt = map.gcsToDisplay(p, gcs), zoom = map.zoom(), zoomFactor = Math.pow(2, zoom), maxr = this._approximateMaxRadius(zoom); @@ -259,13 +262,14 @@ var markerFeature = function (arg) { * This does not take clustering into account. * * @param {geo.polygonObject} poly A polygon as an array of coordinates or an - * object with `outer` and optionally `inner` parameters. All coordinates - * are in map interface gcs. + * object with `outer` and optionally `inner` parameters. * @param {object} [opts] Additional search options. * @param {boolean} [opts.partial=false] If truthy, include markers that are * partially in the polygon, otherwise only include markers that are fully * within the region. If 'center', only markers whose centers are inside * the polygon are returned. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of marker indices, * `found`: a list of markers within the polygon, and `extra`: an object * with index keys containing an object with a `partial` key and a boolean @@ -273,7 +277,7 @@ var markerFeature = function (arg) { * `distance` key to indicate how far within the polygon the marker is * located. */ - this.polygonSearch = function (poly, opts) { + this.polygonSearch = function (poly, opts, gcs) { var fgcs = m_this.gcs(), // this feature's gcs found = [], ifound = [], @@ -289,6 +293,7 @@ var markerFeature = function (arg) { zoomFactor = Math.pow(2, zoom), maxr = this._approximateMaxRadius(zoom); + gcs = (gcs === null ? map.gcs() : (gcs === undefined ? map.ingcs() : gcs)); if (!poly.outer) { poly = {outer: poly, inner: []}; } @@ -301,7 +306,7 @@ var markerFeature = function (arg) { } opts = opts || {}; opts.partial = opts.partial || false; - poly = {outer: map.gcsToDisplay(poly.outer), inner: (poly.inner || []).map(inner => map.gcsToDisplay(inner))}; + poly = {outer: map.gcsToDisplay(poly.outer, gcs), inner: (poly.inner || []).map(inner => map.gcsToDisplay(inner, gcs))}; poly.outer.forEach(p => { if (!min) { min = {x: p.x, y: p.y}; diff --git a/src/pixelmapFeature.js b/src/pixelmapFeature.js index 2bee447dcc..e3fca27b62 100644 --- a/src/pixelmapFeature.js +++ b/src/pixelmapFeature.js @@ -165,13 +165,15 @@ var pixelmapFeature = function (arg) { * information from the quad to determine the pixelmap index value so that it * can be included in the `found` results. * - * @param {geo.geoPosition} geo Coordinate in interface gcs. + * @param {geo.geoPosition} geo Coordinate. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {geo.feature.searchResult} An object with a list of features and * feature indices that are located at the specified point. */ - this.pointSearch = function (geo) { + this.pointSearch = function (geo, gcs) { if (m_quadFeature && m_info) { - var result = m_quadFeature.pointSearch(geo); + var result = m_quadFeature.pointSearch(geo, gcs); if (result.index.length === 1 && result.extra && result.extra[result.index[0]].basis) { var basis = result.extra[result.index[0]].basis, x, y, idx; x = Math.floor(basis.x * m_info.width); diff --git a/src/pointFeature.js b/src/pointFeature.js index fa59268e45..2965b45301 100644 --- a/src/pointFeature.js +++ b/src/pointFeature.js @@ -276,11 +276,13 @@ var pointFeature = function (arg) { * https://github.com/dotskapes/wigglemaps/blob/cf5bed3fbfe2c3e48d31799462a80c564be1fb60/src/query/PointQuerier.js * This does not take into account clustering. * - * @param {geo.geoPosition} p point to search for in map interface gcs. + * @param {geo.geoPosition} p point to search for. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of point indices, and * `found`: a list of points that contain the specified coordinate. */ - this.pointSearch = function (p) { + this.pointSearch = function (p, gcs) { var min, max, data, idx = [], found = [], ifound = [], map, pt, fgcs = m_this.gcs(), // this feature's gcs corners, @@ -302,7 +304,7 @@ var pointFeature = function (arg) { m_this._updateRangeTree(); map = m_this.layer().map(); - pt = map.gcsToDisplay(p); + pt = map.gcsToDisplay(p, gcs); // check all corners to make sure we handle rotations corners = [ map.displayToGcs({x: pt.x - m_maxRadius, y: pt.y - m_maxRadius}, fgcs), @@ -357,13 +359,14 @@ var pointFeature = function (arg) { * This does not take clustering into account. * * @param {geo.polygonObject} poly A polygon as an array of coordinates or an - * object with `outer` and optionally `inner` parameters. All coordinates - * are in map interface gcs. + * object with `outer` and optionally `inner` parameters. * @param {object} [opts] Additional search options. * @param {boolean} [opts.partial=false] If truthy, include points that are * partially in the polygon, otherwise only include points that are fully * within the region. If 'center', only points whose centers are inside * the polygon are returned. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of point indices, * `found`: a list of points within the polygon, and `extra`: an object * with index keys containing an object with a `partial` key and a boolean @@ -371,7 +374,7 @@ var pointFeature = function (arg) { * `distance` key to indicate how far within the polygon the point is * located. */ - this.polygonSearch = function (poly, opts) { + this.polygonSearch = function (poly, opts, gcs) { var fgcs = m_this.gcs(), // this feature's gcs found = [], ifound = [], @@ -395,7 +398,7 @@ var pointFeature = function (arg) { } opts = opts || {}; opts.partial = opts.partial || false; - poly = {outer: map.gcsToDisplay(poly.outer), inner: (poly.inner || []).map(inner => map.gcsToDisplay(inner))}; + poly = {outer: map.gcsToDisplay(poly.outer, gcs), inner: (poly.inner || []).map(inner => map.gcsToDisplay(inner, gcs))}; poly.outer.forEach(p => { if (!min) { min = {x: p.x, y: p.y}; diff --git a/src/polygonFeature.js b/src/polygonFeature.js index 45950d6ab9..2db62abe87 100644 --- a/src/polygonFeature.js +++ b/src/polygonFeature.js @@ -260,15 +260,17 @@ var polygonFeature = function (arg) { * Point search method for selection api. Returns markers containing the * given point. * - * @param {geo.geoPosition} coordinate point to search for in map interface - * gcs. + * @param {geo.geoPosition} coordinate point to search for. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of polygon indices, and * `found`: a list of polygons that contain the specified coordinate. */ - this.pointSearch = function (coordinate) { + this.pointSearch = function (coordinate, gcs) { var found = [], indices = [], irecord = {}, data = m_this.data(), - map = m_this.layer().map(), - pt = transform.transformCoordinates(map.ingcs(), map.gcs(), coordinate); + map = m_this.layer().map(); + gcs = (gcs === null ? map.gcs() : (gcs === undefined ? map.ingcs() : gcs)); + var pt = transform.transformCoordinates(gcs, map.gcs(), coordinate); m_coordinates.forEach(function (coord, i) { var inside = util.pointInPolygon( pt, @@ -304,21 +306,23 @@ var polygonFeature = function (arg) { * specified polygon and whose vertices are not near the selected polygon. * * @param {geo.polygonObject} poly A polygon as an array of coordinates or an - * object with `outer` and optionally `inner` parameters. All coordinates - * are in map interface gcs. + * object with `outer` and optionally `inner` parameters. * @param {object} [opts] Additional search options. * @param {boolean} [opts.partial=false] If truthy, include polygons that are * partially in the polygon, otherwise only include polygons that are fully * within the region. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of polygon indices, * `found`: a list of polygons within the polygon, and `extra`: an object * with index keys containing an object with a `partial` key and a boolean * value to indicate if the polygon is on the specified polygon's border. */ - this.polygonSearch = function (poly, opts) { + this.polygonSearch = function (poly, opts, gcs) { var data = m_this.data(), indices = [], found = [], extra = {}, min, max, origPoly = poly, irecord = {}, map = m_this.layer().map(); + gcs = (gcs === null ? map.gcs() : (gcs === undefined ? map.ingcs() : gcs)); if (!poly.outer) { poly = {outer: poly, inner: []}; } @@ -331,7 +335,7 @@ var polygonFeature = function (arg) { } opts = opts || {}; opts.partial = opts.partial || false; - poly = {outer: transform.transformCoordinates(map.ingcs(), map.gcs(), poly.outer), inner: (poly.inner || []).map(inner => transform.transformCoordinates(map.ingcs(), map.gcs(), inner))}; + poly = {outer: transform.transformCoordinates(gcs, map.gcs(), poly.outer), inner: (poly.inner || []).map(inner => transform.transformCoordinates(gcs, map.gcs(), inner))}; poly.outer.forEach(p => { if (!min) { min = {x: p.x, y: p.y}; diff --git a/src/quadFeature.js b/src/quadFeature.js index 1552bbd0e4..595076c6c0 100644 --- a/src/quadFeature.js +++ b/src/quadFeature.js @@ -154,21 +154,24 @@ var quadFeature = function (arg) { * given point. * * @param {geo.geoPosition} coordinate Coordinate in input gcs to check if it - * is located in any quad in map interface gcs. + * is located in any quad. + * @param {string|geo.transform|null} [gcs] Input gcs. `undefined` to use + * the interface gcs, `null` to use the map gcs, or any other transform. * @returns {object} An object with `index`: a list of quad indices, `found`: * a list of quads that contain the specified coordinate, and `extra`: an * object with keys that are quad indices and values that are objects with * `basis.x` and `basis.y`, values from 0 - 1 relative to interior of the * quad. */ - this.pointSearch = function (coordinate) { + this.pointSearch = function (coordinate, gcs) { var found = [], indices = [], extra = {}, poly1 = [{}, {}, {}, {}], poly2 = [{}, {}, {}, {}], order1 = [0, 1, 2, 0], order2 = [1, 2, 3, 1], data = m_this.data(), map = m_this.layer().map(), i, coordbasis; - coordinate = transform.transformCoordinates(map.ingcs(), map.gcs(), coordinate); + gcs = (gcs === null ? map.gcs() : (gcs === undefined ? map.ingcs() : gcs)); + coordinate = transform.transformCoordinates(gcs, map.gcs(), coordinate); if (!m_quads) { m_this._generateQuads(); }