brouter/brouter-map-creator/src/main/java/btools/mapsplitter/NodeData.java

181 lines
4.1 KiB
Java

package btools.mapsplitter;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import btools.util.DiffCoderDataInputStream;
import btools.util.DiffCoderDataOutputStream;
/**
* Container for node data on the preprocessor level
*
* @author ab
*/
public class NodeData extends MapCreatorBase
{
public long nid;
public int ilon;
public int ilat;
public byte[] description;
public short selev = Short.MIN_VALUE;
public long gid; // geo-id
public int zoom = -1; // the zoom level this node is on
public int nativeIndex; // the index along all NATIVE nodes of it's tile
public transient int localeIndex; // the index along all USED nodes of it's tile
public transient boolean used; // whether this node is used by a way
public NodeData( long id, double lon, double lat )
{
nid = id;
double y = gudermannianInv( lat );
ilat = (int)( (1.-y/Math.PI )*( 1L << 27 )+ 0.5);
ilon = (int)( ( lon/180. + 1. )*( 1L << 27 ) + 0.5 );
}
public NodeData( long id, int ilon, int ilat )
{
this.nid = id;
this.ilat = ilat;
this.ilon = ilon;
}
public boolean inBBox( int z, int x, int y )
{
int shift = 28-z;
int x0 = x << shift;
int x1 = (x+1) << shift;
int y0 = y << shift;
int y1 = (y+1) << shift;
boolean outofbox = x1 < ilon || x0 >= ilon || y1 < ilat || y0 >= ilat;
return !outofbox;
}
public static double gudermannianInv(double latitude)
{
double sign = latitude < 0. ? -1. : 1.;
double sin = Math.sin( latitude * (Math.PI / 180.) * sign);
return sign * (Math.log((1.0 + sin) / (1.0 - sin)) / 2.0);
}
public static double gudermannian(double y)
{
return Math.atan(Math.sinh(y)) * (180. / Math.PI);
}
public double getLon()
{
return (((double)ilon)/( 1L << 27 ) - 1.)*180.;
}
public double getLat()
{
double y = (1. - ((double)ilat)/( 1L << 27 ))*Math.PI;
return gudermannian(y);
}
public void calcGeoId()
{
if ( zoom < 0 ) throw new IllegalArgumentException( "no zoom level yet" );
gid = 0L;
for( long bm = 1L << (27-zoom); bm > 0; bm >>= 1 )
{
gid <<= 2;
if ( ( ilon & bm ) != 0 ) gid |= 1;
if ( ( ilat & bm ) != 0 ) gid |= 2;
}
}
public static void sortByGeoId( List<NodeData> nodes )
{
Collections.sort( nodes, new Comparator<NodeData>()
{
@Override
public int compare(NodeData n1, NodeData n2)
{
long d = n1.gid - n2.gid;
// for equal positions sort by nid
if ( d == 0L )
{
d = n1.nid - n2.nid;
}
return d == 0 ? 0 : ( d < 0 ? -1 : 1 );
}
} );
}
public NodeData( DiffCoderDataInputStream dis ) throws Exception
{
zoom = dis.readInt();
nativeIndex = dis.readInt();
nid = dis.readDiffed( 0 );
ilon = (int)dis.readDiffed( 1 );
ilat = (int)dis.readDiffed( 2 );
for (;;)
{
String key = dis.readUTF();
if ( key.length() == 0 ) break;
String value = dis.readUTF();
putTag( key, value );
}
}
public void writeTo( DiffCoderDataOutputStream dos ) throws Exception
{
dos.writeInt( zoom );
dos.writeInt( nativeIndex );
dos.writeDiffed( nid, 0 );
dos.writeDiffed( ilon, 1 );
dos.writeDiffed( ilat, 2 );
if ( getTagsOrNull() != null )
{
for( Map.Entry<String,String> me : getTagsOrNull().entrySet() )
{
if ( me.getKey().length() > 0 )
{
dos.writeUTF( me.getKey() );
dos.writeUTF( me.getValue() );
}
}
}
dos.writeUTF( "" );
}
private int mercatorLon( long x, long z )
{
return (int) ( ( 360000000L * x ) >> z );
}
private int mercatorLat( long y, long z )
{
double n = Math.PI - ( 2.0 * Math.PI * y ) / ( 1L << z );
double d = Math.toDegrees( Math.atan( Math.sinh( n ) ) );
return (int) ( ( d + 90. ) * 1000000. + 0.5 );
}
@Override
public boolean equals( Object o )
{
if ( o instanceof NodeData )
{
NodeData n = (NodeData) o;
return n.nid == nid;
}
return false;
}
@Override
public int hashCode()
{
return (int)((nid >> 32) ^ nid);
}
}