From fde0350414afeae6346d1e818da7e1978edfd92d Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Mon, 16 Dec 2013 20:25:49 +0100 Subject: [PATCH] Add ol.format.IGC --- src/objectliterals.jsdoc | 6 ++ src/ol/format/igcformat.exports | 1 + src/ol/format/igcformat.js | 154 ++++++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 src/ol/format/igcformat.exports create mode 100644 src/ol/format/igcformat.js diff --git a/src/objectliterals.jsdoc b/src/objectliterals.jsdoc index 6f981585ed..5c66ab9706 100644 --- a/src/objectliterals.jsdoc +++ b/src/objectliterals.jsdoc @@ -254,6 +254,12 @@ * @property {ol.proj.ProjectionLike} defaultProjection Default projection. */ +/** + * @typedef {Object} olx.format.IGCOptions + * @property {ol.format.IGCZ|undefined} altitudeMode Altitude mode. + * Possible values are `barometric`, `gps`, and `none`. Default is `none`. + */ + /** * @typedef {Object} olx.interaction.DoubleClickZoomOptions * @property {number|undefined} duration Animation duration in milliseconds. Default is `250`. diff --git a/src/ol/format/igcformat.exports b/src/ol/format/igcformat.exports new file mode 100644 index 0000000000..640005aa90 --- /dev/null +++ b/src/ol/format/igcformat.exports @@ -0,0 +1 @@ +@exportSymbol ol.format.IGC diff --git a/src/ol/format/igcformat.js b/src/ol/format/igcformat.js new file mode 100644 index 0000000000..826c62c1c3 --- /dev/null +++ b/src/ol/format/igcformat.js @@ -0,0 +1,154 @@ +goog.provide('ol.format.IGC'); + +goog.require('goog.asserts'); +goog.require('goog.string'); +goog.require('goog.string.newlines'); +goog.require('ol.Feature'); +goog.require('ol.format.Text'); +goog.require('ol.geom.LineString'); +goog.require('ol.proj'); + + +/** + * @enum {string} + */ +ol.format.IGCZ = { + BAROMETRIC: 'barometric', + GPS: 'gps', + NONE: 'none' +}; + + + +/** + * @constructor + * @extends {ol.format.Text} + * @param {olx.format.IGCOptions=} opt_options Options. + */ +ol.format.IGC = function(opt_options) { + + var options = goog.isDef(opt_options) ? opt_options : {}; + + goog.base(this); + + /** + * @private + * @type {ol.format.IGCZ} + */ + this.altitudeMode_ = goog.isDef(options.altitudeMode) ? + options.altitudeMode : ol.format.IGCZ.NONE; + +}; +goog.inherits(ol.format.IGC, ol.format.Text); + + +/** + * @const {RegExp} + * @private + */ +ol.format.IGC.B_RECORD_RE_ = + /^B(\d{2})(\d{2})(\d{2})(\d{2})(\d{5})([NS])(\d{3})(\d{5})([EW])([AV])(\d{5})(\d{5})/; + + +/** + * @const {RegExp} + * @private + */ +ol.format.IGC.H_RECORD_RE_ = /^H.([A-Z]{3}).*?:(.*)/; + + +/** + * @const {RegExp} + * @private + */ +ol.format.IGC.HFDTE_RECORD_RE_ = /^HFDTE(\d{2})(\d{2})(\d{2})/; + + +/** + * @inheritDoc + */ +ol.format.IGC.prototype.readFeatureFromText = function(text) { + var altitudeMode = this.altitudeMode_; + var lines = goog.string.newlines.splitLines(text); + /** @type {Object.} */ + var properties = {}; + var flatCoordinates = []; + var year = 2000; + var month = 1; + var day = 1; + var i, ii; + for (i = 0, ii = lines.length; i < ii; ++i) { + var line = lines[i]; + var m; + if (line.charAt(0) == 'B') { + m = ol.format.IGC.B_RECORD_RE_.exec(line); + if (m) { + var hour = parseInt(m[1], 10); + var minute = parseInt(m[2], 10); + var second = parseInt(m[3], 10); + var y = parseInt(m[4], 10) + parseInt(m[5], 10) / 60000; + if (m[6] == 'S') { + y = -y; + } + var x = parseInt(m[7], 10) + parseInt(m[8], 10) / 60000; + if (m[9] == 'W') { + x = -x; + } + flatCoordinates.push(x, y); + if (altitudeMode != ol.format.IGCZ.NONE) { + var z; + if (altitudeMode == ol.format.IGCZ.GPS) { + z = parseInt(m[11], 10); + } else if (altitudeMode == ol.format.IGCZ.BAROMETRIC) { + z = parseInt(m[12], 10); + } else { + goog.asserts.fail(); + z = 0; + } + flatCoordinates.push(z); + } + var date = new Date(year, month, day, hour, minute, second, 0); + flatCoordinates.push(date.getTime() / 1000); + } + } else if (line.charAt(0) == 'H') { + m = ol.format.IGC.H_RECORD_RE_.exec(line); + if (m) { + properties[m[1]] = goog.string.trim(m[2]); + m = ol.format.IGC.HFDTE_RECORD_RE_.exec(line); + if (m) { + year = 2000 + parseInt(m[1], 10); + month = parseInt(m[2], 10); + day = parseInt(m[3], 10); + } + } + } + } + var lineString = new ol.geom.LineString(null); + var layout = altitudeMode == ol.format.IGCZ.NONE ? + ol.geom.GeometryLayout.XYM : ol.geom.GeometryLayout.XYZM; + lineString.setFlatCoordinates(layout, flatCoordinates); + var feature = new ol.Feature(lineString); + feature.setValues(properties); + return feature; +}; + + +/** + * @inheritDoc + */ +ol.format.IGC.prototype.readFeaturesFromText = function(text) { + var feature = this.readFeatureFromText(text); + if (!goog.isNull(feature)) { + return [feature]; + } else { + return []; + } +}; + + +/** + * @inheritDoc + */ +ol.format.IGC.prototype.readProjectionFromText = function(text) { + return ol.proj.get('EPSG:4326'); +};