All files / geonet-geohash/src GeohashStream.js

100% Statements 41/41
100% Branches 18/18
100% Functions 3/3
100% Lines 41/41

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112                1x     1x 1x     1x                                   7x   7x 1x       6x       1x   5x 1x     4x               4x 4x 4x 4x   4x         904x 4x 4x 4x   4x 4x   4x   900x 852x 852x 852x   852x   48x 44x   44x 44x 44x 44x   44x     4x           1x 60x     1x       1x  
/** ****************************************************************************************************
 * File: GeohashStream.js
 * Project: geohash
 * @author Nick Soggin <iSkore@users.noreply.github.com> on 11-Feb-2019
 *******************************************************************************************************/
'use strict';
 
const
	{ Readable } = require( 'stream' );
 
const
	getBBoxStartingPoint = require( './getBBoxStartingPoint' ),
	neighbor             = require( './neighbor' ),
	{
		isNumber
	}                    = require( './utils' );
 
class GeohashStream extends Readable
{
	/**
	 * GeohashStream
	 *
	 * extends Readable stream
	 *
	 * @param {object} opts - configuration object
	 * @param {number} opts.minLng - bbox min longitude
	 * @param {number} opts.minLat - bbox min latitude
	 * @param {number} opts.maxLng - bbox max longitude
	 * @param {number} opts.maxLat - bbox max latitude
	 * @param {number} opts.precision - geohash precision
	 */
	constructor( opts )
	{
		super();
 
		if ( !opts ) {
			throw new Error(
				'[GeohashStream] requires options defining bbox (minLng, minLat, maxLng, maxLat) and precision'
			);
		}
		else if (
			!isNumber( opts.minLng ) || !isNumber( opts.minLat ) ||
			!isNumber( opts.maxLng ) || !isNumber( opts.maxLat )
		) {
			throw new Error( '[GeohashStream] minLng, minLat, maxLng, and maxLat must be numbers' );
		}
		else if ( !isNumber( opts.precision ) ) {
			throw new Error( '[GeohashStream] precision must be a number' );
		}
 
		this.startingBBox = getBBoxStartingPoint(
			opts.minLng,
			opts.minLat,
			opts.maxLng,
			opts.maxLat,
			opts.precision
		);
 
		this._x = -1;
		this._y = -1;
		this.x  = this.startingBBox.lngStep;
		this.y  = this.startingBBox.latStep;
 
		this._nextChunk = null;
	}
 
	nextChunk()
	{
		if ( this._x === -1 && this._y === -1 ) {
			this._nextChunk = this.startingBBox.hashSouthWest;
			this.lastNorth  = this._nextChunk;
			this.lastEast   = this._nextChunk;
 
			this._x++;
			this._y++;
 
			return this._nextChunk;
		}
		else if ( this._x < this.x ) {
			this._nextChunk = neighbor( this.lastEast, 'e' );
			this.lastEast   = this._nextChunk;
			this._x++;
 
			return this._nextChunk;
		}
		else if ( this._y < this.y ) {
			this._x = 0;
 
			this._nextChunk = neighbor( this.lastNorth, 'n' );
			this.lastNorth  = this._nextChunk;
			this.lastEast   = this._nextChunk;
			this._y++;
 
			return this._nextChunk;
		}
 
		return null;
	}
 
	_read()
	{
		let chunk;
		while ( ( chunk = this.nextChunk() ) !== null ) {
			this.push( chunk );
		}
 
		this.push( null );
	}
}
 
module.exports = GeohashStream;