/* * Copyright 2007-2012, martin isenburg, rapidlasso - fast tools to catch reality * * This is free software; you can redistribute and/or modify it under the * terms of the GNU Lesser General Licence as published by the Free Software * Foundation. See the LICENSE.txt file for more information. * * This software is distributed WITHOUT ANY WARRANTY and without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ package com.revolsys.elevation.cloud.las.zip; import com.revolsys.elevation.cloud.las.pointformat.LasPoint; public class LazDecompressGpsTime11V2 extends LazDecompressGpsTime11 implements LazDecompress { private static int LASZIP_GPSTIME_MULTI = 500; private static int LASZIP_GPSTIME_MULTI_MINUS = -10; private static int LASZIP_GPSTIME_MULTI_UNCHANGED = LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 1; private static int LASZIP_GPSTIME_MULTI_CODE_FULL = LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 2; private static int LASZIP_GPSTIME_MULTI_TOTAL = LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 6; private int last; private int next; private final long[] lastGpsTime = new long[4]; private final int[] lastGpsTimeDiff = new int[4]; private final int[] multiExtremeCounter = new int[4]; public LazDecompressGpsTime11V2(final ArithmeticDecoder decoder) { super(decoder); this.gpsTimeMulti = ArithmeticDecoder.createSymbolModel(LASZIP_GPSTIME_MULTI_TOTAL); this.gpsTime0Diff = ArithmeticDecoder.createSymbolModel(6); this.decompressGpsTime = new IntegerCompressor(decoder, 32, 9); } @Override public void init(final LasPoint point) { super.init(point); this.last = 0; this.next = 0; this.lastGpsTimeDiff[0] = 0; this.lastGpsTimeDiff[1] = 0; this.lastGpsTimeDiff[2] = 0; this.lastGpsTimeDiff[3] = 0; this.multiExtremeCounter[0] = 0; this.multiExtremeCounter[1] = 0; this.multiExtremeCounter[2] = 0; this.multiExtremeCounter[3] = 0; this.lastGpsTime[0] = Double.doubleToLongBits(point.getGpsTime()); this.lastGpsTime[1] = 0; this.lastGpsTime[2] = 0; this.lastGpsTime[3] = 0; } @Override public void read(final LasPoint point) { int multi; final int[] lastGpsTimeDiff = this.lastGpsTimeDiff; final int lastDiff = lastGpsTimeDiff[this.last]; final ArithmeticDecoder decoder = this.decoder; final long[] lastGpsTime = this.lastGpsTime; final int[] multiExtremeCounter = this.multiExtremeCounter; int last = this.last; int next = this.next; final IntegerCompressor decompressGpsTime = this.decompressGpsTime; if (lastDiff == 0) { // if the last integer difference was zero multi = decoder.decodeSymbol(this.gpsTime0Diff); if (multi == 1) {// the difference can be represented with 32 bits final int gpsTimeDiff = decompressGpsTime.decompress(0, 0); lastGpsTimeDiff[last] = gpsTimeDiff; lastGpsTime[last] += gpsTimeDiff; multiExtremeCounter[last] = 0; } else if (multi == 2) {// the difference is huge long gpsTime = decompressGpsTime.decompress((int)(lastGpsTime[last] >>> 32), 8); gpsTime <<= 32; gpsTime |= Integer.toUnsignedLong(decoder.getInt()); next = this.next + 1; next &= 3; this.next = next; lastGpsTime[next] = gpsTime; last = next; this.last = next; lastGpsTimeDiff[last] = 0; multiExtremeCounter[last] = 0; } else if (multi > 2) {// we switch to another sequence last = last + multi - 2; this.last = last & 3; read(point); } } else { multi = decoder.decodeSymbol(this.gpsTimeMulti); if (multi == 1) { final int gpsTimeDiff = lastGpsTimeDiff[last]; lastGpsTime[last] += decompressGpsTime.decompress(gpsTimeDiff, 1); multiExtremeCounter[last] = 0; } else if (multi < LASZIP_GPSTIME_MULTI_UNCHANGED) { int gpsTimeDiff; if (multi == 0) { gpsTimeDiff = decompressGpsTime.decompress(0, 7); multiExtremeCounter[last]++; if (multiExtremeCounter[last] > 3) { lastGpsTimeDiff[last] = gpsTimeDiff; multiExtremeCounter[last] = 0; } } else if (multi < LASZIP_GPSTIME_MULTI) { gpsTimeDiff = lastGpsTimeDiff[last]; if (multi < 10) { gpsTimeDiff = decompressGpsTime.decompress(multi * gpsTimeDiff, 2); } else { gpsTimeDiff = decompressGpsTime.decompress(multi * gpsTimeDiff, 3); } } else if (multi == LASZIP_GPSTIME_MULTI) { gpsTimeDiff = lastGpsTimeDiff[last]; gpsTimeDiff = decompressGpsTime.decompress(LASZIP_GPSTIME_MULTI * gpsTimeDiff, 4); multiExtremeCounter[last]++; if (multiExtremeCounter[last] > 3) { lastGpsTimeDiff[last] = gpsTimeDiff; multiExtremeCounter[last] = 0; } } else { gpsTimeDiff = lastGpsTimeDiff[last]; multi = LASZIP_GPSTIME_MULTI - multi; if (multi > LASZIP_GPSTIME_MULTI_MINUS) { gpsTimeDiff = decompressGpsTime.decompress(multi * gpsTimeDiff, 5); } else { gpsTimeDiff = decompressGpsTime.decompress(LASZIP_GPSTIME_MULTI_MINUS * gpsTimeDiff, 6); multiExtremeCounter[last]++; if (multiExtremeCounter[last] > 3) { lastGpsTimeDiff[last] = gpsTimeDiff; multiExtremeCounter[last] = 0; } } } lastGpsTime[last] += gpsTimeDiff; } else if (multi == LASZIP_GPSTIME_MULTI_CODE_FULL) { next += 1; next &= 3; this.next = next; long gpsTime = lastGpsTime[last]; gpsTime >>= 32; gpsTime = decompressGpsTime.decompress((int)gpsTime, 8); gpsTime <<= 32; gpsTime |= Integer.toUnsignedLong(decoder.getInt()); lastGpsTime[next] = gpsTime; last = next; this.last = last; lastGpsTimeDiff[last] = 0; multiExtremeCounter[last] = 0; } else if (multi >= LASZIP_GPSTIME_MULTI_CODE_FULL) { last += multi - LASZIP_GPSTIME_MULTI_CODE_FULL; this.last = last & 3; read(point); return; } } point.setGpsTime(Double.longBitsToDouble(lastGpsTime[this.last])); } }