org.tinfour.gis.shapefile.DbfFieldDouble Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of TinfourGis Show documentation
Show all versions of TinfourGis Show documentation
Classes for accessing data from GIS sources including Shapefiles and airborne Lidar
/* --------------------------------------------------------------------
* Copyright (C) 2018 Gary W. Lucas.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ---------------------------------------------------------------------
*/
/*
* -----------------------------------------------------------------------
*
* Revision History:
* Date Name Description
* ------ --------- -------------------------------------------------
* 11/2018 G. Lucas Created
*
* Notes:
*
* -----------------------------------------------------------------------
*/
package org.tinfour.gis.shapefile;
import java.io.IOException;
import java.util.Arrays;
import org.tinfour.io.BufferedRandomAccessReader;
/**
* Extends DbfField with special handling for reading numeric values.
*/
public class DbfFieldDouble extends DbfField {
private final static double LOG10 = Math.log(10.0);
private double value;
private boolean engineeringNotation;
DbfFieldDouble(
String name,
char fieldType,
int dataAddress,
int fieldLength,
int fieldDecimalCount,
int offset) {
super(name, fieldType, dataAddress, fieldLength, fieldDecimalCount, offset);
}
@Override
void read(BufferedRandomAccessReader brad, long recordFilePos) throws IOException {
brad.seek(recordFilePos + offset);
builder.setLength(0);
engineeringNotation = false;
int i = 0;
double sign = 1;
long s = 0; // should these be longs?
long f = 0;
long d = 1;
// find first non-space character
while (i < fieldLength) {
int b = brad.readUnsignedByte();
builder.append((char)b);
if (b == 32) {
i++;
} else if (b == '-') {
sign = -1;
i++;
break;
} else if (b == '+') {
i++;
break;
} else if (48 <= b && b <= 57) {
s = b - 48;
i++;
break;
}else if(b=='.' || b==','){
// assume this is a leading decimal point and defer processing
break;
} else {
// a non-whitespace character. at this time,
// the meaning of this is unknown.
value = Double.NaN;
return;
}
}
if(i==fieldLength){
value = Double.NaN;
return;
}
// process the non-fractional part
while (i < fieldLength) {
int b = brad.readUnsignedByte();
builder.append((char)b);
if (b == '.' || b == ',') {
// transition to fractiional part
i++;
break;
}
s = s * 10 + (b - 48);
i++;
}
// process the fractional part
engineeringNotation = false;
while (i < fieldLength) {
int b = brad.readUnsignedByte();
builder.append((char)b);
if (b == 32) {
break;
}else if(b=='e' || b=='E'){
engineeringNotation = true;
break;
}
d = d * 10;
f = f * 10 + (b - 48);
i++;
}
value = sign * ((double) s + (double) f / (double) d);
if(engineeringNotation){
if(i>fieldLength-3){
value = Double.NaN;
}else{
s = 0;
i++;
int b = brad.readUnsignedByte();
builder.append((char)b);
if(b=='-'){
sign = -1;
}else{
sign = 1;
}
i++;
d = 0;
while(iInteger.MAX_VALUE){
return Integer.MAX_VALUE;
}
return (int)value;
}
@Override
public Object getApplicationData(){
return value;
}
/**
* Gets an array of unique values for this field.
* @param dbf a valid instance
* @return if successful an array of zero or more elements.
* @throws IOException in the event of an unrecoverable I/O condition.
*/
public double [] getUniqueValueArray(DbfFileReader dbf) throws IOException {
Double vMin = Double.POSITIVE_INFINITY;
Double vMax = Double.NEGATIVE_INFINITY;
int nRecords = dbf.getRecordCount();
double[] vArray = new double[nRecords];
if (nRecords == 0) {
return new double[0];
}
int k = 0;
for (int i = 1; i <= nRecords; i++) {
dbf.readField(i, this);
double v = getDouble();
if (v < vMin) {
vMin = v;
}
if (v > vMax) {
vMax = v;
}
vArray[k++] = v;
}
Arrays.sort(vArray);
int nUniqueValues = 1;
double prior = vArray[0];
for (int i = 1; i < nRecords; i++) {
if (vArray[i] != prior) {
prior = vArray[i];
vArray[nUniqueValues] = vArray[i];
nUniqueValues++;
}
}
return Arrays.copyOf(vArray, nUniqueValues);
}
}