content: /**
   * Container for link between two Osm nodes
   *
   * @author ab
   */
  package btools.mapaccess;
  
  import btools.util.ByteDataReader;
  
  
  public final class GeometryDecoder {
    private ByteDataReader r = new ByteDataReader(null);
    private OsmTransferNode[] cachedNodes;
    private int nCachedNodes = 128;
  
    // result-cache
    private OsmTransferNode firstTransferNode;
    private boolean lastReverse;
    private byte[] lastGeometry;
  
    public GeometryDecoder() {
      // create some caches
      cachedNodes = new OsmTransferNode[nCachedNodes];
      for (int i = 0; i < nCachedNodes; i++) {
        cachedNodes[i] = new OsmTransferNode();
      }
    }
  
    public OsmTransferNode decodeGeometry(byte[] geometry, OsmNode sourceNode, OsmNode targetNode, boolean reverseLink) {
      if ((lastGeometry == geometry) && (lastReverse == reverseLink)) {
        return firstTransferNode;
      }
  
      firstTransferNode = null;
      OsmTransferNode lastTransferNode = null;
      OsmNode startnode = reverseLink ? targetNode : sourceNode;
      r.reset(geometry);
      int olon = startnode.ilon;
      int olat = startnode.ilat;
      int oselev = startnode.selev;
      int idx = 0;
      while (r.hasMoreData()) {
        OsmTransferNode trans = idx < nCachedNodes ? cachedNodes[idx++] : new OsmTransferNode();
        trans.ilon = olon + r.readVarLengthSigned();
        trans.ilat = olat + r.readVarLengthSigned();
        trans.selev = (short) (oselev + r.readVarLengthSigned());
        olon = trans.ilon;
        olat = trans.ilat;
        oselev = trans.selev;
        if (reverseLink) { // reverse chaining
          trans.next = firstTransferNode;
          firstTransferNode = trans;
        } else {
          trans.next = null;
          if (lastTransferNode == null) {
            firstTransferNode = trans;
          } else {
            lastTransferNode.next = trans;
          }
          lastTransferNode = trans;
        }
      }
  
      lastReverse = reverseLink;
      lastGeometry = geometry;
  
      return firstTransferNode;
    }
  }
  