/*
* GribGDS.java
*
* Created on 17 August 2006, 20:19
*
* $Id: GribGDS.java 8 2006-08-24 11:06:19Z gabriel $
*
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Viperfish.
*
* The Initial Developer of the Original Code is Gabriel Galibourg.
* Portions created by Gabriel Galibourg are Copyright (C) 2005-2006
* Gabriel Galibourg. All Rights Reserved.
*
* Contributor(s):
*
*/
package com.solfin.grib;
import java.io.DataInputStream;
import com.solfin.tools.MapPoint;
/**
* This class describes the GDS section of a GRIB record.
*
* A GDS is a grid description section, please note that it is optional. Its
* presence will be indicated in the PDS section. If the GDS is not present then
* the PDS will have to make a reference to a 'hard-coded' GDS code. We do
* not implement hard coded GDS codes yet, therefore if a GDS is missing
* a BadGribException will be raised.
*
* @author gabriel
*/
class GribGDS extends _GribSection {
private GribRecord dad;
private short nv;
private short pvl;
private short representationType;
protected GDS_LatLon subGDS;
public class GDS_LatLon {
public int ni;
public int nj;
float la1;
float lo1;
float la2;
float lo2;
short resComp;
float di;
float dj;
short scanModeFlag;
float sdi; // di with sign adjusted as per scanModeFlag
float sdj; // dj with sign adjusted as per scanModeFlag
public GDS_LatLon(byte[] buf) {
ni=GribTools.uint(buf[7],buf[8]);
nj=GribTools.uint(buf[9],buf[10]);
la1=GribTools.sint(buf[11],buf[12],buf[13]) / 1000F;
lo1=GribTools.sint(buf[14],buf[15],buf[16]) / 1000F;
la2=GribTools.sint(buf[18],buf[19],buf[20]) / 1000F;
lo2=GribTools.sint(buf[21],buf[22],buf[23]) / 1000F;
resComp=GribTools.uint(buf[17]);
di=GribTools.uint(buf[24],buf[25]) / 1000F;
dj=GribTools.uint(buf[26],buf[27]) / 1000F;
scanModeFlag=GribTools.uint(buf[28]);
sdi = (scanModeFlag & 128) == 0 ? +di : -di ;
sdj = (scanModeFlag & 64) == 0 ? -dj : +dj ;
// TODO scan mode flag also indicates i or j adjacency
// TODO that codes needs to be written!
}
public float getLon(int seqNum) {
// TODO: what if adjacency is in j direction ? (see scanModeFlag)
return (float) ( lo1 + ( (seqNum % ni) * sdi ) ) ;
}
public float getLat(int seqNum) {
// TODO: what if adjacency is in j direction ? (see scanModeFlag)
return (float) ( la1 + ( (seqNum / ni) * sdj ) ) ;
}
public int getNi() {
return ni;
}
public int getNj() {
return nj;
}
public int getClosestPoints(MapPoint p1, int[] retIdx, double[] dists) {
// a direct calculation method is possible //TODO
int lastI=dists.length-1;
int nbVal=0;
for (int i=lastI ; i>=0 ; --i) {
retIdx[i]=Integer.MAX_VALUE;
dists[i]=Double.MAX_VALUE;
}
for (int i=ni*nj-1 ; i>=0 ; --i) {
MapPoint p2=new MapPoint(getLon(i),getLat(i));
double dist=GribValue.distanceHaversine(p1, p2).value();
if (dist > dists[lastI])
continue;
int j;
for (j=lastI-1 ; j>=0 && dists[j]>dist ; --j) {
retIdx[j+1]=retIdx[j];
dists[j+1] =dists[j];
}
dists[j+1] = dist;
retIdx[j+1]= i;
++nbVal;
}
return (nbVal>dists.length?dists.length:nbVal);
}
public String toString() {
return "ni="+ni+" nj="+nj+
" [la1="+la1+" la2="+la2 + "] [lo1="+lo1+" lo2="+lo2+"]"+
" resComp="+resComp+
" di="+di+" dj="+dj+
" scanModeFlag="+scanModeFlag+
"";
}
}
protected GribGDS(GribRecord dad) {
this.dad = dad;
}
public void read(DataInputStream in) {
try {
byte[] buf=new byte[4];
in.readFully(buf,1,3);
length=GribTools.uint(buf[1],buf[2],buf[3]);
buf = new byte[length+1];
in.readFully(buf,4,length-3);
nv=GribTools.uint(buf[4]);
pvl=GribTools.uint(buf[5]);
representationType=buf[6];
if (representationType==0) {
subGDS=new GDS_LatLon(buf);
}
} catch (Exception e) {
System.err.println("Exception in GribRecord.GDS.GDS: "+e);
}
}
public int gridSize() {
if (subGDS!=null)
return (subGDS.ni*subGDS.nj);
return 0;
}
public String toString() {
return "length="+length+
" nv="+nv+" pv/pl="+pvl+
" representationType="+representationType+
(subGDS!=null?" :: "+subGDS.toString():"");
}
}