
org.numenta.nupic.encoders.GeospatialCoordinateEncoder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of htm.java Show documentation
Show all versions of htm.java Show documentation
The Java version of Numenta's HTM technology
/* ---------------------------------------------------------------------
* Numenta Platform for Intelligent Computing (NuPIC)
* Copyright (C) 2014, Numenta, Inc. Unless you have an agreement
* with Numenta, Inc., for a separate license for this software code, the
* following terms and conditions apply:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* http://numenta.org/licenses/
* ---------------------------------------------------------------------
*/
package org.numenta.nupic.encoders;
import org.numenta.nupic.util.Tuple;
public class GeospatialCoordinateEncoder extends CoordinateEncoder {
private int scale;
private int timestep;
public GeospatialCoordinateEncoder() {
Tuple desc = new Tuple("longitude", 0);
Tuple desc2 = new Tuple("lattitude", 1);
Tuple desc3 = new Tuple("speed", 2);
description.add(desc);
description.add(desc2);
description.add(desc3);
}
/**
* Returns a builder for building ScalarEncoders.
* This builder may be reused to produce multiple builders
*
* @return a {@code CoordinateEncoder.Builder}
*/
public static GeospatialCoordinateEncoder.Builder geobuilder() {
return new GeospatialCoordinateEncoder.Builder();
}
/**
* {@inheritDoc}
*/
@Override
public void encodeIntoArray(Tuple inputData, int[] output) {
double longitude = (double)inputData.get(0);
double lattitude = (double)inputData.get(1);
double speed = (double)inputData.get(2);
int[] coordinate = coordinateForPosition(longitude, lattitude);
double radius = radiusForSpeed(speed);
super.encodeIntoArray(new Tuple(coordinate, radius), output);
}
public int[] coordinateForPosition(double longitude, double lattitude) {
double[] coordinate = toMercator(longitude, lattitude);
coordinate[0] /= scale;
coordinate[1] /= scale;
return new int[] { (int)coordinate[0], (int)coordinate[1] };
}
/**
* Returns coordinates converted to Mercator Spherical projection
*
* @param lon the longitude
* @param lat the lattitude
* @return
*/
protected double[] toMercator(double lon, double lat) {
double x = lon * 20037508.34d / 180;
double y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
y = y * 20037508.34d / 180;
return new double[] { x, y};
}
/**
* Returns coordinates converted to Long/Lat from Mercator Spherical projection
*
* @param lon the longitude
* @param lat the lattitude
* @return
*/
protected double[] inverseMercator(double x, double y) {
double lon = (x / 20037508.34d) * 180;
double lat = (y / 20037508.34d) * 180;
lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);
return new double[] { lon, lat };
}
/**
* Tries to get the encodings of consecutive readings to be
* adjacent with some overlap.
*
* @param speed Speed (in meters per second)
* @return Radius for given speed
*/
public double radiusForSpeed(double speed) {
double overlap = 1.5;
double coordinatesPerTimestep = speed * timestep / scale;
int radius = (int)Math.round(coordinatesPerTimestep / 2D * overlap);
int minRadius = (int)Math.ceil((Math.sqrt(w) - 1) / 2);
return Math.max(radius, minRadius);
}
/**
* Returns a {@link EncoderBuilder} for constructing {@link GeospatialCoordinateEncoder}s
*
* The base class architecture is put together in such a way where boilerplate
* initialization can be kept to a minimum for implementing subclasses, while avoiding
* the mistake-proneness of extremely long argument lists.
*
* @see ScalarEncoder.Builder#setStuff(int)
*/
public static class Builder extends Encoder.Builder {
private int scale;
private int timestep;
private Builder() {}
@Override
public GeospatialCoordinateEncoder build() {
//Must be instantiated so that super class can initialize
//boilerplate variables.
encoder = new GeospatialCoordinateEncoder();
//Call super class here
super.build();
////////////////////////////////////////////////////////
// Implementing classes would do setting of specific //
// vars here together with any sanity checking //
////////////////////////////////////////////////////////
if(scale == 0 || timestep == 0) {
throw new IllegalStateException("Scale or Timestep not set");
}
((GeospatialCoordinateEncoder)encoder).scale = scale;
((GeospatialCoordinateEncoder)encoder).timestep = timestep;
if(w <= 0 || w % 2 == 0) {
throw new IllegalArgumentException("w must be odd, and must be a positive integer");
}
if(n <= 6 * w) {
throw new IllegalArgumentException(
"n must be an int strictly greater than 6*w. For " +
"good results we recommend n be strictly greater than 11*w");
}
if(name == null || name.equals("None")) {
name = new StringBuilder("[").append(n).append(":").append(w).append("]").toString();
}
return (GeospatialCoordinateEncoder)encoder;
}
/**
* Scale of the map, as measured by
* distance between two coordinates
* (in meters per dimensional unit)
* @param scale
* @return
*/
public Builder scale(int scale) {
this.scale = scale;
return this;
}
/**
* Time between readings
* @param timestep
* @return
*/
public Builder timestep(int timestep) {
this.timestep = timestep;
return this;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy