/* * Copyright 2007-2014, 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.LasPointCloud; import com.revolsys.elevation.cloud.las.pointformat.LasPoint; public class LazDecompressPoint10V1 extends LazDecompressPoint10 { private final int[] lastDiffX = new int[3]; private final int[] lastDiffY = new int[3]; private int lastIncrement; private final IntegerCompressor decompressScanAngleRank; public LazDecompressPoint10V1(final LasPointCloud pointCloud, final ArithmeticDecoder decoder) { super(pointCloud, decoder); this.decompressDeltaX = new IntegerCompressor(decoder, 32); this.decompressDeltaY = new IntegerCompressor(decoder, 32, 20); this.decompressZ = new IntegerCompressor(decoder, 32, 20); this.decompressIntensity = new IntegerCompressor(decoder, 16); this.decompressScanAngleRank = new IntegerCompressor(decoder, 8, 2); this.decompressPointSourceId = new IntegerCompressor(decoder, 16); } @Override public void init(final LasPoint point) { super.init(point); this.lastDiffX[0] = this.lastDiffX[1] = this.lastDiffX[2] = 0; this.lastDiffY[0] = this.lastDiffY[1] = this.lastDiffY[2] = 0; this.lastIncrement = 0; this.decompressScanAngleRank.initDecompressor(); this.intensity = point.getIntensity(); } private int median(final int[] lastDiffs) { int medianX; final int diff0 = lastDiffs[0]; final int diff1 = lastDiffs[1]; final int diff2 = lastDiffs[2]; if (diff0 < diff1) { if (diff1 < diff2) { medianX = diff1; } else if (diff0 < diff2) { medianX = diff2; } else { medianX = diff0; } } else { if (diff0 < diff2) { medianX = diff0; } else if (diff1 < diff2) { medianX = diff2; } else { medianX = diff1; } } return medianX; } @Override public void read(final LasPoint point) { final int medianX = median(this.lastDiffX); final int medianY = median(this.lastDiffY); // decompress x y z coordinates final int diffX = this.decompressDeltaX.decompress(medianX); this.x += diffX; // we use the number k of bits corrector bits to switch contexts final int kBitsX = this.decompressDeltaX.getK(); // unsigned final int diffY = this.decompressDeltaY.decompress(medianY, kBitsX < 19 ? kBitsX : 19); this.y += diffY; final int kBitsY = (kBitsX + this.decompressDeltaY.getK()) / 2; this.z = this.decompressZ.decompress(this.z, kBitsY < 19 ? kBitsY : 19); final int changedValues = this.decoder.decodeSymbol(this.decompressChangedValues); if (changedValues != 0) { if ((changedValues & 32) != 0) { this.intensity = this.decompressIntensity.decompress(this.intensity); } if ((changedValues & 16) != 0) { this.returnByte = read(this.decompressBitByte, this.returnByte); } if ((changedValues & 8) != 0) { this.classificationByte = read(this.decompressClassification, this.classificationByte); } if ((changedValues & 4) != 0) { this.scanAngleRank = (byte)this.decompressScanAngleRank.decompress(this.scanAngleRank, kBitsY < 3 ? 1 : 0); } if ((changedValues & 2) != 0) { this.userData = read(this.decompressUserData, this.userData); } if ((changedValues & 1) != 0) { this.pointSourceId = this.decompressPointSourceId.decompress(this.pointSourceId); } } // record the difference this.lastDiffX[this.lastIncrement] = diffX; this.lastDiffY[this.lastIncrement] = diffY; this.lastIncrement++; if (this.lastIncrement > 2) { this.lastIncrement = 0; } postRead(point); } }