Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Annotation geojson #617

Merged
merged 10 commits into from
Oct 12, 2016
Next Next commit
Export annotations in a geojson compatible object.
  • Loading branch information
manthey committed Sep 23, 2016
commit 8112e5a9c6074da8de288af7074a7cb0a3c7597e
9 changes: 1 addition & 8 deletions examples/annotations/main.js
Original file line number Diff line number Diff line change
@@ -266,14 +266,7 @@ $(function () {
value = opt.style[key];
switch (format) {
case 'color':
value = geo.util.convertColor(value);
if (!value.r && !value.g && !value.b) {
value = '#000000';
} else {
value = '#' + ((1 << 24) + (Math.round(value.r * 255) << 16) +
(Math.round(value.g * 255) << 8) +
Math.round(value.b * 255)).toString(16).slice(1);
}
value = geo.util.convertColorToHex(value);
break;
}
$('[option]', ctl).val('' + value);
181 changes: 178 additions & 3 deletions src/annotation.js
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ var $ = require('jquery');
var inherit = require('./inherit');
var geo_event = require('./event');
var transform = require('./transform');
var util = require('./util');
var registerAnnotation = require('./registry').registerAnnotation;

var annotationId = 0;
@@ -241,10 +242,88 @@ var annotation = function (type, args) {
};

/**
* TODO: return the annotation as a geojson object
* Return a list of styles that should be preserved in a geojson
* representation of the annotation.
*
* @return {array} a list of style names to store.
*/
this.geojson = function () {
return 'not implemented';
this._geojsonStyles = function () {
return ['fill', 'fillColor', 'fillOpacity', 'stroke', 'strokeColor',
'strokeOpacity', 'strokeWidth'];
};

/**
* Return the coordinates to be stored in a geojson geometery object.
*
* @param {string|geo.transform} [gcs] undefined to use the interface gcs,
* null to use the map gcs, or any other transform.
* @return {array} an array of flattened coordinates in the ingcs coordinate
* system. Undefined if this annotation is incompelte.
*/
this._geojsonCoordinates = function (gcs) {
};

/**
* Return the geometry type that is used to store this annotation in geojson.
*
* @return {string} a geojson geometry type.
*/
this._geojsonGeometryType = function () {
};

/**
* Return the annotation as a geojson object.
*
* @param {string|geo.transform} [gcs] undefined to use the interface gcs,
* null to use the map gcs, or any other transform.
* @param {boolean} includeCrs: if true, include the coordinate system.
* @return {object} the annotation as a geojson object, or undefined if it
* should not be represented (for instance, while it is being created).
*/
this.geojson = function (gcs, includeCrs) {
var coor = this._geojsonCoordinates(gcs),
geotype = this._geojsonGeometryType(),
styles = this._geojsonStyles(),
objStyle = this.options('style'),
i, key, value;
if (!coor || !coor.length || !geotype) {
return;
}
var obj = {
type: 'Feature',
geometry: {
type: geotype,
coordinates: coor
},
properties: {
annotationType: m_type,
name: this.name(),
style: {}
}
};
for (i = 0; i < styles.length; i += 1) {
key = styles[i];
value = util.ensureFunction(objStyle[key])();
if (value !== undefined) {
if (key.toLowerCase().match(/color$/)) {
value = util.convertColorToHex(value);
}
obj.properties.style[key] = value;
}
}
if (includeCrs) {
var map = this.layer().map();
gcs = (gcs === null ? map.gcs() : (
gcs === undefined ? map.ingcs() : gcs));
obj.crs = {
type: 'name',
properties: {
type: 'proj4',
name: gcs
}
};
}
return obj;
};
};

@@ -308,6 +387,36 @@ var rectangleAnnotation = function (args) {
this._coordinates = function () {
return this.options('corners');
};

/**
* Return the coordinates to be stored in a geojson geometery object.
*
* @param {string|geo.transform} [gcs] undefined to use the interface gcs,
* null to use the map gcs, or any other transform.
* @return {array} an array of flattened coordinates in the ingcs coordinate
* system. Undefined if this annotation is incompelte.
*/
this._geojsonCoordinates = function (gcs) {
var src = this.coordinates(gcs);
if (src.length < 4) {
return;
}
var coor = [];
for (var i = 0; i < 4; i += 1) {
coor.push([src[i].x, src[i].y]);
}
coor.push([src[0].x, src[0].y]);
return [coor];
};

/**
* Return the geometry type that is used to store this annotation in geojson.
*
* @return {string} a geojson geometry type.
*/
this._geojsonGeometryType = function () {
return 'Polygon';
};
};
inherit(rectangleAnnotation, annotation);

@@ -505,6 +614,36 @@ var polygonAnnotation = function (args) {
}
return (end || !skip);
};

/**
* Return the coordinates to be stored in a geojson geometery object.
*
* @param {string|geo.transform} [gcs] undefined to use the interface gcs,
* null to use the map gcs, or any other transform.
* @return {array} an array of flattened coordinates in the ingcs coordinate
* system. Undefined if this annotation is incompelte.
*/
this._geojsonCoordinates = function (gcs) {
var src = this.coordinates(gcs);
if (src.length < 3 || this.state() === annotationState.create) {
return;
}
var coor = [];
for (var i = 0; i < src.length; i += 1) {
coor.push([src[i].x, src[i].y]);
}
coor.push([src[0].x, src[0].y]);
return [coor];
};

/**
* Return the geometry type that is used to store this annotation in geojson.
*
* @return {string} a geojson geometry type.
*/
this._geojsonGeometryType = function () {
return 'Polygon';
};
};
inherit(polygonAnnotation, annotation);

@@ -602,6 +741,42 @@ var pointAnnotation = function (args) {
this.state(annotationState.done);
return 'done';
};

/**
* Return a list of styles that should be preserved in a geojson
* representation of the annotation.
*
* @return {array} a list of style names to store.
*/
this._geojsonStyles = function () {
return ['fill', 'fillColor', 'fillOpacity', 'radius', 'stroke',
'strokeColor', 'strokeOpacity', 'strokeWidth'];
};

/**
* Return the coordinates to be stored in a geojson geometery object.
*
* @param {string|geo.transform} [gcs] undefined to use the interface gcs,
* null to use the map gcs, or any other transform.
* @return {array} an array of flattened coordinates in the ingcs coordinate
* system. Undefined if this annotation is incompelte.
*/
this._geojsonCoordinates = function (gcs) {
var src = this.coordinates(gcs);
if (this.state() === annotationState.create || src.length < 1) {
return;
}
return [src[0].x, src[0].y];
};

/**
* Return the geometry type that is used to store this annotation in geojson.
*
* @return {string} a geojson geometry type.
*/
this._geojsonGeometryType = function () {
return 'Point';
};
};
inherit(pointAnnotation, annotation);

40 changes: 40 additions & 0 deletions src/annotationLayer.js
Original file line number Diff line number Diff line change
@@ -351,6 +351,46 @@ var annotationLayer = function (args) {
return this;
};

/**
* Return the current set of annotations as a geojson object. Alternately,
* add a set of annotations from a geojson object.
*
* @param {object} geojson: if present, add annotations based on the given
* geojson object. If undefined, return the current annotations as
* geojson. This may bei either a JSON string or a javascript object.
* @param {boolean} clear: if true, when adding objects, first remove all
* existing objects.
* @param {string|geo.transform} [gcs] undefined to use the interface gcs,
* null to use the map gcs, or any other transform.
* @param {boolean} includeCrs: if true, include the coordinate system in the
Copy link
Member

@aashish24 aashish24 Sep 30, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we rename includeCrs to includeGcs to be consistent?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In geojson it is called crs. Since this affects the geojson output, I figured it should be crs in this context, not gcs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay thats fine, I just thought that everywhere else we used gcs but I don't have strong feeling about it.

* output.
* @return {object} the current annotations as a javascript object that
* can be converted to geojson using JSON.stringify.
*/
this.geojson = function (geojson, clear, gcs, includeCrs) {
if (geojson !== undefined) {
if (clear) {
this.removeAllAnnotations();
}
//DWM::
}
geojson = null;
var features = [];
$.each(m_annotations, function (annotation_idx, annotation) {
var obj = annotation.geojson(gcs, includeCrs);
if (obj) {
features.push(obj);
}
});
if (features.length) {
geojson = {
type: 'FeatureCollection',
features: features
};
}
return geojson;
};

///////////////////////////////////////////////////////////////////////////
/**
* Update layer
15 changes: 15 additions & 0 deletions src/util/init.js
Original file line number Diff line number Diff line change
@@ -140,6 +140,21 @@
return color;
},

/**
* Convert a color to a six digit hex value prefixed with #.
*/
convertColorToHex: function (color) {
var value = geo.util.convertColor(color);
if (!value.r && !value.g && !value.b) {
value = '#000000';
} else {
value = '#' + ((1 << 24) + (Math.round(value.r * 255) << 16) +
(Math.round(value.g * 255) << 8) +
Math.round(value.b * 255)).toString(16).slice(1);
}
return value;
},

/**
* Normalize a coordinate object into {x: ..., y: ..., z: ... } form.
* Accepts 2-3d arrays,
2 changes: 1 addition & 1 deletion tests/cases/annotation.js
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ describe('geo.annotation', function () {
expect(ann.mouseClick()).toBe(undefined);
expect(ann.mouseMove()).toBe(undefined);
expect(ann._coordinates()).toEqual([]);
expect(ann.geojson()).toBe('not implemented');
expect(ann.geojson()).toBe(undefined);
map = create_map();
layer = map.createLayer('annotation', {
annotations: geo.listAnnotations()