@@ -36,6 +36,7 @@
|
|||||||
<div id="docs">
|
<div id="docs">
|
||||||
<p>See the <a href="igc.js" target="_blank">igc.js source</a> to see how this is done.</p>
|
<p>See the <a href="igc.js" target="_blank">igc.js source</a> to see how this is done.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<input id="time" type="range" value="0" steps="1"></input>
|
||||||
<div id="tags">complex-geometry, closest-feature, igc, opencyclemap</div>
|
<div id="tags">complex-geometry, closest-feature, igc, opencyclemap</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="span4 offset4">
|
<div class="span4 offset4">
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
goog.require('ol.Attribution');
|
goog.require('ol.Attribution');
|
||||||
|
goog.require('ol.Feature');
|
||||||
|
goog.require('ol.FeatureOverlay');
|
||||||
goog.require('ol.Map');
|
goog.require('ol.Map');
|
||||||
goog.require('ol.View2D');
|
goog.require('ol.View2D');
|
||||||
goog.require('ol.geom.LineString');
|
goog.require('ol.geom.LineString');
|
||||||
@@ -8,6 +10,7 @@ goog.require('ol.layer.Vector');
|
|||||||
goog.require('ol.source.IGC');
|
goog.require('ol.source.IGC');
|
||||||
goog.require('ol.source.OSM');
|
goog.require('ol.source.OSM');
|
||||||
goog.require('ol.style.Circle');
|
goog.require('ol.style.Circle');
|
||||||
|
goog.require('ol.style.Fill');
|
||||||
goog.require('ol.style.Stroke');
|
goog.require('ol.style.Stroke');
|
||||||
goog.require('ol.style.Style');
|
goog.require('ol.style.Style');
|
||||||
|
|
||||||
@@ -47,6 +50,19 @@ var vectorSource = new ol.source.IGC({
|
|||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var time = {
|
||||||
|
start: Infinity,
|
||||||
|
stop: -Infinity,
|
||||||
|
duration: 0
|
||||||
|
};
|
||||||
|
vectorSource.on('addfeature', function(event) {
|
||||||
|
var geometry = event.feature.getGeometry();
|
||||||
|
time.start = Math.min(time.start, geometry.getFirstCoordinate()[2]);
|
||||||
|
time.stop = Math.max(time.stop, geometry.getLastCoordinate()[2]);
|
||||||
|
time.duration = time.stop - time.start;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
var map = new ol.Map({
|
var map = new ol.Map({
|
||||||
layers: [
|
layers: [
|
||||||
new ol.layer.Tile({
|
new ol.layer.Tile({
|
||||||
@@ -137,3 +153,34 @@ map.on('postcompose', function(evt) {
|
|||||||
vectorContext.drawLineStringGeometry(line);
|
vectorContext.drawLineStringGeometry(line);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var featureOverlay = new ol.FeatureOverlay({
|
||||||
|
map: map,
|
||||||
|
style: new ol.style.Style({
|
||||||
|
image: new ol.style.Circle({
|
||||||
|
radius: 5,
|
||||||
|
fill: new ol.style.Fill({
|
||||||
|
color: 'rgba(255,0,0,0.9)'
|
||||||
|
}),
|
||||||
|
stroke: null
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#time').on('input', function(event) {
|
||||||
|
var value = parseInt($(this).val(), 10) / 100;
|
||||||
|
var m = time.start + (time.duration * value);
|
||||||
|
vectorSource.forEachFeature(function(feature) {
|
||||||
|
var geometry = /** @type {ol.geom.LineString} */ (feature.getGeometry());
|
||||||
|
var coordinate = geometry.getCoordinateAtM(m, true);
|
||||||
|
var highlight = feature.get('highlight');
|
||||||
|
if (highlight == undefined) {
|
||||||
|
highlight = new ol.Feature(new ol.geom.Point(coordinate));
|
||||||
|
feature.set('highlight', highlight);
|
||||||
|
featureOverlay.addFeature(highlight);
|
||||||
|
} else {
|
||||||
|
highlight.getGeometry().setCoordinates(coordinate);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
map.render();
|
||||||
|
});
|
||||||
|
|||||||
@@ -305,6 +305,75 @@ ol.geom.flat.lineStringInterpolate =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||||
|
* @param {number} offset Offset.
|
||||||
|
* @param {number} end End.
|
||||||
|
* @param {number} stride Stride.
|
||||||
|
* @param {ol.geom.GeometryLayout} layout Layout.
|
||||||
|
* @param {number} m M.
|
||||||
|
* @param {boolean} extrapolate Extrapolate.
|
||||||
|
* @return {ol.Coordinate} Coordinate.
|
||||||
|
*/
|
||||||
|
ol.geom.flat.lineStringCoordinateAtM =
|
||||||
|
function(flatCoordinates, offset, end, stride, layout, m, extrapolate) {
|
||||||
|
if ((layout != ol.geom.GeometryLayout.XYM &&
|
||||||
|
layout != ol.geom.GeometryLayout.XYZM) ||
|
||||||
|
end == offset) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
var coordinate;
|
||||||
|
if (m < flatCoordinates[offset + stride - 1]) {
|
||||||
|
if (extrapolate) {
|
||||||
|
coordinate = flatCoordinates.slice(offset, offset + stride);
|
||||||
|
coordinate[stride - 1] = m;
|
||||||
|
return coordinate;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else if (flatCoordinates[end - 1] < m) {
|
||||||
|
if (extrapolate) {
|
||||||
|
coordinate = flatCoordinates.slice(end - stride, end);
|
||||||
|
coordinate[stride - 1] = m;
|
||||||
|
return coordinate;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// FIXME use O(1) search
|
||||||
|
if (m == flatCoordinates[offset + stride - 1]) {
|
||||||
|
return flatCoordinates.slice(offset, offset + stride);
|
||||||
|
}
|
||||||
|
var lo = offset / stride;
|
||||||
|
var hi = end / stride;
|
||||||
|
while (lo < hi) {
|
||||||
|
var mid = (lo + hi) >> 1;
|
||||||
|
if (m < flatCoordinates[(mid + 1) * stride - 1]) {
|
||||||
|
hi = mid;
|
||||||
|
} else {
|
||||||
|
lo = mid + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var m0 = flatCoordinates[lo * stride - 1];
|
||||||
|
if (m == m0) {
|
||||||
|
return flatCoordinates.slice((lo - 1) * stride, (lo - 1) * stride + stride);
|
||||||
|
}
|
||||||
|
var m1 = flatCoordinates[(lo + 1) * stride - 1];
|
||||||
|
goog.asserts.assert(m0 < m);
|
||||||
|
goog.asserts.assert(m <= m1);
|
||||||
|
var t = (m - m0) / (m1 - m0);
|
||||||
|
coordinate = [];
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < stride - 1; ++i) {
|
||||||
|
coordinate.push((1 - t) * flatCoordinates[(lo - 1) * stride + i] +
|
||||||
|
t * flatCoordinates[lo * stride + i]);
|
||||||
|
}
|
||||||
|
coordinate.push(m);
|
||||||
|
goog.asserts.assert(coordinate.length == stride);
|
||||||
|
return coordinate;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||||
* @param {number} offset Offset.
|
* @param {number} offset Offset.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
@exportSymbol ol.geom.LineString
|
@exportSymbol ol.geom.LineString
|
||||||
@exportProperty ol.geom.LineString.prototype.clone
|
@exportProperty ol.geom.LineString.prototype.clone
|
||||||
|
@exportProperty ol.geom.LineString.prototype.getCoordinateAtM
|
||||||
@exportProperty ol.geom.LineString.prototype.getCoordinates
|
@exportProperty ol.geom.LineString.prototype.getCoordinates
|
||||||
@exportProperty ol.geom.LineString.prototype.getLength
|
@exportProperty ol.geom.LineString.prototype.getLength
|
||||||
@exportProperty ol.geom.LineString.prototype.getType
|
@exportProperty ol.geom.LineString.prototype.getType
|
||||||
|
|||||||
@@ -80,6 +80,18 @@ ol.geom.LineString.prototype.closestPointXY =
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} m M.
|
||||||
|
* @param {boolean=} opt_extrapolate Extrapolate.
|
||||||
|
* @return {ol.Coordinate} Coordinate.
|
||||||
|
*/
|
||||||
|
ol.geom.LineString.prototype.getCoordinateAtM = function(m, opt_extrapolate) {
|
||||||
|
var extrapolate = goog.isDef(opt_extrapolate) ? opt_extrapolate : false;
|
||||||
|
return ol.geom.flat.lineStringCoordinateAtM(this.flatCoordinates, 0,
|
||||||
|
this.flatCoordinates.length, this.stride, this.layout, m, extrapolate);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {ol.geom.RawLineString} Coordinates.
|
* @return {ol.geom.RawLineString} Coordinates.
|
||||||
* @todo stability experimental
|
* @todo stability experimental
|
||||||
|
|||||||
@@ -228,6 +228,69 @@ describe('ol.geom.LineString', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('with a simple XYM coordinates', function() {
|
||||||
|
|
||||||
|
var lineString;
|
||||||
|
beforeEach(function() {
|
||||||
|
lineString = new ol.geom.LineString(
|
||||||
|
[[1, 2, 3], [4, 5, 6]], ol.geom.GeometryLayout.XYM);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getCoordinateAtM', function() {
|
||||||
|
|
||||||
|
it('returns the expected value', function() {
|
||||||
|
expect(lineString.getCoordinateAtM(2, false)).to.be(null);
|
||||||
|
expect(lineString.getCoordinateAtM(2, true)).to.eql([1, 2, 2]);
|
||||||
|
expect(lineString.getCoordinateAtM(3, false)).to.eql([1, 2, 3]);
|
||||||
|
expect(lineString.getCoordinateAtM(3, true)).to.eql([1, 2, 3]);
|
||||||
|
expect(lineString.getCoordinateAtM(4, false)).to.eql([2, 3, 4]);
|
||||||
|
expect(lineString.getCoordinateAtM(4, true)).to.eql([2, 3, 4]);
|
||||||
|
expect(lineString.getCoordinateAtM(5, false)).to.eql([3, 4, 5]);
|
||||||
|
expect(lineString.getCoordinateAtM(5, true)).to.eql([3, 4, 5]);
|
||||||
|
expect(lineString.getCoordinateAtM(6, false)).to.eql([4, 5, 6]);
|
||||||
|
expect(lineString.getCoordinateAtM(6, true)).to.eql([4, 5, 6]);
|
||||||
|
expect(lineString.getCoordinateAtM(7, false)).to.eql(null);
|
||||||
|
expect(lineString.getCoordinateAtM(7, true)).to.eql([4, 5, 7]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with several XYZM coordinates', function() {
|
||||||
|
|
||||||
|
var lineString;
|
||||||
|
beforeEach(function() {
|
||||||
|
lineString = new ol.geom.LineString([
|
||||||
|
[0, 0, 0, 0],
|
||||||
|
[1, -1, 2, 1],
|
||||||
|
[2, -2, 4, 2],
|
||||||
|
[4, -4, 8, 4],
|
||||||
|
[8, -8, 16, 8],
|
||||||
|
[12, -12, 24, 12],
|
||||||
|
[14, -14, 28, 14],
|
||||||
|
[15, -15, 30, 15],
|
||||||
|
[16, -16, 32, 16],
|
||||||
|
[18, -18, 36, 18],
|
||||||
|
[22, -22, 44, 22]
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('#getCoordinateAtM', function() {
|
||||||
|
|
||||||
|
it('returns the expected value', function() {
|
||||||
|
expect(lineString.getLayout()).to.be(ol.geom.GeometryLayout.XYZM);
|
||||||
|
var m;
|
||||||
|
for (m = 0; m <= 22; m += 0.5) {
|
||||||
|
expect(lineString.getCoordinateAtM(m, true)).to.eql(
|
||||||
|
[m, -m, 2 * m, m]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user