Skip to content

Commit

Permalink
Merge branch 'master' into layer-lag
Browse files Browse the repository at this point in the history
  • Loading branch information
manthey authored Nov 21, 2016
2 parents bb8bf12 + 73e8285 commit 739e2ab
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 70 deletions.
106 changes: 97 additions & 9 deletions src/annotation.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var $ = require('jquery');
var inherit = require('./inherit');
var geo_event = require('./event');
var geo_action = require('./action');
var transform = require('./transform');
var util = require('./util');
var registerAnnotation = require('./registry').registerAnnotation;
Expand All @@ -16,6 +17,8 @@ var annotationState = {
edit: 'edit'
};

var annotationActionOwner = 'annotationAction';

/////////////////////////////////////////////////////////////////////////////
/**
* Base annotation class
Expand Down Expand Up @@ -121,6 +124,28 @@ var annotation = function (type, args) {
return this;
};

/**
* Return actions needed for the specified state of this annotation.
*
* @param {string} state: the state to return actions for. Defaults to
* the current state.
* @returns {array}: a list of actions.
*/
this.actions = function () {
return [];
};

/**
* Process any actions for this annotation.
*
* @param {object} evt: the action event.
* @returns {boolean|string} true to update the annotation, 'done' if the
* annotation was completed (changed from create to done state), 'remove'
* if the annotation should be removed, falsy to not update anything.
*/
this.processAction = function () {
};

/**
* Set or get options.
*
Expand Down Expand Up @@ -221,7 +246,7 @@ var annotation = function (type, args) {
* @returns {array} an array of coordinates.
*/
this.coordinates = function (gcs) {
var coord = this._coordinates();
var coord = this._coordinates() || [];
if (this.layer()) {
var map = this.layer().map();
gcs = (gcs === null ? map.gcs() : (
Expand Down Expand Up @@ -379,19 +404,81 @@ var rectangleAnnotation = function (args) {
delete args.coordinates;
annotation.call(this, 'rectangle', args);

/**
* Return actions needed for the specified state of this annotation.
*
* @param {string} state: the state to return actions for. Defaults to
* the current state.
* @returns {array}: a list of actions.
*/
this.actions = function (state) {
if (!state) {
state = this.state();
}
switch (state) {
case annotationState.create:
return [{
action: geo_action.annotation_rectangle,
name: 'rectangle create',
owner: annotationActionOwner,
input: 'left',
modifiers: {shift: false, ctrl: false},
selectionRectangle: true
}];
default:
return [];
}
};

/**
* Process any actions for this annotation.
*
* @param {object} evt: the action event.
* @returns {boolean|string} true to update the annotation, 'done' if the
* annotation was completed (changed from create to done state), 'remove'
* if the annotation should be removed, falsy to not update anything.
*/
this.processAction = function (evt) {
var layer = this.layer();
if (this.state() !== annotationState.create || !layer ||
evt.state.action !== geo_action.annotation_rectangle) {
return;
}
var map = layer.map();
this.options('corners', [
/* Keep in map gcs, not interface gcs to avoid wrapping issues */
map.displayToGcs({x: evt.lowerLeft.x, y: evt.lowerLeft.y}, null),
map.displayToGcs({x: evt.lowerLeft.x, y: evt.upperRight.y}, null),
map.displayToGcs({x: evt.upperRight.x, y: evt.upperRight.y}, null),
map.displayToGcs({x: evt.upperRight.x, y: evt.lowerLeft.y}, null)
]);
this.state(annotationState.done);
return 'done';
};

/**
* Get a list of renderable features for this annotation.
*
* @returns {array} an array of features.
*/
this.features = function () {
var opt = this.options();
return [{
polygon: {
polygon: opt.corners,
style: opt.style
}
}];
var opt = this.options(),
state = this.state(),
features;
switch (state) {
case annotationState.create:
features = [];
break;
default:
features = [{
polygon: {
polygon: opt.corners,
style: opt.style
}
}];
break;
}
return features;
};

/**
Expand Down Expand Up @@ -420,7 +507,7 @@ var rectangleAnnotation = function (args) {
*/
this._geojsonCoordinates = function (gcs) {
var src = this.coordinates(gcs);
if (!src || src.length < 4) {
if (!src || this.state() === annotationState.create || src.length < 4) {
return;
}
var coor = [];
Expand Down Expand Up @@ -849,6 +936,7 @@ registerAnnotation('point', pointAnnotation, pointRequiredFeatures);

module.exports = {
state: annotationState,
actionOwner: annotationActionOwner,
annotation: annotation,
pointAnnotation: pointAnnotation,
polygonAnnotation: polygonAnnotation,
Expand Down
88 changes: 41 additions & 47 deletions src/annotationLayer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
var inherit = require('./inherit');
var featureLayer = require('./featureLayer');
var geo_action = require('./action');
var geo_annotation = require('./annotation');
var geo_event = require('./event');
var registry = require('./registry');
Expand Down Expand Up @@ -47,7 +46,6 @@ var annotationLayer = function (args) {
s_update = this._update,
m_buildTime = timestamp(),
m_options,
m_actions,
m_mode = null,
m_annotations = [],
m_features = [];
Expand All @@ -70,39 +68,44 @@ var annotationLayer = function (args) {
finalPointProximity: 10 // in pixels, 0 is exact
}, args);

m_actions = {
rectangle: {
action: geo_action.annotation_rectangle,
owner: 'annotationLayer',
input: 'left',
modifiers: {shift: false, ctrl: false},
selectionRectangle: true
}
};

/**
* Process a selection event. If we are in rectangle-creation mode, this
* creates a rectangle.
*
* @param {geo.event} evt the selection event.
*/
this._processSelection = function (evt) {
if (m_this.mode() === 'rectangle') {
m_this.mode(null);
if (evt.state.action === geo_action.annotation_rectangle) {
var map = m_this.map();
var params = {
corners: [
/* Keep in map gcs, not interface gcs to avoid wrapping issues */
map.displayToGcs({x: evt.lowerLeft.x, y: evt.lowerLeft.y}, null),
map.displayToGcs({x: evt.lowerLeft.x, y: evt.upperRight.y}, null),
map.displayToGcs({x: evt.upperRight.x, y: evt.upperRight.y}, null),
map.displayToGcs({x: evt.upperRight.x, y: evt.lowerLeft.y}, null)
],
layer: this
};
this.addAnnotation(geo_annotation.rectangleAnnotation(params));
}
var update;
if (evt.state && evt.state.actionRecord &&
evt.state.actionRecord.owner === geo_annotation.actionOwner &&
this.currentAnnotation) {
update = this.currentAnnotation.processAction(evt);
}
this._updateFromEvent(update);
};

/**
* Handle updating the current annotation based on an update state.
*
* @param {string|undefined} update: truthy to update. 'done' if the
* annotation was completed and the mode should return to null. 'remove'
* to remove the current annotation and set the mode to null. Falsy to do
* nothing.
*/
this._updateFromEvent = function (update) {
switch (update) {
case 'remove':
m_this.removeAnnotation(m_this.currentAnnotation, false);
m_this.mode(null);
break;
case 'done':
m_this.mode(null);
break;
}
if (update) {
m_this.modified();
m_this._update();
m_this.draw();
}
};

Expand Down Expand Up @@ -132,20 +135,7 @@ var annotationLayer = function (args) {
this._handleMouseClick = function (evt) {
if (this.mode() && this.currentAnnotation) {
var update = this.currentAnnotation.mouseClick(evt);
switch (update) {
case 'remove':
m_this.removeAnnotation(m_this.currentAnnotation, false);
m_this.mode(null);
break;
case 'done':
m_this.mode(null);
break;
}
if (update) {
m_this.modified();
m_this._update();
m_this.draw();
}
this._updateFromEvent(update);
}
};

Expand Down Expand Up @@ -323,7 +313,8 @@ var annotationLayer = function (args) {
return m_mode;
}
if (arg !== m_mode) {
var createAnnotation, mapNode = m_this.map().node(), oldMode = m_mode;
var createAnnotation, actions,
mapNode = m_this.map().node(), oldMode = m_mode;
m_mode = arg;
mapNode.css('cursor', m_mode ? 'crosshair' : '');
if (m_mode) {
Expand All @@ -347,18 +338,21 @@ var annotationLayer = function (args) {
createAnnotation = geo_annotation.polygonAnnotation;
break;
case 'rectangle':
m_this.map().interactor().addAction(m_actions.rectangle);
createAnnotation = geo_annotation.rectangleAnnotation;
break;
}
m_this.map().interactor().removeAction(
undefined, undefined, geo_annotation.actionOwner);
if (createAnnotation) {
this.currentAnnotation = createAnnotation({
state: geo_annotation.state.create,
layer: this
});
this.addAnnotation(m_this.currentAnnotation);
}
if (m_mode !== 'rectangle') {
m_this.map().interactor().removeAction(m_actions.rectangle);
actions = this.currentAnnotation.actions(geo_annotation.state.create);
$.each(actions, function (idx, action) {
m_this.map().interactor().addAction(action);
});
}
m_this.geoTrigger(geo_event.annotation.mode, {
mode: m_mode, oldMode: oldMode});
Expand Down
14 changes: 12 additions & 2 deletions src/camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,17 @@

/**
* Getter/setter for the viewport.
*
* The viewport consists of a width and height in pixels, plus a left and
* top offset in pixels. The offsets are only used to determine if pixel
* alignment is possible.
*/
Object.defineProperty(this, 'viewport', {
get: function () {
return {width: this._viewport.width, height: this._viewport.height};
return {
width: this._viewport.width, height: this._viewport.height,
left: this._viewport.left, top: this._viewport.top
};
},
set: function (viewport) {
if (!(viewport.width > 0 &&
Expand Down Expand Up @@ -335,7 +342,10 @@
]);
}

this._viewport = {width: viewport.width, height: viewport.height};
this._viewport = {
width: viewport.width, height: viewport.height,
left: viewport.left, top: viewport.top
};
this._update();
this.geoTrigger(geo_event.camera.viewport, {
camera: this,
Expand Down
20 changes: 16 additions & 4 deletions src/gl/vglRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,20 @@ var vglRenderer = function (arg) {
m_lastZoom = map.zoom();
cam.setViewMatrix(view, true);
cam.setProjectionMatrix(proj);
var viewport = camera.viewport;
/* Test if we should align texels. We won't if the projection matrix
* is not simple, if there is a rotation that isn't a multiple of 90
* degrees, if the viewport is not at an integer location, or if the zoom
* level is not close to an integer.
* Note that the test for the viewport is strict (val % 1 is non-zero
* if the value is not an integer), as, in general, the alignment is only
* non-integral if a percent offset or calculation was used in css
* somewhere. The test for zoom level always has some allowance for
* precision, as it is often the result of repeated computations. */
if (proj[1] || proj[2] || proj[3] || proj[4] || proj[6] || proj[7] ||
proj[8] || proj[9] || proj[11] || proj[15] !== 1 || !ortho ||
(viewport.left && viewport.left % 1) ||
(viewport.top && viewport.top % 1) ||
(parseFloat(m_lastZoom.toFixed(6)) !==
parseFloat(m_lastZoom.toFixed(0)))) {
/* Don't align texels */
Expand All @@ -208,11 +220,11 @@ var vglRenderer = function (arg) {
* probably be divided by window.devicePixelRatio. */
cam.viewAlignment = function () {
var align = {
roundx: 2.0 / camera.viewport.width,
roundy: 2.0 / camera.viewport.height
roundx: 2.0 / viewport.width,
roundy: 2.0 / viewport.height
};
align.dx = (camera.viewport.width % 2) ? align.roundx * 0.5 : 0;
align.dy = (camera.viewport.height % 2) ? align.roundy * 0.5 : 0;
align.dx = (viewport.width % 2) ? align.roundx * 0.5 : 0;
align.dy = (viewport.height % 2) ? align.roundy * 0.5 : 0;
return align;
};
}
Expand Down
10 changes: 8 additions & 2 deletions src/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,10 @@ var map = function (arg) {
m_unitsPerPixel = (arg.unitsPerPixel || (
m_maxBounds.right - m_maxBounds.left) / 256);

m_camera.viewport = {width: m_width, height: m_height};
m_camera.viewport = {
width: m_width, height: m_height,
left: m_node.offset().left, top: m_node.offset().top
};
arg.center = util.normalizeCoordinates(arg.center);
arg.autoResize = arg.autoResize === undefined ? true : arg.autoResize;
m_clampBoundsX = arg.clampBoundsX === undefined ? false : arg.clampBoundsX;
Expand Down Expand Up @@ -687,7 +690,10 @@ var map = function (arg) {
if (newZoom !== m_zoom) {
m_this.zoom(newZoom);
}
m_this.camera().viewport = {width: m_width, height: m_height};
m_this.camera().viewport = {
width: m_width, height: m_height,
left: m_node.offset().left, top: m_node.offset().top
};
m_this.center(oldCenter);

m_this.geoTrigger(geo_event.resize, {
Expand Down
Loading

0 comments on commit 739e2ab

Please sign in to comment.