statistical encoding
This commit is contained in:
parent
f8dee5b7d1
commit
ccf6641bad
41 changed files with 4543 additions and 1965 deletions
|
|
@ -1,363 +1,471 @@
|
|||
/**
|
||||
* Container for an osm node
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import btools.util.ByteArrayUnifier;
|
||||
|
||||
|
||||
|
||||
public class OsmNode implements OsmPos
|
||||
{
|
||||
public static final int EXTERNAL_BITMASK = 0x80; // old semantic
|
||||
public static final int SIGNLON_BITMASK = 0x80;
|
||||
public static final int SIGNLAT_BITMASK = 0x40;
|
||||
public static final int TRANSFERNODE_BITMASK = 0x20;
|
||||
public static final int WRITEDESC_BITMASK = 0x10;
|
||||
public static final int SKIPDETAILS_BITMASK = 0x08;
|
||||
public static final int NODEDESC_BITMASK = 0x04;
|
||||
public static final int RESERVED1_BITMASK = 0x02;
|
||||
public static final int RESERVED2_BITMASK = 0x01;
|
||||
|
||||
public OsmNode()
|
||||
{
|
||||
}
|
||||
|
||||
public OsmNode( int ilon, int ilat )
|
||||
{
|
||||
this.ilon = ilon;
|
||||
this.ilat = ilat;
|
||||
}
|
||||
|
||||
public OsmNode( long id )
|
||||
{
|
||||
ilon = (int)(id >> 32);
|
||||
ilat = (int)(id & 0xffffffff);
|
||||
}
|
||||
|
||||
/**
|
||||
* The latitude
|
||||
*/
|
||||
public int ilat;
|
||||
|
||||
/**
|
||||
* The longitude
|
||||
*/
|
||||
public int ilon;
|
||||
|
||||
/**
|
||||
* The elevation
|
||||
*/
|
||||
public short selev;
|
||||
|
||||
public byte[] nodeDescription;
|
||||
|
||||
// interface OsmPos
|
||||
public int getILat()
|
||||
{
|
||||
return ilat;
|
||||
}
|
||||
|
||||
public int getILon()
|
||||
{
|
||||
return ilon;
|
||||
}
|
||||
|
||||
public short getSElev()
|
||||
{
|
||||
return selev;
|
||||
}
|
||||
|
||||
public double getElev()
|
||||
{
|
||||
return selev / 4.;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The links to other nodes
|
||||
*/
|
||||
public OsmLink firstlink = null;
|
||||
|
||||
// preliminry in forward order to avoid regressions
|
||||
public void addLink( OsmLink link )
|
||||
{
|
||||
if ( firstlink == null )
|
||||
{
|
||||
firstlink = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
OsmLink l = firstlink;
|
||||
while( l.next != null ) l = l.next;
|
||||
l.next = link;
|
||||
}
|
||||
}
|
||||
|
||||
private OsmLink getCompatibleLink( int ilon, int ilat, boolean counterLinkWritten, int state )
|
||||
{
|
||||
for( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( counterLinkWritten == l.counterLinkWritten && l.state == state )
|
||||
{
|
||||
OsmNode t = l.targetNode;
|
||||
if ( t.ilon == ilon && t.ilat == ilat )
|
||||
{
|
||||
l.state = 0;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
// second try ignoring counterLinkWritten
|
||||
// (border links are written in both directions)
|
||||
for( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( l.state == state )
|
||||
{
|
||||
OsmNode t = l.targetNode;
|
||||
if ( t.ilon == ilon && t.ilat == ilat )
|
||||
{
|
||||
l.state = 0;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int calcDistance( OsmPos p )
|
||||
{
|
||||
double l = (ilat-90000000) * 0.00000001234134;
|
||||
double l2 = l*l;
|
||||
double l4 = l2*l2;
|
||||
double coslat = 1.- l2 + l4 / 6.;
|
||||
|
||||
double dlat = (ilat - p.getILat() )/1000000.;
|
||||
double dlon = (ilon - p.getILon() )/1000000. * coslat;
|
||||
double d = Math.sqrt( dlat*dlat + dlon*dlon ) * (6378000. / 57.3);
|
||||
return (int)(d + 1.0 );
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "" + getIdFromPos();
|
||||
}
|
||||
|
||||
public void parseNodeBody( MicroCache is, OsmNodesMap hollowNodes, DistanceChecker dc )
|
||||
{
|
||||
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
|
||||
|
||||
selev = is.readShort();
|
||||
|
||||
while( is.hasMoreData() )
|
||||
{
|
||||
int ilonref = ilon;
|
||||
int ilatref = ilat;
|
||||
|
||||
boolean counterLinkWritten = false;
|
||||
OsmTransferNode firstTransferNode = null;
|
||||
OsmTransferNode lastTransferNode = null;
|
||||
int linklon;
|
||||
int linklat;
|
||||
byte[] description = null;
|
||||
for(;;)
|
||||
{
|
||||
int bitField = is.readByte();
|
||||
int dlon = is.readVarLengthUnsigned();
|
||||
int dlat = is.readVarLengthUnsigned();
|
||||
if ( (bitField & SIGNLON_BITMASK) != 0 ) { dlon = -dlon;}
|
||||
if ( (bitField & SIGNLAT_BITMASK) != 0 ) { dlat = -dlat;}
|
||||
linklon = ilonref + dlon;
|
||||
linklat = ilatref + dlat;
|
||||
ilonref = linklon;
|
||||
ilatref = linklat;
|
||||
// read variable length or old 8 byte fixed, and ensure that 8 bytes is only fixed
|
||||
if ( (bitField & WRITEDESC_BITMASK ) != 0 )
|
||||
{
|
||||
byte[] ab = new byte[is.readByte()];
|
||||
is.readFully( ab );
|
||||
description = abUnifier.unify( ab );
|
||||
}
|
||||
if ( (bitField & NODEDESC_BITMASK ) != 0 )
|
||||
{
|
||||
byte[] ab = new byte[is.readByte()];
|
||||
is.readFully( ab );
|
||||
nodeDescription = abUnifier.unify( ab );
|
||||
}
|
||||
if ( (bitField & RESERVED1_BITMASK ) != 0 )
|
||||
{
|
||||
byte[] ab = new byte[is.readByte()];
|
||||
is.readFully( ab );
|
||||
}
|
||||
if ( (bitField & RESERVED2_BITMASK ) != 0 )
|
||||
{
|
||||
byte[] ab = new byte[is.readByte()];
|
||||
is.readFully( ab );
|
||||
}
|
||||
if ( (bitField & SKIPDETAILS_BITMASK ) != 0 )
|
||||
{
|
||||
counterLinkWritten = true;
|
||||
}
|
||||
|
||||
if ( description == null && !counterLinkWritten ) throw new IllegalArgumentException( "internal error: missing way description!" );
|
||||
|
||||
boolean isTransfer = (bitField & TRANSFERNODE_BITMASK ) != 0;
|
||||
if ( isTransfer )
|
||||
{
|
||||
OsmTransferNode trans = new OsmTransferNode();
|
||||
trans.ilon = linklon;
|
||||
trans.ilat = linklat;
|
||||
trans.descriptionBitmap = description;
|
||||
trans.selev = (short)(selev + is.readVarLengthSigned());
|
||||
if ( lastTransferNode == null )
|
||||
{
|
||||
firstTransferNode = trans;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastTransferNode.next = trans;
|
||||
}
|
||||
lastTransferNode = trans;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// performance shortcut: ignore link if out of reach
|
||||
if ( dc != null && !counterLinkWritten )
|
||||
{
|
||||
if ( !dc.isWithinRadius( ilon, ilat, firstTransferNode, linklon, linklat ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( linklon == ilon && linklat == ilat )
|
||||
{
|
||||
continue; // skip self-ref
|
||||
}
|
||||
|
||||
// first check the known links for that target
|
||||
OsmLink link = getCompatibleLink( linklon, linklat, counterLinkWritten, 2 );
|
||||
if ( link == null ) // .. not found, then check the hollow nodes
|
||||
{
|
||||
long targetNodeId = ((long)linklon)<<32 | linklat;
|
||||
OsmNode tn = hollowNodes.get( targetNodeId ); // target node
|
||||
if ( tn == null ) // node not yet known, create a new hollow proxy
|
||||
{
|
||||
tn = new OsmNode(linklon, linklat);
|
||||
tn.setHollow();
|
||||
hollowNodes.put( tn );
|
||||
}
|
||||
link = new OsmLink();
|
||||
link.targetNode = tn;
|
||||
link.counterLinkWritten = counterLinkWritten;
|
||||
link.state = 1;
|
||||
addLink( link );
|
||||
}
|
||||
|
||||
// now we have a link with a target node -> get the reverse link
|
||||
OsmLink rlink = link.targetNode.getCompatibleLink( ilon, ilat, !counterLinkWritten, 1 );
|
||||
if ( rlink == null ) // .. not found, create it
|
||||
{
|
||||
rlink = new OsmLink();
|
||||
rlink.targetNode = this;
|
||||
rlink.counterLinkWritten = !counterLinkWritten;
|
||||
rlink.state = 2;
|
||||
link.targetNode.addLink( rlink );
|
||||
}
|
||||
|
||||
if ( !counterLinkWritten )
|
||||
{
|
||||
// we have the data for that link, so fill both the link ..
|
||||
link.descriptionBitmap = description;
|
||||
link.encodeFirsttransfer(firstTransferNode);
|
||||
|
||||
// .. and the reverse
|
||||
if ( rlink.counterLinkWritten )
|
||||
{
|
||||
rlink.descriptionBitmap = description; // default for no transfer-nodes
|
||||
OsmTransferNode previous = null;
|
||||
OsmTransferNode rtrans = null;
|
||||
for( OsmTransferNode trans = firstTransferNode; trans != null; trans = trans.next )
|
||||
{
|
||||
if ( previous == null )
|
||||
{
|
||||
rlink.descriptionBitmap = trans.descriptionBitmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous.descriptionBitmap = trans.descriptionBitmap;
|
||||
}
|
||||
rtrans = new OsmTransferNode();
|
||||
rtrans.ilon = trans.ilon;
|
||||
rtrans.ilat = trans.ilat;
|
||||
rtrans.selev = trans.selev;
|
||||
rtrans.next = previous;
|
||||
rtrans.descriptionBitmap = description;
|
||||
previous = rtrans;
|
||||
}
|
||||
rlink.encodeFirsttransfer(rtrans);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ( dc == null )
|
||||
{
|
||||
hollowNodes.remove( this );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHollow()
|
||||
{
|
||||
return selev == -12345;
|
||||
}
|
||||
|
||||
public void setHollow()
|
||||
{
|
||||
selev = -12345;
|
||||
}
|
||||
|
||||
public long getIdFromPos()
|
||||
{
|
||||
return ((long)ilon)<<32 | ilat;
|
||||
}
|
||||
|
||||
public void unlinkLink( OsmLink link )
|
||||
{
|
||||
if ( link == firstlink )
|
||||
{
|
||||
firstlink = link.next;
|
||||
return;
|
||||
}
|
||||
for( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( l.next == link )
|
||||
{
|
||||
l.next = link.next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object o )
|
||||
{
|
||||
if ( o instanceof OsmNode )
|
||||
{
|
||||
OsmNode n = (OsmNode)o;
|
||||
return n.ilon == ilon && n.ilat == ilat;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode( )
|
||||
{
|
||||
return ilon + ilat;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Container for an osm node
|
||||
*
|
||||
* @author ab
|
||||
*/
|
||||
package btools.mapaccess;
|
||||
|
||||
import btools.codec.MicroCache;
|
||||
import btools.codec.MicroCache1;
|
||||
import btools.codec.MicroCache2;
|
||||
import btools.util.ByteArrayUnifier;
|
||||
|
||||
public class OsmNode implements OsmPos
|
||||
{
|
||||
public static final int EXTERNAL_BITMASK = 0x80; // old semantic
|
||||
public static final int SIGNLON_BITMASK = 0x80;
|
||||
public static final int SIGNLAT_BITMASK = 0x40;
|
||||
public static final int TRANSFERNODE_BITMASK = 0x20;
|
||||
public static final int WRITEDESC_BITMASK = 0x10;
|
||||
public static final int SKIPDETAILS_BITMASK = 0x08;
|
||||
public static final int NODEDESC_BITMASK = 0x04;
|
||||
public static final int RESERVED1_BITMASK = 0x02;
|
||||
public static final int RESERVED2_BITMASK = 0x01;
|
||||
|
||||
public OsmNode()
|
||||
{
|
||||
}
|
||||
|
||||
public OsmNode( int ilon, int ilat )
|
||||
{
|
||||
this.ilon = ilon;
|
||||
this.ilat = ilat;
|
||||
}
|
||||
|
||||
public OsmNode( long id )
|
||||
{
|
||||
ilon = (int) ( id >> 32 );
|
||||
ilat = (int) ( id & 0xffffffff );
|
||||
}
|
||||
|
||||
/**
|
||||
* The latitude
|
||||
*/
|
||||
public int ilat;
|
||||
|
||||
/**
|
||||
* The longitude
|
||||
*/
|
||||
public int ilon;
|
||||
|
||||
/**
|
||||
* The elevation
|
||||
*/
|
||||
public short selev;
|
||||
|
||||
public byte[] nodeDescription;
|
||||
|
||||
// interface OsmPos
|
||||
public int getILat()
|
||||
{
|
||||
return ilat;
|
||||
}
|
||||
|
||||
public int getILon()
|
||||
{
|
||||
return ilon;
|
||||
}
|
||||
|
||||
public short getSElev()
|
||||
{
|
||||
return selev;
|
||||
}
|
||||
|
||||
public double getElev()
|
||||
{
|
||||
return selev / 4.;
|
||||
}
|
||||
|
||||
/**
|
||||
* The links to other nodes
|
||||
*/
|
||||
public OsmLink firstlink = null;
|
||||
|
||||
// preliminry in forward order to avoid regressions
|
||||
public void addLink( OsmLink link )
|
||||
{
|
||||
if ( firstlink == null )
|
||||
{
|
||||
firstlink = link;
|
||||
}
|
||||
else
|
||||
{
|
||||
OsmLink l = firstlink;
|
||||
while (l.next != null)
|
||||
l = l.next;
|
||||
l.next = link;
|
||||
}
|
||||
}
|
||||
|
||||
private OsmLink getCompatibleLink( int ilon, int ilat, boolean counterLinkWritten, int state )
|
||||
{
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( counterLinkWritten == l.counterLinkWritten && l.state == state )
|
||||
{
|
||||
OsmNode t = l.targetNode;
|
||||
if ( t.ilon == ilon && t.ilat == ilat )
|
||||
{
|
||||
l.state = 0;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
// second try ignoring counterLinkWritten
|
||||
// (border links are written in both directions)
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( l.state == state )
|
||||
{
|
||||
OsmNode t = l.targetNode;
|
||||
if ( t.ilon == ilon && t.ilat == ilat )
|
||||
{
|
||||
l.state = 0;
|
||||
return l;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int calcDistance( OsmPos p )
|
||||
{
|
||||
double l = ( ilat - 90000000 ) * 0.00000001234134;
|
||||
double l2 = l * l;
|
||||
double l4 = l2 * l2;
|
||||
double coslat = 1. - l2 + l4 / 6.;
|
||||
|
||||
double dlat = ( ilat - p.getILat() ) / 1000000.;
|
||||
double dlon = ( ilon - p.getILon() ) / 1000000. * coslat;
|
||||
double d = Math.sqrt( dlat * dlat + dlon * dlon ) * ( 6378000. / 57.3 );
|
||||
return (int) ( d + 1.0 );
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "" + getIdFromPos();
|
||||
}
|
||||
|
||||
public void parseNodeBody( MicroCache mc, OsmNodesMap hollowNodes, DistanceChecker dc )
|
||||
{
|
||||
if ( mc instanceof MicroCache1 )
|
||||
{
|
||||
parseNodeBody1( (MicroCache1) mc, hollowNodes, dc );
|
||||
}
|
||||
else if ( mc instanceof MicroCache2 )
|
||||
{
|
||||
parseNodeBody2( (MicroCache2) mc, hollowNodes, dc );
|
||||
}
|
||||
else
|
||||
throw new IllegalArgumentException( "unknown cache version: " + mc.getClass() );
|
||||
}
|
||||
|
||||
public void parseNodeBody2( MicroCache2 mc, OsmNodesMap hollowNodes, DistanceChecker dc )
|
||||
{
|
||||
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
|
||||
|
||||
selev = mc.readShort();
|
||||
int nodeDescSize = mc.readVarLengthUnsigned();
|
||||
nodeDescription = nodeDescSize == 0 ? null : mc.readUnified( nodeDescSize, abUnifier );
|
||||
|
||||
while (mc.hasMoreData())
|
||||
{
|
||||
// read link data
|
||||
int endPointer = mc.getEndPointer();
|
||||
int linklon = ilon + mc.readVarLengthSigned();
|
||||
int linklat = ilat + mc.readVarLengthSigned();
|
||||
int sizecode = mc.readVarLengthUnsigned();
|
||||
boolean isReverse = ( sizecode & 1 ) != 0;
|
||||
byte[] description = null;
|
||||
int descSize = sizecode >> 1;
|
||||
if ( descSize > 0 )
|
||||
{
|
||||
description = mc.readUnified( descSize, abUnifier );
|
||||
}
|
||||
byte[] geometry = mc.readDataUntil( endPointer );
|
||||
|
||||
// preliminary hack: way-point-matching not here (done at decoding time)
|
||||
if ( dc != null )
|
||||
continue;
|
||||
|
||||
if ( linklon == ilon && linklat == ilat )
|
||||
{
|
||||
continue; // skip self-ref
|
||||
}
|
||||
|
||||
// first check the known links for that target
|
||||
OsmLink link = getCompatibleLink( linklon, linklat, isReverse, 2 );
|
||||
if ( link == null ) // .. not found, then check the hollow nodes
|
||||
{
|
||||
long targetNodeId = ( (long) linklon ) << 32 | linklat;
|
||||
OsmNode tn = hollowNodes.get( targetNodeId ); // target node
|
||||
if ( tn == null ) // node not yet known, create a new hollow proxy
|
||||
{
|
||||
tn = new OsmNode( linklon, linklat );
|
||||
tn.setHollow();
|
||||
hollowNodes.put( tn );
|
||||
}
|
||||
link = new OsmLink();
|
||||
link.targetNode = tn;
|
||||
link.counterLinkWritten = isReverse;
|
||||
link.state = 1;
|
||||
addLink( link );
|
||||
}
|
||||
|
||||
// now we have a link with a target node -> get the reverse link
|
||||
OsmLink rlink = link.targetNode.getCompatibleLink( ilon, ilat, !isReverse, 1 );
|
||||
if ( rlink == null ) // .. not found, create it
|
||||
{
|
||||
rlink = new OsmLink();
|
||||
rlink.targetNode = this;
|
||||
rlink.counterLinkWritten = !isReverse;
|
||||
rlink.state = 2;
|
||||
link.targetNode.addLink( rlink );
|
||||
}
|
||||
|
||||
if ( !isReverse )
|
||||
{
|
||||
// we have the data for that link, so fill both the link ..
|
||||
link.descriptionBitmap = description;
|
||||
link.setGeometry( geometry );
|
||||
|
||||
// .. and the reverse
|
||||
if ( rlink.counterLinkWritten )
|
||||
{
|
||||
rlink.descriptionBitmap = description;
|
||||
rlink.setGeometry( geometry );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ( dc == null )
|
||||
{
|
||||
hollowNodes.remove( this );
|
||||
}
|
||||
}
|
||||
|
||||
public void parseNodeBody1( MicroCache1 is, OsmNodesMap hollowNodes, DistanceChecker dc )
|
||||
{
|
||||
ByteArrayUnifier abUnifier = hollowNodes.getByteArrayUnifier();
|
||||
|
||||
selev = is.readShort();
|
||||
|
||||
while (is.hasMoreData())
|
||||
{
|
||||
int ilonref = ilon;
|
||||
int ilatref = ilat;
|
||||
|
||||
boolean counterLinkWritten = false;
|
||||
OsmTransferNode firstTransferNode = null;
|
||||
OsmTransferNode lastTransferNode = null;
|
||||
int linklon;
|
||||
int linklat;
|
||||
byte[] description = null;
|
||||
for ( ;; )
|
||||
{
|
||||
int bitField = is.readByte();
|
||||
int dlon = is.readVarLengthUnsigned();
|
||||
int dlat = is.readVarLengthUnsigned();
|
||||
if ( ( bitField & SIGNLON_BITMASK ) != 0 )
|
||||
{
|
||||
dlon = -dlon;
|
||||
}
|
||||
if ( ( bitField & SIGNLAT_BITMASK ) != 0 )
|
||||
{
|
||||
dlat = -dlat;
|
||||
}
|
||||
linklon = ilonref + dlon;
|
||||
linklat = ilatref + dlat;
|
||||
ilonref = linklon;
|
||||
ilatref = linklat;
|
||||
// read variable length or old 8 byte fixed, and ensure that 8 bytes is
|
||||
// only fixed
|
||||
if ( ( bitField & WRITEDESC_BITMASK ) != 0 )
|
||||
{
|
||||
byte[] ab = new byte[is.readByte()];
|
||||
is.readFully( ab );
|
||||
description = abUnifier.unify( ab );
|
||||
}
|
||||
if ( ( bitField & NODEDESC_BITMASK ) != 0 )
|
||||
{
|
||||
byte[] ab = new byte[is.readByte()];
|
||||
is.readFully( ab );
|
||||
nodeDescription = abUnifier.unify( ab );
|
||||
}
|
||||
if ( ( bitField & RESERVED1_BITMASK ) != 0 )
|
||||
{
|
||||
byte[] ab = new byte[is.readByte()];
|
||||
is.readFully( ab );
|
||||
}
|
||||
if ( ( bitField & RESERVED2_BITMASK ) != 0 )
|
||||
{
|
||||
byte[] ab = new byte[is.readByte()];
|
||||
is.readFully( ab );
|
||||
}
|
||||
if ( ( bitField & SKIPDETAILS_BITMASK ) != 0 )
|
||||
{
|
||||
counterLinkWritten = true;
|
||||
}
|
||||
|
||||
if ( description == null && !counterLinkWritten )
|
||||
throw new IllegalArgumentException( "internal error: missing way description!" );
|
||||
|
||||
boolean isTransfer = ( bitField & TRANSFERNODE_BITMASK ) != 0;
|
||||
if ( isTransfer )
|
||||
{
|
||||
OsmTransferNode trans = new OsmTransferNode();
|
||||
trans.ilon = linklon;
|
||||
trans.ilat = linklat;
|
||||
trans.descriptionBitmap = description;
|
||||
trans.selev = (short) ( selev + is.readVarLengthSigned() );
|
||||
if ( lastTransferNode == null )
|
||||
{
|
||||
firstTransferNode = trans;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastTransferNode.next = trans;
|
||||
}
|
||||
lastTransferNode = trans;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// performance shortcut: ignore link if out of reach
|
||||
if ( dc != null && !counterLinkWritten )
|
||||
{
|
||||
if ( !dc.isWithinRadius( ilon, ilat, firstTransferNode, linklon, linklat ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( linklon == ilon && linklat == ilat )
|
||||
{
|
||||
continue; // skip self-ref
|
||||
}
|
||||
|
||||
// first check the known links for that target
|
||||
OsmLink link = getCompatibleLink( linklon, linklat, counterLinkWritten, 2 );
|
||||
if ( link == null ) // .. not found, then check the hollow nodes
|
||||
{
|
||||
long targetNodeId = ( (long) linklon ) << 32 | linklat;
|
||||
OsmNode tn = hollowNodes.get( targetNodeId ); // target node
|
||||
if ( tn == null ) // node not yet known, create a new hollow proxy
|
||||
{
|
||||
tn = new OsmNode( linklon, linklat );
|
||||
tn.setHollow();
|
||||
hollowNodes.put( tn );
|
||||
}
|
||||
link = new OsmLink();
|
||||
link.targetNode = tn;
|
||||
link.counterLinkWritten = counterLinkWritten;
|
||||
link.state = 1;
|
||||
addLink( link );
|
||||
}
|
||||
|
||||
// now we have a link with a target node -> get the reverse link
|
||||
OsmLink rlink = link.targetNode.getCompatibleLink( ilon, ilat, !counterLinkWritten, 1 );
|
||||
if ( rlink == null ) // .. not found, create it
|
||||
{
|
||||
rlink = new OsmLink();
|
||||
rlink.targetNode = this;
|
||||
rlink.counterLinkWritten = !counterLinkWritten;
|
||||
rlink.state = 2;
|
||||
link.targetNode.addLink( rlink );
|
||||
}
|
||||
|
||||
if ( !counterLinkWritten )
|
||||
{
|
||||
// we have the data for that link, so fill both the link ..
|
||||
link.descriptionBitmap = description;
|
||||
link.encodeFirsttransfer( firstTransferNode );
|
||||
|
||||
// .. and the reverse
|
||||
if ( rlink.counterLinkWritten )
|
||||
{
|
||||
rlink.descriptionBitmap = description; // default for no
|
||||
// transfer-nodes
|
||||
OsmTransferNode previous = null;
|
||||
OsmTransferNode rtrans = null;
|
||||
for ( OsmTransferNode trans = firstTransferNode; trans != null; trans = trans.next )
|
||||
{
|
||||
if ( previous == null )
|
||||
{
|
||||
rlink.descriptionBitmap = trans.descriptionBitmap;
|
||||
}
|
||||
else
|
||||
{
|
||||
previous.descriptionBitmap = trans.descriptionBitmap;
|
||||
}
|
||||
rtrans = new OsmTransferNode();
|
||||
rtrans.ilon = trans.ilon;
|
||||
rtrans.ilat = trans.ilat;
|
||||
rtrans.selev = trans.selev;
|
||||
rtrans.next = previous;
|
||||
rtrans.descriptionBitmap = description;
|
||||
previous = rtrans;
|
||||
}
|
||||
rlink.encodeFirsttransfer( rtrans );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if ( dc == null )
|
||||
{
|
||||
hollowNodes.remove( this );
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isHollow()
|
||||
{
|
||||
return selev == -12345;
|
||||
}
|
||||
|
||||
public void setHollow()
|
||||
{
|
||||
selev = -12345;
|
||||
}
|
||||
|
||||
public long getIdFromPos()
|
||||
{
|
||||
return ( (long) ilon ) << 32 | ilat;
|
||||
}
|
||||
|
||||
public void unlinkLink( OsmLink link )
|
||||
{
|
||||
if ( link == firstlink )
|
||||
{
|
||||
firstlink = link.next;
|
||||
return;
|
||||
}
|
||||
for ( OsmLink l = firstlink; l != null; l = l.next )
|
||||
{
|
||||
if ( l.next == link )
|
||||
{
|
||||
l.next = link.next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object o )
|
||||
{
|
||||
if ( o instanceof OsmNode )
|
||||
{
|
||||
OsmNode n = (OsmNode) o;
|
||||
return n.ilon == ilon && n.ilat == ilat;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return ilon + ilat;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue