|
|
@ -13,18 +13,54 @@ public class TemperatureDataService { |
|
|
private int maxRow, maxCol; |
|
|
private int maxRow, maxCol; |
|
|
private float minTemp = Float.MAX_VALUE; |
|
|
private float minTemp = Float.MAX_VALUE; |
|
|
private float maxTemp = Float.MIN_VALUE; |
|
|
private float maxTemp = Float.MIN_VALUE; |
|
|
|
|
|
private float avgTemp; |
|
|
|
|
|
|
|
|
|
|
|
private static boolean containsPoint(double[] xs, double[] ys, double px, double py) { |
|
|
|
|
|
boolean inside = false; |
|
|
|
|
|
for (int i = 0, j = xs.length - 1; i < xs.length; j = i++) { |
|
|
|
|
|
double yi = ys[i], yj = ys[j]; |
|
|
|
|
|
if ((yi > py) != (yj > py)) { |
|
|
|
|
|
double xi = xs[i], xj = xs[j]; |
|
|
|
|
|
if (px < (xj - xi) * (py - yi) / (yj - yi) + xi) { |
|
|
|
|
|
inside = !inside; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return inside; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public String toString() { |
|
|
public String toString() { |
|
|
return "TemperatureDataService{" + "rows=" + rows + ", cols=" + cols + ", minRow=" + minRow + ", minCol=" + minCol + ", maxRow=" + maxRow + ", maxCol=" + maxCol + ", minTemp=" + minTemp + ", maxTemp=" + maxTemp + '}'; |
|
|
return "TemperatureDataService{" + "rows=" + rows + ", cols=" + cols + ", minRow=" + minRow + ", minCol=" + minCol + ", maxRow=" + maxRow + ", maxCol=" + maxCol + ", minTemp=" + minTemp + ", maxTemp=" + maxTemp + '}'; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static boolean hasTemperatureData(float[][] temperatureMatrix) { |
|
|
|
|
|
if (temperatureMatrix == null || temperatureMatrix.length == 0) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (float[] row : temperatureMatrix) { |
|
|
|
|
|
if (row == null) { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
for (float value : row) { |
|
|
|
|
|
if (!Float.isNaN(value)) { |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
public void load(float[][] temperatureMatrix) { |
|
|
public void load(float[][] temperatureMatrix) { |
|
|
temperatures = temperatureMatrix; |
|
|
temperatures = temperatureMatrix; |
|
|
rows = temperatures.length; |
|
|
rows = temperatures.length; |
|
|
cols = temperatures[0].length; |
|
|
cols = temperatures[0].length; |
|
|
|
|
|
double sum = 0; |
|
|
|
|
|
int count = 0; |
|
|
|
|
|
|
|
|
for (int r = 0; r < rows; r++) { |
|
|
for (int r = 0; r < rows; r++) { |
|
|
|
|
|
System.arraycopy(temperatures[r], 0, this.temperatures[r], 0, cols); |
|
|
for (int c = 0; c < cols; c++) { |
|
|
for (int c = 0; c < cols; c++) { |
|
|
float v = temperatures[r][c]; |
|
|
float v = temperatures[r][c]; |
|
|
if (!Float.isNaN(v)) { |
|
|
if (!Float.isNaN(v)) { |
|
|
@ -38,22 +74,27 @@ public class TemperatureDataService { |
|
|
maxRow = r; |
|
|
maxRow = r; |
|
|
maxCol = c; |
|
|
maxCol = c; |
|
|
} |
|
|
} |
|
|
|
|
|
sum += v; |
|
|
|
|
|
count++; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
this.avgTemp = count == 0 ? Float.NaN : (float) (sum / count); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
public RegionStats calcRegion(double[] xs, double[] ys) { |
|
|
public RegionStats calcRegion(double[] xs, double[] ys) { |
|
|
if (xs == null || ys == null || xs.length != ys.length || xs.length < 3) { |
|
|
if (xs == null || ys == null || xs.length != ys.length || xs.length < 3) { |
|
|
return new RegionStats(0, 0, 0, -1, -1,-1,-1); |
|
|
|
|
|
|
|
|
return new RegionStats(0, 0, 0, -1, -1, -1, -1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Bounding box of the polygon, clamped to the CSV grid |
|
|
// Bounding box of the polygon, clamped to the CSV grid |
|
|
double minX = Double.MAX_VALUE, maxX = -Double.MAX_VALUE; |
|
|
double minX = Double.MAX_VALUE, maxX = -Double.MAX_VALUE; |
|
|
double minY = Double.MAX_VALUE, maxY = -Double.MAX_VALUE; |
|
|
double minY = Double.MAX_VALUE, maxY = -Double.MAX_VALUE; |
|
|
for (int i = 0; i < xs.length; i++) { |
|
|
for (int i = 0; i < xs.length; i++) { |
|
|
minX = Math.min(minX, xs[i]); maxX = Math.max(maxX, xs[i]); |
|
|
|
|
|
minY = Math.min(minY, ys[i]); maxY = Math.max(maxY, ys[i]); |
|
|
|
|
|
|
|
|
minX = Math.min(minX, xs[i]); |
|
|
|
|
|
maxX = Math.max(maxX, xs[i]); |
|
|
|
|
|
minY = Math.min(minY, ys[i]); |
|
|
|
|
|
maxY = Math.max(maxY, ys[i]); |
|
|
} |
|
|
} |
|
|
int r0 = Math.max(0, (int) Math.floor(minY)); |
|
|
int r0 = Math.max(0, (int) Math.floor(minY)); |
|
|
int r1 = Math.min(rows, (int) Math.ceil(maxY)); |
|
|
int r1 = Math.min(rows, (int) Math.ceil(maxY)); |
|
|
@ -69,42 +110,36 @@ public class TemperatureDataService { |
|
|
if (!containsPoint(xs, ys, c + 0.5, r + 0.5)) continue; |
|
|
if (!containsPoint(xs, ys, c + 0.5, r + 0.5)) continue; |
|
|
float v = temperatures[r][c]; |
|
|
float v = temperatures[r][c]; |
|
|
if (!Float.isNaN(v)) { |
|
|
if (!Float.isNaN(v)) { |
|
|
if (v < min) { min = v; minR = r; minC = c; } |
|
|
|
|
|
if (v > max) { max = v; maxR = r; maxC = c; } |
|
|
|
|
|
|
|
|
if (v < min) { |
|
|
|
|
|
min = v; |
|
|
|
|
|
minR = r; |
|
|
|
|
|
minC = c; |
|
|
|
|
|
} |
|
|
|
|
|
if (v > max) { |
|
|
|
|
|
max = v; |
|
|
|
|
|
maxR = r; |
|
|
|
|
|
maxC = c; |
|
|
|
|
|
} |
|
|
sum += v; |
|
|
sum += v; |
|
|
count++; |
|
|
count++; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
if (count == 0) return new RegionStats(0, 0, 0, -1, -1,-1,-1); |
|
|
|
|
|
return new RegionStats(min, max, sum / count, minR, minC, maxR, maxC); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static boolean containsPoint(double[] xs, double[] ys, double px, double py) { |
|
|
|
|
|
boolean inside = false; |
|
|
|
|
|
for (int i = 0, j = xs.length - 1; i < xs.length; j = i++) { |
|
|
|
|
|
double yi = ys[i], yj = ys[j]; |
|
|
|
|
|
if ((yi > py) != (yj > py)) { |
|
|
|
|
|
double xi = xs[i], xj = xs[j]; |
|
|
|
|
|
if (px < (xj - xi) * (py - yi) / (yj - yi) + xi) { |
|
|
|
|
|
inside = !inside; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return inside; |
|
|
|
|
|
|
|
|
if (count == 0) return new RegionStats(0, 0, 0, -1, -1, -1, -1); |
|
|
|
|
|
return new RegionStats(min, max, (float) (sum / count), minR, minC, maxR, maxC); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Getter |
|
|
@Getter |
|
|
public static class RegionStats { |
|
|
public static class RegionStats { |
|
|
private final float min; |
|
|
private final float min; |
|
|
private final float max; |
|
|
private final float max; |
|
|
private final double avg; |
|
|
|
|
|
|
|
|
private final float avg; |
|
|
private final int minRow; |
|
|
private final int minRow; |
|
|
private final int minCol; |
|
|
private final int minCol; |
|
|
private final int maxRow; |
|
|
private final int maxRow; |
|
|
private final int maxCol; |
|
|
private final int maxCol; |
|
|
|
|
|
|
|
|
public RegionStats(float min, float max, double avg, int minRow, int minCol, int maxRow, int maxCol) { |
|
|
|
|
|
|
|
|
public RegionStats(float min, float max, float avg, int minRow, int minCol, int maxRow, int maxCol) { |
|
|
this.min = min; |
|
|
this.min = min; |
|
|
this.max = max; |
|
|
this.max = max; |
|
|
this.avg = avg; |
|
|
this.avg = avg; |
|
|
|