Skip to content

Commit

Permalink
Merge pull request #635 from OpenGeoscience/quad-location
Browse files Browse the repository at this point in the history
Report where in a quad a point is located.
  • Loading branch information
manthey authored Oct 27, 2016
2 parents 6861609 + 4b1c4fd commit 6c9cd90
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 9 deletions.
10 changes: 8 additions & 2 deletions src/feature.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,13 @@ var feature = function (arg) {
var mouse = m_this.layer().map().interactor().mouse(),
data = m_this.data(),
over = m_this.pointSearch(mouse.geo),
newFeatures = [], oldFeatures = [], lastTop = -1, top = -1;
newFeatures = [], oldFeatures = [], lastTop = -1, top = -1, extra;

// exit if we have no old or new found entries
if (!m_selectedFeatures.length && !over.index.length) {
return;
}
extra = over.extra || {};
// Get the index of the element that was previously on top
if (m_selectedFeatures.length) {
lastTop = m_selectedFeatures[m_selectedFeatures.length - 1];
Expand All @@ -164,6 +165,7 @@ var feature = function (arg) {
m_this.geoTrigger(geo_event.feature.mouseover, {
data: data[i],
index: i,
extra: extra[i],
mouse: mouse,
eventID: feature.eventID,
top: idx === newFeatures.length - 1
Expand All @@ -188,6 +190,7 @@ var feature = function (arg) {
m_this.geoTrigger(geo_event.feature.mousemove, {
data: data[i],
index: i,
extra: extra[i],
mouse: mouse,
eventID: feature.eventID,
top: idx === over.index.length - 1
Expand Down Expand Up @@ -216,6 +219,7 @@ var feature = function (arg) {
m_this.geoTrigger(geo_event.feature.mouseon, {
data: data[top],
index: top,
extra: extra[top],
mouse: mouse
}, true);
}
Expand All @@ -230,14 +234,16 @@ var feature = function (arg) {
this._handleMouseclick = function (evt) {
var mouse = m_this.layer().map().interactor().mouse(),
data = m_this.data(),
over = m_this.pointSearch(mouse.geo);
over = m_this.pointSearch(mouse.geo),
extra = over.extra || {};

mouse.buttonsDown = evt.buttonsDown;
feature.eventID += 1;
over.index.forEach(function (i, idx) {
m_this.geoTrigger(geo_event.feature.mouseclick, {
data: data[i],
index: i,
extra: extra[i],
mouse: mouse,
eventID: feature.eventID,
top: idx === over.index.length - 1
Expand Down
36 changes: 31 additions & 5 deletions src/quadFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,12 @@ var quadFeature = function (arg) {
*/
////////////////////////////////////////////////////////////////////////////
this.pointSearch = function (coordinate) {
var found = [], indices = [], data = m_this.data(), i,
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(),
order1 = [0, 1, 2, 0], order2 = [1, 2, 3, 1];
i, coordbasis;
coordinate = transform.transformCoordinates(
map.ingcs(), map.gcs(), coordinate);
if (!m_quads) {
Expand All @@ -161,12 +163,36 @@ var quadFeature = function (arg) {
util.pointInPolygon(coordinate, poly2)) {
indices.push(quad.idx);
found.push(data[quad.idx]);
/* If a point is in the quad (based on pointInPolygon, above), check
* where in the quad it is located. We want to output coordinates
* where the upper-left is (0, 0) and the lower-right is (1, 1). */
coordbasis = util.pointTo2DTriangleBasis(
coordinate, poly1[0], poly1[1], poly1[2]);
if (!coordbasis || coordbasis.x + coordbasis.y > 1) {
coordbasis = util.pointTo2DTriangleBasis(
coordinate, poly2[2], poly2[1], poly2[0]);
if (coordbasis) {
/* In the second triangle, (0, 0) is upper-right, (1, 0) is
* upper-left, and (0, 1) is lower-right. Invert x to get to
* the desired output coordinates. */
coordbasis.x = 1 - coordbasis.x;
}
} else {
/* In the first triangle, (0, 0) is lower-left, (1, 0) is lower-
* right, and (0, 1) is upper-left. Invert y to get to the
* desired output coordinates. */
coordbasis.y = 1 - coordbasis.y;
}
if (coordbasis) {
extra[quad.idx] = {basis: coordbasis};
}
}
});
});
return {
index: indices,
found: found
found: found,
extra: extra
};
};

Expand Down Expand Up @@ -241,7 +267,7 @@ var quadFeature = function (arg) {

/**
* Convert the current data set to a pair of arrays, one of quads that are
* solid color and one of qudas that have an image. All quads are objects
* solid color and one of quads that have an image. All quads are objects
* with pos (a 12 value array containing 4 three-dimensional position
* coordinates), and opacity. Color quads also have a color. Image quads
* may have an image element, if the image is loaded. If it isn't, this
Expand Down Expand Up @@ -275,7 +301,7 @@ var quadFeature = function (arg) {
clrQuads = [], imgQuads = [],
origin = [0, 0, 0], origindiag2, diag2;
/* Keep track of images that we are using. This prevents creating
* additional Image elemnts for repeated urls. */
* additional Image elements for repeated urls. */
m_this._objectListStart(m_images);
$.each(data, function (i, d) {
if (d._cachedQuad) {
Expand Down
26 changes: 26 additions & 0 deletions src/util/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,32 @@
return inside;
},

/**
* Return a point in the basis of the triangle. If the point is located on
* a vertex of the triangle, it will be at vert0: (0, 0), vert1: (1, 0),
* vert2: (0, 1). If it is within the triangle, its coordinates will be
* 0 <= x <= 1, 0 <= y <= 1, x + y <= 1.
*
* @param {object} point: the point to convert.
* @param {object} vert0: vertex 0 of the triangle
* @param {object} vert1: vertex 1 (x direction) of the triangle
* @param {object} vert2: vertex 2 (y direction) of the triangle
* @returns {object} basisPoint: the point in the triangle basis, or
* undefined if the triangle is degenerate.
*/
pointTo2DTriangleBasis: function (point, vert0, vert1, vert2) {
var a = vert1.x - vert0.x,
b = vert2.x - vert0.x,
c = vert1.y - vert0.y,
d = vert2.y - vert0.y,
x = point.x - vert0.x,
y = point.y - vert0.y,
det = a * d - b * c;
if (det) {
return {x: (x * d - y * b) / det, y: (x * -c + y * a) / det};
}
},

/**
* Returns true if the argument is a function.
*/
Expand Down
17 changes: 15 additions & 2 deletions tests/cases/quadFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,9 @@ describe('geo.quadFeature', function () {
quad = geo.quadFeature({layer: layer});
quad._init();
data = [{
ll: [-60, 10], ur: [-40, 30], image: preloadImage
ll: [-40, 30], ur: [-60, 10], image: preloadImage
}, {
ll: [-90, 10], ur: [-100, 10], image: preloadImage
}, {
ll: [-80, 10], lr: [-50, 10], ur: [-70, 30], image: preloadImage
}];
Expand All @@ -205,12 +207,23 @@ describe('geo.quadFeature', function () {
expect(pt.index).toEqual([0]);
expect(pt.found.length).toBe(1);
expect(pt.found[0].ll).toEqual(data[0].ll);
expect(pt.extra[0].basis.x).toBeCloseTo(0.25);
expect(pt.extra[0].basis.y).toBeCloseTo(0.047477);
pt = quad.pointSearch({x: -55, y: 11});
expect(pt.index).toEqual([0, 1]);
expect(pt.index).toEqual([0, 2]);
expect(pt.found.length).toBe(2);
expect(pt.extra[0].basis.x).toBeCloseTo(0.75);
expect(pt.extra[0].basis.y).toBeCloseTo(0.047477);
expect(pt.extra[2].basis.x).toBeCloseTo(0.833333);
expect(pt.extra[2].basis.y).toBeCloseTo(0.952523);
pt = quad.pointSearch({x: -35, y: 11});
expect(pt.index).toEqual([]);
expect(pt.found.length).toBe(0);
/* not in a degenerate quad */
pt = quad.pointSearch({x: -95, y: 10});
expect(pt.index).toEqual([]);
expect(pt.found.length).toBe(0);
expect(pt.extra[1]).toBe(undefined);
});
});
});
Expand Down

0 comments on commit 6c9cd90

Please sign in to comment.