Skip to content

Commit

Permalink
Merge pull request #1051 from OpenGeoscience/search-gcs
Browse files Browse the repository at this point in the history
Add a gcs option to pointSearch and polygonSearch.
  • Loading branch information
manthey authored Apr 14, 2020
2 parents f36a947 + e82fe5a commit 3b67dfe
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 48 deletions.
23 changes: 14 additions & 9 deletions src/feature.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: [],
Expand All @@ -195,36 +197,39 @@ 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);
};

/**
* Search for features contained within a polygon. This should be defined in
* 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: [],
Expand Down
23 changes: 14 additions & 9 deletions src/lineFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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(),
Expand Down Expand Up @@ -264,25 +267,27 @@ 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
* indicating one of the line segments that is inside the polygon and
* `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: []};
}
Expand All @@ -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};
Expand Down
21 changes: 13 additions & 8 deletions src/markerFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -259,21 +262,22 @@ 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
* value to indicate if the marker is on the polygon's border and a
* `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 = [],
Expand All @@ -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: []};
}
Expand All @@ -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};
Expand Down
8 changes: 5 additions & 3 deletions src/pixelmapFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 10 additions & 7 deletions src/pointFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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),
Expand Down Expand Up @@ -357,21 +359,22 @@ 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
* value to indicate if the point is on the polygon's border and a
* `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 = [],
Expand All @@ -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};
Expand Down
22 changes: 13 additions & 9 deletions src/polygonFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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: []};
}
Expand All @@ -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};
Expand Down
9 changes: 6 additions & 3 deletions src/quadFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down

0 comments on commit 3b67dfe

Please sign in to comment.