Utility to get the longest straight chunk of a linestring
This commit is contained in:
@@ -0,0 +1,49 @@
|
|||||||
|
goog.provide('ol.geom.flat.straightchunk');
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} maxAngle Maximum acceptable angle delta between segments.
|
||||||
|
* @param {Array.<number>} flatCoordinates Flat coordinates.
|
||||||
|
* @param {number} offset Offset.
|
||||||
|
* @param {number} end End.
|
||||||
|
* @param {number} stride Stride.
|
||||||
|
* @return {Array.<number>} Start and end of the first suitable chunk of the
|
||||||
|
* given `flatCoordinates`.
|
||||||
|
*/
|
||||||
|
ol.geom.flat.straightchunk.lineString = function(maxAngle, flatCoordinates, offset, end, stride) {
|
||||||
|
var chunkStart = offset;
|
||||||
|
var chunkEnd = offset;
|
||||||
|
var chunkM = 0;
|
||||||
|
var m = 0;
|
||||||
|
var start = offset;
|
||||||
|
var acos, i, m12, m23, x1, y1, x12, y12, x23, y23;
|
||||||
|
for (i = offset; i < end; i += stride) {
|
||||||
|
var x2 = flatCoordinates[i];
|
||||||
|
var y2 = flatCoordinates[i + 1];
|
||||||
|
if (x1 !== undefined) {
|
||||||
|
x23 = x2 - x1;
|
||||||
|
y23 = y2 - y1;
|
||||||
|
m23 = Math.sqrt(x23 * x23 + y23 * y23);
|
||||||
|
if (x12 !== undefined) {
|
||||||
|
m += m12;
|
||||||
|
acos = Math.acos((x12 * x23 + y12 * y23) / (m12 * m23));
|
||||||
|
if (acos > maxAngle) {
|
||||||
|
if (m > chunkM) {
|
||||||
|
chunkM = m;
|
||||||
|
chunkStart = start;
|
||||||
|
chunkEnd = i;
|
||||||
|
}
|
||||||
|
m = 0;
|
||||||
|
start = i - stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m12 = m23;
|
||||||
|
x12 = x23;
|
||||||
|
y12 = y23;
|
||||||
|
}
|
||||||
|
x1 = x2;
|
||||||
|
y1 = y2;
|
||||||
|
}
|
||||||
|
m += m23;
|
||||||
|
return m > chunkM ? [start, i] : [chunkStart, chunkEnd];
|
||||||
|
};
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
goog.require('ol.geom.flat.straightchunk');
|
||||||
|
|
||||||
|
|
||||||
|
describe('ol.geom.flat.straightchunk', function() {
|
||||||
|
|
||||||
|
describe('ol.geom.flat.straightchunk.lineString', function() {
|
||||||
|
|
||||||
|
describe('single segment with stride == 3', function() {
|
||||||
|
var flatCoords = [0, 0, 42, 1, 1, 42];
|
||||||
|
var stride = 3;
|
||||||
|
|
||||||
|
it('returns whole line with angle delta', function() {
|
||||||
|
var got = ol.geom.flat.straightchunk.lineString(Math.PI / 4, flatCoords, 0, 6, stride);
|
||||||
|
expect(got).to.eql([0, 6]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns whole line with zero angle delta', function() {
|
||||||
|
var got = ol.geom.flat.straightchunk.lineString(0, flatCoords, 0, 6, stride);
|
||||||
|
expect(got).to.eql([0, 6]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('short line string', function() {
|
||||||
|
var flatCoords = [0, 0, 1, 0, 1, 1, 0, 1];
|
||||||
|
var stride = 2;
|
||||||
|
|
||||||
|
it('returns whole line if straight enough', function() {
|
||||||
|
var got = ol.geom.flat.straightchunk.lineString(Math.PI, flatCoords, 0, 8, stride);
|
||||||
|
expect(got).to.eql([0, 8]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns first matching chunk if all chunk lengths are the same', function() {
|
||||||
|
var got = ol.geom.flat.straightchunk.lineString(Math.PI / 4, flatCoords, 0, 8, stride);
|
||||||
|
expect(got).to.eql([0, 4]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('longer line string', function() {
|
||||||
|
var flatCoords = [0, 0, 1, 0, 1, 1, 0, 1, 0, -1, -1, -1, -1, 0, -1, 2, -2, 4];
|
||||||
|
var stride = 2;
|
||||||
|
|
||||||
|
it('returns stright chunk from within the linestring', function() {
|
||||||
|
var got = ol.geom.flat.straightchunk.lineString(0, flatCoords, 0, 18, stride);
|
||||||
|
expect(got).to.eql([10, 16]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns long chunk at the end if angle and length within threshold', function() {
|
||||||
|
var got = ol.geom.flat.straightchunk.lineString(Math.PI / 4, flatCoords, 0, 18, stride);
|
||||||
|
expect(got).to.eql([10, 18]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user