diff --git a/src/ol/geom/flat/straightchunk.js b/src/ol/geom/flat/straightchunk.js new file mode 100644 index 0000000000..a33dcac391 --- /dev/null +++ b/src/ol/geom/flat/straightchunk.js @@ -0,0 +1,49 @@ +goog.provide('ol.geom.flat.straightchunk'); + + +/** + * @param {number} maxAngle Maximum acceptable angle delta between segments. + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @return {Array.} 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]; +}; diff --git a/test/spec/ol/geom/flat/straightchunk.test.js b/test/spec/ol/geom/flat/straightchunk.test.js new file mode 100644 index 0000000000..4b645d8d58 --- /dev/null +++ b/test/spec/ol/geom/flat/straightchunk.test.js @@ -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]); + }); + + }); + + }); + +});