001 /** 002 * 003 */ 004 package org.wdssii.core; 005 006 import java.util.Arrays; 007 008 /** 009 * @author lakshman 010 * 011 */ 012 public class Radial { 013 private float[] values; 014 015 private final float startAzimuth; 016 017 private final float beamWidth; 018 019 private final float azimuthalSpacing; 020 021 private final float nyquist; 022 023 private final float gateWidth; 024 025 private CVector unitVector; 026 027 /** in degrees and kilometers. Does not copy array 028 * @param ny 029 * @param */ 030 public Radial(float startAz, float beamWidth, 031 float azimuthalSpacing, float gateWidth, 032 float nyquist, float[] values) { 033 this.gateWidth = gateWidth; 034 this.values = values; 035 this.startAzimuth = startAz; 036 this.beamWidth = beamWidth; 037 this.azimuthalSpacing = azimuthalSpacing; 038 this.nyquist = nyquist; 039 } 040 041 /** 042 * Creates a completely separate copy of the data so that the master can change 043 * without affecting this value. 044 * @param radial 045 */ 046 public Radial(Radial master) { 047 this.values = Arrays.copyOf(master.values, master.values.length); 048 this.startAzimuth = master.startAzimuth; 049 this.beamWidth = master.beamWidth; 050 this.azimuthalSpacing = master.azimuthalSpacing; 051 this.nyquist = master.nyquist; 052 this.gateWidth = master.gateWidth; 053 this.unitVector = master.unitVector; 054 } 055 056 /** puts the given angle in the range [0,360) */ 057 public static float normalizeAzimuth(float az) { 058 // in range [0,360) 059 if (az < 0) 060 az += 360; 061 else if (az >= 360) 062 az -= 360; 063 return az; 064 } 065 066 public boolean contains(float az) { 067 // returns range [0,360) 068 float diff = normalizeAzimuth(az - startAzimuth); 069 return (diff < azimuthalSpacing); 070 } 071 072 public float[] getValues() { 073 return values; 074 } 075 076 /** returns a completely separate copy of the array. */ 077 public float[] getClonedValues() { 078 float[] temp = new float[values.length]; 079 for (int i = 0; i < values.length; ++i) 080 temp[i] = values[i]; 081 return temp; 082 } 083 084 /** may not be normalized */ 085 public float getStartAzimuth() { 086 return startAzimuth; 087 } 088 089 /** 090 * the end azimuth is not normalized in range [0,360) -- the rule instead is 091 * that the azimuth will be greater than the start azimuth. 092 */ 093 public float getEndAzimuth() { 094 return (startAzimuth + azimuthalSpacing); 095 } 096 097 /** 098 * the mid azimuth is not normalized in range [0,360) -- the rule instead is 099 * that the azimuth will be greater than the start azimuth. 100 */ 101 public float getMidAzimuth() { 102 return (float) (startAzimuth + 0.5 * azimuthalSpacing); 103 } 104 105 /** always positive */ 106 public float getBeamWidth() { 107 return beamWidth; 108 } 109 110 public float getAzimuthalSpacing(){ 111 return azimuthalSpacing; 112 } 113 114 /** in meters */ 115 public float getGateWidthKms() { 116 return gateWidth; 117 } 118 119 public float getValue(int index) { 120 return values[index]; 121 } 122 123 public int getNumGates() { 124 return values.length; 125 } 126 127 /** in m/s */ 128 public float getNyquist(){ 129 return nyquist; 130 } 131 132 /** range in kilometers. */ 133 public double getRawValue(double range) { 134 int i = (int) Math.round(range / gateWidth); 135 if (i >= 0 && i < values.length) 136 return values[i]; 137 else 138 return DataType.MissingData; 139 } 140 141 /** 142 * get the unit vector along the direction of this radial. This method will 143 * do the computation only on the first call, and return old values after 144 * that, so the elevation is not used after that. 145 */ 146 public CVector getUnitVector(float elevation) { 147 if (unitVector == null) { 148 // unit vector in co-ordinate system tangential to 149 // earth at the radar location. 150 double angle_to_xdir = (90 - getMidAzimuth()) * Math.PI / 180.0; 151 unitVector = new CVector(Math.cos(angle_to_xdir), Math 152 .sin(angle_to_xdir), Math.sin(elevation * Math.PI / 180.0)) 153 .unit(); 154 return unitVector; 155 } 156 return unitVector; 157 } 158 159 /* 160 * @param elevation of the RadialSet @param gateno of point @param radar 161 * location of radar @param ux x-axis of local co-ordinate system tangential 162 * to earth's surface at radar location 163 */ 164 public CPoint getLocation(float elevation, int gateno, CPoint radar, 165 CVector ux, CVector uy, CVector uz) { 166 CVector disp = getUnitVector(elevation).multiply( 167 gateno * getGateWidthKms() ); 168 CVector disp_global = ux.multiply(disp.x).plus(uy.multiply(disp.y)) 169 .plus(uz.multiply(disp.z)); 170 CPoint result = radar.plus(disp_global); 171 return result; 172 } 173 174 /** debugging output */ 175 public String toStringDB() { 176 String s = "Radial " + startAzimuth + " to " + getEndAzimuth() + " deg" 177 + " " + gateWidth + "km " + " first 10 values: \n"; 178 for (int i = 0; i < 10; ++i) 179 s += getValue(i) + " "; 180 return (s + "\n"); 181 } 182 183 }