diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index aa4cfdc1..f65d2590 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -1,24 +1,25 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index a1aecb0c..dea81a50 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -13,5 +13,7 @@
+
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__com_google_code_findbugs_jsr305_3_0_2.xml b/.idea/libraries/Maven__com_google_code_findbugs_jsr305_3_0_2.xml
new file mode 100644
index 00000000..1c380d0b
--- /dev/null
+++ b/.idea/libraries/Maven__com_google_code_findbugs_jsr305_3_0_2.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index e7648d85..17b8190b 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -1,12 +1,13 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MeteoInfoLab/MeteoInfoLab.iml b/MeteoInfoLab/MeteoInfoLab.iml
index b438efaa..53ab16e2 100644
--- a/MeteoInfoLab/MeteoInfoLab.iml
+++ b/MeteoInfoLab/MeteoInfoLab.iml
@@ -22,6 +22,8 @@
+
+
diff --git a/MeteoInfoLab/milconfig.xml b/MeteoInfoLab/milconfig.xml
index 88c963b6..f5aa03fb 100644
--- a/MeteoInfoLab/milconfig.xml
+++ b/MeteoInfoLab/milconfig.xml
@@ -13,19 +13,16 @@
-
-
-
@@ -34,5 +31,5 @@
-
+
diff --git a/MeteoInfoLab/pom.xml b/MeteoInfoLab/pom.xml
index 4e44bc64..c93eee20 100644
--- a/MeteoInfoLab/pom.xml
+++ b/MeteoInfoLab/pom.xml
@@ -4,7 +4,7 @@
org.meteothink
MeteoInfo
- 2.4.6
+ 3.0.0
MeteoInfoLab
jar
diff --git a/MeteoInfoLib/MeteoInfoLib.iml b/MeteoInfoLib/MeteoInfoLib.iml
index d93b7292..ff1ddf53 100644
--- a/MeteoInfoLib/MeteoInfoLib.iml
+++ b/MeteoInfoLib/MeteoInfoLib.iml
@@ -12,6 +12,8 @@
+
+
diff --git a/MeteoInfoLib/pom.xml b/MeteoInfoLib/pom.xml
index 95b613f6..fc6ad5d4 100644
--- a/MeteoInfoLib/pom.xml
+++ b/MeteoInfoLib/pom.xml
@@ -5,7 +5,7 @@
org.meteothink
MeteoInfo
- 2.4.6
+ 3.0.0
MeteoInfoLib
@@ -47,6 +47,11 @@
+
+ ${project.groupId}
+ meteoinfo-ndarray
+ ${project.version}
+
edu.ucar
netcdfAll
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayUtil.java
index 3f60d40f..c7a38c84 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayUtil.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/bak/ArrayUtil.java
@@ -1,5546 +1,5546 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.meteoinfo.bak;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Random;
-import java.util.Scanner;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import org.meteoinfo.data.mapdata.Field;
-import org.meteoinfo.geoprocess.GeoComputation;
-import org.meteoinfo.geoprocess.analysis.ResampleMethods;
-import org.meteoinfo.global.DataConvert;
-import org.meteoinfo.global.Extent;
-import org.meteoinfo.global.MIMath;
-import org.meteoinfo.global.PointD;
-import org.meteoinfo.global.util.BigDecimalUtil;
-import org.meteoinfo.global.util.GlobalUtil;
-import org.meteoinfo.io.EndianDataOutputStream;
-import org.locationtech.jts.geom.Coordinate;
-import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.geom.GeometryFactory;
-import org.meteoinfo.data.StationData;
-import org.meteoinfo.layer.VectorLayer;
-import org.meteoinfo.legend.LegendScheme;
-import org.meteoinfo.ndarray.Complex;
-import org.meteoinfo.math.ListIndexComparator;
-import org.meteoinfo.math.spatial.KDTree;
-import org.meteoinfo.math.spatial.KDTree.SearchResult;
-import org.meteoinfo.projection.KnownCoordinateSystems;
-import org.meteoinfo.projection.info.ProjectionInfo;
-import org.meteoinfo.projection.ProjectionUtil;
-import org.meteoinfo.projection.Reproject;
-import org.meteoinfo.shape.PolygonShape;
-import org.meteoinfo.shape.ShapeTypes;
-import org.python.core.PyComplex;
-import org.meteoinfo.ndarray.Array;
-import org.meteoinfo.ndarray.DataType;
-import org.meteoinfo.ndarray.Index;
-import org.meteoinfo.ndarray.Index2D;
-import org.meteoinfo.ndarray.IndexIterator;
-import org.meteoinfo.ndarray.InvalidRangeException;
-import org.meteoinfo.ndarray.Range;
-
-/**
- *
- * @author yaqiang
- */
-public class ArrayUtil {
-
- //
- /**
- * Read ASCII data file to an array
- *
- * @param fileName File name
- * @param delimiter Delimiter
- * @param headerLines Headerline number
- * @param dataType Data type string
- * @param shape Shape
- * @param readFirstCol Read first column data or not
- * @return Result array
- * @throws UnsupportedEncodingException
- * @throws FileNotFoundException
- * @throws IOException
- */
- public static Array readASCIIFile(String fileName, String delimiter, int headerLines, String dataType,
- List shape, boolean readFirstCol) throws UnsupportedEncodingException, FileNotFoundException, IOException {
- BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
- if (headerLines > 0) {
- for (int i = 0; i < headerLines; i++) {
- sr.readLine();
- }
- }
-
- DataType dt = DataType.DOUBLE;
- if (dataType != null) {
- if (dataType.contains("%")) {
- dataType = dataType.split("%")[1];
- }
- dt = ArrayUtil.toDataType(dataType);
- }
-
- int i;
- int[] ss = new int[shape.size()];
- for (i = 0; i < shape.size(); i++) {
- ss[i] = shape.get(i);
- }
- Array a = Array.factory(dt, ss);
-
- String[] dataArray;
- i = 0;
- String line = sr.readLine();
- int sCol = 0;
- if (!readFirstCol) {
- sCol = 1;
- }
- while (line != null) {
- line = line.trim();
- if (line.isEmpty()) {
- line = sr.readLine();
- continue;
- }
- dataArray = GlobalUtil.split(line, delimiter);
- for (int j = sCol; j < dataArray.length; j++) {
- a.setDouble(i, Double.parseDouble(dataArray[j]));
- i += 1;
- if (i >= a.getSize()) {
- break;
- }
- }
- if (i >= a.getSize()) {
- break;
- }
-
- line = sr.readLine();
- }
- sr.close();
-
- return a;
- }
-
- /**
- * Get row number of a ASCII file
- *
- * @param fileName File name
- * @return Row number
- * @throws FileNotFoundException
- */
- public static int numASCIIRow(String fileName) throws FileNotFoundException {
- File f = new File(fileName);
- int lineNumber;
- try (Scanner fileScanner = new Scanner(f)) {
- lineNumber = 0;
- while (fileScanner.hasNextLine()) {
- fileScanner.nextLine();
- lineNumber++;
- }
- }
-
- return lineNumber;
- }
-
- /**
- * Get row number of a ASCII file
- *
- * @param fileName File name
- * @param delimiter
- * @param headerLines
- * @return Row number
- * @throws FileNotFoundException
- */
- public static int numASCIICol(String fileName, String delimiter, int headerLines) throws FileNotFoundException, IOException {
- String[] dataArray;
- try (BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)))) {
- if (headerLines > 0) {
- for (int i = 0; i < headerLines; i++) {
- sr.readLine();
- }
- }
- String line = sr.readLine().trim();
- dataArray = GlobalUtil.split(line, delimiter);
- }
-
- return dataArray.length;
- }
-
- /**
- * Save an array data to a binary file
- *
- * @param fn File path
- * @param a Array
- * @param byteOrder Byte order
- * @param append If append to existing file
- * @param sequential If write as sequential binary file - Fortran
- */
- public static void saveBinFile(String fn, Array a, String byteOrder, boolean append,
- boolean sequential) {
- try (DataOutputStream out = new DataOutputStream(new FileOutputStream(new File(fn), append))) {
- EndianDataOutputStream outs = new EndianDataOutputStream(out);
- ByteBuffer bb = a.getDataAsByteBuffer();
- int n = (int) a.getSize();
- ByteOrder bOrder = ByteOrder.LITTLE_ENDIAN;
- if (byteOrder.equalsIgnoreCase("big_endian")) {
- bOrder = ByteOrder.BIG_ENDIAN;
- }
-
- if (sequential) {
- if (bOrder == ByteOrder.BIG_ENDIAN) {
- outs.writeIntBE(n * 4);
- } else {
- outs.writeIntLE(n * 4);
- }
- }
-
- if (bOrder == ByteOrder.BIG_ENDIAN) {
- outs.write(bb.array());
- } else if (a.getDataType() == DataType.BYTE) {
- outs.write(bb.array());
- } else {
- ByteBuffer nbb = ByteBuffer.allocate(bb.array().length);
- nbb.order(bOrder);
- switch (a.getDataType()) {
- case INT:
- for (int i = 0; i < a.getSize(); i++) {
- nbb.putInt(i * 4, bb.getInt());
- //nbb.putInt(a.getInt(i));
- }
- break;
- case FLOAT:
- for (int i = 0; i < a.getSize(); i++) {
- nbb.putFloat(i * 4, bb.getFloat());
- }
- break;
- case DOUBLE:
- for (int i = 0; i < a.getSize(); i++) {
- nbb.putDouble(i * 8, bb.getDouble());
- }
- break;
- default:
- nbb.put(bb);
- }
- outs.write(nbb.array());
- }
-
- if (sequential) {
- if (bOrder == ByteOrder.BIG_ENDIAN) {
- outs.writeIntBE(n * 4);
- } else {
- outs.writeIntLE(n * 4);
- }
- }
-
- outs.close();
- } catch (FileNotFoundException ex) {
- Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex);
- } catch (IOException ex) {
- Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex);
- }
- }
-
- /**
- * Save an array data to a ASCII file
- *
- * @param fn File path
- * @param a Array
- * @param colNum Column number of each line
- * @param format String format
- * @param delimiter Delimiter
- * @throws java.io.IOException
- */
- public static void saveASCIIFile(String fn, Array a, int colNum,
- String format, String delimiter) throws IOException {
- BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fn)));
- String line = "";
- int j = 0;
- for (int i = 0; i < a.getSize(); i++) {
- j += 1;
- if (format == null) {
- line = line + a.getObject(i).toString();
- } else {
- line = line + String.format(format, a.getObject(i));
- }
- if (j < colNum && i < a.getSize() - 1) {
- if (delimiter == null) {
- line = line + " ";
- } else {
- line = line + delimiter;
- }
- } else {
- sw.write(line);
- sw.newLine();
- line = "";
- j = 0;
- }
- }
- sw.flush();
- sw.close();
- }
-
- /**
- * Read array from a binary file
- *
- * @param fn Binary file name
- * @param dims Dimensions
- * @param dataType Data type string
- * @param skip Skip bytes
- * @param byteOrder Byte order
- * @return Result array
- */
- public static Array readBinFile(String fn, List dims, String dataType, int skip,
- String byteOrder) {
- DataType dt = DataType.DOUBLE;
- if (dataType != null) {
- if (dataType.contains("%")) {
- dataType = dataType.split("%")[1];
- }
- dt = ArrayUtil.toDataType(dataType);
- }
- DataType ndt = dt;
- if (dt == DataType.BYTE) {
- ndt = DataType.INT;
- }
-
- ByteOrder bOrder = ByteOrder.LITTLE_ENDIAN;
- if (byteOrder.equalsIgnoreCase("big_endian")) {
- bOrder = ByteOrder.BIG_ENDIAN;
- }
-
- int[] shape = new int[dims.size()];
- for (int i = 0; i < dims.size(); i++) {
- shape[i] = dims.get(i);
- }
- Array r = Array.factory(ndt, shape);
- IndexIterator iter = r.getIndexIterator();
- try {
- DataInputStream ins = new DataInputStream(new FileInputStream(fn));
- ins.skip(skip);
- byte[] bytes;
- byte[] db;
- int start = 0;
- switch (dt) {
- case BYTE:
- bytes = new byte[(int) r.getSize()];
- ins.read(bytes);
- for (int i = 0; i < r.getSize(); i++) {
- r.setInt(i, DataConvert.byte2Int(bytes[i]));
- }
- break;
- case SHORT:
- bytes = new byte[(int) r.getSize() * 2];
- db = new byte[2];
- ins.read(bytes);
- while (iter.hasNext()) {
- System.arraycopy(bytes, start, db, 0, 2);
- iter.setShortNext(DataConvert.bytes2Short(db, bOrder));
- start += 2;
- }
- break;
- case INT:
- bytes = new byte[(int) r.getSize() * 4];
- db = new byte[4];
- ins.read(bytes);
- while (iter.hasNext()) {
- System.arraycopy(bytes, start, db, 0, 4);
- iter.setIntNext(DataConvert.bytes2Int(db, bOrder));
- start += 4;
- }
- break;
- case FLOAT:
- bytes = new byte[(int) r.getSize() * 4];
- db = new byte[4];
- ins.read(bytes);
- while (iter.hasNext()) {
- System.arraycopy(bytes, start, db, 0, 4);
- iter.setFloatNext(DataConvert.bytes2Float(db, bOrder));
- start += 4;
- }
- break;
- case DOUBLE:
- bytes = new byte[(int) r.getSize() * 8];
- db = new byte[8];
- ins.read(bytes);
- while (iter.hasNext()) {
- System.arraycopy(bytes, start, db, 0, 8);
- iter.setDoubleNext(DataConvert.bytes2Double(db, bOrder));
- start += 8;
- }
- break;
- }
- ins.close();
- } catch (FileNotFoundException ex) {
- Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex);
- } catch (IOException ex) {
- Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex);
- }
-
- return r;
- }
-
- //
- //
-
- /**
- * Create an array
- *
- * @param data Object
- * @return Array
- */
- public static Array array(Object data) {
- if (data instanceof Number) {
- DataType dt = ArrayMath.getDataType(data);
- Array a = Array.factory(dt, new int[]{1});
- a.setObject(0, data);
- return a;
- } else if (data instanceof Array) {
- return (Array) data;
- } else if (data instanceof ArrayList) {
- return array((List
- //
- /**
- * Array to string
- *
- * @param a Array a
- * @return String
- */
- public static String convertToString(Array a) {
- StringBuilder sbuff = new StringBuilder();
- sbuff.append("array(");
- int ndim = a.getRank();
- if (ndim > 1) {
- sbuff.append("[");
- }
- int i = 0, n = 0;
- IndexIterator ii = a.getIndexIterator();
- int shapeIdx = ndim - 1;
- if (shapeIdx < 0) {
- sbuff.append("[");
- sbuff.append(ii.getObjectNext());
- sbuff.append("])");
- return sbuff.toString();
- }
-
- int len = a.getShape()[shapeIdx];
- Object data;
- String dstr;
- while (ii.hasNext()) {
- if (i == 0) {
- if (n > 0) {
- sbuff.append("\n ");
- }
- sbuff.append("[");
- }
- data = ii.getObjectNext();
- dstr = data.toString();
- if (a.getDataType() == DataType.BOOLEAN) {
- dstr = GlobalUtil.capitalize(dstr);
- }
- sbuff.append(dstr);
- i += 1;
- if (i == len) {
- sbuff.append("]");
- len = a.getShape()[shapeIdx];
- i = 0;
- } else {
- sbuff.append(", ");
- }
- n += 1;
- if (n > 200) {
- sbuff.append("...]");
- break;
- }
- }
- if (ndim > 1) {
- sbuff.append("]");
- }
- sbuff.append(")");
- return sbuff.toString();
- }
-
- /**
- * Array to string
- *
- * @param a Array a
- * @return String
- */
- public static String toString_old(Array a) {
- StringBuilder sbuff = new StringBuilder();
- sbuff.append("array(");
- int ndim = a.getRank();
- if (ndim > 1) {
- sbuff.append("[");
- }
- int i = 0;
- int shapeIdx = ndim - 1;
- int len = a.getShape()[shapeIdx];
- IndexIterator ii = a.getIndexIterator();
- while (ii.hasNext()) {
- if (i == 0) {
- sbuff.append("[");
- }
- Object data = ii.getObjectNext();
- sbuff.append(data);
- i += 1;
- if (i == len) {
- sbuff.append("]");
- len = a.getShape()[shapeIdx];
- i = 0;
- } else {
- sbuff.append(", ");
- }
- }
- if (ndim > 1) {
- sbuff.append("]");
- }
- return sbuff.toString();
- }
-
- /**
- * Get array list from StationData
- *
- * @param stdata StationData
- * @return Array list
- */
- public static List getArraysFromStationData(StationData stdata) {
- int n = stdata.getStNum();
- int[] shape = new int[1];
- shape[0] = n;
- Array lon = Array.factory(DataType.FLOAT, shape);
- Array lat = Array.factory(DataType.FLOAT, shape);
- Array value = Array.factory(DataType.FLOAT, shape);
- double v;
- for (int i = 0; i < n; i++) {
- lon.setFloat(i, (float) stdata.getX(i));
- lat.setFloat(i, (float) stdata.getY(i));
- v = stdata.getValue(i);
- if (v == stdata.missingValue) {
- v = Double.NaN;
- }
- value.setFloat(i, (float) v);
- }
-
- List r = new ArrayList<>();
- r.add(lon);
- r.add(lat);
- r.add(value);
- return r;
- }
-
- //
- //
- /**
- * Get data type string
- *
- * @param dt The data type
- * @return Data type string
- */
- public static String dataTypeString(DataType dt) {
- String str = "string";
- switch (dt) {
- case BYTE:
- str = "byte";
- break;
- case SHORT:
- str = "short";
- break;
- case INT:
- str = "int";
- break;
- case FLOAT:
- str = "float";
- break;
- case DOUBLE:
- str = "double";
- break;
- }
-
- return str;
- }
-
- /**
- * To data type - ucar.ma2
- *
- * @param dt Data type string
- * @return Data type
- */
- public static DataType toDataType(String dt) {
- if (dt.contains("%")) {
- dt = dt.split("%")[1];
- }
- switch (dt.toLowerCase()) {
- case "c":
- case "s":
- case "string":
- return DataType.STRING;
- case "b":
- case "byte":
- return DataType.BYTE;
- case "short":
- return DataType.SHORT;
- case "i":
- case "int":
- return DataType.INT;
- case "f":
- case "float":
- return DataType.FLOAT;
- case "d":
- case "double":
- return DataType.DOUBLE;
- case "bool":
- case "boolean":
- return DataType.BOOLEAN;
- default:
- return DataType.OBJECT;
- }
- }
-
- /**
- * Convert array to integer type
- *
- * @param a Array a
- * @return Result array
- */
- public static Array toInteger(Array a) {
- Array r = Array.factory(DataType.INT, a.getShape());
- if (a.getDataType().isNumeric()) {
- for (int i = 0; i < r.getSize(); i++) {
- r.setInt(i, a.getInt(i));
- }
- } else {
- if (a.getDataType() == DataType.BOOLEAN) {
- for (int i = 0; i < r.getSize(); i++) {
- r.setInt(i, a.getBoolean(i) ? 1 : 0);
- }
- } else {
- for (int i = 0; i < r.getSize(); i++) {
- r.setInt(i, Integer.valueOf(a.getObject(i).toString()));
- }
- }
- }
-
- return r;
- }
-
- /**
- * Convert array to float type
- *
- * @param a Array a
- * @return Result array
- */
- public static Array toFloat(Array a) {
- Array r = Array.factory(DataType.FLOAT, a.getShape());
- if (a.getDataType().isNumeric()) {
- for (int i = 0; i < r.getSize(); i++) {
- r.setFloat(i, a.getFloat(i));
- }
- } else {
- for (int i = 0; i < r.getSize(); i++) {
- r.setFloat(i, Float.valueOf(a.getObject(i).toString()));
- }
- }
-
- return r;
- }
-
- /**
- * Convert array to double type
- *
- * @param a Array a
- * @return Result array
- */
- public static Array toDouble(Array a) {
- Array r = Array.factory(DataType.DOUBLE, a.getShape());
- if (a.getDataType().isNumeric()) {
- for (int i = 0; i < r.getSize(); i++) {
- r.setDouble(i, a.getDouble(i));
- }
- } else {
- for (int i = 0; i < r.getSize(); i++) {
- r.setDouble(i, Double.valueOf(a.getObject(i).toString()));
- }
- }
-
- return r;
- }
-
- /**
- * Convert array to boolean type
- *
- * @param a Array a
- * @return Result array
- */
- public static Array toBoolean(Array a) {
- Array r = Array.factory(DataType.BOOLEAN, a.getShape());
- for (int i = 0; i < r.getSize(); i++) {
- r.setBoolean(i, a.getDouble(i) != 0);
- }
-
- return r;
- }
-
- /**
- * Concatenate arrays to one array along a axis
- *
- * @param arrays Array list
- * @param axis The axis
- * @return Concatenated array
- * @throws org.meteoinfo.ndarray.InvalidRangeException
- */
- public static Array concatenate(List arrays, Integer axis) throws InvalidRangeException {
- int ndim = arrays.get(0).getRank();
- if (axis == -1) {
- axis = ndim - 1;
- }
- int len = 0;
- int[] lens = new int[arrays.size()];
- int i = 0;
- List indexList = new ArrayList<>();
- for (Array a : arrays) {
- len += a.getShape()[axis];
- lens[i] = len;
- indexList.add(Index.factory(a.getShape()));
- i += 1;
- }
- int[] shape = arrays.get(0).getShape();
- shape[axis] = len;
- Array r = Array.factory(arrays.get(0).getDataType(), shape);
- int[] current;
- IndexIterator ii = r.getIndexIterator();
- Index index;
- int idx = 0;
- while (ii.hasNext()) {
- ii.next();
- current = ii.getCurrentCounter();
- for (i = 0; i < lens.length; i++) {
- if (current[axis] < lens[i]) {
- idx = i;
- break;
- }
- }
- if (idx > 0) {
- current[axis] = current[axis] - lens[idx - 1];
- }
- index = indexList.get(idx);
- index.set(current);
- ii.setObjectCurrent(arrays.get(idx).getObject(index));
- }
-
- return r;
- }
-
- /**
- * Concatenate two arrays to one array along a axis
- *
- * @param a Array a
- * @param b Array b
- * @param axis The axis
- * @return Concatenated array
- * @throws org.meteoinfo.ndarray.InvalidRangeException
- */
- public static Array concatenate(Array a, Array b, Integer axis) throws InvalidRangeException {
- int n = a.getRank();
- int[] shape = a.getShape();
- if (axis == -1) {
- axis = n - 1;
- }
- int nn = shape[axis];
- int[] bshape = b.getShape();
- int[] nshape = new int[n];
- for (int i = 0; i < n; i++) {
- if (i == axis) {
- nshape[i] = shape[i] + bshape[i];
- } else {
- nshape[i] = shape[i];
- }
- }
- Array r = Array.factory(a.getDataType(), nshape);
- Index indexr = r.getIndex();
- Index indexa = a.getIndex();
- Index indexb = b.getIndex();
- int[] current;
- for (int i = 0; i < r.getSize(); i++) {
- current = indexr.getCurrentCounter();
- if (current[axis] < nn) {
- indexa.set(current);
- r.setObject(indexr, a.getObject(indexa));
- } else {
- current[axis] = current[axis - nn];
- indexb.set(current);
- r.setObject(indexr, b.getObject(indexb));
- }
- indexr.incr();
- }
-
- return r;
- }
-
- /**
- * Sort array along an axis
- *
- * @param a Array a
- * @param axis The axis
- * @return Sorted array
- * @throws InvalidRangeException
- */
- public static Array sort(Array a, Integer axis) throws InvalidRangeException {
- int n = a.getRank();
- int[] shape = a.getShape();
- if (axis == null) {
- int[] nshape = new int[1];
- nshape[0] = (int) a.getSize();
- Array r = Array.factory(a.getDataType(), nshape);
- List tlist = new ArrayList();
- IndexIterator ii = a.getIndexIterator();
- while (ii.hasNext()) {
- tlist.add(ii.getObjectNext());
- }
- Collections.sort(tlist);
- for (int i = 0; i < r.getSize(); i++) {
- r.setObject(i, tlist.get(i));
- }
-
- return r;
- } else {
- if (axis == -1) {
- axis = n - 1;
- }
- int nn = shape[axis];
- Array r = Array.factory(a.getDataType(), shape);
- Index indexr = r.getIndex();
- int[] current;
- List ranges = new ArrayList<>();
- for (int i = 0; i < n; i++) {
- if (i == axis) {
- ranges.add(new Range(0, 0, 1));
- } else {
- ranges.add(new Range(0, shape[i] - 1, 1));
- }
- }
- IndexIterator rii = r.sectionNoReduce(ranges).getIndexIterator();
- while (rii.hasNext()) {
- rii.next();
- current = rii.getCurrentCounter();
- ranges = new ArrayList<>();
- for (int j = 0; j < n; j++) {
- if (j == axis) {
- ranges.add(new Range(0, shape[j] - 1, 1));
- } else {
- ranges.add(new Range(current[j], current[j], 1));
- }
- }
- List tlist = new ArrayList();
- IndexIterator ii = a.getRangeIterator(ranges);
- while (ii.hasNext()) {
- tlist.add(ii.getObjectNext());
- }
- Collections.sort(tlist);
- for (int j = 0; j < nn; j++) {
- indexr.set(current);
- r.setObject(indexr, tlist.get(j));
- current[axis] = current[axis] + 1;
- }
- }
-
- return r;
- }
- }
-
- /**
- * Get sorted array index along an axis
- *
- * @param a Array a
- * @param axis The axis
- * @return Index of sorted array
- * @throws InvalidRangeException
- */
- public static Array argSort(Array a, Integer axis) throws InvalidRangeException {
- int n = a.getRank();
- int[] shape = a.getShape();
- Object v;
- if (axis == null) {
- int[] nshape = new int[1];
- nshape[0] = (int) a.getSize();
- Array r = Array.factory(DataType.INT, nshape);
- List stlist = new ArrayList();
- IndexIterator ii = a.getIndexIterator();
- while (ii.hasNext()) {
- v = ii.getObjectNext();
- stlist.add(v);
- }
- //Collections.sort(stlist);
- ListIndexComparator comparator = new ListIndexComparator(stlist);
- Integer[] indexes = comparator.createIndexArray();
- Arrays.sort(indexes, comparator);
- for (int i = 0; i < r.getSize(); i++) {
- r.setInt(i, indexes[i]);
- }
-
- return r;
- } else {
- if (axis == -1) {
- axis = n - 1;
- }
- int nn = shape[axis];
- Array r = Array.factory(DataType.INT, shape);
- Index indexr = r.getIndex();
- int[] current;
- List ranges = new ArrayList<>();
- for (int i = 0; i < n; i++) {
- if (i == axis) {
- ranges.add(new Range(0, 0, 1));
- } else {
- ranges.add(new Range(0, shape[i] - 1, 1));
- }
- }
- IndexIterator rii = r.sectionNoReduce(ranges).getIndexIterator();
- while (rii.hasNext()) {
- rii.next();
- current = rii.getCurrentCounter();
- ranges = new ArrayList<>();
- for (int j = 0; j < n; j++) {
- if (j == axis) {
- ranges.add(new Range(0, shape[j] - 1, 1));
- } else {
- ranges.add(new Range(current[j], current[j], 1));
- }
- }
- List stlist = new ArrayList();
- IndexIterator ii = a.getRangeIterator(ranges);
- while (ii.hasNext()) {
- v = ii.getObjectNext();
- stlist.add(v);
- }
- //Collections.sort(stlist);
- ListIndexComparator comparator = new ListIndexComparator(stlist);
- Integer[] indexes = comparator.createIndexArray();
- Arrays.sort(indexes, comparator);
- for (int j = 0; j < nn; j++) {
- indexr.set(current);
- r.setObject(indexr, indexes[j]);
- current[axis] = current[axis] + 1;
- }
- }
-
- return r;
- }
- }
-
- /**
- * Convert array to N-Dimension double Java array
- *
- * @param a Array a
- * @param dtype Data type string
- * @return N-D Java array
- */
- public static Object copyToNDJavaArray(Array a, String dtype) {
- if (dtype == null) {
- return copyToNDJavaArray(a);
- }
-
- switch (dtype.toLowerCase()) {
- case "double":
- return copyToNDJavaArray_Double(a);
- case "long":
- return copyToNDJavaArray_Long(a);
- default:
- return copyToNDJavaArray(a);
- }
- }
-
- /**
- * Convert array to N-Dimension double Java array
- *
- * @param a Array a
- * @return N-D Java array
- */
- public static Object copyToNDJavaArray(Array a) {
- Object javaArray;
- try {
- javaArray = java.lang.reflect.Array.newInstance(Double.TYPE, a.getShape());
- } catch (IllegalArgumentException | NegativeArraySizeException e) {
- throw new IllegalArgumentException(e);
- }
- IndexIterator iter = a.getIndexIterator();
- reflectArrayCopyOut(javaArray, a, iter);
-
- return javaArray;
- }
-
- /**
- * Convert array to N-Dimension double Java array
- *
- * @param a Array a
- * @return N-D Java array
- */
- public static Object copyToNDJavaArray_Long(Array a) {
- Object javaArray;
- try {
- javaArray = java.lang.reflect.Array.newInstance(Long.TYPE, a.getShape());
- } catch (IllegalArgumentException | NegativeArraySizeException e) {
- throw new IllegalArgumentException(e);
- }
- IndexIterator iter = a.getIndexIterator();
- reflectArrayCopyOut(javaArray, a, iter);
-
- return javaArray;
- }
-
- /**
- * Convert array to N-Dimension double Java array
- *
- * @param a Array a
- * @return N-D Java array
- */
- public static Object copyToNDJavaArray_Double(Array a) {
- Object javaArray;
- try {
- javaArray = java.lang.reflect.Array.newInstance(Double.TYPE, a.getShape());
- } catch (IllegalArgumentException | NegativeArraySizeException e) {
- throw new IllegalArgumentException(e);
- }
- IndexIterator iter = a.getIndexIterator();
- reflectArrayCopyOut(javaArray, a, iter);
-
- return javaArray;
- }
-
- private static void reflectArrayCopyOut(Object jArray, Array aa, IndexIterator aaIter) {
- Class cType = jArray.getClass().getComponentType();
-
- if (!cType.isArray()) {
- if (cType == long.class) {
- copyTo1DJavaArray_Long(aaIter, jArray);
- } else {
- copyTo1DJavaArray(aaIter, jArray);
- }
- } else {
- for (int i = 0; i < java.lang.reflect.Array.getLength(jArray); i++) {
- reflectArrayCopyOut(java.lang.reflect.Array.get(jArray, i), aa, aaIter);
- }
- }
- }
-
- protected static void copyTo1DJavaArray(IndexIterator iter, Object javaArray) {
- double[] ja = (double[]) javaArray;
- for (int i = 0; i < ja.length; i++) {
- ja[i] = iter.getDoubleNext();
- }
- }
-
- protected static void copyTo1DJavaArray_Long(IndexIterator iter, Object javaArray) {
- long[] ja = (long[]) javaArray;
- for (int i = 0; i < ja.length; i++) {
- ja[i] = iter.getLongNext();
- }
- }
-
- /**
- * Return a new array with sub-arrays along an axis deleted
- *
- * @param a Input array
- * @param idx Index
- * @param axis The axis
- * @return
- */
- public static Array delete(Array a, int idx, int axis) {
- int[] shape = a.getShape();
- int n = shape.length;
- int[] nshape = new int[n];
- for (int i = 0; i < n; i++) {
- if (i == axis) {
- nshape[i] = shape[i] - 1;
- } else {
- nshape[i] = shape[i];
- }
- }
- Array r = Array.factory(a.getDataType(), nshape);
- IndexIterator ii = a.getIndexIterator();
- int[] current;
- int i = 0;
- while (ii.hasNext()) {
- ii.next();
- current = ii.getCurrentCounter();
- if (current[axis] != idx) {
- r.setObject(i, ii.getObjectCurrent());
- i += 1;
- }
- }
-
- return r;
- }
-
- /**
- * Return a new array with sub-arrays along an axis deleted
- *
- * @param a Input array
- * @param idx Index
- * @param axis The axis
- * @return
- */
- public static Array delete(Array a, List idx, int axis) {
- int[] shape = a.getShape();
- int n = shape.length;
- int[] nshape = new int[n];
- for (int i = 0; i < n; i++) {
- if (i == axis) {
- nshape[i] = shape[i] - idx.size();
- } else {
- nshape[i] = shape[i];
- }
- }
- Array r = Array.factory(a.getDataType(), nshape);
- IndexIterator ii = a.getIndexIterator();
- int[] current;
- int i = 0;
- while (ii.hasNext()) {
- ii.next();
- current = ii.getCurrentCounter();
- if (!idx.contains(current[axis])) {
- r.setObject(i, ii.getObjectCurrent());
- i += 1;
- }
- }
-
- return r;
- }
-
- //
- //
- /**
- * Histogram x/y array
- *
- * @param a Data array
- * @param nbins bin number
- * @return X/Y arrays
- */
- public static List histogram(Array a, int nbins) {
- double min = ArrayMath.getMinimum(a);
- double max = ArrayMath.getMaximum(a);
- double interval = BigDecimalUtil.div(BigDecimalUtil.sub(max, min), nbins);
- double[] bins = new double[nbins + 1];
- for (int i = 0; i < nbins + 1; i++) {
- bins[i] = min;
- min = BigDecimalUtil.add(min, interval);
- }
- Array ba = Array.factory(DataType.DOUBLE, new int[]{bins.length}, bins);
- return histogram(a, ba);
- }
-
- /**
- * Histogram x/y array
- *
- * @param a Data array
- * @param bins bin edges
- * @return X/Y arrays
- */
- public static List histogram(Array a, Array bins) {
- int n = (int) bins.getSize();
- Array hist = Array.factory(DataType.INT, new int[]{n - 1});
- double v;
- for (int i = 0; i < a.getSize(); i++) {
- v = a.getDouble(i);
- for (int j = 0; j < n - 1; j++) {
- if (j == n - 2) {
- if (v >= bins.getDouble(j) && v <= bins.getDouble(j + 1)) {
- hist.setInt(j, hist.getInt(j) + 1);
- break;
- }
- } else if (v >= bins.getDouble(j) && v < bins.getDouble(j + 1)) {
- hist.setInt(j, hist.getInt(j) + 1);
- break;
- }
- }
- }
-
- List r = new ArrayList<>();
- r.add(hist);
- r.add(bins);
-
- return r;
- }
-
- /**
- * Histogram x/y array
- *
- * @param a Data array
- * @param bins bin edges
- * @return X/Y arrays
- */
- public static List histogram(Array a, double[] bins) {
- int n = bins.length;
- double delta = bins[1] - bins[0];
- int[] count = new int[n + 1];
- double v;
- for (int i = 0; i < a.getSize(); i++) {
- v = a.getDouble(i);
- if (v < bins[0]) {
- count[0] += 1;
- } else if (v > bins[n - 1]) {
- count[n] += 1;
- } else {
- for (int j = 0; j < n - 1; j++) {
- if (v > bins[j] && v < bins[j + 1]) {
- count[j + 1] += 1;
- break;
- }
- }
- }
- }
-
- Array x = Array.factory(DataType.DOUBLE, new int[]{count.length + 1});
- Array y = Array.factory(DataType.INT, new int[]{count.length});
- for (int i = 0; i < count.length; i++) {
- y.setInt(i, count[i]);
- if (i == 0) {
- x.setDouble(0, bins[0] - delta);
- x.setDouble(1, bins[0]);
- } else if (i == count.length - 1) {
- x.setDouble(i + 1, bins[i - 1] + delta);
- } else {
- x.setDouble(i + 1, bins[i]);
- }
- }
- List r = new ArrayList<>();
- r.add(y);
- r.add(x);
-
- return r;
- }
-
- //
- //
- /**
- * Broadcast array to a new shape
- *
- * @param a Array a
- * @param shape Shape
- * @return Result array
- */
- public static Array broadcast(Array a, int[] shape) {
- int[] bshape = a.getShape();
- if (bshape.length > shape.length) {
- return null;
- }
-
- if (bshape.length < shape.length) {
- int miss = shape.length - a.getRank();
- bshape = new int[shape.length];
- for (int i = 0; i < shape.length; i++) {
- if (i < miss) {
- bshape[i] = 1;
- } else {
- bshape[i] = a.getShape()[i - miss];
- }
- }
- a = a.reshape(bshape);
- }
-
- //Check
- boolean pass = true;
- for (int i = 0; i < shape.length; i++) {
- if (shape[i] != bshape[i] && bshape[i] != 1) {
- pass = false;
- break;
- }
- }
- if (!pass) {
- return null;
- }
-
- //Broadcast
- Index aindex = a.getIndex();
- Array r = Array.factory(a.getDataType(), shape);
- Index index = r.getIndex();
- int[] current;
- for (int i = 0; i < r.getSize(); i++) {
- current = index.getCurrentCounter();
- for (int j = 0; j < shape.length; j++) {
- if (bshape[j] == 1) {
- aindex.setDim(j, 0);
- } else {
- aindex.setDim(j, current[j]);
- }
- }
- r.setObject(index, a.getObject(aindex));
- index.incr();
- }
-
- return r;
- }
-
- /**
- * Broadcast array to a new shape
- *
- * @param a Array a
- * @param shape Shape
- * @return Result array
- */
- public static Array broadcast(Array a, List shape) {
- int[] nshape = new int[shape.size()];
- for (int i = 0; i < shape.size(); i++) {
- nshape[i] = shape.get(i);
- }
- return broadcast(a, nshape);
- }
-
- /**
- * Mesh grid
- *
- * @param x X array - vector
- * @param y Y array - vector
- * @return Result arrays - matrix
- */
- public static Array[] meshgrid(Array x, Array y) {
- int xn = (int) x.getSize();
- int yn = (int) y.getSize();
- int[] shape = new int[]{yn, xn};
- Array rx = Array.factory(x.getDataType(), shape);
- Array ry = Array.factory(y.getDataType(), shape);
- for (int i = 0; i < yn; i++) {
- for (int j = 0; j < xn; j++) {
- rx.setObject(i * xn + j, x.getObject(j));
- ry.setObject(i * xn + j, y.getObject(i));
- }
- }
-
- return new Array[]{rx, ry};
- }
-
- /**
- * Mesh grid
- *
- * @param xs X arrays
- * @return Result arrays - matrix
- */
- public static Array[] meshgrid(Array... xs) {
- int n = xs.length;
- int[] shape = new int[n];
- int i = 0;
- Array x;
- for (i = 0; i < n; i++) {
- x = xs[i];
- shape[n - i - 1] = (int) x.getSize();
- }
-
- Array[] rs = new Array[n];
- Array r;
- int idx;
- for (int s = 0; s < n; s++) {
- x = xs[s];
- r = Array.factory(xs[s].getDataType(), shape);
- Index index = r.getIndex();
- for (i = 0; i < r.getSize(); i++) {
- idx = index.getCurrentCounter()[n - s - 1];
- r.setObject(index, x.getObject(idx));
- index.incr();
- }
- rs[s] = r;
- }
-
- return rs;
- }
-
- /**
- * Create mesh polygon layer
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param ls Legend scheme
- * @param lonlim Longiutde limitation - to avoid the polygon cross -180/180
- * @return Mesh polygon layer
- */
- public static VectorLayer meshLayer(Array x_s, Array y_s, Array a, LegendScheme ls, double lonlim) {
- VectorLayer layer = new VectorLayer(ShapeTypes.Polygon);
- String fieldName = "Data";
- Field aDC = new Field(fieldName, org.meteoinfo.ndarray.DataType.DOUBLE);
- layer.editAddField(aDC);
-
- int[] shape = x_s.getShape();
- int colNum = shape[1];
- int rowNum = shape[0];
- double x1, x2, x3, x4;
- for (int i = 0; i < rowNum - 1; i++) {
- for (int j = 0; j < colNum - 1; j++) {
- x1 = x_s.getDouble(i * colNum + j);
- x2 = x_s.getDouble(i * colNum + j + 1);
- x3 = x_s.getDouble((i + 1) * colNum + j);
- x4 = x_s.getDouble((i + 1) * colNum + j + 1);
- if (lonlim > 0) {
- if (Math.abs(x2 - x4) > lonlim || Math.abs(x1 - x4) > lonlim
- || Math.abs(x3 - x4) > lonlim || Math.abs(x1 - x2) > lonlim
- || Math.abs(x2 - x3) > lonlim) {
- continue;
- }
- }
-
- PolygonShape ps = new PolygonShape();
- List points = new ArrayList<>();
- points.add(new PointD(x1, y_s.getDouble(i * colNum + j)));
- points.add(new PointD(x3, y_s.getDouble((i + 1) * colNum + j)));
- points.add(new PointD(x4, y_s.getDouble((i + 1) * colNum + j + 1)));
- points.add(new PointD(x2, y_s.getDouble(i * colNum + j + 1)));
- points.add((PointD) points.get(0).clone());
- ps.setPoints(points);
- ps.lowValue = a.getDouble(i * colNum + j);
- ps.highValue = ps.lowValue;
- int shapeNum = layer.getShapeNum();
- try {
- if (layer.editInsertShape(ps, shapeNum)) {
- layer.editCellValue(fieldName, shapeNum, ps.lowValue);
- }
- } catch (Exception ex) {
-
- }
- }
- }
- layer.setLayerName("Mesh_Layer");
- ls.setFieldName(fieldName);
- layer.setLegendScheme(ls.convertTo(ShapeTypes.Polygon));
-
- return layer;
- }
-
- /**
- * Create mesh polygon layer
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param ls Legend scheme
- * @return Mesh polygon layer
- */
- public static VectorLayer meshLayer(Array x_s, Array y_s, Array a, LegendScheme ls) {
- VectorLayer layer = new VectorLayer(ShapeTypes.Polygon);
- String fieldName = "Data";
- Field aDC = new Field(fieldName, org.meteoinfo.ndarray.DataType.DOUBLE);
- layer.editAddField(aDC);
-
- int[] shape = x_s.getShape();
- int colNum = shape[1];
- int rowNum = shape[0];
- double x1, x2, x3, x4;
- for (int i = 0; i < rowNum - 1; i++) {
- for (int j = 0; j < colNum - 1; j++) {
- x1 = x_s.getDouble(i * colNum + j);
- x2 = x_s.getDouble(i * colNum + j + 1);
- x3 = x_s.getDouble((i + 1) * colNum + j);
- x4 = x_s.getDouble((i + 1) * colNum + j + 1);
- PolygonShape ps = new PolygonShape();
- List points = new ArrayList<>();
- points.add(new PointD(x1, y_s.getDouble(i * colNum + j)));
- points.add(new PointD(x3, y_s.getDouble((i + 1) * colNum + j)));
- points.add(new PointD(x4, y_s.getDouble((i + 1) * colNum + j + 1)));
- points.add(new PointD(x2, y_s.getDouble(i * colNum + j + 1)));
- points.add((PointD) points.get(0).clone());
- ps.setPoints(points);
- ps.lowValue = a.getDouble(i * colNum + j);
- ps.highValue = ps.lowValue;
- int shapeNum = layer.getShapeNum();
- try {
- if (layer.editInsertShape(ps, shapeNum)) {
- layer.editCellValue(fieldName, shapeNum, ps.lowValue);
- }
- } catch (Exception ex) {
-
- }
- }
- }
- layer.setLayerName("Mesh_Layer");
- ls.setFieldName(fieldName);
- layer.setLegendScheme(ls.convertTo(ShapeTypes.Polygon));
-
- return layer;
- }
-
- /**
- * Smooth with 5 points
- *
- * @param a Array
- * @param rowNum Row number
- * @param colNum Column number
- * @param unDefData Missing value
- * @return Result array
- */
- public static Array smooth5(Array a, int rowNum, int colNum, double unDefData) {
- Array r = Array.factory(a.getDataType(), a.getShape());
- double s = 0.5;
- if (Double.isNaN(unDefData)) {
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- if (i == 0 || i == rowNum - 1 || j == 0 || j == colNum - 1) {
- r.setDouble(i * colNum + j, a.getDouble(i * colNum + j));
- } else {
- if (Double.isNaN(a.getDouble(i * colNum + j)) || Double.isNaN(a.getDouble((i + 1) * colNum + j)) || Double.isNaN(a.getDouble((i - 1) * colNum + j))
- || Double.isNaN(a.getDouble(i * colNum + j + 1)) || Double.isNaN(a.getDouble(i * colNum + j - 1))) {
- r.setDouble(i * colNum + j, a.getDouble(i * colNum + j));
- continue;
- }
- r.setDouble(i * colNum + j, a.getDouble(i * colNum + j) + s / 4 * (a.getDouble((i + 1) * colNum + j) + a.getDouble((i - 1) * colNum + j) + a.getDouble(i * colNum + j + 1)
- + a.getDouble(i * colNum + j - 1) - 4 * a.getDouble(i * colNum + j)));
- }
- }
- }
- } else {
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- if (i == 0 || i == rowNum - 1 || j == 0 || j == colNum - 1) {
- r.setDouble(i * colNum + j, a.getDouble(i * colNum + j));
- } else {
- if (a.getDouble(i * colNum + j) == unDefData || a.getDouble((i + 1) * colNum + j) == unDefData || a.getDouble((i - 1) * colNum + j)
- == unDefData || a.getDouble(i * colNum + j + 1) == unDefData || a.getDouble(i * colNum + j - 1) == unDefData) {
- r.setDouble(i * colNum + j, a.getDouble(i * colNum + j));
- continue;
- }
- r.setDouble(i * colNum + j, a.getDouble(i * colNum + j) + s / 4 * (a.getDouble((i + 1) * colNum + j) + a.getDouble((i - 1) * colNum + j) + a.getDouble(i * colNum + j + 1)
- + a.getDouble(i * colNum + j - 1) - 4 * a.getDouble(i * colNum + j)));
- }
- }
- }
- }
-
- return r;
- }
-
- /**
- * Smooth with 5 points
- *
- * @param a Array
- * @return Result array
- */
- public static Array smooth5(Array a) {
- int[] shape = a.getShape();
- int colNum = shape[1];
- int rowNum = shape[0];
- Array r = Array.factory(a.getDataType(), shape);
- Index2D index = new Index2D(shape);
- double v, w;
- double sum, wsum;
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- sum = 0;
- wsum = 0;
- for (int ii = i - 1; ii <= i + 1; ii++) {
- if (ii < 0 || ii >= rowNum) {
- continue;
- }
- for (int jj = j - 1; jj <= j + 1; jj++) {
- if (jj < 0 || jj >= colNum) {
- continue;
- }
- if ((ii == i - 1 || ii == i + 1) && jj != j) {
- continue;
- }
- v = a.getDouble(index.set(ii, jj));
- if (!Double.isNaN(v)) {
- if (ii == i && jj == j) {
- w = 1;
- } else {
- w = 0.5;
- }
- sum += v * w;
- wsum += w;
- }
- }
- }
- index.set(i, j);
- if (wsum > 0) {
- r.setDouble(index, sum / wsum);
- } else {
- r.setDouble(index, Double.NaN);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Smooth with 9 points
- *
- * @param a Array
- * @return Result array
- */
- public static Array smooth9(Array a) {
- int[] shape = a.getShape();
- int colNum = shape[1];
- int rowNum = shape[0];
- Array r = Array.factory(a.getDataType(), shape);
- Index2D index = new Index2D(shape);
- double v, w;
- double sum, wsum;
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- sum = 0;
- wsum = 0;
- for (int ii = i - 1; ii <= i + 1; ii++) {
- if (ii < 0 || ii >= rowNum) {
- continue;
- }
- for (int jj = j - 1; jj <= j + 1; jj++) {
- if (jj < 0 || jj >= colNum) {
- continue;
- }
- v = a.getDouble(index.set(ii, jj));
- if (!Double.isNaN(v)) {
- if (ii == i && jj == j) {
- w = 1;
- } else {
- if (ii == i || jj == j) {
- w = 0.5;
- } else {
- w = 0.3;
- }
- }
- sum += v * w;
- wsum += w;
- }
- }
- }
- index.set(i, j);
- if (wsum > 0) {
- r.setDouble(index, sum / wsum);
- } else {
- r.setDouble(index, Double.NaN);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolation with IDW radius method
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X grid X array
- * @param Y grid Y array
- * @param neededPointNum needed at least point number
- * @param radius search radius
- * @return interpolated grid data
- */
- public static Array interpolation_IDW_Radius(List x_s, List y_s, Array a,
- List X, List Y, int neededPointNum, double radius) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- int i, j;
- double w, gx, gy, v;
- boolean match;
-
- //Construct K-D tree
- int n = 0;
- KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2);
- for (i = 0; i < pNum; i++) {
- if (!Double.isNaN(a.getDouble(i))) {
- kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i));
- n += 1;
- }
- }
-
- //---- Do interpolation
- for (i = 0; i < rowNum; i++) {
- gy = Y.get(i).doubleValue();
- for (j = 0; j < colNum; j++) {
- gx = X.get(j).doubleValue();
- List> srs = kdTree.ballSearch_distance(new double[]{gx, gy}, radius * radius);
- if (srs == null || srs.size() < neededPointNum) {
- r.setDouble(i * colNum + j, Double.NaN);
- } else {
- double v_sum = 0.0;
- double weight_sum = 0.0;
- match = false;
- for (SearchResult sr : srs) {
- v = (double) sr.payload;
- if (sr.distance == 0) {
- r.setDouble(i * colNum + j, v);
- match = true;
- break;
- } else {
- w = 1. / sr.distance;
- weight_sum += w;
- v_sum += v * w;
- }
- }
- if (!match) {
- r.setDouble(i * colNum + j, v_sum / weight_sum);
- }
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolation with IDW radius method
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X grid X array
- * @param Y grid Y array
- * @param NeededPointNum needed at least point number
- * @param radius search radius
- * @return interpolated grid data
- */
- public static Array interpolation_IDW_Radius_bak(List x_s, List y_s, Array a,
- List X, List Y, int NeededPointNum, double radius) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- //double[][] GCoords = new double[rowNum][colNum];
- Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- int i, j, p, vNum;
- double w, SV, SW;
- boolean ifPointGrid;
- double x, y, v;
-
- //---- Do interpolation
- for (i = 0; i < rowNum; i++) {
- for (j = 0; j < colNum; j++) {
- r.setDouble(i * colNum + j, Double.NaN);
- ifPointGrid = false;
- SV = 0;
- SW = 0;
- vNum = 0;
- for (p = 0; p < pNum; p++) {
- v = a.getDouble(p);
- if (Double.isNaN(v)) {
- continue;
- }
- x = x_s.get(p).doubleValue();
- y = y_s.get(p).doubleValue();
- if (x < X.get(j).doubleValue() - radius || x > X.get(j).doubleValue() + radius || y < Y.get(i).doubleValue() - radius
- || y > Y.get(i).doubleValue() + radius) {
- continue;
- }
-
- if (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2) == 0) {
- r.setDouble(i * colNum + j, v);
- ifPointGrid = true;
- break;
- } else if (Math.sqrt(Math.pow(X.get(j).doubleValue() - x, 2)
- + Math.pow(Y.get(i).doubleValue() - y, 2)) <= radius) {
- w = 1 / (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2));
- SW = SW + w;
- SV = SV + v * w;
- vNum += 1;
- }
- }
-
- if (!ifPointGrid) {
- if (vNum >= NeededPointNum) {
- r.setDouble(i * colNum + j, SV / SW);
- }
- }
- }
- }
-
- //---- Smooth with 5 points
- r = smooth5(r, rowNum, colNum, Double.NaN);
-
- return r;
- }
-
- /**
- * Interpolation with IDW neighbor method
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X grid X array
- * @param Y grid Y array
- * @param points Number of points used for interpolation
- * @return interpolated grid data
- */
- public static Array interpolation_IDW_Neighbor(List x_s, List y_s, Array a,
- List X, List Y, Integer points) {
- int colNum = X.size();
- int rowNum = Y.size();
- int pNum = x_s.size();
- Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- int i, j;
- double w, v, gx, gy;
- boolean match;
-
- //Construct K-D tree
- int n = 0;
- KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2);
- for (i = 0; i < pNum; i++) {
- if (!Double.isNaN(a.getDouble(i))) {
- kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i));
- n += 1;
- }
- }
- if (points == null) {
- points = n;
- }
-
- //---- Do interpolation with IDW method
- for (i = 0; i < rowNum; i++) {
- gy = Y.get(i).doubleValue();
- for (j = 0; j < colNum; j++) {
- gx = X.get(j).doubleValue();
- List> srs = kdTree.nearestNeighbours(new double[]{gx, gy}, points);
- double v_sum = 0.0;
- double weight_sum = 0.0;
- match = false;
- for (SearchResult sr : srs) {
- v = (double) sr.payload;
- if (sr.distance == 0) {
- r.setDouble(i * colNum + j, v);
- match = true;
- break;
- } else {
- w = 1. / sr.distance;
- weight_sum += w;
- v_sum += v * w;
- }
- }
- if (!match) {
- r.setDouble(i * colNum + j, v_sum / weight_sum);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolation with IDW neighbor method
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X grid X array
- * @param Y grid Y array
- * @param NumberOfNearestNeighbors
- * @return interpolated grid data
- */
- public static Array interpolation_IDW_Neighbor_bak(List x_s, List y_s, Array a,
- List X, List Y, int NumberOfNearestNeighbors) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- int i, j, p, l, aP;
- double w, SV, SW, aMin;
- int points;
- points = NumberOfNearestNeighbors;
- double[] AllWeights = new double[pNum];
- double[][] NW = new double[2][points];
- int NWIdx;
- double x, y, v;
-
- //---- Do interpolation with IDW method
- for (i = 0; i < rowNum; i++) {
- for (j = 0; j < colNum; j++) {
- r.setDouble(i * colNum + j, Double.NaN);
- SV = 0;
- SW = 0;
- NWIdx = 0;
- for (p = 0; p < pNum; p++) {
- v = a.getDouble(p);
- if (Double.isNaN(v)) {
- AllWeights[p] = -1;
- continue;
- }
- x = x_s.get(p).doubleValue();
- y = y_s.get(p).doubleValue();
- if (X.get(j).doubleValue() == x && Y.get(i).doubleValue() == y) {
- r.setDouble(i * colNum + j, v);
- break;
- } else {
- w = 1 / (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2));
- AllWeights[p] = w;
- if (NWIdx < points) {
- NW[0][NWIdx] = w;
- NW[1][NWIdx] = p;
- }
- NWIdx += 1;
- }
- }
-
- aMin = NW[0][0];
- aP = 0;
- for (l = 1; l < points; l++) {
- if (NW[0][l] < aMin) {
- aMin = NW[0][l];
- aP = l;
- }
- }
-
- if (Double.isNaN(r.getDouble(i * colNum + j))) {
- for (p = 0; p < pNum; p++) {
- w = AllWeights[p];
- if (w == -1) {
- continue;
- }
-
- if (w > aMin) {
- NW[0][aP] = w;
- NW[1][aP] = p;
- aMin = NW[0][0];
- aP = 0;
- for (l = 1; l < points; l++) {
- if (NW[0][l] < aMin) {
- aMin = NW[0][l];
- aP = l;
- }
- }
- }
- }
- for (p = 0; p < points; p++) {
- SV += NW[0][p] * a.getDouble((int) NW[1][p]);
- SW += NW[0][p];
- }
- r.setDouble(i * colNum + j, SV / SW);
- }
- }
- }
-
- //---- Smooth with 5 points
- r = smooth5(r, rowNum, colNum, Double.NaN);
-
- return r;
- }
-
- /**
- * Interpolate with nearest method
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X x coordinate
- * @param Y y coordinate
- * @param radius Radius
- * @return grid data
- */
- public static Array interpolation_Nearest(List x_s, List y_s, Array a, List X, List Y,
- double radius) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- Array rdata = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- double gx, gy;
-
- //Construct K-D tree
- KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2);
- for (int i = 0; i < pNum; i++) {
- if (!Double.isNaN(a.getDouble(i))) {
- kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i));
- }
- }
-
- //Loop
- if (radius == Double.POSITIVE_INFINITY) {
- for (int i = 0; i < rowNum; i++) {
- gy = Y.get(i).doubleValue();
- for (int j = 0; j < colNum; j++) {
- gx = X.get(j).doubleValue();
- SearchResult r = kdTree.nearestNeighbours(new double[]{gx, gy}, 1).get(0);
- rdata.setDouble(i * colNum + j, ((double) r.payload));
- }
- }
- } else {
- for (int i = 0; i < rowNum; i++) {
- gy = Y.get(i).doubleValue();
- for (int j = 0; j < colNum; j++) {
- gx = X.get(j).doubleValue();
- SearchResult r = kdTree.nearestNeighbours(new double[]{gx, gy}, 1).get(0);
- if (Math.sqrt(r.distance) <= radius) {
- rdata.setDouble(i * colNum + j, ((double) r.payload));
- } else {
- rdata.setDouble(i * colNum + j, Double.NaN);
- }
- }
- }
- }
-
- return rdata;
- }
-
- /**
- * Extend the grid to half cell, so the grid points are the centers of the
- * cells
- *
- * @param x Input x coordinate
- * @param y Input y coordinate
- * @return Result x and y coordinates
- */
- public static Array[] extendHalfCell(Array x, Array y) {
- double dX = x.getDouble(1) - x.getDouble(0);
- double dY = y.getDouble(1) - y.getDouble(0);
- int nx = (int) x.getSize() + 1;
- int ny = (int) y.getSize() + 1;
- Array rx = Array.factory(DataType.DOUBLE, new int[]{nx});
- Array ry = Array.factory(DataType.DOUBLE, new int[]{ny});
- for (int i = 0; i < rx.getSize(); i++) {
- if (i == rx.getSize() - 1) {
- rx.setDouble(i, x.getDouble(i - 1) + dX * 0.5);
- } else {
- rx.setDouble(i, x.getDouble(i) - dX * 0.5);
- }
- }
-
- for (int i = 0; i < ry.getSize(); i++) {
- if (i == ry.getSize() - 1) {
- ry.setDouble(i, y.getDouble(i - 1) + dY * 0.5);
- } else {
- ry.setDouble(i, y.getDouble(i) - dY * 0.5);
- }
- }
-
- return new Array[]{rx, ry};
- }
-
- /**
- * Interpolate with inside method - The grid cell value is the average value
- * of the inside points or fill value if no inside point.
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X x coordinate
- * @param Y y coordinate
- * @param centerPoint the points locate at center or border or grid
- * @return grid data
- */
- public static Array interpolation_Inside(List x_s, List y_s, Array a,
- List X, List Y, boolean centerPoint) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
- double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
- int[][] pNums = new int[rowNum][colNum];
- double x, y, v, sx, sy, ex, ey;
- if (centerPoint) {
- sx = X.get(0).doubleValue() - dX * 0.5;
- sy = Y.get(0).doubleValue() - dY * 0.5;
- ex = X.get(colNum - 1).doubleValue() + dX * 0.5;
- ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5;
- } else {
- sx = X.get(0).doubleValue();
- sy = Y.get(0).doubleValue();
- ex = X.get(colNum - 1).doubleValue();
- ey = Y.get(rowNum - 1).doubleValue();
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- pNums[i][j] = 0;
- r.setDouble(i * colNum + j, 0.0);
- }
- }
-
- for (int p = 0; p < pNum; p++) {
- v = a.getDouble(p);
- if (Double.isNaN(v)) {
- continue;
- }
-
- x = x_s.get(p).doubleValue();
- y = y_s.get(p).doubleValue();
- if (x < sx || x > ex) {
- continue;
- }
- if (y < sy || y > ey) {
- continue;
- }
-
- int j = (int) ((x - sx) / dX);
- int i = (int) ((y - sy) / dY);
- pNums[i][j] += 1;
- r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) + v);
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- if (pNums[i][j] == 0) {
- r.setDouble(i * colNum + j, Double.NaN);
- } else {
- r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) / pNums[i][j]);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolate with inside method - The grid cell value is the average value
- * of the inside points or fill value if no inside point.
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X x coordinate
- * @param Y y coordinate
- * @param centerPoint If the grid point is center or border
- * @return grid data
- */
- public static Array interpolation_Inside(Array x_s, Array y_s, Array a, Array X, Array Y,
- boolean centerPoint) {
- int rowNum, colNum, pNum;
- colNum = (int) X.getSize();
- rowNum = (int) Y.getSize();
- pNum = (int) x_s.getSize();
- Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- double dX = X.getDouble(1) - X.getDouble(0);
- double dY = Y.getDouble(1) - Y.getDouble(0);
- int[][] pNums = new int[rowNum][colNum];
- double x, y, v, sx, sy, ex, ey;
- if (centerPoint) {
- sx = X.getDouble(0) - dX * 0.5;
- sy = Y.getDouble(0) - dY * 0.5;
- ex = X.getDouble(colNum - 1) + dX * 0.5;
- ey = Y.getDouble(rowNum - 1) + dY * 0.5;
- } else {
- sx = X.getDouble(0);
- sy = Y.getDouble(0);
- ex = X.getDouble(colNum - 1);
- ey = Y.getDouble(rowNum - 1);
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- pNums[i][j] = 0;
- r.setDouble(i * colNum + j, 0.0);
- }
- }
-
- for (int p = 0; p < pNum; p++) {
- v = a.getDouble(p);
- if (Double.isNaN(v)) {
- continue;
- }
-
- x = x_s.getDouble(p);
- y = y_s.getDouble(p);
- if (x < sx || x > ex) {
- continue;
- }
- if (y < sy || y > ey) {
- continue;
- }
-
- int j = (int) ((x - sx) / dX);
- int i = (int) ((y - sy) / dY);
- pNums[i][j] += 1;
- r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) + v);
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- if (pNums[i][j] == 0) {
- r.setDouble(i * colNum + j, Double.NaN);
- } else {
- r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) / pNums[i][j]);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolate with inside method - The grid cell value is the maximum value
- * of the inside points or fill value if no inside point.
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X x coordinate
- * @param Y y coordinate
- * @param centerPoint points locate at center or border of grid
- * @return grid data
- */
- public static Array interpolation_Inside_Max(List x_s, List y_s, Array a,
- List X, List Y, boolean centerPoint) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
- double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
- int[][] pNums = new int[rowNum][colNum];
- double x, y, v, sx, sy, ex, ey;
- double min = Double.NEGATIVE_INFINITY;
- if (centerPoint) {
- sx = X.get(0).doubleValue() - dX * 0.5;
- sy = Y.get(0).doubleValue() - dY * 0.5;
- ex = X.get(colNum - 1).doubleValue() + dX * 0.5;
- ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5;
- } else {
- sx = X.get(0).doubleValue();
- sy = Y.get(0).doubleValue();
- ex = X.get(colNum - 1).doubleValue();
- ey = Y.get(rowNum - 1).doubleValue();
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- pNums[i][j] = 0;
- r.setDouble(i * colNum + j, min);
- }
- }
-
- for (int p = 0; p < pNum; p++) {
- v = a.getDouble(p);
- if (Double.isNaN(v)) {
- continue;
- }
-
- x = x_s.get(p).doubleValue();
- y = y_s.get(p).doubleValue();
- if (x < sx || x > ex) {
- continue;
- }
- if (y < sy || y > ey) {
- continue;
- }
-
- int j = (int) ((x - sx) / dX);
- int i = (int) ((y - sy) / dY);
- pNums[i][j] += 1;
- r.setDouble(i * colNum + j, Math.max(r.getDouble(i * colNum + j), v));
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- if (pNums[i][j] == 0 || Double.isInfinite(r.getDouble(i * colNum + j))) {
- r.setDouble(i * colNum + j, Double.NaN);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolate with inside method - The grid cell value is the minimum value
- * of the inside points or fill value if no inside point.
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X x coordinate
- * @param Y y coordinate
- * @param centerPoint points locate at center or border of grid
- * @return grid data
- */
- public static Array interpolation_Inside_Min(List x_s, List y_s, Array a,
- List X, List Y, boolean centerPoint) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
- double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
- double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
- int[][] pNums = new int[rowNum][colNum];
- double x, y, v, sx, sy, ex, ey;
- double max = Double.MAX_VALUE;
- if (centerPoint) {
- sx = X.get(0).doubleValue() - dX * 0.5;
- sy = Y.get(0).doubleValue() - dY * 0.5;
- ex = X.get(colNum - 1).doubleValue() + dX * 0.5;
- ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5;
- } else {
- sx = X.get(0).doubleValue();
- sy = Y.get(0).doubleValue();
- ex = X.get(colNum - 1).doubleValue();
- ey = Y.get(rowNum - 1).doubleValue();
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- pNums[i][j] = 0;
- r.setDouble(i * colNum + j, max);
- }
- }
-
- for (int p = 0; p < pNum; p++) {
- v = a.getDouble(p);
- if (Double.isNaN(v)) {
- continue;
- }
-
- x = x_s.get(p).doubleValue();
- y = y_s.get(p).doubleValue();
- if (x < sx || x > ex) {
- continue;
- }
- if (y < sy || y > ey) {
- continue;
- }
-
- int j = (int) ((x - sx) / dX);
- int i = (int) ((y - sy) / dY);
- pNums[i][j] += 1;
- r.setDouble(i * colNum + j, Math.min(r.getDouble(i * colNum + j), v));
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- if (pNums[i][j] == 0 || r.getDouble(i * colNum + j) == Double.MAX_VALUE) {
- r.setDouble(i * colNum + j, Double.NaN);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolate with inside method - The grid cell value is the count number
- * of the inside points or fill value if no inside point.
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param X x coordinate
- * @param Y y coordinate
- * @param pointDensity If return point density value
- * @param centerPoint points locate at center or border of grid
- * @return grid data
- */
- public static Object interpolation_Inside_Count(List x_s, List y_s,
- List X, List Y, boolean pointDensity, boolean centerPoint) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- Array r = Array.factory(DataType.INT, new int[]{rowNum, colNum});
- double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
- double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
- int[][] pNums = new int[rowNum][colNum];
- double x, y, sx, sy, ex, ey;
- if (centerPoint) {
- sx = X.get(0).doubleValue() - dX * 0.5;
- sy = Y.get(0).doubleValue() - dY * 0.5;
- ex = X.get(colNum - 1).doubleValue() + dX * 0.5;
- ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5;
- } else {
- sx = X.get(0).doubleValue();
- sy = Y.get(0).doubleValue();
- ex = X.get(colNum - 1).doubleValue();
- ey = Y.get(rowNum - 1).doubleValue();
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- pNums[i][j] = 0;
- //r.setInt(i * colNum + j, 0);
- }
- }
-
- for (int p = 0; p < pNum; p++) {
- x = x_s.get(p).doubleValue();
- y = y_s.get(p).doubleValue();
- if (x < sx || x > ex) {
- continue;
- }
- if (y < sy || y > ey) {
- continue;
- }
-
- int j = (int) ((x - sx) / dX);
- int i = (int) ((y - sy) / dY);
- pNums[i][j] += 1;
- //r.setInt(i * colNum + j, r.getInt(i * colNum + j) + 1);
- }
-
- for (int i = 0; i < rowNum; i++) {
- for (int j = 0; j < colNum; j++) {
- r.setInt(i * colNum + j, pNums[i][j]);
- }
- }
-
- if (pointDensity) {
- Array pds = Array.factory(DataType.INT, new int[]{pNum});
- for (int p = 0; p < pNum; p++) {
- x = x_s.get(p).doubleValue();
- y = y_s.get(p).doubleValue();
- if (x < sx || x > ex) {
- continue;
- }
- if (y < sy || y > ey) {
- continue;
- }
-
- int j = (int) ((x - sx) / dX);
- int i = (int) ((y - sy) / dY);
- pds.setInt(p, pNums[i][j]);
- }
- return new Array[]{r, pds};
- }
-
- return r;
- }
-
- private static List getPointsIJ(List x_s, List y_s, List X, List Y) {
- int rowNum, colNum, pNum;
- colNum = X.size();
- rowNum = Y.size();
- pNum = x_s.size();
- double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
- double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
- List pIndices = new ArrayList<>();
- double x, y;
- int i, j;
- for (int p = 0; p < pNum; p++) {
- x = x_s.get(p).doubleValue();
- y = y_s.get(p).doubleValue();
- if (x < X.get(0).doubleValue() || x > X.get(colNum - 1).doubleValue()) {
- continue;
- }
- if (y < Y.get(0).doubleValue() || y > Y.get(rowNum - 1).doubleValue()) {
- continue;
- }
-
- j = (int) ((x - X.get(0).doubleValue()) / dX);
- i = (int) ((y - Y.get(0).doubleValue()) / dY);
- pIndices.add(new int[]{i, j});
- }
-
- return pIndices;
- }
-
- private static List getPointsIdx(List pIJ, int ii, int jj, int radius) {
- List pIdx = new ArrayList<>();
- int[] ij;
- int i, j;
- for (int p = 0; p < pIJ.size(); p++) {
- ij = pIJ.get(p);
- i = ij[0];
- j = ij[1];
- if (Math.abs(i - ii) <= radius && Math.abs(j - jj) <= radius) {
- pIdx.add(p);
- }
- }
-
- return pIdx;
- }
-
- /**
- * Interpolate with surface method
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X x coordinate
- * @param Y y coordinate
- * @param unDefData undefine value
- * @return grid data
- */
- public static Array interpolation_Surface_1(Array x_s, Array y_s, Array a, Array X, Array Y,
- double unDefData) {
- int rowNum, colNum, xn, yn;
- int[] shape = x_s.getShape();
- colNum = shape[1];
- rowNum = shape[0];
- xn = (int) X.getSize();
- yn = (int) Y.getSize();
- Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn});
- double x, y;
-
- PolygonShape[][] polygons = new PolygonShape[rowNum - 1][colNum - 1];
- PolygonShape ps;
- for (int i = 0; i < rowNum - 1; i++) {
- for (int j = 0; j < colNum - 1; j++) {
- ps = new PolygonShape();
- List points = new ArrayList<>();
- points.add(new PointD(x_s.getDouble(i * colNum + j), y_s.getDouble(i * colNum + j)));
- points.add(new PointD(x_s.getDouble((i + 1) * colNum + j), y_s.getDouble((i + 1) * colNum + j)));
- points.add(new PointD(x_s.getDouble((i + 1) * colNum + j + 1), y_s.getDouble((i + 1) * colNum + j + 1)));
- points.add(new PointD(x_s.getDouble(i * colNum + j + 1), y_s.getDouble(i * colNum + j + 1)));
- points.add((PointD) points.get(0).clone());
- ps.setPoints(points);
- polygons[i][j] = ps;
- }
- }
-
- for (int i = 0; i < yn; i++) {
- for (int j = 0; j < xn; j++) {
- r.setDouble(i * xn + j, unDefData);
- }
- }
-
- double v;
- for (int i = 0; i < rowNum - 1; i++) {
- for (int j = 0; j < colNum - 1; j++) {
- ps = polygons[i][j];
- v = a.getDouble(i * colNum + j);
- for (int ii = 0; ii < yn; ii++) {
- y = Y.getDouble(ii);
- for (int jj = 0; jj < xn; jj++) {
- x = X.getDouble(jj);
- if (Double.isNaN(r.getDouble(ii * xn + jj)) || r.getDouble(ii * xn + jj) == unDefData) {
- if (GeoComputation.pointInPolygon(ps, x, y)) {
- r.setDouble(ii * xn + jj, v);
- }
- }
- }
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolate with surface method
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X x coordinate
- * @param Y y coordinate
- * @return grid data
- */
- public static Array interpolation_Surface(Array x_s, Array y_s, Array a, Array X, Array Y) {
- int rowNum, colNum, xn, yn;
- int[] shape = x_s.getShape();
- colNum = shape[1];
- rowNum = shape[0];
- xn = (int) X.getSize();
- yn = (int) Y.getSize();
- Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn});
- for (int i = 0; i < r.getSize(); i++) {
- r.setDouble(i, Double.NaN);
- }
-
- double x, y;
- double v, xll, xtl, xtr, xlr, yll, ytl, ytr, ylr;
- double dX = X.getDouble(1) - X.getDouble(0);
- double dY = Y.getDouble(1) - Y.getDouble(0);
- int minxi, maxxi, minyi, maxyi;
- for (int i = 0; i < rowNum - 1; i++) {
- for (int j = 0; j < colNum - 1; j++) {
- v = a.getDouble(i * colNum + j);
- if (Double.isNaN(v)) {
- continue;
- }
- xll = x_s.getDouble(i * colNum + j);
- xtl = x_s.getDouble((i + 1) * colNum + j);
- xtr = x_s.getDouble((i + 1) * colNum + j + 1);
- xlr = x_s.getDouble(i * colNum + j + 1);
- yll = y_s.getDouble(i * colNum + j);
- ytl = y_s.getDouble((i + 1) * colNum + j);
- ytr = y_s.getDouble((i + 1) * colNum + j + 1);
- ylr = y_s.getDouble(i * colNum + j + 1);
- if (Double.isNaN(xll) || Double.isNaN(xtl) || Double.isNaN(xtr) || Double.isNaN(xlr)
- || Double.isNaN(yll) || Double.isNaN(ytl) || Double.isNaN(ytr) || Double.isNaN(ylr)) {
- continue;
- }
- PolygonShape ps = new PolygonShape();
- List points = new ArrayList<>();
- points.add(new PointD(xll, yll));
- points.add(new PointD(xtl, ytl));
- points.add(new PointD(xtr, ytr));
- points.add(new PointD(xlr, ylr));
- points.add((PointD) points.get(0).clone());
- ps.setPoints(points);
- minxi = (int) ((ps.getExtent().minX - X.getDouble(0)) / dX);
- maxxi = (int) ((ps.getExtent().maxX - X.getDouble(0)) / dX);
- minyi = (int) ((ps.getExtent().minY - Y.getDouble(0)) / dY);
- maxyi = (int) ((ps.getExtent().maxY - Y.getDouble(0)) / dY);
- maxxi += 1;
- maxyi += 1;
- if (maxxi < 0 || minxi >= xn) {
- continue;
- }
- if (maxyi < 0 || minyi >= yn) {
- continue;
- }
- if (minxi < 0) {
- minxi = 0;
- }
- if (maxxi >= xn) {
- maxxi = xn - 1;
- }
- if (maxyi >= yn) {
- maxyi = yn - 1;
- }
- for (int m = minyi; m <= maxyi; m++) {
- y = Y.getDouble(m);
- for (int n = minxi; n <= maxxi; n++) {
- x = X.getDouble(n);
- if (GeoComputation.pointInPolygon(ps, x, y)) {
- r.setDouble(m * xn + n, v);
- }
- }
- }
- }
- }
-
- return r;
- }
-
- /**
- * Interpolate with surface method
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param a scatter value array
- * @param X x coordinate
- * @param Y y coordinate
- * @return grid data
- */
- public static Array interpolation_Surface_bak(Array x_s, Array y_s, Array a, Array X, Array Y) {
- int rowNum, colNum, xn, yn;
- int[] shape = x_s.getShape();
- colNum = shape[1];
- rowNum = shape[0];
- xn = (int) X.getSize();
- yn = (int) Y.getSize();
- Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn});
- double x, y;
- boolean isIn;
-
- PolygonShape[][] polygons = new PolygonShape[rowNum - 1][colNum - 1];
- for (int i = 0; i < rowNum - 1; i++) {
- for (int j = 0; j < colNum - 1; j++) {
- PolygonShape ps = new PolygonShape();
- List points = new ArrayList<>();
- points.add(new PointD(x_s.getDouble(i * colNum + j), y_s.getDouble(i * colNum + j)));
- points.add(new PointD(x_s.getDouble((i + 1) * colNum + j), y_s.getDouble((i + 1) * colNum + j)));
- points.add(new PointD(x_s.getDouble((i + 1) * colNum + j + 1), y_s.getDouble((i + 1) * colNum + j + 1)));
- points.add(new PointD(x_s.getDouble(i * colNum + j + 1), y_s.getDouble(i * colNum + j + 1)));
- points.add((PointD) points.get(0).clone());
- ps.setPoints(points);
- polygons[i][j] = ps;
- }
- }
-
- for (int i = 0; i < yn; i++) {
- y = Y.getDouble(i);
- for (int j = 0; j < xn; j++) {
- x = X.getDouble(j);
- isIn = false;
- for (int ii = 0; ii < rowNum - 1; ii++) {
- for (int jj = 0; jj < colNum - 1; jj++) {
- if (GeoComputation.pointInPolygon(polygons[ii][jj], x, y)) {
- r.setDouble(i * xn + j, a.getDouble(ii * colNum + jj));
- isIn = true;
- break;
- }
- }
- if (isIn) {
- break;
- }
- }
- if (!isIn) {
- r.setDouble(i * xn + j, Double.NaN);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Cressman analysis
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param v_s scatter value array
- * @param X x array
- * @param Y y array
- * @param radList radii list
- * @return result grid data
- */
- public static Array cressman(List x_s, List y_s, Array v_s, List X, List Y,
- List radList) {
- int xNum = X.size();
- int yNum = Y.size();
- int pNum = x_s.size();
- //double[][] gridData = new double[yNum][xNum];
- Array r = Array.factory(DataType.DOUBLE, new int[]{yNum, xNum});
- int irad = radList.size();
- int i, j;
-
- //Loop through each stn report and convert stn lat/lon to grid coordinates
- double xMin = X.get(0).doubleValue();
- double xMax = X.get(xNum - 1).doubleValue();
- double yMin = Y.get(0).doubleValue();
- double yMax = Y.get(yNum - 1).doubleValue();
- double xDelt = X.get(1).doubleValue() - X.get(0).doubleValue();
- double yDelt = Y.get(1).doubleValue() - Y.get(0).doubleValue();
- double x, y;
- double sum;
- int stNum = 0;
- double[][] stationData = new double[pNum][3];
- for (i = 0; i < pNum; i++) {
- x = x_s.get(i).doubleValue();
- y = y_s.get(i).doubleValue();
- stationData[i][0] = (x - xMin) / xDelt;
- stationData[i][1] = (y - yMin) / yDelt;
- stationData[i][2] = v_s.getDouble(i);
- if (!Double.isNaN(stationData[i][2])) {
- //total += stationData[i][2];
- stNum += 1;
- }
- }
- //total = total / stNum;
-
- double HITOP = -999900000000000000000.0;
- double HIBOT = 999900000000000000000.0;
- double[][] TOP = new double[yNum][xNum];
- double[][] BOT = new double[yNum][xNum];
- for (i = 0; i < yNum; i++) {
- for (j = 0; j < xNum; j++) {
- TOP[i][j] = HITOP;
- BOT[i][j] = HIBOT;
- }
- }
-
- //Initial grid values are average of station reports within the first radius
- double val, sx, sy, sxi, syi;
- double rad;
- if (radList.size() > 0) {
- rad = radList.get(0).doubleValue();
- } else {
- rad = 4;
- }
- for (i = 0; i < yNum; i++) {
- y = Y.get(i).doubleValue();
- yMin = y - rad;
- yMax = y + rad;
- for (j = 0; j < xNum; j++) {
- x = X.get(j).doubleValue();
- xMin = x - rad;
- xMax = x + rad;
- stNum = 0;
- sum = 0;
- for (int s = 0; s < pNum; s++) {
- val = stationData[s][2];
- sx = x_s.get(s).doubleValue();
- sy = y_s.get(s).doubleValue();
- sxi = stationData[s][0];
- syi = stationData[s][1];
- if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
- continue;
- }
-
- double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
- if (dis > rad) {
- continue;
- }
-
- sum += val;
- stNum += 1;
- if (TOP[i][j] < val) {
- TOP[i][j] = val;
- }
- if (BOT[i][j] > val) {
- BOT[i][j] = val;
- }
- }
- if (stNum == 0) {
- r.setDouble(i * xNum + j, Double.NaN);
- } else {
- r.setDouble(i * xNum + j, sum / stNum);
- }
- }
- }
-
- //Perform the objective analysis
- for (int p = 0; p < irad; p++) {
- rad = radList.get(p).doubleValue();
- for (i = 0; i < yNum; i++) {
- y = Y.get(i).doubleValue();
- yMin = y - rad;
- yMax = y + rad;
- for (j = 0; j < xNum; j++) {
- if (Double.isNaN(r.getDouble(i * xNum + j))) {
- continue;
- }
-
- x = X.get(j).doubleValue();
- xMin = x - rad;
- xMax = x + rad;
- sum = 0;
- double wSum = 0;
- for (int s = 0; s < pNum; s++) {
- val = stationData[s][2];
- sx = x_s.get(s).doubleValue();
- sy = y_s.get(s).doubleValue();
- sxi = stationData[s][0];
- syi = stationData[s][1];
- if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
- continue;
- }
-
- double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
- if (dis > rad) {
- continue;
- }
-
- int i1 = (int) syi;
- int j1 = (int) sxi;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
- double a = r.getDouble(i1 * xNum + j1);
- double b = r.getDouble(i1 * xNum + j2);
- double c = r.getDouble(i2 * xNum + j1);
- double d = r.getDouble(i2 * xNum + j2);
- List dList = new ArrayList<>();
- if (!Double.isNaN(a)) {
- dList.add(a);
- }
- if (!Double.isNaN(b)) {
- dList.add(b);
- }
- if (!Double.isNaN(c)) {
- dList.add(c);
- }
- if (Double.isNaN(d)) {
- dList.add(d);
- }
-
- double calVal;
- if (dList.isEmpty()) {
- continue;
- } else if (dList.size() == 1) {
- calVal = dList.get(0);
- } else if (dList.size() <= 3) {
- double aSum = 0;
- for (double dd : dList) {
- aSum += dd;
- }
- calVal = aSum / dList.size();
- } else {
- double x1val = a + (c - a) * (syi - i1);
- double x2val = b + (d - b) * (syi - i1);
- calVal = x1val + (x2val - x1val) * (sxi - j1);
- }
- double eVal = val - calVal;
- double w = (rad * rad - dis * dis) / (rad * rad + dis * dis);
- sum += eVal * w;
- wSum += w;
- }
-// if (wSum < 0.000001) {
-// r.setDouble(i * xNum + j, Double.NaN);
-// } else {
-// double aData = r.getDouble(i * xNum + j) + sum / wSum;
-// r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData)));
-// }
- if (wSum >= 0.000001) {
- double aData = r.getDouble(i * xNum + j) + sum / wSum;
- r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData)));
- }
- }
- }
- }
-
- //Return
- return r;
- }
-
- /**
- * Cressman analysis
- *
- * @param x_s scatter X array
- * @param y_s scatter Y array
- * @param v_s scatter value array
- * @param X x array
- * @param Y y array
- * @param radList radii list
- * @return result grid data
- */
- public static Array cressman_bak(List x_s, List y_s, Array v_s, List X, List Y,
- List radList) {
- int xNum = X.size();
- int yNum = Y.size();
- int pNum = x_s.size();
- //double[][] gridData = new double[yNum][xNum];
- Array r = Array.factory(DataType.DOUBLE, new int[]{yNum, xNum});
- int irad = radList.size();
- int i, j;
-
- //Loop through each stn report and convert stn lat/lon to grid coordinates
- double xMin = X.get(0).doubleValue();
- double xMax;
- double yMin = Y.get(0).doubleValue();
- double yMax;
- double xDelt = X.get(1).doubleValue() - X.get(0).doubleValue();
- double yDelt = Y.get(1).doubleValue() - Y.get(0).doubleValue();
- double x, y;
- double sum;
- int stNum = 0;
- double[][] stationData = new double[pNum][3];
- for (i = 0; i < pNum; i++) {
- x = x_s.get(i).doubleValue();
- y = y_s.get(i).doubleValue();
- stationData[i][0] = (x - xMin) / xDelt;
- stationData[i][1] = (y - yMin) / yDelt;
- stationData[i][2] = v_s.getDouble(i);
- if (!Double.isNaN(stationData[i][2])) {
- //total += stationData[i][2];
- stNum += 1;
- }
- }
- //total = total / stNum;
-
- double HITOP = -999900000000000000000.0;
- double HIBOT = 999900000000000000000.0;
- double[][] TOP = new double[yNum][xNum];
- double[][] BOT = new double[yNum][xNum];
- for (i = 0; i < yNum; i++) {
- for (j = 0; j < xNum; j++) {
- TOP[i][j] = HITOP;
- BOT[i][j] = HIBOT;
- }
- }
-
- //Initial grid values are average of station reports within the first radius
- double rad;
- if (radList.size() > 0) {
- rad = radList.get(0).doubleValue();
- } else {
- rad = 4;
- }
- for (i = 0; i < yNum; i++) {
- y = (double) i;
- yMin = y - rad;
- yMax = y + rad;
- for (j = 0; j < xNum; j++) {
- x = (double) j;
- xMin = x - rad;
- xMax = x + rad;
- stNum = 0;
- sum = 0;
- for (int s = 0; s < pNum; s++) {
- double val = stationData[s][2];
- double sx = stationData[s][0];
- double sy = stationData[s][1];
- if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) {
- continue;
- }
-
- if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
- continue;
- }
-
- double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
- if (dis > rad) {
- continue;
- }
-
- sum += val;
- stNum += 1;
- if (TOP[i][j] < val) {
- TOP[i][j] = val;
- }
- if (BOT[i][j] > val) {
- BOT[i][j] = val;
- }
- }
- if (stNum == 0) {
- r.setDouble(i * xNum + j, Double.NaN);
- } else {
- r.setDouble(i * xNum + j, sum / stNum);
- }
- }
- }
-
- //Perform the objective analysis
- for (int p = 0; p < irad; p++) {
- rad = radList.get(p).doubleValue();
- for (i = 0; i < yNum; i++) {
- y = (double) i;
- yMin = y - rad;
- yMax = y + rad;
- for (j = 0; j < xNum; j++) {
- if (Double.isNaN(r.getDouble(i * xNum + j))) {
- continue;
- }
-
- x = (double) j;
- xMin = x - rad;
- xMax = x + rad;
- sum = 0;
- double wSum = 0;
- for (int s = 0; s < pNum; s++) {
- double val = stationData[s][2];
- double sx = stationData[s][0];
- double sy = stationData[s][1];
- if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) {
- continue;
- }
-
- if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
- continue;
- }
-
- double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
- if (dis > rad) {
- continue;
- }
-
- int i1 = (int) sy;
- int j1 = (int) sx;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
- double a = r.getDouble(i1 * xNum + j1);
- double b = r.getDouble(i1 * xNum + j2);
- double c = r.getDouble(i2 * xNum + j1);
- double d = r.getDouble(i2 * xNum + j2);
- List dList = new ArrayList<>();
- if (!Double.isNaN(a)) {
- dList.add(a);
- }
- if (!Double.isNaN(b)) {
- dList.add(b);
- }
- if (!Double.isNaN(c)) {
- dList.add(c);
- }
- if (Double.isNaN(d)) {
- dList.add(d);
- }
-
- double calVal;
- if (dList.isEmpty()) {
- continue;
- } else if (dList.size() == 1) {
- calVal = dList.get(0);
- } else if (dList.size() <= 3) {
- double aSum = 0;
- for (double dd : dList) {
- aSum += dd;
- }
- calVal = aSum / dList.size();
- } else {
- double x1val = a + (c - a) * (sy - i1);
- double x2val = b + (d - b) * (sy - i1);
- calVal = x1val + (x2val - x1val) * (sx - j1);
- }
- double eVal = val - calVal;
- double w = (rad * rad - dis * dis) / (rad * rad + dis * dis);
- sum += eVal * w;
- wSum += w;
- }
- if (wSum < 0.000001) {
- r.setDouble(i * xNum + j, Double.NaN);
- } else {
- double aData = r.getDouble(i * xNum + j) + sum / wSum;
- r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData)));
- }
-// if (wSum >= 0.000001) {
-// double aData = r.getDouble(i * xNum + j) + sum / wSum;
-// r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData)));
-// }
- }
- }
- }
-
- //Return
- return r;
- }
-
- /**
- * Interpolates from a rectilinear grid to another rectilinear grid using
- * bilinear interpolation.
- *
- * @param a The sample array
- * @param X X coordinate of the sample array
- * @param Y Y coordinate of the sample array
- * @param newX X coordinate of the query points
- * @param newY Y coordinate of the query points
- * @return Resampled array
- */
- public static Array linint2(Array a, Array X, Array Y, Array newX, Array newY) {
- int xn = (int) newX.getSize();
- int yn = (int) newY.getSize();
- int[] shape = a.getShape();
- int n = shape.length;
- shape[n - 1] = xn;
- shape[n - 2] = yn;
- double x, y, v;
- Array r = Array.factory(DataType.DOUBLE, shape);
-
- Index index = r.getIndex();
- int[] counter;
- int yi, xi;
- for (int k = 0; k < r.getSize(); k++) {
- counter = index.getCurrentCounter();
- yi = counter[n - 2];
- xi = counter[n - 1];
- y = newY.getDouble(yi);
- x = newX.getDouble(xi);
- v = bilinear(a, index, X, Y, x, y);
- r.setDouble(index, v);
- index.incr();
- }
-
- return r;
- }
-
- /**
- * Resample grid array with bilinear method
- *
- * @param a The sample array
- * @param X X coordinate of the sample array
- * @param Y Y coordinate of the sample array
- * @param newX X coordinate of the query points
- * @param newY Y coordinate of the query points
- * @return Resampled array
- */
- public static Array resample_Bilinear(Array a, List X, List Y, List newX, List newY) {
- int i, j;
- int xn = newX.size();
- int yn = newY.size();
- double x, y, v;
- Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn});
-
- for (i = 0; i < yn; i++) {
- y = newY.get(i).doubleValue();
- for (j = 0; j < xn; j++) {
- x = newX.get(j).doubleValue();
- if (x < X.get(0).doubleValue() || x > X.get(X.size() - 1).doubleValue()) {
- r.setDouble(i * xn + j, Double.NaN);
- } else if (y < Y.get(0).doubleValue() || y > Y.get(Y.size() - 1).doubleValue()) {
- r.setDouble(i * xn + j, Double.NaN);
- } else {
- v = toStation(a, X, Y, x, y);
- r.setDouble(i * xn + j, v);
- }
- }
- }
-
- return r;
- }
-
- /**
- * Resample grid array with bilinear method
- *
- * @param a The sample array
- * @param X X coordinate of the sample array
- * @param Y Y coordinate of the sample array
- * @param newX X coordinate of the query points
- * @param newY Y coordinate of the query points
- * @return Resampled array
- */
- public static Array resample_Bilinear(Array a, Array X, Array Y, Array newX, Array newY) {
- int i;
- int n = (int) newX.getSize();
- double x, y, v;
- Array r = Array.factory(DataType.DOUBLE, newX.getShape());
-
- for (i = 0; i < n; i++) {
- x = newX.getDouble(i);
- y = newY.getDouble(i);
- if (x < X.getDouble(0) || x > X.getDouble((int) X.getSize() - 1)) {
- r.setDouble(i, Double.NaN);
- } else if (y < Y.getDouble(0) || y > Y.getDouble((int) Y.getSize() - 1)) {
- r.setDouble(i, Double.NaN);
- } else {
- v = toStation(a, X, Y, x, y);
- r.setDouble(i, v);
- }
- }
-
- return r;
- }
-
- /**
- * Resample grid array with neighbor method
- *
- * @param a The sample array
- * @param X X coordinate of the sample array
- * @param Y Y coordinate of the sample array
- * @param newX X coordinate of the query points
- * @param newY Y coordinate of the query points
- * @return Resampled array
- */
- public static Array resample_Neighbor(Array a, Array X, Array Y, Array newX, Array newY) {
- int i;
- int n = (int) newX.getSize();
- double x, y, v;
- Array r = Array.factory(DataType.DOUBLE, newX.getShape());
-
- for (i = 0; i < n; i++) {
- x = newX.getDouble(i);
- y = newY.getDouble(i);
- if (x < X.getDouble(0) || x > X.getDouble((int) X.getSize() - 1)) {
- r.setDouble(i, Double.NaN);
- } else if (y < Y.getDouble(0) || y > Y.getDouble((int) Y.getSize() - 1)) {
- r.setDouble(i, Double.NaN);
- } else {
- v = toStation_Neighbor(a, X, Y, x, y);
- r.setDouble(i, v);
- }
- }
-
- return r;
- }
-
- /**
- * Interpolate array data
- *
- * @param a Array
- * @param X X coordinates
- * @param Y Y coordinates
- * @return Result array data
- */
- public Array interpolate(Array a, List X, List Y) {
- int nxNum = X.size() * 2 - 1;
- int nyNum = Y.size() * 2 - 1;
- List newX = new ArrayList<>();
- List newY = new ArrayList<>();
- int i;
-
- for (i = 0; i < nxNum; i++) {
- if (i % 2 == 0) {
- newX.add(X.get(i / 2).doubleValue());
- } else {
- newX.add((X.get((i - 1) / 2).doubleValue() + X.get((i - 1) / 2 + 1).doubleValue()) / 2);
- }
- }
- for (i = 0; i < nyNum; i++) {
- if (i % 2 == 0) {
- newY.add(Y.get(i / 2).doubleValue());
- } else {
- newY.add((Y.get((i - 1) / 2).doubleValue() + Y.get((i - 1) / 2 + 1).doubleValue()) / 2);
- }
- }
-
- return resample_Bilinear(a, X, Y, newX, newY);
- }
-
- /**
- * Multidimensional interpolation on regular grids.
- *
- * @param points The points defining the regular grid in n dimensions.
- * @param values The data on the regular grid in n dimensions.
- * @param xi The coordinates to sample the gridded data at
- * @return Interpolation value
- */
- public static double interpn_s(List> points, Array values, List xi) {
- Object[] r = findIndices(points, xi);
- boolean outBounds = (boolean) r[2];
- if (outBounds) {
- return Double.NaN;
- } else {
- double v, weight;
- Index index = values.getIndex();
- int[] indices = (int[]) r[0];
- double[] distances = (double[]) r[1];
- v = 0;
- List ii = new ArrayList<>();
- iterIndex(ii, index, indices, 0);
- int n = indices.length;
- for (Index idx : ii) {
- weight = 1;
- for (int i = 0; i < n; i++) {
- weight *= idx.getCurrentCounter()[i] == indices[i] ? 1 - distances[i] : distances[i];
- }
- v += values.getDouble(idx) * weight;
- }
-
- return v;
- }
- }
-
- /**
- * Multidimensional interpolation on regular grids.
- *
- * @param points The points defining the regular grid in n dimensions.
- * @param values The data on the regular grid in n dimensions.
- * @param xi The coordinates to sample the gridded data at
- * @return Interpolation value
- */
- public static double interpn_s(List points, Array values, Array xi) {
- Object[] r = findIndices(points, xi);
- boolean outBounds = (boolean) r[2];
- if (outBounds) {
- return Double.NaN;
- } else {
- double v, weight;
- Index index = values.getIndex();
- int[] indices = (int[]) r[0];
- double[] distances = (double[]) r[1];
- v = 0;
- List ii = new ArrayList<>();
- iterIndex(ii, index, indices, 0);
- int n = indices.length;
- for (Index idx : ii) {
- weight = 1;
- for (int i = 0; i < n; i++) {
- weight *= idx.getCurrentCounter()[i] == indices[i] ? 1 - distances[i] : distances[i];
- }
- v += values.getDouble(idx) * weight;
- }
-
- return v;
- }
- }
-
- /**
- * Multidimensional interpolation on regular grids.
- *
- * @param points The points defining the regular grid in n dimensions.
- * @param values The data on the regular grid in n dimensions.
- * @param xi The coordinates to sample the gridded data at - 2D
- * @return Interpolation value
- */
- public static Array interpn(List points, Array values, List xi) {
- int n = xi.size();
- Array r = Array.factory(DataType.DOUBLE, new int[]{n});
- for (int i = 0; i < n; i++) {
- Array x = xi.get(i);
- r.setDouble(i, interpn_s(points, values, x));
- }
-
- return r;
- }
-
- /**
- * Multidimensional interpolation on regular grids.
- *
- * @param points The points defining the regular grid in n dimensions.
- * @param values The data on the regular grid in n dimensions.
- * @param xi The coordinates to sample the gridded data at - 2D
- * @return Interpolation value
- * @throws org.meteoinfo.ndarray.InvalidRangeException
- */
- public static Object interpn(List points, Array values, Array xi) throws InvalidRangeException {
- if (xi.getRank() == 1) {
- return interpn_s(points, values, xi);
- }
-
- int n = xi.getShape()[0];
- int m = xi.getShape()[1];
- Array r = Array.factory(DataType.DOUBLE, new int[]{n});
- for (int i = 0; i < n; i++) {
- Array x = xi.section(new int[]{i, 0}, new int[]{1, m});
- r.setDouble(i, interpn_s(points, values, x));
- }
-
- return r;
- }
-
- private static void iterIndex(List ii, Index index, int[] indices, int idx) {
- int n = indices.length;
- if (idx < n - 1) {
- index.setDim(idx, indices[idx]);
- iterIndex(ii, index, indices, idx + 1);
- index.setDim(idx, indices[idx] + 1);
- iterIndex(ii, index, indices, idx + 1);
- } else {
- index.setDim(idx, indices[idx]);
- ii.add((Index) index.clone());
- //System.out.println(index);
- index.setDim(idx, indices[idx] + 1);
- ii.add((Index) index.clone());
- //System.out.println(index);
- }
- }
-
- /**
- * Find indices
- *
- * @param points The points defining the regular grid in n dimensions.
- * @param xi The coordinates to sample the gridded data at
- * @return Indices
- */
- public static Object[] findIndices(List> points, List xi) {
- int n = points.size();
- int[] indices = new int[n];
- double[] distances = new double[n];
- boolean outBounds = false;
- double x;
- List a;
- for (int i = 0; i < n; i++) {
- x = xi.get(i).doubleValue();
- a = points.get(i);
- int idx = searchSorted(a, x);
- if (idx < 0) {
- outBounds = true;
- idx = 0;
- }
- indices[i] = idx;
- distances[i] = (x - a.get(idx).doubleValue()) / (a.get(idx + 1).doubleValue() - a.get(idx).doubleValue());
- }
-
- return new Object[]{indices, distances, outBounds};
- }
-
- /**
- * Find indices
- *
- * @param points The points defining the regular grid in n dimensions.
- * @param xi The coordinates to sample the gridded data at
- * @return Indices
- */
- public static Object[] findIndices(List points, Array xi) {
- int n = points.size();
- int[] indices = new int[n];
- double[] distances = new double[n];
- boolean outBounds = false;
- double x;
- Array a;
- for (int i = 0; i < n; i++) {
- x = xi.getDouble(i);
- a = points.get(i);
- int idx = searchSorted(a, x);
- if (idx < 0) {
- outBounds = true;
- idx = 0;
- }
- indices[i] = idx;
- distances[i] = (x - a.getDouble(idx)) / (a.getDouble(idx + 1) - a.getDouble(idx));
- }
-
- return new Object[]{indices, distances, outBounds};
- }
-
- /**
- * Search sorted list index
- *
- * @param a Sorted list
- * @param v value
- * @return Index
- */
- public static int searchSorted(List a, double v) {
- int idx = -1;
- int n = a.size();
- if (a.get(1).doubleValue() > a.get(0).doubleValue()) {
- if (v < a.get(0).doubleValue()) {
- return idx;
- }
-
- if (v > a.get(n - 1).doubleValue()) {
- return idx;
- }
-
- for (int i = 1; i < n; i++) {
- if (v < a.get(i).doubleValue()) {
- idx = i - 1;
- break;
- }
- }
- } else {
- if (v > a.get(0).doubleValue()) {
- return idx;
- }
-
- if (v < a.get(n - 1).doubleValue()) {
- return idx;
- }
-
- for (int i = 1; i < n; i++) {
- if (v > a.get(i).doubleValue()) {
- idx = i - 1;
- break;
- }
- }
- }
-
- return idx;
- }
-
- /**
- * Search sorted list index
- *
- * @param a Sorted list
- * @param v value
- * @return Index
- */
- public static int searchSorted(Array a, double v) {
- int idx = -1;
- int n = (int) a.getSize();
- if (a.getDouble(1) > a.getDouble(0)) {
- if (v < a.getDouble(0)) {
- return idx;
- }
-
- if (v > a.getDouble(n - 1)) {
- return idx;
- }
-
- for (int i = 1; i < n; i++) {
- if (v < a.getDouble(i)) {
- idx = i - 1;
- break;
- }
- }
- } else {
- if (v > a.getDouble(0)) {
- return idx;
- }
-
- if (v < a.getDouble(n - 1)) {
- return idx;
- }
-
- for (int i = 1; i < n; i++) {
- if (v > a.getDouble(i)) {
- idx = i - 1;
- break;
- }
- }
- }
-
- return idx;
- }
-
-// /**
-// * Search sorted list index
-// *
-// * @param a Sorted list
-// * @param v value
-// * @return Index
-// */
-// public static int searchSorted(Array a, double v) {
-// if (v < a.getDouble(0) || v > a.getDouble((int)a.getSize() - 1)) {
-// return -1;
-// }
-//
-// int idx = Arrays.binarySearch((double[])a.get1DJavaArray(double.class), v);
-// if (idx < 0) {
-// idx = -idx - 1;
-// }
-// return idx;
-// }
- /**
- * Interpolates data with any shape over a specified axis.
- *
- * @param x Desired interpolated value
- * @param xp The x-coordinates of the data points.
- * @param a The data to be interpolated.
- * @param axis The axis to interpolate over.
- * @return Interpolated data
- * @throws InvalidRangeException
- */
- public static Array interpolate_1d(double x, Array xp, Array a, int axis) throws InvalidRangeException {
- int[] dataShape = xp.getShape();
- int[] shape = new int[dataShape.length - 1];
- for (int i = 0; i < dataShape.length; i++) {
- if (i < axis) {
- shape[i] = dataShape[i];
- } else if (i > axis) {
- shape[i - 1] = dataShape[i];
- }
- }
-
- Array r = Array.factory(a.getDataType(), shape);
- Index indexr = r.getIndex();
- Index indexa = a.getIndex();
- int[] current, dcurrent = new int[dataShape.length];
- int idx;
- Array tArray;
- double belowp, abovep, belowa, abovea;
- for (int i = 0; i < r.getSize(); i++) {
- current = indexr.getCurrentCounter();
- List ranges = new ArrayList<>();
- for (int j = 0; j < dataShape.length; j++) {
- if (j == axis) {
- ranges.add(new Range(0, dataShape[j] - 1, 1));
- } else {
- idx = j;
- if (idx > axis) {
- idx -= 1;
- }
- ranges.add(new Range(current[idx], current[idx], 1));
- dcurrent[j] = current[idx];
- }
- }
- tArray = ArrayMath.section(xp, ranges);
- idx = searchSorted(tArray, x);
- if (idx < 0) {
- r.setDouble(i, Double.NaN);
- } else if (idx == dataShape[axis] - 1) {
- dcurrent[axis] = idx;
- r.setObject(i, a.getObject(indexa.set(dcurrent)));
- } else {
- dcurrent[axis] = idx;
- indexa.set(dcurrent);
- belowp = xp.getDouble(indexa);
- belowa = a.getDouble(indexa);
- dcurrent[axis] = idx + 1;
- indexa.set(dcurrent);
- abovep = xp.getDouble(indexa);
- abovea = a.getDouble(indexa);
- r.setDouble(i, (x - belowp) / (abovep - belowp) * (abovea - belowa) + belowa);
- }
- indexr.incr();
- }
-
- return r;
- }
-
- /**
- * Interpolates data with any shape over a specified axis.
- *
- * @param xa Desired interpolated values
- * @param xp The x-coordinates of the data points.
- * @param a The data to be interpolated.
- * @param axis The axis to interpolate over.
- * @return Interpolated data
- * @throws InvalidRangeException
- */
- public static Array interpolate_1d(Array xa, Array xp, Array a, int axis) throws InvalidRangeException {
- int[] dataShape = xp.getShape();
- int[] shape = new int[dataShape.length];
- int[] tshape = new int[shape.length - 1];
- for (int i = 0; i < dataShape.length; i++) {
- if (i == axis) {
- shape[i] = xa.getShape()[0];
- } else {
- shape[i] = dataShape[i];
- if (i < axis) {
- tshape[i] = dataShape[i];
- } else {
- tshape[i - 1] = dataShape[i];
- }
- }
- }
-
- Array r = Array.factory(a.getDataType(), shape);
- Array rr = Array.factory(DataType.BYTE, tshape);
- Index indexrr = rr.getIndex();
- Index indexr = r.getIndex();
- Index indexa = a.getIndex();
- int[] currentrr, currenta = new int[dataShape.length], currentr = new int[shape.length];
- int idx;
- Array tArray;
- double belowp, abovep, belowa, abovea, x;
- for (int i = 0; i < rr.getSize(); i++) {
- currentrr = indexrr.getCurrentCounter();
- List ranges = new ArrayList<>();
- for (int j = 0; j < dataShape.length; j++) {
- if (j == axis) {
- ranges.add(new Range(0, dataShape[j] - 1, 1));
- } else {
- idx = j;
- if (idx > axis) {
- idx -= 1;
- }
- ranges.add(new Range(currentrr[idx], currentrr[idx], 1));
- currenta[j] = currentrr[idx];
- currentr[j] = currentrr[idx];
- }
- }
- tArray = ArrayMath.section(xp, ranges);
- for (int j = 0; j < xa.getSize(); j++) {
- x = xa.getDouble(j);
- idx = searchSorted(tArray, x);
- currentr[axis] = j;
- indexr.set(currentr);
- if (idx < 0) {
- r.setDouble(indexr, Double.NaN);
- } else if (idx == dataShape[axis] - 1) {
- currenta[axis] = idx;
- r.setObject(indexr, a.getObject(indexa.set(currenta)));
- } else {
- currenta[axis] = idx;
- indexa.set(currenta);
- belowp = xp.getDouble(indexa);
- belowa = a.getDouble(indexa);
- currenta[axis] = idx + 1;
- indexa.set(currenta);
- abovep = xp.getDouble(indexa);
- abovea = a.getDouble(indexa);
- r.setDouble(indexr, (x - belowp) / (abovep - belowp) * (abovea - belowa) + belowa);
- }
- }
- indexrr.incr();
- }
-
- return r;
- }
-
- //
- //
- /**
- * Reproject
- *
- * @param x X array
- * @param y Y array
- * @param toProj To projection
- * @return Result arrays
- */
- public static Array[] reproject(Array x, Array y, ProjectionInfo toProj) {
- ProjectionInfo fromProj = KnownCoordinateSystems.geographic.world.WGS1984;
- return reproject(x, y, fromProj, toProj);
- }
-
- /**
- * Reproject
- *
- * @param x X array
- * @param y Y array
- * @param fromProj From projection
- * @param toProj To projection
- * @return Result arrays
- */
- public static Array[] reproject(Array x, Array y, ProjectionInfo fromProj, ProjectionInfo toProj) {
- Array rx = Array.factory(DataType.DOUBLE, x.getShape());
- Array ry = Array.factory(DataType.DOUBLE, x.getShape());
- int n = (int) x.getSize();
- double[][] points = new double[n][];
- for (int i = 0; i < n; i++) {
- points[i] = new double[]{x.getDouble(i), y.getDouble(i)};
- }
- Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length);
- for (int i = 0; i < n; i++) {
- rx.setDouble(i, points[i][0]);
- ry.setDouble(i, points[i][1]);
- }
-
- return new Array[]{rx, ry};
- }
-
- /**
- * Interpolate data to a station point
- *
- * @param data Data array
- * @param xArray X array
- * @param yArray Y array
- * @param x X coordinate of the station
- * @param y Y coordinate of the station
- * @param missingValue Missing value
- * @return Interpolated value
- */
- public static double toStation(Array data, List xArray, List yArray, double x, double y,
- double missingValue) {
- double iValue = Double.NaN;
- int nx = xArray.size();
- int ny = yArray.size();
- if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue()
- || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) {
- return iValue;
- }
-
- //Get x/y index
- int xIdx = 0, yIdx = 0;
- int i;
- boolean isIn = false;
- for (i = 1; i < nx; i++) {
- if (x < xArray.get(i).doubleValue()) {
- xIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- xIdx = nx - 2;
- }
- isIn = false;
- for (i = 1; i < ny; i++) {
- if (y < yArray.get(i).doubleValue()) {
- yIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- yIdx = ny - 2;
- }
-
- int i1 = yIdx;
- int j1 = xIdx;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
- Index index = data.getIndex();
- double a = data.getDouble(index.set(i1, j1));
- double b = data.getDouble(index.set(i1, j2));
- double c = data.getDouble(index.set(i2, j1));
- double d = data.getDouble(index.set(i2, j2));
- List dList = new ArrayList<>();
- if (!Double.isNaN(a) && !MIMath.doubleEquals(a, missingValue)) {
- dList.add(a);
- }
- if (!Double.isNaN(b) && !MIMath.doubleEquals(b, missingValue)) {
- dList.add(b);
- }
- if (!Double.isNaN(c) && !MIMath.doubleEquals(c, missingValue)) {
- dList.add(c);
- }
- if (!Double.isNaN(d) && !MIMath.doubleEquals(d, missingValue)) {
- dList.add(d);
- }
-
- if (dList.isEmpty()) {
- return iValue;
- } else if (dList.size() == 1) {
- iValue = dList.get(0);
- } else if (dList.size() <= 3) {
- double aSum = 0;
- for (double dd : dList) {
- aSum += dd;
- }
- iValue = aSum / dList.size();
- } else {
- double dx = xArray.get(xIdx + 1).doubleValue() - xArray.get(xIdx).doubleValue();
- double dy = yArray.get(yIdx + 1).doubleValue() - yArray.get(yIdx).doubleValue();
- double x1val = a + (c - a) * (y - yArray.get(i1).doubleValue()) / dy;
- double x2val = b + (d - b) * (y - yArray.get(i1).doubleValue()) / dy;
- iValue = x1val + (x2val - x1val) * (x - xArray.get(j1).doubleValue()) / dx;
- }
-
- return iValue;
- }
-
- /**
- * Interpolate data to a station point
- *
- * @param data Data array
- * @param xArray X array
- * @param yArray Y array
- * @param x X coordinate of the station
- * @param y Y coordinate of the station
- * @return Interpolated value
- */
- public static double toStation(Array data, List xArray, List yArray, double x, double y) {
- double iValue = Double.NaN;
- int nx = xArray.size();
- int ny = yArray.size();
- if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue()
- || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) {
- return iValue;
- }
-
- //Get x/y index
- int xIdx = 0, yIdx = 0;
- int i;
- boolean isIn = false;
- for (i = 1; i < nx; i++) {
- if (x < xArray.get(i).doubleValue()) {
- xIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- xIdx = nx - 2;
- }
- isIn = false;
- for (i = 1; i < ny; i++) {
- if (y < yArray.get(i).doubleValue()) {
- yIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- yIdx = ny - 2;
- }
-
- int i1 = yIdx;
- int j1 = xIdx;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
- Index index = data.getIndex();
- double a = data.getDouble(index.set(i1, j1));
- double b = data.getDouble(index.set(i1, j2));
- double c = data.getDouble(index.set(i2, j1));
- double d = data.getDouble(index.set(i2, j2));
- List dList = new ArrayList<>();
- if (!Double.isNaN(a)) {
- dList.add(a);
- }
- if (!Double.isNaN(b)) {
- dList.add(b);
- }
- if (!Double.isNaN(c)) {
- dList.add(c);
- }
- if (!Double.isNaN(d)) {
- dList.add(d);
- }
-
- if (dList.isEmpty()) {
- return iValue;
- } else if (dList.size() == 1) {
- iValue = dList.get(0);
- } else if (dList.size() <= 3) {
- double aSum = 0;
- for (double dd : dList) {
- aSum += dd;
- }
- iValue = aSum / dList.size();
- } else {
- double dx = xArray.get(xIdx + 1).doubleValue() - xArray.get(xIdx).doubleValue();
- double dy = yArray.get(yIdx + 1).doubleValue() - yArray.get(yIdx).doubleValue();
- double x1val = a + (c - a) * (y - yArray.get(i1).doubleValue()) / dy;
- double x2val = b + (d - b) * (y - yArray.get(i1).doubleValue()) / dy;
- iValue = x1val + (x2val - x1val) * (x - xArray.get(j1).doubleValue()) / dx;
- }
-
- return iValue;
- }
-
- /**
- * Get value index in a dimension array
- *
- * @param dim Dimension array
- * @param v The value
- * @return value index
- */
- public static int getDimIndex(Array dim, double v) {
- int n = (int) dim.getSize();
- if (v < dim.getDouble(0) || v > dim.getDouble(n - 1)) {
- return -1;
- }
-
- int idx = n - 1;
- for (int i = 1; i < n; i++) {
- if (v < dim.getDouble(i)) {
- idx = i - 1;
- break;
- }
- }
- return idx;
- }
-
- private static int[] gridIndex(Array xdim, Array ydim, double x, double y) {
- int xn = (int) xdim.getSize();
- int yn = (int) ydim.getSize();
- int xIdx = getDimIndex(xdim, x);
- if (xIdx < 0) {
- return null;
- }
-
- int yIdx = getDimIndex(ydim, y);
- if (yIdx < 0) {
- return null;
- }
-
- if (xIdx == xn - 1) {
- xIdx = xn - 2;
- }
- if (yIdx == yn - 1) {
- yIdx = yn - 2;
- }
- int i1 = yIdx;
- int j1 = xIdx;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
-
- return new int[]{i1, j1, i2, j2};
- }
-
- private static double bilinear(Array data, Index dindex, Array xdim, Array ydim, double x, double y) {
- double iValue = Double.NaN;
- int[] xyIdx = gridIndex(xdim, ydim, x, y);
- if (xyIdx == null) {
- return iValue;
- }
-
- int i1 = xyIdx[0];
- int j1 = xyIdx[1];
- int i2 = xyIdx[2];
- int j2 = xyIdx[3];
- Index index = Index.factory(data.getShape());
- int n = index.getRank();
- for (int i = 0; i < n - 2; i++) {
- index.setDim(i, dindex.getCurrentCounter()[i]);
- }
- index.setDim(n - 2, i1);
- index.setDim(n - 1, j1);
- double a = data.getDouble(index);
- index.setDim(n - 1, j2);
- double b = data.getDouble(index);
- index.setDim(n - 2, i2);
- index.setDim(n - 1, j1);
- double c = data.getDouble(index);
- index.setDim(n - 2, i2);
- index.setDim(n - 1, j2);
- double d = data.getDouble(index);
- List dList = new ArrayList<>();
- if (!Double.isNaN(a)) {
- dList.add(a);
- }
- if (!Double.isNaN(b)) {
- dList.add(b);
- }
- if (!Double.isNaN(c)) {
- dList.add(c);
- }
- if (!Double.isNaN(d)) {
- dList.add(d);
- }
-
- if (dList.isEmpty()) {
- return iValue;
- } else if (dList.size() == 1) {
- iValue = dList.get(0);
- } else if (dList.size() <= 3) {
- double aSum = 0;
- for (double dd : dList) {
- aSum += dd;
- }
- iValue = aSum / dList.size();
- } else {
- double dx = xdim.getDouble(j1 + 1) - xdim.getDouble(j1);
- double dy = ydim.getDouble(i1 + 1) - ydim.getDouble(i1);
- double x1val = a + (c - a) * (y - ydim.getDouble(i1)) / dy;
- double x2val = b + (d - b) * (y - ydim.getDouble(i1)) / dy;
- iValue = x1val + (x2val - x1val) * (x - xdim.getDouble(j1)) / dx;
- }
-
- return iValue;
- }
-
- /**
- * Interpolate data to a station point
- *
- * @param data Data array
- * @param xArray X array
- * @param yArray Y array
- * @param x X coordinate of the station
- * @param y Y coordinate of the station
- * @return Interpolated value
- */
- public static double toStation(Array data, Array xArray, Array yArray, double x, double y) {
- double iValue = Double.NaN;
- int nx = (int) xArray.getSize();
- int ny = (int) yArray.getSize();
- if (x < xArray.getDouble(0) || x > xArray.getDouble(nx - 1)
- || y < yArray.getDouble(0) || y > yArray.getDouble(ny - 1)) {
- return iValue;
- }
-
- //Get x/y index
- int xIdx = 0, yIdx = 0;
- int i;
- boolean isIn = false;
- for (i = 1; i < nx; i++) {
- if (x < xArray.getDouble(i)) {
- xIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- xIdx = nx - 2;
- }
- isIn = false;
- for (i = 1; i < ny; i++) {
- if (y < yArray.getDouble(i)) {
- yIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- yIdx = ny - 2;
- }
-
- int i1 = yIdx;
- int j1 = xIdx;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
- Index index = data.getIndex();
- double a = data.getDouble(index.set(i1, j1));
- double b = data.getDouble(index.set(i1, j2));
- double c = data.getDouble(index.set(i2, j1));
- double d = data.getDouble(index.set(i2, j2));
- List dList = new ArrayList<>();
- if (!Double.isNaN(a)) {
- dList.add(a);
- }
- if (!Double.isNaN(b)) {
- dList.add(b);
- }
- if (!Double.isNaN(c)) {
- dList.add(c);
- }
- if (!Double.isNaN(d)) {
- dList.add(d);
- }
-
- if (dList.isEmpty()) {
- return iValue;
- } else if (dList.size() == 1) {
- iValue = dList.get(0);
- } else if (dList.size() <= 3) {
- double aSum = 0;
- for (double dd : dList) {
- aSum += dd;
- }
- iValue = aSum / dList.size();
- } else {
- double dx = xArray.getDouble(xIdx + 1) - xArray.getDouble(xIdx);
- double dy = yArray.getDouble(yIdx + 1) - yArray.getDouble(yIdx);
- double x1val = a + (c - a) * (y - yArray.getDouble(i1)) / dy;
- double x2val = b + (d - b) * (y - yArray.getDouble(i1)) / dy;
- iValue = x1val + (x2val - x1val) * (x - xArray.getDouble(j1)) / dx;
- }
-
- return iValue;
- }
-
- /**
- * Interpolate data to a station point
- *
- * @param data Data array
- * @param xArray X array
- * @param yArray Y array
- * @param x X coordinate of the station
- * @param y Y coordinate of the station
- * @param missingValue Missing value
- * @return Interpolated value
- */
- public static double toStation_Neighbor(Array data, List xArray, List yArray, double x, double y,
- double missingValue) {
- double iValue = Double.NaN;
- int nx = xArray.size();
- int ny = yArray.size();
- if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue()
- || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) {
- return iValue;
- }
-
- //Get x/y index
- int xIdx = 0, yIdx = 0;
- int i;
- boolean isIn = false;
- for (i = 1; i < nx; i++) {
- if (x < xArray.get(i).doubleValue()) {
- xIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- xIdx = nx - 2;
- }
- isIn = false;
- for (i = 1; i < ny; i++) {
- if (y < yArray.get(i).doubleValue()) {
- yIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- yIdx = ny - 2;
- }
-
- int i1 = yIdx;
- int j1 = xIdx;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
- Index index = data.getIndex();
- double a = data.getDouble(index.set(i1, j1));
- double b = data.getDouble(index.set(i1, j2));
- double c = data.getDouble(index.set(i2, j1));
- double d = data.getDouble(index.set(i2, j2));
-
- if (Math.abs(x - xArray.get(j1).doubleValue()) < Math.abs(xArray.get(j2).doubleValue() - x)) {
- if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) {
- iValue = a;
- } else {
- iValue = c;
- }
- } else if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) {
- iValue = b;
- } else {
- iValue = d;
- }
-
- return iValue;
- }
-
- /**
- * Interpolate data to a station point
- *
- * @param data Data array
- * @param xArray X array
- * @param yArray Y array
- * @param x X coordinate of the station
- * @param y Y coordinate of the station
- * @return Interpolated value
- */
- public static double toStation_Neighbor(Array data, List xArray, List yArray, double x, double y) {
- //ouble iValue = Double.NaN;
- int nx = xArray.size();
- int ny = yArray.size();
- if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue()
- || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) {
- return Double.NaN;
- }
-
- //Get x/y index
- int xIdx = 0, yIdx = 0;
- int i;
- boolean isIn = false;
- for (i = 1; i < nx; i++) {
- if (x < xArray.get(i).doubleValue()) {
- xIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- xIdx = nx - 2;
- }
- isIn = false;
- for (i = 1; i < ny; i++) {
- if (y < yArray.get(i).doubleValue()) {
- yIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- yIdx = ny - 2;
- }
-
- int i1 = yIdx;
- int j1 = xIdx;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
- Index index = data.getIndex();
- double a = data.getDouble(index.set(i1, j1));
- double b = data.getDouble(index.set(i1, j2));
- double c = data.getDouble(index.set(i2, j1));
- double d = data.getDouble(index.set(i2, j2));
-
- double iValue;
- if (Math.abs(x - xArray.get(j1).doubleValue()) < Math.abs(xArray.get(j2).doubleValue() - x)) {
- if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) {
- iValue = a;
- } else {
- iValue = c;
- }
- } else if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) {
- iValue = b;
- } else {
- iValue = d;
- }
-
- return iValue;
- }
-
- /**
- * Interpolate data to a station point
- *
- * @param data Data array
- * @param xArray X array
- * @param yArray Y array
- * @param x X coordinate of the station
- * @param y Y coordinate of the station
- * @return Interpolated value
- */
- public static double toStation_Neighbor(Array data, Array xArray, Array yArray, double x, double y) {
- //ouble iValue = Double.NaN;
- int nx = (int) xArray.getSize();
- int ny = (int) yArray.getSize();
- if (x < xArray.getDouble(0) || x > xArray.getDouble(nx - 1)
- || y < yArray.getDouble(0) || y > yArray.getDouble(ny - 1)) {
- return Double.NaN;
- }
-
- //Get x/y index
- int xIdx = 0, yIdx = 0;
- int i;
- boolean isIn = false;
- for (i = 1; i < nx; i++) {
- if (x < xArray.getDouble(i)) {
- xIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- xIdx = nx - 2;
- }
- isIn = false;
- for (i = 1; i < ny; i++) {
- if (y < yArray.getDouble(i)) {
- yIdx = i - 1;
- isIn = true;
- break;
- }
- }
- if (!isIn) {
- yIdx = ny - 2;
- }
-
- int i1 = yIdx;
- int j1 = xIdx;
- int i2 = i1 + 1;
- int j2 = j1 + 1;
- Index index = data.getIndex();
- double a = data.getDouble(index.set(i1, j1));
- double b = data.getDouble(index.set(i1, j2));
- double c = data.getDouble(index.set(i2, j1));
- double d = data.getDouble(index.set(i2, j2));
-
- double iValue;
- if (Math.abs(x - xArray.getDouble(j1)) < Math.abs(xArray.getDouble(j2) - x)) {
- if (Math.abs(y - yArray.getDouble(i1)) < Math.abs(yArray.getDouble(i2) - y)) {
- iValue = a;
- } else {
- iValue = c;
- }
- } else if (Math.abs(y - yArray.getDouble(i1)) < Math.abs(yArray.getDouble(i2) - y)) {
- iValue = b;
- } else {
- iValue = d;
- }
-
- return iValue;
- }
-
- /**
- * Project grid data
- *
- * @param data Data array
- * @param xx X array
- * @param yy Y array
- * @param fromProj From projection
- * @param toProj To projection
- * @return Porjected grid data
- * @throws org.meteoinfo.ndarray.InvalidRangeException
- */
- public static Object[] reproject_back(Array data, List xx, List yy, ProjectionInfo fromProj, ProjectionInfo toProj) throws InvalidRangeException {
- Extent aExtent;
- int xnum = xx.size();
- int ynum = yy.size();
- double xdelta = xx.get(1).doubleValue() - xx.get(0).doubleValue();
- double ydelta = yy.get(1).doubleValue() - yy.get(0).doubleValue();
- aExtent = ProjectionUtil.getProjectionExtent(fromProj, toProj, xx, yy);
-
- double xDelt = (aExtent.maxX - aExtent.minX) / (xnum - 1);
- double yDelt = (aExtent.maxY - aExtent.minY) / (ynum - 1);
- Array rx = Array.factory(DataType.DOUBLE, new int[]{xnum});
- Array ry = Array.factory(DataType.DOUBLE, new int[]{ynum});
- int i, j, xIdx, yIdx;
- for (i = 0; i < xnum; i++) {
- rx.setDouble(i, aExtent.minX + i * xDelt);
- }
-
- for (i = 0; i < ynum; i++) {
- ry.setDouble(i, aExtent.minY + i * yDelt);
- }
-
- double x, y;
- Array r = Array.factory(data.getDataType(), data.getShape());
- double[][] points = new double[1][];
- Object fill_value = Double.NaN;
- switch (data.getDataType()) {
- case INT:
- fill_value = Integer.MIN_VALUE;
- break;
- case FLOAT:
- fill_value = Float.NaN;
- break;
- }
- for (i = 0; i < ynum; i++) {
- for (j = 0; j < xnum; j++) {
- points[0] = new double[]{rx.getDouble(j), ry.getDouble(i)};
- try {
- Reproject.reprojectPoints(points, toProj, fromProj, 0, 1);
- x = points[0][0];
- y = points[0][1];
-
- if (x < xx.get(0).doubleValue() || x > xx.get(xx.size() - 1).doubleValue()) {
- r.setObject(i * xnum + j, fill_value);
- } else if (y < yy.get(0).doubleValue() || y > yy.get(yy.size() - 1).doubleValue()) {
- r.setObject(i * xnum + j, fill_value);
- } else {
- xIdx = (int) ((x - xx.get(0).doubleValue()) / xdelta);
- yIdx = (int) ((y - yy.get(0).doubleValue()) / ydelta);
- r.setObject(i * xnum + j, data.getObject(yIdx * xnum + xIdx));
- }
- } catch (Exception e) {
- r.setObject(i * xnum + j, fill_value);
- j++;
- }
- }
- }
-
- return new Object[]{r, rx, ry};
- }
-
- /**
- * Project grid data
- *
- * @param data Data array
- * @param xx X array
- * @param yy Y array
- * @param fromProj From projection
- * @param toProj To projection
- * @param method Resample method
- * @return Porjected grid data
- * @throws org.meteoinfo.ndarray.InvalidRangeException
- */
- public static Object[] reproject(Array data, List xx, List yy, ProjectionInfo fromProj,
- ProjectionInfo toProj, ResampleMethods method) throws InvalidRangeException {
- Extent aExtent;
- int xnum = xx.size();
- int ynum = yy.size();
- aExtent = ProjectionUtil.getProjectionExtent(fromProj, toProj, xx, yy);
-
- double xDelt = (aExtent.maxX - aExtent.minX) / (xnum - 1);
- double yDelt = (aExtent.maxY - aExtent.minY) / (ynum - 1);
- int i;
- Array rx = Array.factory(DataType.DOUBLE, new int[]{xnum});
- Array ry = Array.factory(DataType.DOUBLE, new int[]{ynum});
- for (i = 0; i < xnum; i++) {
- rx.setDouble(i, aExtent.minX + i * xDelt);
- }
-
- for (i = 0; i < ynum; i++) {
- ry.setDouble(i, aExtent.minY + i * yDelt);
- }
-
- Array[] rr = ArrayUtil.meshgrid(rx, ry);
-
- Array r = ArrayUtil.reproject(data, xx, yy, rr[0], rr[1], fromProj, toProj, method);
-
- return new Object[]{r, rx, ry};
- }
-
- /**
- * Project grid data
- *
- * @param data Data array
- * @param xx X array
- * @param yy Y array
- * @param fromProj From projection
- * @param toProj To projection
- * @return Porjected grid data
- * @throws org.meteoinfo.ndarray.InvalidRangeException
- */
- public static Object[] reproject(Array data, List xx, List yy, ProjectionInfo fromProj,
- ProjectionInfo toProj) throws InvalidRangeException {
- return reproject(data, xx, yy, fromProj, toProj, ResampleMethods.NearestNeighbor);
- }
-
- /**
- * Reproject
- *
- * @param data Data array
- * @param x X array
- * @param y Y array
- * @param rx Result x array
- * @param ry Result y array
- * @param fromProj From projection
- * @param toProj To projection
- * @param fill_value Fill value
- * @param resampleMethod Resample method
- * @return Result arrays
- * @throws org.meteoinfo.ndarray.InvalidRangeException
- */
- public static Array reproject(Array data, List x, List y, Array rx, Array ry,
- ProjectionInfo fromProj, ProjectionInfo toProj, double fill_value, ResampleMethods resampleMethod) throws InvalidRangeException {
- int n = (int) rx.getSize();
- int[] dshape = data.getShape();
- int[] shape;
- if (rx.getRank() == 1) {
- shape = new int[1];
- shape[0] = rx.getShape()[0];
- } else {
- shape = new int[data.getRank()];
- for (int i = 0; i < shape.length; i++) {
- if (i == shape.length - 2) {
- shape[i] = rx.getShape()[0];
- } else if (i == shape.length - 1) {
- shape[i] = rx.getShape()[1];
- } else {
- shape[i] = data.getShape()[i];
- }
- }
- }
- Array r = Array.factory(data.getDataType(), shape);
-
- double[][] points = new double[n][];
- for (int i = 0; i < n; i++) {
- points[i] = new double[]{rx.getDouble(i), ry.getDouble(i)};
- }
- if (!fromProj.equals(toProj)) {
- Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length);
- }
- double xx, yy;
- if (resampleMethod == ResampleMethods.Bilinear) {
- if (shape.length <= 2) {
- for (int i = 0; i < n; i++) {
- xx = points[i][0];
- yy = points[i][1];
- if (Double.isNaN(xx) || Double.isNaN(yy)) {
- r.setObject(i, Double.NaN);
- } else {
- r.setObject(i, toStation(data, x, y, xx, yy, fill_value));
- }
- }
- } else {
- Index indexr = r.getIndex();
- int[] current, cc = null;
- boolean isNew;
- Array ndata = null;
- int k;
- for (int i = 0; i < r.getSize(); i++) {
- current = indexr.getCurrentCounter();
- isNew = true;
- if (i > 0) {
- for (int j = 0; j < shape.length - 2; j++) {
- if (cc[j] != current[j]) {
- isNew = false;
- break;
- }
- }
- }
- cc = Arrays.copyOf(current, current.length);
- if (isNew) {
- List ranges = new ArrayList<>();
- for (int j = 0; j < shape.length - 2; j++) {
- ranges.add(new Range(current[j], current[j], 1));
- }
- ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1));
- ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1));
- ndata = data.section(ranges).reduce();
- }
- k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1];
- xx = points[k][0];
- yy = points[k][1];
- if (Double.isNaN(xx) || Double.isNaN(yy)) {
- r.setObject(i, Double.NaN);
- } else {
- r.setObject(i, toStation(ndata, x, y, xx, yy, fill_value));
- }
- indexr.incr();
- }
- }
- } else if (shape.length <= 2) {
- for (int i = 0; i < n; i++) {
- xx = points[i][0];
- yy = points[i][1];
- if (Double.isNaN(xx) || Double.isNaN(yy)) {
- r.setObject(i, Double.NaN);
- } else {
- r.setObject(i, toStation_Neighbor(data, x, y, xx, yy, fill_value));
- }
- }
- } else {
- Index indexr = r.getIndex();
- int[] current, cc = null;
- boolean isNew;
- Array ndata = null;
- int k;
- for (int i = 0; i < r.getSize(); i++) {
- current = indexr.getCurrentCounter();
- isNew = true;
- if (i > 0) {
- for (int j = 0; j < shape.length - 2; j++) {
- if (cc[j] != current[j]) {
- isNew = false;
- break;
- }
- }
- }
- cc = Arrays.copyOf(current, current.length);
- if (isNew) {
- List ranges = new ArrayList<>();
- for (int j = 0; j < shape.length - 2; j++) {
- ranges.add(new Range(current[j], current[j], 1));
- }
- ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1));
- ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1));
- ndata = data.section(ranges).reduce();
- }
- k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1];
- xx = points[k][0];
- yy = points[k][1];
- if (Double.isNaN(xx) || Double.isNaN(yy)) {
- r.setObject(i, Double.NaN);
- } else {
- r.setObject(i, toStation_Neighbor(ndata, x, y, xx, yy, fill_value));
- }
- indexr.incr();
- }
- }
-
- return r;
- }
-
- /**
- * Reproject
- *
- * @param data Data array
- * @param x X array
- * @param y Y array
- * @param rx Result x array
- * @param ry Result y array
- * @param fromProj From projection
- * @param toProj To projection
- * @param resampleMethod Resample method
- * @return Result arrays
- * @throws org.meteoinfo.ndarray.InvalidRangeException
- */
- public static Array reproject(Array data, List x, List y, Array rx, Array ry,
- ProjectionInfo fromProj, ProjectionInfo toProj, ResampleMethods resampleMethod) throws InvalidRangeException {
- int n = (int) rx.getSize();
- int[] dshape = data.getShape();
- int[] shape;
- if (rx.getRank() == 1) {
- shape = new int[1];
- shape[0] = rx.getShape()[0];
- } else {
- shape = new int[data.getRank()];
- for (int i = 0; i < shape.length; i++) {
- if (i == shape.length - 2) {
- shape[i] = rx.getShape()[0];
- } else if (i == shape.length - 1) {
- shape[i] = rx.getShape()[1];
- } else {
- shape[i] = data.getShape()[i];
- }
- }
- }
- Array r = Array.factory(data.getDataType(), shape);
-
- double[][] points = new double[n][];
- for (int i = 0; i < n; i++) {
- points[i] = new double[]{rx.getDouble(i), ry.getDouble(i)};
- }
- if (!fromProj.equals(toProj)) {
- Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length);
- }
- double xx, yy;
- if (resampleMethod == ResampleMethods.Bilinear) {
- if (shape.length <= 2) {
- for (int i = 0; i < n; i++) {
- xx = points[i][0];
- yy = points[i][1];
- r.setObject(i, toStation(data, x, y, xx, yy));
- }
- } else {
- Index indexr = r.getIndex();
- int[] current, cc = null;
- boolean isNew;
- Array ndata = null;
- int k;
- for (int i = 0; i < r.getSize(); i++) {
- current = indexr.getCurrentCounter();
- isNew = true;
- if (i > 0) {
- for (int j = 0; j < shape.length - 2; j++) {
- if (cc[j] != current[j]) {
- isNew = false;
- break;
- }
- }
- }
- cc = Arrays.copyOf(current, current.length);
- if (isNew) {
- List ranges = new ArrayList<>();
- for (int j = 0; j < shape.length - 2; j++) {
- ranges.add(new Range(current[j], current[j], 1));
- }
- ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1));
- ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1));
- ndata = data.section(ranges).reduce();
- }
- k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1];
- xx = points[k][0];
- yy = points[k][1];
- r.setObject(i, toStation(ndata, x, y, xx, yy));
- indexr.incr();
- }
- }
- } else if (shape.length == 2) {
- for (int i = 0; i < n; i++) {
- xx = points[i][0];
- yy = points[i][1];
- r.setObject(i, toStation_Neighbor(data, x, y, xx, yy));
- }
- } else {
- Index indexr = r.getIndex();
- int[] current, cc = null;
- boolean isNew;
- Array ndata = null;
- int k;
- for (int i = 0; i < r.getSize(); i++) {
- current = indexr.getCurrentCounter();
- isNew = true;
- if (i > 0) {
- for (int j = 0; j < shape.length - 2; j++) {
- if (cc[j] != current[j]) {
- isNew = false;
- break;
- }
- }
- }
- cc = Arrays.copyOf(current, current.length);
- if (isNew) {
- List ranges = new ArrayList<>();
- for (int j = 0; j < shape.length - 2; j++) {
- ranges.add(new Range(current[j], current[j], 1));
- }
- ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1));
- ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1));
- ndata = data.section(ranges).reduce();
- }
- k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1];
- xx = points[k][0];
- yy = points[k][1];
- r.setObject(i, toStation_Neighbor(ndata, x, y, xx, yy));
- indexr.incr();
- }
- }
-
- return r;
- }
-
- /**
- * Reproject
- *
- * @param data Data array
- * @param x X array
- * @param y Y array
- * @param rx Result x array
- * @param ry Result y array
- * @param fromProj From projection
- * @param toProj To projection
- * @param fill_value Fill value
- * @param resampleMethod Resample method
- * @return Result arrays
- */
- public static Array reproject(Array data, List x, List y, List rx, List ry,
- ProjectionInfo fromProj, ProjectionInfo toProj, double fill_value, ResampleMethods resampleMethod) {
- int n = rx.size() * ry.size();
- int[] shape = new int[]{ry.size(), rx.size()};
- Array r = Array.factory(data.getDataType(), shape);
-
- double[][] points = new double[n][];
- for (int i = 0; i < ry.size(); i++) {
- for (int j = 0; j < rx.size(); j++) {
- points[i * rx.size() + j] = new double[]{rx.get(j).doubleValue(), ry.get(i).doubleValue()};
- }
- }
- if (!fromProj.equals(toProj)) {
- Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length);
- }
- double xx, yy;
- if (resampleMethod == ResampleMethods.Bilinear) {
- for (int i = 0; i < n; i++) {
- xx = points[i][0];
- yy = points[i][1];
- r.setObject(i, toStation(data, x, y, xx, yy, fill_value));
- }
- } else {
- for (int i = 0; i < n; i++) {
- xx = points[i][0];
- yy = points[i][1];
- r.setObject(i, toStation_Neighbor(data, x, y, xx, yy, fill_value));
- }
- }
-
- return r;
- }
-
- /**
- * Computes the smallest convex Polygon that contains all the
- * points
- *
- * @param x X array
- * @param y Y array
- * @return PolygonShape
- */
- public static PolygonShape convexHull(Array x, Array y) {
- int n = (int) x.getSize();
- Geometry[] geos = new Geometry[n];
- GeometryFactory factory = new GeometryFactory();
- for (int i = 0; i < n; i++) {
- Coordinate c = new Coordinate(x.getDouble(i), y.getDouble(i));
- geos[i] = factory.createPoint(c);
- }
- Geometry gs = factory.createGeometryCollection(geos);
- Geometry ch = gs.convexHull();
- return new PolygonShape(ch);
- }
-
- //
- //
- //
-}
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.meteoinfo.bak;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.Scanner;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.meteoinfo.data.mapdata.Field;
+import org.meteoinfo.geoprocess.GeoComputation;
+import org.meteoinfo.geoprocess.analysis.ResampleMethods;
+import org.meteoinfo.global.DataConvert;
+import org.meteoinfo.global.Extent;
+import org.meteoinfo.global.MIMath;
+import org.meteoinfo.global.PointD;
+import org.meteoinfo.global.util.GlobalUtil;
+import org.meteoinfo.io.EndianDataOutputStream;
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.Geometry;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.meteoinfo.data.StationData;
+import org.meteoinfo.layer.VectorLayer;
+import org.meteoinfo.legend.LegendScheme;
+import org.meteoinfo.ndarray.Complex;
+import org.meteoinfo.math.ListIndexComparator;
+import org.meteoinfo.math.spatial.KDTree;
+import org.meteoinfo.math.spatial.KDTree.SearchResult;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
+import org.meteoinfo.projection.KnownCoordinateSystems;
+import org.meteoinfo.projection.info.ProjectionInfo;
+import org.meteoinfo.projection.ProjectionUtil;
+import org.meteoinfo.projection.Reproject;
+import org.meteoinfo.shape.PolygonShape;
+import org.meteoinfo.shape.ShapeTypes;
+import org.python.core.PyComplex;
+import org.meteoinfo.ndarray.Array;
+import org.meteoinfo.ndarray.DataType;
+import org.meteoinfo.ndarray.Index;
+import org.meteoinfo.ndarray.Index2D;
+import org.meteoinfo.ndarray.IndexIterator;
+import org.meteoinfo.ndarray.InvalidRangeException;
+import org.meteoinfo.ndarray.Range;
+
+/**
+ *
+ * @author yaqiang
+ */
+public class ArrayUtil {
+
+ //
+ /**
+ * Read ASCII data file to an array
+ *
+ * @param fileName File name
+ * @param delimiter Delimiter
+ * @param headerLines Headerline number
+ * @param dataType Data type string
+ * @param shape Shape
+ * @param readFirstCol Read first column data or not
+ * @return Result array
+ * @throws UnsupportedEncodingException
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ public static Array readASCIIFile(String fileName, String delimiter, int headerLines, String dataType,
+ List shape, boolean readFirstCol) throws UnsupportedEncodingException, FileNotFoundException, IOException {
+ BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)));
+ if (headerLines > 0) {
+ for (int i = 0; i < headerLines; i++) {
+ sr.readLine();
+ }
+ }
+
+ DataType dt = DataType.DOUBLE;
+ if (dataType != null) {
+ if (dataType.contains("%")) {
+ dataType = dataType.split("%")[1];
+ }
+ dt = ArrayUtil.toDataType(dataType);
+ }
+
+ int i;
+ int[] ss = new int[shape.size()];
+ for (i = 0; i < shape.size(); i++) {
+ ss[i] = shape.get(i);
+ }
+ Array a = Array.factory(dt, ss);
+
+ String[] dataArray;
+ i = 0;
+ String line = sr.readLine();
+ int sCol = 0;
+ if (!readFirstCol) {
+ sCol = 1;
+ }
+ while (line != null) {
+ line = line.trim();
+ if (line.isEmpty()) {
+ line = sr.readLine();
+ continue;
+ }
+ dataArray = GlobalUtil.split(line, delimiter);
+ for (int j = sCol; j < dataArray.length; j++) {
+ a.setDouble(i, Double.parseDouble(dataArray[j]));
+ i += 1;
+ if (i >= a.getSize()) {
+ break;
+ }
+ }
+ if (i >= a.getSize()) {
+ break;
+ }
+
+ line = sr.readLine();
+ }
+ sr.close();
+
+ return a;
+ }
+
+ /**
+ * Get row number of a ASCII file
+ *
+ * @param fileName File name
+ * @return Row number
+ * @throws FileNotFoundException
+ */
+ public static int numASCIIRow(String fileName) throws FileNotFoundException {
+ File f = new File(fileName);
+ int lineNumber;
+ try (Scanner fileScanner = new Scanner(f)) {
+ lineNumber = 0;
+ while (fileScanner.hasNextLine()) {
+ fileScanner.nextLine();
+ lineNumber++;
+ }
+ }
+
+ return lineNumber;
+ }
+
+ /**
+ * Get row number of a ASCII file
+ *
+ * @param fileName File name
+ * @param delimiter
+ * @param headerLines
+ * @return Row number
+ * @throws FileNotFoundException
+ */
+ public static int numASCIICol(String fileName, String delimiter, int headerLines) throws FileNotFoundException, IOException {
+ String[] dataArray;
+ try (BufferedReader sr = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)))) {
+ if (headerLines > 0) {
+ for (int i = 0; i < headerLines; i++) {
+ sr.readLine();
+ }
+ }
+ String line = sr.readLine().trim();
+ dataArray = GlobalUtil.split(line, delimiter);
+ }
+
+ return dataArray.length;
+ }
+
+ /**
+ * Save an array data to a binary file
+ *
+ * @param fn File path
+ * @param a Array
+ * @param byteOrder Byte order
+ * @param append If append to existing file
+ * @param sequential If write as sequential binary file - Fortran
+ */
+ public static void saveBinFile(String fn, Array a, String byteOrder, boolean append,
+ boolean sequential) {
+ try (DataOutputStream out = new DataOutputStream(new FileOutputStream(new File(fn), append))) {
+ EndianDataOutputStream outs = new EndianDataOutputStream(out);
+ ByteBuffer bb = a.getDataAsByteBuffer();
+ int n = (int) a.getSize();
+ ByteOrder bOrder = ByteOrder.LITTLE_ENDIAN;
+ if (byteOrder.equalsIgnoreCase("big_endian")) {
+ bOrder = ByteOrder.BIG_ENDIAN;
+ }
+
+ if (sequential) {
+ if (bOrder == ByteOrder.BIG_ENDIAN) {
+ outs.writeIntBE(n * 4);
+ } else {
+ outs.writeIntLE(n * 4);
+ }
+ }
+
+ if (bOrder == ByteOrder.BIG_ENDIAN) {
+ outs.write(bb.array());
+ } else if (a.getDataType() == DataType.BYTE) {
+ outs.write(bb.array());
+ } else {
+ ByteBuffer nbb = ByteBuffer.allocate(bb.array().length);
+ nbb.order(bOrder);
+ switch (a.getDataType()) {
+ case INT:
+ for (int i = 0; i < a.getSize(); i++) {
+ nbb.putInt(i * 4, bb.getInt());
+ //nbb.putInt(a.getInt(i));
+ }
+ break;
+ case FLOAT:
+ for (int i = 0; i < a.getSize(); i++) {
+ nbb.putFloat(i * 4, bb.getFloat());
+ }
+ break;
+ case DOUBLE:
+ for (int i = 0; i < a.getSize(); i++) {
+ nbb.putDouble(i * 8, bb.getDouble());
+ }
+ break;
+ default:
+ nbb.put(bb);
+ }
+ outs.write(nbb.array());
+ }
+
+ if (sequential) {
+ if (bOrder == ByteOrder.BIG_ENDIAN) {
+ outs.writeIntBE(n * 4);
+ } else {
+ outs.writeIntLE(n * 4);
+ }
+ }
+
+ outs.close();
+ } catch (FileNotFoundException ex) {
+ Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IOException ex) {
+ Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ /**
+ * Save an array data to a ASCII file
+ *
+ * @param fn File path
+ * @param a Array
+ * @param colNum Column number of each line
+ * @param format String format
+ * @param delimiter Delimiter
+ * @throws java.io.IOException
+ */
+ public static void saveASCIIFile(String fn, Array a, int colNum,
+ String format, String delimiter) throws IOException {
+ BufferedWriter sw = new BufferedWriter(new FileWriter(new File(fn)));
+ String line = "";
+ int j = 0;
+ for (int i = 0; i < a.getSize(); i++) {
+ j += 1;
+ if (format == null) {
+ line = line + a.getObject(i).toString();
+ } else {
+ line = line + String.format(format, a.getObject(i));
+ }
+ if (j < colNum && i < a.getSize() - 1) {
+ if (delimiter == null) {
+ line = line + " ";
+ } else {
+ line = line + delimiter;
+ }
+ } else {
+ sw.write(line);
+ sw.newLine();
+ line = "";
+ j = 0;
+ }
+ }
+ sw.flush();
+ sw.close();
+ }
+
+ /**
+ * Read array from a binary file
+ *
+ * @param fn Binary file name
+ * @param dims Dimensions
+ * @param dataType Data type string
+ * @param skip Skip bytes
+ * @param byteOrder Byte order
+ * @return Result array
+ */
+ public static Array readBinFile(String fn, List dims, String dataType, int skip,
+ String byteOrder) {
+ DataType dt = DataType.DOUBLE;
+ if (dataType != null) {
+ if (dataType.contains("%")) {
+ dataType = dataType.split("%")[1];
+ }
+ dt = ArrayUtil.toDataType(dataType);
+ }
+ DataType ndt = dt;
+ if (dt == DataType.BYTE) {
+ ndt = DataType.INT;
+ }
+
+ ByteOrder bOrder = ByteOrder.LITTLE_ENDIAN;
+ if (byteOrder.equalsIgnoreCase("big_endian")) {
+ bOrder = ByteOrder.BIG_ENDIAN;
+ }
+
+ int[] shape = new int[dims.size()];
+ for (int i = 0; i < dims.size(); i++) {
+ shape[i] = dims.get(i);
+ }
+ Array r = Array.factory(ndt, shape);
+ IndexIterator iter = r.getIndexIterator();
+ try {
+ DataInputStream ins = new DataInputStream(new FileInputStream(fn));
+ ins.skip(skip);
+ byte[] bytes;
+ byte[] db;
+ int start = 0;
+ switch (dt) {
+ case BYTE:
+ bytes = new byte[(int) r.getSize()];
+ ins.read(bytes);
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setInt(i, DataConvert.byte2Int(bytes[i]));
+ }
+ break;
+ case SHORT:
+ bytes = new byte[(int) r.getSize() * 2];
+ db = new byte[2];
+ ins.read(bytes);
+ while (iter.hasNext()) {
+ System.arraycopy(bytes, start, db, 0, 2);
+ iter.setShortNext(DataConvert.bytes2Short(db, bOrder));
+ start += 2;
+ }
+ break;
+ case INT:
+ bytes = new byte[(int) r.getSize() * 4];
+ db = new byte[4];
+ ins.read(bytes);
+ while (iter.hasNext()) {
+ System.arraycopy(bytes, start, db, 0, 4);
+ iter.setIntNext(DataConvert.bytes2Int(db, bOrder));
+ start += 4;
+ }
+ break;
+ case FLOAT:
+ bytes = new byte[(int) r.getSize() * 4];
+ db = new byte[4];
+ ins.read(bytes);
+ while (iter.hasNext()) {
+ System.arraycopy(bytes, start, db, 0, 4);
+ iter.setFloatNext(DataConvert.bytes2Float(db, bOrder));
+ start += 4;
+ }
+ break;
+ case DOUBLE:
+ bytes = new byte[(int) r.getSize() * 8];
+ db = new byte[8];
+ ins.read(bytes);
+ while (iter.hasNext()) {
+ System.arraycopy(bytes, start, db, 0, 8);
+ iter.setDoubleNext(DataConvert.bytes2Double(db, bOrder));
+ start += 8;
+ }
+ break;
+ }
+ ins.close();
+ } catch (FileNotFoundException ex) {
+ Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex);
+ } catch (IOException ex) {
+ Logger.getLogger(ArrayUtil.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ return r;
+ }
+
+ //
+ //
+
+ /**
+ * Create an array
+ *
+ * @param data Object
+ * @return Array
+ */
+ public static Array array(Object data) {
+ if (data instanceof Number) {
+ DataType dt = ArrayMath.getDataType(data);
+ Array a = Array.factory(dt, new int[]{1});
+ a.setObject(0, data);
+ return a;
+ } else if (data instanceof Array) {
+ return (Array) data;
+ } else if (data instanceof ArrayList) {
+ return array((List) data);
+ } else if (data.getClass().isArray()) {
+ return Array.factory(data);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Create an array
+ *
+ * @param data Array like data
+ * @return
+ */
+ public static Array array(ArrayList data) {
+ return array((List) data);
+ }
+
+ /**
+ * Create an array
+ *
+ * @param data Array like data
+ * @return Array
+ */
+ public static Array array(List data) {
+ Object d0 = data.get(0);
+ if (d0 instanceof Number) {
+ DataType dt = ArrayUtil.objectsToType(data);
+ Array a = Array.factory(dt, new int[]{data.size()});
+ for (int i = 0; i < data.size(); i++) {
+ a.setObject(i, data.get(i));
+ }
+ return a;
+ } else if (d0 instanceof String) {
+ Array a = Array.factory(DataType.STRING, new int[]{data.size()});
+ for (int i = 0; i < data.size(); i++) {
+ a.setObject(i, data.get(i));
+ }
+ return a;
+ } else if (d0 instanceof Boolean) {
+ Array a = Array.factory(DataType.BOOLEAN, new int[]{data.size()});
+ for (int i = 0; i < data.size(); i++) {
+ a.setObject(i, data.get(i));
+ }
+ return a;
+ } else if (d0 instanceof PyComplex) {
+ Array a = Array.factory(DataType.OBJECT, new int[]{data.size()});
+ PyComplex d;
+ for (int i = 0; i < data.size(); i++) {
+ d = (PyComplex) data.get(i);
+ a.setObject(i, new Complex(d.real, d.imag));
+ }
+ return a;
+ } else if (d0 instanceof List) {
+ int ndim = data.size();
+ int len = ((List) d0).size();
+ DataType dt = ArrayUtil.objectsToType((List) d0);
+ Array a = Array.factory(dt, new int[]{ndim, len});
+ for (int i = 0; i < ndim; i++) {
+ List d = (List) data.get(i);
+ for (int j = 0; j < len; j++) {
+ a.setObject(i * len + j, d.get(j));
+ }
+ }
+ return a;
+ } else {
+ Array a = Array.factory(DataType.OBJECT, new int[]{data.size()});
+ for (int i = 0; i < data.size(); i++) {
+ a.setObject(i, data.get(i));
+ }
+ return a;
+ }
+ }
+
+ /**
+ * Array range
+ *
+ * @param start Start value
+ * @param stop Stop value
+ * @param step Step value
+ * @return Array
+ */
+ public static Array arrayRange_bak(Number start, Number stop, final Number step) {
+ if (stop == null) {
+ stop = start;
+ start = 0;
+ }
+ DataType dataType = ArrayUtil.objectsToType(new Object[]{
+ start,
+ stop,
+ step});
+ double startv = start.doubleValue();
+ double stopv = stop.doubleValue();
+ double stepv = step.doubleValue();
+ List data = new ArrayList<>();
+ if (dataType == DataType.FLOAT || dataType == DataType.DOUBLE) {
+ while (startv < stopv) {
+ data.add(startv);
+ startv = BigDecimalUtil.add(startv, stepv);
+ }
+ } else {
+ while (startv < stopv) {
+ data.add(startv);
+ startv += stepv;
+ }
+ }
+ int length = data.size();
+ Array a = Array.factory(dataType, new int[]{length});
+ for (int i = 0; i < length; i++) {
+ a.setObject(i, data.get(i));
+ }
+ return a;
+ }
+
+ /**
+ * Array range
+ *
+ * @param start Start value
+ * @param stop Stop value
+ * @param step Step value
+ * @return Array
+ */
+ public static Array arrayRange(Number start, Number stop, final Number step) {
+ if (stop == null) {
+ stop = start;
+ start = 0;
+ }
+ DataType dataType = ArrayUtil.objectsToType(new Object[]{
+ start,
+ stop,
+ step});
+ double startv = start.doubleValue();
+ double stopv = stop.doubleValue();
+ double stepv = step.doubleValue();
+ final int length = Math.max(0, (int) Math.ceil((stopv
+ - startv) / stepv));
+ Array a = Array.factory(dataType, new int[]{length});
+ if (dataType == DataType.FLOAT || dataType == DataType.DOUBLE) {
+ for (int i = 0; i < length; i++) {
+ a.setObject(i, BigDecimalUtil.add(BigDecimalUtil.mul(i, stepv), startv));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ a.setObject(i, i * stepv + startv);
+ }
+ }
+ return a;
+ }
+
+ /**
+ * Array range
+ *
+ * @param start Start value
+ * @param length Length
+ * @param step Step value
+ * @return Array
+ */
+ public static Array arrayRange1(Number start, final int length, final Number step) {
+ DataType dataType = ArrayUtil.objectsToType(new Object[]{
+ start,
+ step});
+ double startv = start.doubleValue();
+ double stepv = step.doubleValue();
+ Array a = Array.factory(dataType, new int[]{length});
+ if (dataType == DataType.FLOAT || dataType == DataType.DOUBLE) {
+ for (int i = 0; i < length; i++) {
+ a.setObject(i, BigDecimalUtil.add(BigDecimalUtil.mul(i, stepv), startv));
+ }
+ } else {
+ for (int i = 0; i < length; i++) {
+ a.setObject(i, i * stepv + startv);
+ }
+ }
+ return a;
+ }
+
+ /**
+ * Array line space
+ *
+ * @param start Start value
+ * @param stop Stop value
+ * @param n Number value
+ * @param endpoint If stop is included
+ * @return Array
+ */
+ public static Array lineSpace(Number start, Number stop, final int n, boolean endpoint) {
+ if (stop == null) {
+ stop = start;
+ start = 0;
+ }
+ double startv = start.doubleValue();
+ double stopv = stop.doubleValue();
+ int div = endpoint ? (n - 1) : n;
+ double stepv = (stopv - startv) / div;
+ Array a = Array.factory(DataType.DOUBLE, new int[]{n});
+ double v = startv;
+ for (int i = 0; i < n; i++) {
+ a.setDouble(i, v);
+ v += stepv;
+ }
+ if (endpoint) {
+ if (a.getDouble(n - 1) != stopv) {
+ a.setDouble(n - 1, stopv);
+ }
+ }
+
+ return a;
+ }
+
+ /**
+ * Array line space
+ *
+ * @param start Start value
+ * @param stop Stop value
+ * @param n Number value
+ * @param endpoint If stop is included
+ * @return Array
+ */
+ public static Array lineSpace_bak(Number start, Number stop, final int n, boolean endpoint) {
+ if (stop == null) {
+ stop = start;
+ start = 0;
+ }
+ double startv = start.doubleValue();
+ double stopv = stop.doubleValue();
+ double stepv = (stopv - startv) / (n - 1);
+ double endv = n * stepv + startv;
+ int nn = n;
+ if (endpoint) {
+ if (endv < stopv) {
+ nn += 1;
+ }
+ } else if (endv >= stopv) {
+ nn -= 1;
+ }
+ Array a = Array.factory(DataType.FLOAT, new int[]{nn});
+ for (int i = 0; i < nn; i++) {
+ a.setObject(i, BigDecimalUtil.add(BigDecimalUtil.mul(i, stepv), startv));
+ }
+
+ return a;
+ }
+
+ /**
+ * Get zero array
+ *
+ * @param n Number
+ * @return Array
+ */
+ public static Array zeros(int n) {
+ Array a = Array.factory(DataType.FLOAT, new int[]{n});
+ for (int i = 0; i < n; i++) {
+ a.setFloat(i, 0);
+ }
+
+ return a;
+ }
+
+ /**
+ * Get zero array
+ *
+ * @param shape Shape
+ * @param dtype Data type
+ * @return Array Result array
+ */
+ public static Array zeros(List shape, String dtype) {
+ DataType dt = toDataType(dtype);
+ return zeros(shape, dt);
+ }
+
+ /**
+ * Get zero array
+ *
+ * @param shape Shape
+ * @param dtype Data type
+ * @return Array Result array
+ */
+ public static Array zeros(List shape, DataType dtype) {
+ int[] ashape = new int[shape.size()];
+ for (int i = 0; i < shape.size(); i++) {
+ ashape[i] = shape.get(i);
+ }
+ Array a = Array.factory(dtype, ashape);
+
+ return a;
+ }
+
+ /**
+ * Return a new array of given shape and type, filled with fill value.
+ *
+ * @param shape Shape
+ * @param fillValue Fill value
+ * @param dtype Data type
+ * @return Array Result array
+ */
+ public static Array full(List shape, Object fillValue, DataType dtype) {
+ int[] ashape = new int[shape.size()];
+ for (int i = 0; i < shape.size(); i++) {
+ ashape[i] = shape.get(i);
+ }
+ if (dtype == null) {
+ dtype = ArrayMath.getDataType(fillValue);
+ }
+ Array a = Array.factory(dtype, ashape);
+
+ for (int i = 0; i < a.getSize(); i++) {
+ a.setObject(i, fillValue);
+ }
+
+ return a;
+ }
+
+ /**
+ * Get ones array
+ *
+ * @param n Number
+ * @return Array Result array
+ */
+ public static Array ones(int n) {
+ Array a = Array.factory(DataType.FLOAT, new int[]{n});
+ for (int i = 0; i < n; i++) {
+ a.setFloat(i, 1);
+ }
+
+ return a;
+ }
+
+ /**
+ * Get ones array
+ *
+ * @param shape Shape
+ * @param dtype Data type
+ * @return Array Result array
+ */
+ public static Array ones(List shape, String dtype) {
+ DataType dt = toDataType(dtype);
+ int[] ashape = new int[shape.size()];
+ for (int i = 0; i < shape.size(); i++) {
+ ashape[i] = shape.get(i);
+ }
+ Array a = Array.factory(dt, ashape);
+ for (int i = 0; i < a.getSize(); i++) {
+ a.setObject(i, 1);
+ }
+
+ return a;
+ }
+
+ /**
+ * Return the identity array - a square array with ones on the main
+ * diagonal.
+ *
+ * @param n Number of rows (and columns) in n x n output.
+ * @param dtype Data type
+ * @return Identity array
+ */
+ public static Array identity(int n, String dtype) {
+ DataType dt = toDataType(dtype);
+ int[] shape = new int[]{n, n};
+ Array a = Array.factory(dt, shape);
+ IndexIterator index = a.getIndexIterator();
+ int[] current;
+ while (index.hasNext()) {
+ index.next();
+ current = index.getCurrentCounter();
+ if (current[0] == current[1]) {
+ index.setObjectCurrent(1);
+ } else {
+ index.setObjectCurrent(0);
+ }
+ }
+
+ return a;
+ }
+
+ /**
+ * Return a 2-D array with ones on the diagonal and zeros elsewhere.
+ *
+ * @param n Number of rows in the output.
+ * @param m Number of columns in the output.
+ * @param k Index of the diagonal: 0 (the default) refers to the main
+ * diagonal, a positive value refers to an upper diagonal, and a negative
+ * value to a lower diagonal.
+ * @param dtype Data type
+ * @return Created array
+ */
+ public static Array eye(int n, int m, int k, String dtype) {
+ DataType dt = toDataType(dtype);
+ int[] shape = new int[]{n, m};
+ Array a = Array.factory(dt, shape);
+ IndexIterator index = a.getIndexIterator();
+ int[] current;
+ int i, j;
+ while (index.hasNext()) {
+ index.next();
+ current = index.getCurrentCounter();
+ i = current[0];
+ j = current[1] - k;
+ if (i == j) {
+ index.setObjectCurrent(1);
+ } else {
+ index.setObjectCurrent(0);
+ }
+ }
+
+ return a;
+ }
+
+ /**
+ * Extract a diagonal or construct a diagonal array.
+ *
+ * @param a If a is a 2-D array, return a copy of its k-th diagonal. If a is
+ * a 1-D array, return a 2-D array with a on the k-th diagonal.
+ * @param k Diagonal in question.
+ * @return Diagonal array
+ */
+ public static Array diag(Array a, int k) {
+ if (a.getRank() == 2) {
+ int m = a.getShape()[0];
+ int n = a.getShape()[1];
+ int len = Math.min(m, n) - Math.abs(k);
+ Array r = Array.factory(a.getDataType(), new int[]{len});
+ IndexIterator index = a.getIndexIterator();
+ int[] current;
+ int idx = 0, i, j;
+ while (index.hasNext()) {
+ index.next();
+ current = index.getCurrentCounter();
+ i = current[0];
+ j = current[1] - k;
+ if (i == j) {
+ r.setObject(idx, index.getObjectCurrent());
+ idx += 1;
+ if (idx == len) {
+ break;
+ }
+ }
+ }
+ return r;
+ } else {
+ int m = a.getShape()[0];
+ Array r = Array.factory(a.getDataType(), new int[]{m, m});
+ for (int i = 0; i < m; i++) {
+ for (int j = 0; j < m; j++) {
+ if (i == j - k) {
+ r.setObject(i * m + j, a.getObject(i));
+ } else {
+ r.setObject(i * m + j, 0);
+ }
+ }
+ }
+ return r;
+ }
+ }
+
+ /**
+ * Repeat a value n times
+ *
+ * @param v The value
+ * @param n N times
+ * @return Repeated array
+ */
+ public static Array repeat(Number v, int n) {
+ DataType dt = ArrayMath.getDataType(v);
+ Array r = Array.factory(dt, new int[]{n});
+ for (int i = 0; i < n; i++) {
+ r.setObject(i, v);
+ }
+
+ return r;
+ }
+
+ /**
+ * Repeat elements of an array.
+ *
+ * @param a The value
+ * @param repeats The number of repetitions for each element
+ * @return Repeated array
+ */
+ public static Array repeat(Array a, List repeats) {
+ Array r;
+ if (repeats.size() == 1) {
+ int n = repeats.get(0);
+ r = Array.factory(a.getDataType(), new int[]{(int) a.getSize() * n});
+ for (int i = 0; i < a.getSize(); i++) {
+ for (int j = 0; j < n; j++) {
+ r.setObject(i * n + j, a.getObject(i));
+ }
+ }
+ } else {
+ int n = 0;
+ for (int i = 0; i < repeats.size(); i++) {
+ n += repeats.get(i);
+ }
+ r = Array.factory(a.getDataType(), new int[]{n});
+ int idx = 0;
+ for (int i = 0; i < a.getSize(); i++) {
+ for (int j = 0; j < repeats.get(i); j++) {
+ r.setObject(idx, a.getObject(i));
+ idx += 1;
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Repeat elements of an array.
+ *
+ * @param a The value
+ * @param repeats The number of repetitions for each element
+ * @param axis The axis
+ * @return Repeated array
+ */
+ public static Array repeat(Array a, List repeats, int axis) {
+ Array r;
+ if (repeats.size() == 1) {
+ int n = repeats.get(0);
+ int[] shape = a.getShape();
+ shape[axis] = shape[axis] * n;
+ r = Array.factory(a.getDataType(), shape);
+ Index aindex = a.getIndex();
+ Index index = r.getIndex();
+ int[] current;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = index.getCurrentCounter();
+ current[axis] = current[axis] / n;
+ aindex.set(current);
+ r.setObject(index, a.getObject(aindex));
+ index.incr();
+ }
+ } else {
+ int n = 0;
+ int[] rsum = new int[repeats.size()];
+ for (int i = 0; i < repeats.size(); i++) {
+ rsum[i] = n;
+ n += repeats.get(i);
+ }
+ int[] shape = a.getShape();
+ shape[axis] = n;
+ r = Array.factory(a.getDataType(), shape);
+ Index aindex = a.getIndex();
+ Index index = r.getIndex();
+ int[] current;
+ int idx;
+ for (int i = 0; i < a.getSize(); i++) {
+ current = aindex.getCurrentCounter();
+ idx = current[axis];
+ for (int j = 0; j < repeats.get(idx); j++) {
+ current[axis] = rsum[idx] + j;
+ index.set(current);
+ r.setObject(index, a.getObject(aindex));
+ }
+ aindex.incr();
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Repeat a value n times
+ *
+ * @param v The value
+ * @param n N times
+ * @return Repeated array
+ */
+ public static Array tile(Number v, int n) {
+ DataType dt = ArrayMath.getDataType(v);
+ Array r = Array.factory(dt, new int[]{n});
+ for (int i = 0; i < n; i++) {
+ r.setObject(i, v);
+ }
+
+ return r;
+ }
+
+ /**
+ * Repeat a value n times
+ *
+ * @param v The value
+ * @param repeats The number of repetitions for each element
+ * @return Repeated array
+ */
+ public static Array tile(Number v, List repeats) {
+ int[] shape = new int[repeats.size()];
+ for (int i = 0; i < repeats.size(); i++) {
+ shape[i] = repeats.get(i);
+ }
+ DataType dt = ArrayMath.getDataType(v);
+ Array r = Array.factory(dt, shape);
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setObject(i, v);
+ }
+
+ return r;
+ }
+
+ /**
+ * Repeat elements of an array.
+ *
+ * @param a The value
+ * @param repeats The number of repetitions for each element
+ * @return Repeated array
+ */
+ public static Array tile(Array a, List repeats) {
+ if (a.getRank() > repeats.size()) {
+ int n = a.getRank() - repeats.size();
+ for (int i = 0; i < n; i++) {
+ repeats.add(0, 1);
+ }
+ } else if (a.getRank() < repeats.size()) {
+ int[] shape = a.getShape();
+ int[] nshape = new int[repeats.size()];
+ int n = repeats.size() - shape.length;
+ for (int i = 0; i < nshape.length; i++) {
+ if (i < n) {
+ nshape[i] = 1;
+ } else {
+ nshape[i] = shape[i - n];
+ }
+ }
+ a = a.reshape(nshape);
+ }
+ int[] ashape = a.getShape();
+ int[] shape = a.getShape();
+ for (int i = 0; i < shape.length; i++) {
+ shape[i] = shape[i] * repeats.get(i);
+ }
+ Array r = Array.factory(a.getDataType(), shape);
+ Index index = r.getIndex();
+ Index aindex = a.getIndex();
+ int[] current;
+ int idx;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = index.getCurrentCounter();
+ for (int j = 0; j < repeats.size(); j++) {
+ idx = current[j];
+ idx = idx % ashape[j];
+ current[j] = idx;
+ }
+ aindex.set(current);
+ r.setObject(index, a.getObject(aindex));
+ index.incr();
+ }
+
+ return r;
+ }
+
+ /**
+ * Get random value
+ *
+ * @return Random value
+ */
+ public static double rand() {
+ Random r = new Random();
+ return r.nextDouble();
+ }
+
+ /**
+ * Get random array - one dimension
+ *
+ * @param n Array length
+ * @return Result array
+ */
+ public static Array rand(int n) {
+ Array r = Array.factory(DataType.DOUBLE, new int[]{n});
+ Random rd = new Random();
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setDouble(i, rd.nextDouble());
+ }
+
+ return r;
+ }
+
+ /**
+ * Get random array
+ *
+ * @param shape Shape
+ * @return Array Result array
+ */
+ public static Array rand(List shape) {
+ int[] ashape = new int[shape.size()];
+ for (int i = 0; i < shape.size(); i++) {
+ ashape[i] = shape.get(i);
+ }
+ Array a = Array.factory(DataType.DOUBLE, ashape);
+ Random rd = new Random();
+ for (int i = 0; i < a.getSize(); i++) {
+ a.setDouble(i, rd.nextDouble());
+ }
+
+ return a;
+ }
+
+ private static DataType objectsToType(final Object[] objects) {
+ if (objects.length == 0) {
+ return DataType.INT;
+ }
+ short new_sz, sz = -1;
+ DataType dataType = DataType.INT;
+ for (final Object o : objects) {
+ final DataType _type = ArrayMath.getDataType(o);
+ new_sz = ArrayMath.typeToNBytes(_type);
+ if (new_sz > sz) {
+ dataType = _type;
+ }
+ }
+ return dataType;
+ }
+
+ private static DataType objectsToType(final List objects) {
+ if (objects.isEmpty()) {
+ return DataType.INT;
+ }
+ short new_sz, sz = -1;
+ DataType dataType = DataType.INT;
+ for (final Object o : objects) {
+ final DataType _type = ArrayMath.getDataType(o);
+ new_sz = ArrayMath.typeToNBytes(_type);
+ if (new_sz > sz) {
+ dataType = _type;
+ sz = new_sz;
+ }
+ }
+ return dataType;
+ }
+
+ /**
+ * Merge data type to one data type
+ *
+ * @param dt1 Data type 1
+ * @param dt2 Data type 2
+ * @return Merged data type
+ */
+ public static DataType mergeDataType(DataType dt1, DataType dt2) {
+ if (dt1 == DataType.OBJECT || dt2 == DataType.OBJECT) {
+ return DataType.OBJECT;
+ } else if (dt1 == DataType.STRING || dt2 == DataType.STRING) {
+ return DataType.STRING;
+ } else if (dt1 == DataType.DOUBLE || dt2 == DataType.DOUBLE) {
+ return DataType.DOUBLE;
+ } else if (dt1 == DataType.FLOAT || dt2 == DataType.FLOAT) {
+ return DataType.FLOAT;
+ } else {
+ return dt1;
+ }
+ }
+
+ //
+ //
+ /**
+ * Array to string
+ *
+ * @param a Array a
+ * @return String
+ */
+ public static String convertToString(Array a) {
+ StringBuilder sbuff = new StringBuilder();
+ sbuff.append("array(");
+ int ndim = a.getRank();
+ if (ndim > 1) {
+ sbuff.append("[");
+ }
+ int i = 0, n = 0;
+ IndexIterator ii = a.getIndexIterator();
+ int shapeIdx = ndim - 1;
+ if (shapeIdx < 0) {
+ sbuff.append("[");
+ sbuff.append(ii.getObjectNext());
+ sbuff.append("])");
+ return sbuff.toString();
+ }
+
+ int len = a.getShape()[shapeIdx];
+ Object data;
+ String dstr;
+ while (ii.hasNext()) {
+ if (i == 0) {
+ if (n > 0) {
+ sbuff.append("\n ");
+ }
+ sbuff.append("[");
+ }
+ data = ii.getObjectNext();
+ dstr = data.toString();
+ if (a.getDataType() == DataType.BOOLEAN) {
+ dstr = GlobalUtil.capitalize(dstr);
+ }
+ sbuff.append(dstr);
+ i += 1;
+ if (i == len) {
+ sbuff.append("]");
+ len = a.getShape()[shapeIdx];
+ i = 0;
+ } else {
+ sbuff.append(", ");
+ }
+ n += 1;
+ if (n > 200) {
+ sbuff.append("...]");
+ break;
+ }
+ }
+ if (ndim > 1) {
+ sbuff.append("]");
+ }
+ sbuff.append(")");
+ return sbuff.toString();
+ }
+
+ /**
+ * Array to string
+ *
+ * @param a Array a
+ * @return String
+ */
+ public static String toString_old(Array a) {
+ StringBuilder sbuff = new StringBuilder();
+ sbuff.append("array(");
+ int ndim = a.getRank();
+ if (ndim > 1) {
+ sbuff.append("[");
+ }
+ int i = 0;
+ int shapeIdx = ndim - 1;
+ int len = a.getShape()[shapeIdx];
+ IndexIterator ii = a.getIndexIterator();
+ while (ii.hasNext()) {
+ if (i == 0) {
+ sbuff.append("[");
+ }
+ Object data = ii.getObjectNext();
+ sbuff.append(data);
+ i += 1;
+ if (i == len) {
+ sbuff.append("]");
+ len = a.getShape()[shapeIdx];
+ i = 0;
+ } else {
+ sbuff.append(", ");
+ }
+ }
+ if (ndim > 1) {
+ sbuff.append("]");
+ }
+ return sbuff.toString();
+ }
+
+ /**
+ * Get array list from StationData
+ *
+ * @param stdata StationData
+ * @return Array list
+ */
+ public static List getArraysFromStationData(StationData stdata) {
+ int n = stdata.getStNum();
+ int[] shape = new int[1];
+ shape[0] = n;
+ Array lon = Array.factory(DataType.FLOAT, shape);
+ Array lat = Array.factory(DataType.FLOAT, shape);
+ Array value = Array.factory(DataType.FLOAT, shape);
+ double v;
+ for (int i = 0; i < n; i++) {
+ lon.setFloat(i, (float) stdata.getX(i));
+ lat.setFloat(i, (float) stdata.getY(i));
+ v = stdata.getValue(i);
+ if (v == stdata.missingValue) {
+ v = Double.NaN;
+ }
+ value.setFloat(i, (float) v);
+ }
+
+ List r = new ArrayList<>();
+ r.add(lon);
+ r.add(lat);
+ r.add(value);
+ return r;
+ }
+
+ //
+ //
+ /**
+ * Get data type string
+ *
+ * @param dt The data type
+ * @return Data type string
+ */
+ public static String dataTypeString(DataType dt) {
+ String str = "string";
+ switch (dt) {
+ case BYTE:
+ str = "byte";
+ break;
+ case SHORT:
+ str = "short";
+ break;
+ case INT:
+ str = "int";
+ break;
+ case FLOAT:
+ str = "float";
+ break;
+ case DOUBLE:
+ str = "double";
+ break;
+ }
+
+ return str;
+ }
+
+ /**
+ * To data type - ucar.ma2
+ *
+ * @param dt Data type string
+ * @return Data type
+ */
+ public static DataType toDataType(String dt) {
+ if (dt.contains("%")) {
+ dt = dt.split("%")[1];
+ }
+ switch (dt.toLowerCase()) {
+ case "c":
+ case "s":
+ case "string":
+ return DataType.STRING;
+ case "b":
+ case "byte":
+ return DataType.BYTE;
+ case "short":
+ return DataType.SHORT;
+ case "i":
+ case "int":
+ return DataType.INT;
+ case "f":
+ case "float":
+ return DataType.FLOAT;
+ case "d":
+ case "double":
+ return DataType.DOUBLE;
+ case "bool":
+ case "boolean":
+ return DataType.BOOLEAN;
+ default:
+ return DataType.OBJECT;
+ }
+ }
+
+ /**
+ * Convert array to integer type
+ *
+ * @param a Array a
+ * @return Result array
+ */
+ public static Array toInteger(Array a) {
+ Array r = Array.factory(DataType.INT, a.getShape());
+ if (a.getDataType().isNumeric()) {
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setInt(i, a.getInt(i));
+ }
+ } else {
+ if (a.getDataType() == DataType.BOOLEAN) {
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setInt(i, a.getBoolean(i) ? 1 : 0);
+ }
+ } else {
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setInt(i, Integer.valueOf(a.getObject(i).toString()));
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Convert array to float type
+ *
+ * @param a Array a
+ * @return Result array
+ */
+ public static Array toFloat(Array a) {
+ Array r = Array.factory(DataType.FLOAT, a.getShape());
+ if (a.getDataType().isNumeric()) {
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setFloat(i, a.getFloat(i));
+ }
+ } else {
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setFloat(i, Float.valueOf(a.getObject(i).toString()));
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Convert array to double type
+ *
+ * @param a Array a
+ * @return Result array
+ */
+ public static Array toDouble(Array a) {
+ Array r = Array.factory(DataType.DOUBLE, a.getShape());
+ if (a.getDataType().isNumeric()) {
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setDouble(i, a.getDouble(i));
+ }
+ } else {
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setDouble(i, Double.valueOf(a.getObject(i).toString()));
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Convert array to boolean type
+ *
+ * @param a Array a
+ * @return Result array
+ */
+ public static Array toBoolean(Array a) {
+ Array r = Array.factory(DataType.BOOLEAN, a.getShape());
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setBoolean(i, a.getDouble(i) != 0);
+ }
+
+ return r;
+ }
+
+ /**
+ * Concatenate arrays to one array along a axis
+ *
+ * @param arrays Array list
+ * @param axis The axis
+ * @return Concatenated array
+ * @throws org.meteoinfo.ndarray.InvalidRangeException
+ */
+ public static Array concatenate(List arrays, Integer axis) throws InvalidRangeException {
+ int ndim = arrays.get(0).getRank();
+ if (axis == -1) {
+ axis = ndim - 1;
+ }
+ int len = 0;
+ int[] lens = new int[arrays.size()];
+ int i = 0;
+ List indexList = new ArrayList<>();
+ for (Array a : arrays) {
+ len += a.getShape()[axis];
+ lens[i] = len;
+ indexList.add(Index.factory(a.getShape()));
+ i += 1;
+ }
+ int[] shape = arrays.get(0).getShape();
+ shape[axis] = len;
+ Array r = Array.factory(arrays.get(0).getDataType(), shape);
+ int[] current;
+ IndexIterator ii = r.getIndexIterator();
+ Index index;
+ int idx = 0;
+ while (ii.hasNext()) {
+ ii.next();
+ current = ii.getCurrentCounter();
+ for (i = 0; i < lens.length; i++) {
+ if (current[axis] < lens[i]) {
+ idx = i;
+ break;
+ }
+ }
+ if (idx > 0) {
+ current[axis] = current[axis] - lens[idx - 1];
+ }
+ index = indexList.get(idx);
+ index.set(current);
+ ii.setObjectCurrent(arrays.get(idx).getObject(index));
+ }
+
+ return r;
+ }
+
+ /**
+ * Concatenate two arrays to one array along a axis
+ *
+ * @param a Array a
+ * @param b Array b
+ * @param axis The axis
+ * @return Concatenated array
+ * @throws org.meteoinfo.ndarray.InvalidRangeException
+ */
+ public static Array concatenate(Array a, Array b, Integer axis) throws InvalidRangeException {
+ int n = a.getRank();
+ int[] shape = a.getShape();
+ if (axis == -1) {
+ axis = n - 1;
+ }
+ int nn = shape[axis];
+ int[] bshape = b.getShape();
+ int[] nshape = new int[n];
+ for (int i = 0; i < n; i++) {
+ if (i == axis) {
+ nshape[i] = shape[i] + bshape[i];
+ } else {
+ nshape[i] = shape[i];
+ }
+ }
+ Array r = Array.factory(a.getDataType(), nshape);
+ Index indexr = r.getIndex();
+ Index indexa = a.getIndex();
+ Index indexb = b.getIndex();
+ int[] current;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = indexr.getCurrentCounter();
+ if (current[axis] < nn) {
+ indexa.set(current);
+ r.setObject(indexr, a.getObject(indexa));
+ } else {
+ current[axis] = current[axis - nn];
+ indexb.set(current);
+ r.setObject(indexr, b.getObject(indexb));
+ }
+ indexr.incr();
+ }
+
+ return r;
+ }
+
+ /**
+ * Sort array along an axis
+ *
+ * @param a Array a
+ * @param axis The axis
+ * @return Sorted array
+ * @throws InvalidRangeException
+ */
+ public static Array sort(Array a, Integer axis) throws InvalidRangeException {
+ int n = a.getRank();
+ int[] shape = a.getShape();
+ if (axis == null) {
+ int[] nshape = new int[1];
+ nshape[0] = (int) a.getSize();
+ Array r = Array.factory(a.getDataType(), nshape);
+ List tlist = new ArrayList();
+ IndexIterator ii = a.getIndexIterator();
+ while (ii.hasNext()) {
+ tlist.add(ii.getObjectNext());
+ }
+ Collections.sort(tlist);
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setObject(i, tlist.get(i));
+ }
+
+ return r;
+ } else {
+ if (axis == -1) {
+ axis = n - 1;
+ }
+ int nn = shape[axis];
+ Array r = Array.factory(a.getDataType(), shape);
+ Index indexr = r.getIndex();
+ int[] current;
+ List ranges = new ArrayList<>();
+ for (int i = 0; i < n; i++) {
+ if (i == axis) {
+ ranges.add(new Range(0, 0, 1));
+ } else {
+ ranges.add(new Range(0, shape[i] - 1, 1));
+ }
+ }
+ IndexIterator rii = r.sectionNoReduce(ranges).getIndexIterator();
+ while (rii.hasNext()) {
+ rii.next();
+ current = rii.getCurrentCounter();
+ ranges = new ArrayList<>();
+ for (int j = 0; j < n; j++) {
+ if (j == axis) {
+ ranges.add(new Range(0, shape[j] - 1, 1));
+ } else {
+ ranges.add(new Range(current[j], current[j], 1));
+ }
+ }
+ List tlist = new ArrayList();
+ IndexIterator ii = a.getRangeIterator(ranges);
+ while (ii.hasNext()) {
+ tlist.add(ii.getObjectNext());
+ }
+ Collections.sort(tlist);
+ for (int j = 0; j < nn; j++) {
+ indexr.set(current);
+ r.setObject(indexr, tlist.get(j));
+ current[axis] = current[axis] + 1;
+ }
+ }
+
+ return r;
+ }
+ }
+
+ /**
+ * Get sorted array index along an axis
+ *
+ * @param a Array a
+ * @param axis The axis
+ * @return Index of sorted array
+ * @throws InvalidRangeException
+ */
+ public static Array argSort(Array a, Integer axis) throws InvalidRangeException {
+ int n = a.getRank();
+ int[] shape = a.getShape();
+ Object v;
+ if (axis == null) {
+ int[] nshape = new int[1];
+ nshape[0] = (int) a.getSize();
+ Array r = Array.factory(DataType.INT, nshape);
+ List stlist = new ArrayList();
+ IndexIterator ii = a.getIndexIterator();
+ while (ii.hasNext()) {
+ v = ii.getObjectNext();
+ stlist.add(v);
+ }
+ //Collections.sort(stlist);
+ ListIndexComparator comparator = new ListIndexComparator(stlist);
+ Integer[] indexes = comparator.createIndexArray();
+ Arrays.sort(indexes, comparator);
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setInt(i, indexes[i]);
+ }
+
+ return r;
+ } else {
+ if (axis == -1) {
+ axis = n - 1;
+ }
+ int nn = shape[axis];
+ Array r = Array.factory(DataType.INT, shape);
+ Index indexr = r.getIndex();
+ int[] current;
+ List ranges = new ArrayList<>();
+ for (int i = 0; i < n; i++) {
+ if (i == axis) {
+ ranges.add(new Range(0, 0, 1));
+ } else {
+ ranges.add(new Range(0, shape[i] - 1, 1));
+ }
+ }
+ IndexIterator rii = r.sectionNoReduce(ranges).getIndexIterator();
+ while (rii.hasNext()) {
+ rii.next();
+ current = rii.getCurrentCounter();
+ ranges = new ArrayList<>();
+ for (int j = 0; j < n; j++) {
+ if (j == axis) {
+ ranges.add(new Range(0, shape[j] - 1, 1));
+ } else {
+ ranges.add(new Range(current[j], current[j], 1));
+ }
+ }
+ List stlist = new ArrayList();
+ IndexIterator ii = a.getRangeIterator(ranges);
+ while (ii.hasNext()) {
+ v = ii.getObjectNext();
+ stlist.add(v);
+ }
+ //Collections.sort(stlist);
+ ListIndexComparator comparator = new ListIndexComparator(stlist);
+ Integer[] indexes = comparator.createIndexArray();
+ Arrays.sort(indexes, comparator);
+ for (int j = 0; j < nn; j++) {
+ indexr.set(current);
+ r.setObject(indexr, indexes[j]);
+ current[axis] = current[axis] + 1;
+ }
+ }
+
+ return r;
+ }
+ }
+
+ /**
+ * Convert array to N-Dimension double Java array
+ *
+ * @param a Array a
+ * @param dtype Data type string
+ * @return N-D Java array
+ */
+ public static Object copyToNDJavaArray(Array a, String dtype) {
+ if (dtype == null) {
+ return copyToNDJavaArray(a);
+ }
+
+ switch (dtype.toLowerCase()) {
+ case "double":
+ return copyToNDJavaArray_Double(a);
+ case "long":
+ return copyToNDJavaArray_Long(a);
+ default:
+ return copyToNDJavaArray(a);
+ }
+ }
+
+ /**
+ * Convert array to N-Dimension double Java array
+ *
+ * @param a Array a
+ * @return N-D Java array
+ */
+ public static Object copyToNDJavaArray(Array a) {
+ Object javaArray;
+ try {
+ javaArray = java.lang.reflect.Array.newInstance(Double.TYPE, a.getShape());
+ } catch (IllegalArgumentException | NegativeArraySizeException e) {
+ throw new IllegalArgumentException(e);
+ }
+ IndexIterator iter = a.getIndexIterator();
+ reflectArrayCopyOut(javaArray, a, iter);
+
+ return javaArray;
+ }
+
+ /**
+ * Convert array to N-Dimension double Java array
+ *
+ * @param a Array a
+ * @return N-D Java array
+ */
+ public static Object copyToNDJavaArray_Long(Array a) {
+ Object javaArray;
+ try {
+ javaArray = java.lang.reflect.Array.newInstance(Long.TYPE, a.getShape());
+ } catch (IllegalArgumentException | NegativeArraySizeException e) {
+ throw new IllegalArgumentException(e);
+ }
+ IndexIterator iter = a.getIndexIterator();
+ reflectArrayCopyOut(javaArray, a, iter);
+
+ return javaArray;
+ }
+
+ /**
+ * Convert array to N-Dimension double Java array
+ *
+ * @param a Array a
+ * @return N-D Java array
+ */
+ public static Object copyToNDJavaArray_Double(Array a) {
+ Object javaArray;
+ try {
+ javaArray = java.lang.reflect.Array.newInstance(Double.TYPE, a.getShape());
+ } catch (IllegalArgumentException | NegativeArraySizeException e) {
+ throw new IllegalArgumentException(e);
+ }
+ IndexIterator iter = a.getIndexIterator();
+ reflectArrayCopyOut(javaArray, a, iter);
+
+ return javaArray;
+ }
+
+ private static void reflectArrayCopyOut(Object jArray, Array aa, IndexIterator aaIter) {
+ Class cType = jArray.getClass().getComponentType();
+
+ if (!cType.isArray()) {
+ if (cType == long.class) {
+ copyTo1DJavaArray_Long(aaIter, jArray);
+ } else {
+ copyTo1DJavaArray(aaIter, jArray);
+ }
+ } else {
+ for (int i = 0; i < java.lang.reflect.Array.getLength(jArray); i++) {
+ reflectArrayCopyOut(java.lang.reflect.Array.get(jArray, i), aa, aaIter);
+ }
+ }
+ }
+
+ protected static void copyTo1DJavaArray(IndexIterator iter, Object javaArray) {
+ double[] ja = (double[]) javaArray;
+ for (int i = 0; i < ja.length; i++) {
+ ja[i] = iter.getDoubleNext();
+ }
+ }
+
+ protected static void copyTo1DJavaArray_Long(IndexIterator iter, Object javaArray) {
+ long[] ja = (long[]) javaArray;
+ for (int i = 0; i < ja.length; i++) {
+ ja[i] = iter.getLongNext();
+ }
+ }
+
+ /**
+ * Return a new array with sub-arrays along an axis deleted
+ *
+ * @param a Input array
+ * @param idx Index
+ * @param axis The axis
+ * @return
+ */
+ public static Array delete(Array a, int idx, int axis) {
+ int[] shape = a.getShape();
+ int n = shape.length;
+ int[] nshape = new int[n];
+ for (int i = 0; i < n; i++) {
+ if (i == axis) {
+ nshape[i] = shape[i] - 1;
+ } else {
+ nshape[i] = shape[i];
+ }
+ }
+ Array r = Array.factory(a.getDataType(), nshape);
+ IndexIterator ii = a.getIndexIterator();
+ int[] current;
+ int i = 0;
+ while (ii.hasNext()) {
+ ii.next();
+ current = ii.getCurrentCounter();
+ if (current[axis] != idx) {
+ r.setObject(i, ii.getObjectCurrent());
+ i += 1;
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Return a new array with sub-arrays along an axis deleted
+ *
+ * @param a Input array
+ * @param idx Index
+ * @param axis The axis
+ * @return
+ */
+ public static Array delete(Array a, List idx, int axis) {
+ int[] shape = a.getShape();
+ int n = shape.length;
+ int[] nshape = new int[n];
+ for (int i = 0; i < n; i++) {
+ if (i == axis) {
+ nshape[i] = shape[i] - idx.size();
+ } else {
+ nshape[i] = shape[i];
+ }
+ }
+ Array r = Array.factory(a.getDataType(), nshape);
+ IndexIterator ii = a.getIndexIterator();
+ int[] current;
+ int i = 0;
+ while (ii.hasNext()) {
+ ii.next();
+ current = ii.getCurrentCounter();
+ if (!idx.contains(current[axis])) {
+ r.setObject(i, ii.getObjectCurrent());
+ i += 1;
+ }
+ }
+
+ return r;
+ }
+
+ //
+ //
+ /**
+ * Histogram x/y array
+ *
+ * @param a Data array
+ * @param nbins bin number
+ * @return X/Y arrays
+ */
+ public static List histogram(Array a, int nbins) {
+ double min = ArrayMath.getMinimum(a);
+ double max = ArrayMath.getMaximum(a);
+ double interval = BigDecimalUtil.div(BigDecimalUtil.sub(max, min), nbins);
+ double[] bins = new double[nbins + 1];
+ for (int i = 0; i < nbins + 1; i++) {
+ bins[i] = min;
+ min = BigDecimalUtil.add(min, interval);
+ }
+ Array ba = Array.factory(DataType.DOUBLE, new int[]{bins.length}, bins);
+ return histogram(a, ba);
+ }
+
+ /**
+ * Histogram x/y array
+ *
+ * @param a Data array
+ * @param bins bin edges
+ * @return X/Y arrays
+ */
+ public static List histogram(Array a, Array bins) {
+ int n = (int) bins.getSize();
+ Array hist = Array.factory(DataType.INT, new int[]{n - 1});
+ double v;
+ for (int i = 0; i < a.getSize(); i++) {
+ v = a.getDouble(i);
+ for (int j = 0; j < n - 1; j++) {
+ if (j == n - 2) {
+ if (v >= bins.getDouble(j) && v <= bins.getDouble(j + 1)) {
+ hist.setInt(j, hist.getInt(j) + 1);
+ break;
+ }
+ } else if (v >= bins.getDouble(j) && v < bins.getDouble(j + 1)) {
+ hist.setInt(j, hist.getInt(j) + 1);
+ break;
+ }
+ }
+ }
+
+ List r = new ArrayList<>();
+ r.add(hist);
+ r.add(bins);
+
+ return r;
+ }
+
+ /**
+ * Histogram x/y array
+ *
+ * @param a Data array
+ * @param bins bin edges
+ * @return X/Y arrays
+ */
+ public static List histogram(Array a, double[] bins) {
+ int n = bins.length;
+ double delta = bins[1] - bins[0];
+ int[] count = new int[n + 1];
+ double v;
+ for (int i = 0; i < a.getSize(); i++) {
+ v = a.getDouble(i);
+ if (v < bins[0]) {
+ count[0] += 1;
+ } else if (v > bins[n - 1]) {
+ count[n] += 1;
+ } else {
+ for (int j = 0; j < n - 1; j++) {
+ if (v > bins[j] && v < bins[j + 1]) {
+ count[j + 1] += 1;
+ break;
+ }
+ }
+ }
+ }
+
+ Array x = Array.factory(DataType.DOUBLE, new int[]{count.length + 1});
+ Array y = Array.factory(DataType.INT, new int[]{count.length});
+ for (int i = 0; i < count.length; i++) {
+ y.setInt(i, count[i]);
+ if (i == 0) {
+ x.setDouble(0, bins[0] - delta);
+ x.setDouble(1, bins[0]);
+ } else if (i == count.length - 1) {
+ x.setDouble(i + 1, bins[i - 1] + delta);
+ } else {
+ x.setDouble(i + 1, bins[i]);
+ }
+ }
+ List r = new ArrayList<>();
+ r.add(y);
+ r.add(x);
+
+ return r;
+ }
+
+ //
+ //
+ /**
+ * Broadcast array to a new shape
+ *
+ * @param a Array a
+ * @param shape Shape
+ * @return Result array
+ */
+ public static Array broadcast(Array a, int[] shape) {
+ int[] bshape = a.getShape();
+ if (bshape.length > shape.length) {
+ return null;
+ }
+
+ if (bshape.length < shape.length) {
+ int miss = shape.length - a.getRank();
+ bshape = new int[shape.length];
+ for (int i = 0; i < shape.length; i++) {
+ if (i < miss) {
+ bshape[i] = 1;
+ } else {
+ bshape[i] = a.getShape()[i - miss];
+ }
+ }
+ a = a.reshape(bshape);
+ }
+
+ //Check
+ boolean pass = true;
+ for (int i = 0; i < shape.length; i++) {
+ if (shape[i] != bshape[i] && bshape[i] != 1) {
+ pass = false;
+ break;
+ }
+ }
+ if (!pass) {
+ return null;
+ }
+
+ //Broadcast
+ Index aindex = a.getIndex();
+ Array r = Array.factory(a.getDataType(), shape);
+ Index index = r.getIndex();
+ int[] current;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = index.getCurrentCounter();
+ for (int j = 0; j < shape.length; j++) {
+ if (bshape[j] == 1) {
+ aindex.setDim(j, 0);
+ } else {
+ aindex.setDim(j, current[j]);
+ }
+ }
+ r.setObject(index, a.getObject(aindex));
+ index.incr();
+ }
+
+ return r;
+ }
+
+ /**
+ * Broadcast array to a new shape
+ *
+ * @param a Array a
+ * @param shape Shape
+ * @return Result array
+ */
+ public static Array broadcast(Array a, List shape) {
+ int[] nshape = new int[shape.size()];
+ for (int i = 0; i < shape.size(); i++) {
+ nshape[i] = shape.get(i);
+ }
+ return broadcast(a, nshape);
+ }
+
+ /**
+ * Mesh grid
+ *
+ * @param x X array - vector
+ * @param y Y array - vector
+ * @return Result arrays - matrix
+ */
+ public static Array[] meshgrid(Array x, Array y) {
+ int xn = (int) x.getSize();
+ int yn = (int) y.getSize();
+ int[] shape = new int[]{yn, xn};
+ Array rx = Array.factory(x.getDataType(), shape);
+ Array ry = Array.factory(y.getDataType(), shape);
+ for (int i = 0; i < yn; i++) {
+ for (int j = 0; j < xn; j++) {
+ rx.setObject(i * xn + j, x.getObject(j));
+ ry.setObject(i * xn + j, y.getObject(i));
+ }
+ }
+
+ return new Array[]{rx, ry};
+ }
+
+ /**
+ * Mesh grid
+ *
+ * @param xs X arrays
+ * @return Result arrays - matrix
+ */
+ public static Array[] meshgrid(Array... xs) {
+ int n = xs.length;
+ int[] shape = new int[n];
+ int i = 0;
+ Array x;
+ for (i = 0; i < n; i++) {
+ x = xs[i];
+ shape[n - i - 1] = (int) x.getSize();
+ }
+
+ Array[] rs = new Array[n];
+ Array r;
+ int idx;
+ for (int s = 0; s < n; s++) {
+ x = xs[s];
+ r = Array.factory(xs[s].getDataType(), shape);
+ Index index = r.getIndex();
+ for (i = 0; i < r.getSize(); i++) {
+ idx = index.getCurrentCounter()[n - s - 1];
+ r.setObject(index, x.getObject(idx));
+ index.incr();
+ }
+ rs[s] = r;
+ }
+
+ return rs;
+ }
+
+ /**
+ * Create mesh polygon layer
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param ls Legend scheme
+ * @param lonlim Longiutde limitation - to avoid the polygon cross -180/180
+ * @return Mesh polygon layer
+ */
+ public static VectorLayer meshLayer(Array x_s, Array y_s, Array a, LegendScheme ls, double lonlim) {
+ VectorLayer layer = new VectorLayer(ShapeTypes.Polygon);
+ String fieldName = "Data";
+ Field aDC = new Field(fieldName, org.meteoinfo.ndarray.DataType.DOUBLE);
+ layer.editAddField(aDC);
+
+ int[] shape = x_s.getShape();
+ int colNum = shape[1];
+ int rowNum = shape[0];
+ double x1, x2, x3, x4;
+ for (int i = 0; i < rowNum - 1; i++) {
+ for (int j = 0; j < colNum - 1; j++) {
+ x1 = x_s.getDouble(i * colNum + j);
+ x2 = x_s.getDouble(i * colNum + j + 1);
+ x3 = x_s.getDouble((i + 1) * colNum + j);
+ x4 = x_s.getDouble((i + 1) * colNum + j + 1);
+ if (lonlim > 0) {
+ if (Math.abs(x2 - x4) > lonlim || Math.abs(x1 - x4) > lonlim
+ || Math.abs(x3 - x4) > lonlim || Math.abs(x1 - x2) > lonlim
+ || Math.abs(x2 - x3) > lonlim) {
+ continue;
+ }
+ }
+
+ PolygonShape ps = new PolygonShape();
+ List points = new ArrayList<>();
+ points.add(new PointD(x1, y_s.getDouble(i * colNum + j)));
+ points.add(new PointD(x3, y_s.getDouble((i + 1) * colNum + j)));
+ points.add(new PointD(x4, y_s.getDouble((i + 1) * colNum + j + 1)));
+ points.add(new PointD(x2, y_s.getDouble(i * colNum + j + 1)));
+ points.add((PointD) points.get(0).clone());
+ ps.setPoints(points);
+ ps.lowValue = a.getDouble(i * colNum + j);
+ ps.highValue = ps.lowValue;
+ int shapeNum = layer.getShapeNum();
+ try {
+ if (layer.editInsertShape(ps, shapeNum)) {
+ layer.editCellValue(fieldName, shapeNum, ps.lowValue);
+ }
+ } catch (Exception ex) {
+
+ }
+ }
+ }
+ layer.setLayerName("Mesh_Layer");
+ ls.setFieldName(fieldName);
+ layer.setLegendScheme(ls.convertTo(ShapeTypes.Polygon));
+
+ return layer;
+ }
+
+ /**
+ * Create mesh polygon layer
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param ls Legend scheme
+ * @return Mesh polygon layer
+ */
+ public static VectorLayer meshLayer(Array x_s, Array y_s, Array a, LegendScheme ls) {
+ VectorLayer layer = new VectorLayer(ShapeTypes.Polygon);
+ String fieldName = "Data";
+ Field aDC = new Field(fieldName, org.meteoinfo.ndarray.DataType.DOUBLE);
+ layer.editAddField(aDC);
+
+ int[] shape = x_s.getShape();
+ int colNum = shape[1];
+ int rowNum = shape[0];
+ double x1, x2, x3, x4;
+ for (int i = 0; i < rowNum - 1; i++) {
+ for (int j = 0; j < colNum - 1; j++) {
+ x1 = x_s.getDouble(i * colNum + j);
+ x2 = x_s.getDouble(i * colNum + j + 1);
+ x3 = x_s.getDouble((i + 1) * colNum + j);
+ x4 = x_s.getDouble((i + 1) * colNum + j + 1);
+ PolygonShape ps = new PolygonShape();
+ List points = new ArrayList<>();
+ points.add(new PointD(x1, y_s.getDouble(i * colNum + j)));
+ points.add(new PointD(x3, y_s.getDouble((i + 1) * colNum + j)));
+ points.add(new PointD(x4, y_s.getDouble((i + 1) * colNum + j + 1)));
+ points.add(new PointD(x2, y_s.getDouble(i * colNum + j + 1)));
+ points.add((PointD) points.get(0).clone());
+ ps.setPoints(points);
+ ps.lowValue = a.getDouble(i * colNum + j);
+ ps.highValue = ps.lowValue;
+ int shapeNum = layer.getShapeNum();
+ try {
+ if (layer.editInsertShape(ps, shapeNum)) {
+ layer.editCellValue(fieldName, shapeNum, ps.lowValue);
+ }
+ } catch (Exception ex) {
+
+ }
+ }
+ }
+ layer.setLayerName("Mesh_Layer");
+ ls.setFieldName(fieldName);
+ layer.setLegendScheme(ls.convertTo(ShapeTypes.Polygon));
+
+ return layer;
+ }
+
+ /**
+ * Smooth with 5 points
+ *
+ * @param a Array
+ * @param rowNum Row number
+ * @param colNum Column number
+ * @param unDefData Missing value
+ * @return Result array
+ */
+ public static Array smooth5(Array a, int rowNum, int colNum, double unDefData) {
+ Array r = Array.factory(a.getDataType(), a.getShape());
+ double s = 0.5;
+ if (Double.isNaN(unDefData)) {
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ if (i == 0 || i == rowNum - 1 || j == 0 || j == colNum - 1) {
+ r.setDouble(i * colNum + j, a.getDouble(i * colNum + j));
+ } else {
+ if (Double.isNaN(a.getDouble(i * colNum + j)) || Double.isNaN(a.getDouble((i + 1) * colNum + j)) || Double.isNaN(a.getDouble((i - 1) * colNum + j))
+ || Double.isNaN(a.getDouble(i * colNum + j + 1)) || Double.isNaN(a.getDouble(i * colNum + j - 1))) {
+ r.setDouble(i * colNum + j, a.getDouble(i * colNum + j));
+ continue;
+ }
+ r.setDouble(i * colNum + j, a.getDouble(i * colNum + j) + s / 4 * (a.getDouble((i + 1) * colNum + j) + a.getDouble((i - 1) * colNum + j) + a.getDouble(i * colNum + j + 1)
+ + a.getDouble(i * colNum + j - 1) - 4 * a.getDouble(i * colNum + j)));
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ if (i == 0 || i == rowNum - 1 || j == 0 || j == colNum - 1) {
+ r.setDouble(i * colNum + j, a.getDouble(i * colNum + j));
+ } else {
+ if (a.getDouble(i * colNum + j) == unDefData || a.getDouble((i + 1) * colNum + j) == unDefData || a.getDouble((i - 1) * colNum + j)
+ == unDefData || a.getDouble(i * colNum + j + 1) == unDefData || a.getDouble(i * colNum + j - 1) == unDefData) {
+ r.setDouble(i * colNum + j, a.getDouble(i * colNum + j));
+ continue;
+ }
+ r.setDouble(i * colNum + j, a.getDouble(i * colNum + j) + s / 4 * (a.getDouble((i + 1) * colNum + j) + a.getDouble((i - 1) * colNum + j) + a.getDouble(i * colNum + j + 1)
+ + a.getDouble(i * colNum + j - 1) - 4 * a.getDouble(i * colNum + j)));
+ }
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Smooth with 5 points
+ *
+ * @param a Array
+ * @return Result array
+ */
+ public static Array smooth5(Array a) {
+ int[] shape = a.getShape();
+ int colNum = shape[1];
+ int rowNum = shape[0];
+ Array r = Array.factory(a.getDataType(), shape);
+ Index2D index = new Index2D(shape);
+ double v, w;
+ double sum, wsum;
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ sum = 0;
+ wsum = 0;
+ for (int ii = i - 1; ii <= i + 1; ii++) {
+ if (ii < 0 || ii >= rowNum) {
+ continue;
+ }
+ for (int jj = j - 1; jj <= j + 1; jj++) {
+ if (jj < 0 || jj >= colNum) {
+ continue;
+ }
+ if ((ii == i - 1 || ii == i + 1) && jj != j) {
+ continue;
+ }
+ v = a.getDouble(index.set(ii, jj));
+ if (!Double.isNaN(v)) {
+ if (ii == i && jj == j) {
+ w = 1;
+ } else {
+ w = 0.5;
+ }
+ sum += v * w;
+ wsum += w;
+ }
+ }
+ }
+ index.set(i, j);
+ if (wsum > 0) {
+ r.setDouble(index, sum / wsum);
+ } else {
+ r.setDouble(index, Double.NaN);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Smooth with 9 points
+ *
+ * @param a Array
+ * @return Result array
+ */
+ public static Array smooth9(Array a) {
+ int[] shape = a.getShape();
+ int colNum = shape[1];
+ int rowNum = shape[0];
+ Array r = Array.factory(a.getDataType(), shape);
+ Index2D index = new Index2D(shape);
+ double v, w;
+ double sum, wsum;
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ sum = 0;
+ wsum = 0;
+ for (int ii = i - 1; ii <= i + 1; ii++) {
+ if (ii < 0 || ii >= rowNum) {
+ continue;
+ }
+ for (int jj = j - 1; jj <= j + 1; jj++) {
+ if (jj < 0 || jj >= colNum) {
+ continue;
+ }
+ v = a.getDouble(index.set(ii, jj));
+ if (!Double.isNaN(v)) {
+ if (ii == i && jj == j) {
+ w = 1;
+ } else {
+ if (ii == i || jj == j) {
+ w = 0.5;
+ } else {
+ w = 0.3;
+ }
+ }
+ sum += v * w;
+ wsum += w;
+ }
+ }
+ }
+ index.set(i, j);
+ if (wsum > 0) {
+ r.setDouble(index, sum / wsum);
+ } else {
+ r.setDouble(index, Double.NaN);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolation with IDW radius method
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X grid X array
+ * @param Y grid Y array
+ * @param neededPointNum needed at least point number
+ * @param radius search radius
+ * @return interpolated grid data
+ */
+ public static Array interpolation_IDW_Radius(List x_s, List y_s, Array a,
+ List X, List Y, int neededPointNum, double radius) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ int i, j;
+ double w, gx, gy, v;
+ boolean match;
+
+ //Construct K-D tree
+ int n = 0;
+ KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2);
+ for (i = 0; i < pNum; i++) {
+ if (!Double.isNaN(a.getDouble(i))) {
+ kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i));
+ n += 1;
+ }
+ }
+
+ //---- Do interpolation
+ for (i = 0; i < rowNum; i++) {
+ gy = Y.get(i).doubleValue();
+ for (j = 0; j < colNum; j++) {
+ gx = X.get(j).doubleValue();
+ List> srs = kdTree.ballSearch_distance(new double[]{gx, gy}, radius * radius);
+ if (srs == null || srs.size() < neededPointNum) {
+ r.setDouble(i * colNum + j, Double.NaN);
+ } else {
+ double v_sum = 0.0;
+ double weight_sum = 0.0;
+ match = false;
+ for (SearchResult sr : srs) {
+ v = (double) sr.payload;
+ if (sr.distance == 0) {
+ r.setDouble(i * colNum + j, v);
+ match = true;
+ break;
+ } else {
+ w = 1. / sr.distance;
+ weight_sum += w;
+ v_sum += v * w;
+ }
+ }
+ if (!match) {
+ r.setDouble(i * colNum + j, v_sum / weight_sum);
+ }
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolation with IDW radius method
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X grid X array
+ * @param Y grid Y array
+ * @param NeededPointNum needed at least point number
+ * @param radius search radius
+ * @return interpolated grid data
+ */
+ public static Array interpolation_IDW_Radius_bak(List x_s, List y_s, Array a,
+ List X, List Y, int NeededPointNum, double radius) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ //double[][] GCoords = new double[rowNum][colNum];
+ Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ int i, j, p, vNum;
+ double w, SV, SW;
+ boolean ifPointGrid;
+ double x, y, v;
+
+ //---- Do interpolation
+ for (i = 0; i < rowNum; i++) {
+ for (j = 0; j < colNum; j++) {
+ r.setDouble(i * colNum + j, Double.NaN);
+ ifPointGrid = false;
+ SV = 0;
+ SW = 0;
+ vNum = 0;
+ for (p = 0; p < pNum; p++) {
+ v = a.getDouble(p);
+ if (Double.isNaN(v)) {
+ continue;
+ }
+ x = x_s.get(p).doubleValue();
+ y = y_s.get(p).doubleValue();
+ if (x < X.get(j).doubleValue() - radius || x > X.get(j).doubleValue() + radius || y < Y.get(i).doubleValue() - radius
+ || y > Y.get(i).doubleValue() + radius) {
+ continue;
+ }
+
+ if (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2) == 0) {
+ r.setDouble(i * colNum + j, v);
+ ifPointGrid = true;
+ break;
+ } else if (Math.sqrt(Math.pow(X.get(j).doubleValue() - x, 2)
+ + Math.pow(Y.get(i).doubleValue() - y, 2)) <= radius) {
+ w = 1 / (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2));
+ SW = SW + w;
+ SV = SV + v * w;
+ vNum += 1;
+ }
+ }
+
+ if (!ifPointGrid) {
+ if (vNum >= NeededPointNum) {
+ r.setDouble(i * colNum + j, SV / SW);
+ }
+ }
+ }
+ }
+
+ //---- Smooth with 5 points
+ r = smooth5(r, rowNum, colNum, Double.NaN);
+
+ return r;
+ }
+
+ /**
+ * Interpolation with IDW neighbor method
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X grid X array
+ * @param Y grid Y array
+ * @param points Number of points used for interpolation
+ * @return interpolated grid data
+ */
+ public static Array interpolation_IDW_Neighbor(List x_s, List y_s, Array a,
+ List X, List Y, Integer points) {
+ int colNum = X.size();
+ int rowNum = Y.size();
+ int pNum = x_s.size();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ int i, j;
+ double w, v, gx, gy;
+ boolean match;
+
+ //Construct K-D tree
+ int n = 0;
+ KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2);
+ for (i = 0; i < pNum; i++) {
+ if (!Double.isNaN(a.getDouble(i))) {
+ kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i));
+ n += 1;
+ }
+ }
+ if (points == null) {
+ points = n;
+ }
+
+ //---- Do interpolation with IDW method
+ for (i = 0; i < rowNum; i++) {
+ gy = Y.get(i).doubleValue();
+ for (j = 0; j < colNum; j++) {
+ gx = X.get(j).doubleValue();
+ List> srs = kdTree.nearestNeighbours(new double[]{gx, gy}, points);
+ double v_sum = 0.0;
+ double weight_sum = 0.0;
+ match = false;
+ for (SearchResult sr : srs) {
+ v = (double) sr.payload;
+ if (sr.distance == 0) {
+ r.setDouble(i * colNum + j, v);
+ match = true;
+ break;
+ } else {
+ w = 1. / sr.distance;
+ weight_sum += w;
+ v_sum += v * w;
+ }
+ }
+ if (!match) {
+ r.setDouble(i * colNum + j, v_sum / weight_sum);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolation with IDW neighbor method
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X grid X array
+ * @param Y grid Y array
+ * @param NumberOfNearestNeighbors
+ * @return interpolated grid data
+ */
+ public static Array interpolation_IDW_Neighbor_bak(List x_s, List y_s, Array a,
+ List X, List Y, int NumberOfNearestNeighbors) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ int i, j, p, l, aP;
+ double w, SV, SW, aMin;
+ int points;
+ points = NumberOfNearestNeighbors;
+ double[] AllWeights = new double[pNum];
+ double[][] NW = new double[2][points];
+ int NWIdx;
+ double x, y, v;
+
+ //---- Do interpolation with IDW method
+ for (i = 0; i < rowNum; i++) {
+ for (j = 0; j < colNum; j++) {
+ r.setDouble(i * colNum + j, Double.NaN);
+ SV = 0;
+ SW = 0;
+ NWIdx = 0;
+ for (p = 0; p < pNum; p++) {
+ v = a.getDouble(p);
+ if (Double.isNaN(v)) {
+ AllWeights[p] = -1;
+ continue;
+ }
+ x = x_s.get(p).doubleValue();
+ y = y_s.get(p).doubleValue();
+ if (X.get(j).doubleValue() == x && Y.get(i).doubleValue() == y) {
+ r.setDouble(i * colNum + j, v);
+ break;
+ } else {
+ w = 1 / (Math.pow(X.get(j).doubleValue() - x, 2) + Math.pow(Y.get(i).doubleValue() - y, 2));
+ AllWeights[p] = w;
+ if (NWIdx < points) {
+ NW[0][NWIdx] = w;
+ NW[1][NWIdx] = p;
+ }
+ NWIdx += 1;
+ }
+ }
+
+ aMin = NW[0][0];
+ aP = 0;
+ for (l = 1; l < points; l++) {
+ if (NW[0][l] < aMin) {
+ aMin = NW[0][l];
+ aP = l;
+ }
+ }
+
+ if (Double.isNaN(r.getDouble(i * colNum + j))) {
+ for (p = 0; p < pNum; p++) {
+ w = AllWeights[p];
+ if (w == -1) {
+ continue;
+ }
+
+ if (w > aMin) {
+ NW[0][aP] = w;
+ NW[1][aP] = p;
+ aMin = NW[0][0];
+ aP = 0;
+ for (l = 1; l < points; l++) {
+ if (NW[0][l] < aMin) {
+ aMin = NW[0][l];
+ aP = l;
+ }
+ }
+ }
+ }
+ for (p = 0; p < points; p++) {
+ SV += NW[0][p] * a.getDouble((int) NW[1][p]);
+ SW += NW[0][p];
+ }
+ r.setDouble(i * colNum + j, SV / SW);
+ }
+ }
+ }
+
+ //---- Smooth with 5 points
+ r = smooth5(r, rowNum, colNum, Double.NaN);
+
+ return r;
+ }
+
+ /**
+ * Interpolate with nearest method
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @param radius Radius
+ * @return grid data
+ */
+ public static Array interpolation_Nearest(List x_s, List y_s, Array a, List X, List Y,
+ double radius) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ Array rdata = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ double gx, gy;
+
+ //Construct K-D tree
+ KDTree.Euclidean kdTree = new KDTree.Euclidean<>(2);
+ for (int i = 0; i < pNum; i++) {
+ if (!Double.isNaN(a.getDouble(i))) {
+ kdTree.addPoint(new double[]{x_s.get(i).doubleValue(), y_s.get(i).doubleValue()}, a.getDouble(i));
+ }
+ }
+
+ //Loop
+ if (radius == Double.POSITIVE_INFINITY) {
+ for (int i = 0; i < rowNum; i++) {
+ gy = Y.get(i).doubleValue();
+ for (int j = 0; j < colNum; j++) {
+ gx = X.get(j).doubleValue();
+ SearchResult r = kdTree.nearestNeighbours(new double[]{gx, gy}, 1).get(0);
+ rdata.setDouble(i * colNum + j, ((double) r.payload));
+ }
+ }
+ } else {
+ for (int i = 0; i < rowNum; i++) {
+ gy = Y.get(i).doubleValue();
+ for (int j = 0; j < colNum; j++) {
+ gx = X.get(j).doubleValue();
+ SearchResult r = kdTree.nearestNeighbours(new double[]{gx, gy}, 1).get(0);
+ if (Math.sqrt(r.distance) <= radius) {
+ rdata.setDouble(i * colNum + j, ((double) r.payload));
+ } else {
+ rdata.setDouble(i * colNum + j, Double.NaN);
+ }
+ }
+ }
+ }
+
+ return rdata;
+ }
+
+ /**
+ * Extend the grid to half cell, so the grid points are the centers of the
+ * cells
+ *
+ * @param x Input x coordinate
+ * @param y Input y coordinate
+ * @return Result x and y coordinates
+ */
+ public static Array[] extendHalfCell(Array x, Array y) {
+ double dX = x.getDouble(1) - x.getDouble(0);
+ double dY = y.getDouble(1) - y.getDouble(0);
+ int nx = (int) x.getSize() + 1;
+ int ny = (int) y.getSize() + 1;
+ Array rx = Array.factory(DataType.DOUBLE, new int[]{nx});
+ Array ry = Array.factory(DataType.DOUBLE, new int[]{ny});
+ for (int i = 0; i < rx.getSize(); i++) {
+ if (i == rx.getSize() - 1) {
+ rx.setDouble(i, x.getDouble(i - 1) + dX * 0.5);
+ } else {
+ rx.setDouble(i, x.getDouble(i) - dX * 0.5);
+ }
+ }
+
+ for (int i = 0; i < ry.getSize(); i++) {
+ if (i == ry.getSize() - 1) {
+ ry.setDouble(i, y.getDouble(i - 1) + dY * 0.5);
+ } else {
+ ry.setDouble(i, y.getDouble(i) - dY * 0.5);
+ }
+ }
+
+ return new Array[]{rx, ry};
+ }
+
+ /**
+ * Interpolate with inside method - The grid cell value is the average value
+ * of the inside points or fill value if no inside point.
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @param centerPoint the points locate at center or border or grid
+ * @return grid data
+ */
+ public static Array interpolation_Inside(List x_s, List y_s, Array a,
+ List X, List Y, boolean centerPoint) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
+ double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
+ int[][] pNums = new int[rowNum][colNum];
+ double x, y, v, sx, sy, ex, ey;
+ if (centerPoint) {
+ sx = X.get(0).doubleValue() - dX * 0.5;
+ sy = Y.get(0).doubleValue() - dY * 0.5;
+ ex = X.get(colNum - 1).doubleValue() + dX * 0.5;
+ ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5;
+ } else {
+ sx = X.get(0).doubleValue();
+ sy = Y.get(0).doubleValue();
+ ex = X.get(colNum - 1).doubleValue();
+ ey = Y.get(rowNum - 1).doubleValue();
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ pNums[i][j] = 0;
+ r.setDouble(i * colNum + j, 0.0);
+ }
+ }
+
+ for (int p = 0; p < pNum; p++) {
+ v = a.getDouble(p);
+ if (Double.isNaN(v)) {
+ continue;
+ }
+
+ x = x_s.get(p).doubleValue();
+ y = y_s.get(p).doubleValue();
+ if (x < sx || x > ex) {
+ continue;
+ }
+ if (y < sy || y > ey) {
+ continue;
+ }
+
+ int j = (int) ((x - sx) / dX);
+ int i = (int) ((y - sy) / dY);
+ pNums[i][j] += 1;
+ r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) + v);
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ if (pNums[i][j] == 0) {
+ r.setDouble(i * colNum + j, Double.NaN);
+ } else {
+ r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) / pNums[i][j]);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolate with inside method - The grid cell value is the average value
+ * of the inside points or fill value if no inside point.
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @param centerPoint If the grid point is center or border
+ * @return grid data
+ */
+ public static Array interpolation_Inside(Array x_s, Array y_s, Array a, Array X, Array Y,
+ boolean centerPoint) {
+ int rowNum, colNum, pNum;
+ colNum = (int) X.getSize();
+ rowNum = (int) Y.getSize();
+ pNum = (int) x_s.getSize();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ double dX = X.getDouble(1) - X.getDouble(0);
+ double dY = Y.getDouble(1) - Y.getDouble(0);
+ int[][] pNums = new int[rowNum][colNum];
+ double x, y, v, sx, sy, ex, ey;
+ if (centerPoint) {
+ sx = X.getDouble(0) - dX * 0.5;
+ sy = Y.getDouble(0) - dY * 0.5;
+ ex = X.getDouble(colNum - 1) + dX * 0.5;
+ ey = Y.getDouble(rowNum - 1) + dY * 0.5;
+ } else {
+ sx = X.getDouble(0);
+ sy = Y.getDouble(0);
+ ex = X.getDouble(colNum - 1);
+ ey = Y.getDouble(rowNum - 1);
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ pNums[i][j] = 0;
+ r.setDouble(i * colNum + j, 0.0);
+ }
+ }
+
+ for (int p = 0; p < pNum; p++) {
+ v = a.getDouble(p);
+ if (Double.isNaN(v)) {
+ continue;
+ }
+
+ x = x_s.getDouble(p);
+ y = y_s.getDouble(p);
+ if (x < sx || x > ex) {
+ continue;
+ }
+ if (y < sy || y > ey) {
+ continue;
+ }
+
+ int j = (int) ((x - sx) / dX);
+ int i = (int) ((y - sy) / dY);
+ pNums[i][j] += 1;
+ r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) + v);
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ if (pNums[i][j] == 0) {
+ r.setDouble(i * colNum + j, Double.NaN);
+ } else {
+ r.setDouble(i * colNum + j, r.getDouble(i * colNum + j) / pNums[i][j]);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolate with inside method - The grid cell value is the maximum value
+ * of the inside points or fill value if no inside point.
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @param centerPoint points locate at center or border of grid
+ * @return grid data
+ */
+ public static Array interpolation_Inside_Max(List x_s, List y_s, Array a,
+ List X, List Y, boolean centerPoint) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
+ double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
+ int[][] pNums = new int[rowNum][colNum];
+ double x, y, v, sx, sy, ex, ey;
+ double min = Double.NEGATIVE_INFINITY;
+ if (centerPoint) {
+ sx = X.get(0).doubleValue() - dX * 0.5;
+ sy = Y.get(0).doubleValue() - dY * 0.5;
+ ex = X.get(colNum - 1).doubleValue() + dX * 0.5;
+ ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5;
+ } else {
+ sx = X.get(0).doubleValue();
+ sy = Y.get(0).doubleValue();
+ ex = X.get(colNum - 1).doubleValue();
+ ey = Y.get(rowNum - 1).doubleValue();
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ pNums[i][j] = 0;
+ r.setDouble(i * colNum + j, min);
+ }
+ }
+
+ for (int p = 0; p < pNum; p++) {
+ v = a.getDouble(p);
+ if (Double.isNaN(v)) {
+ continue;
+ }
+
+ x = x_s.get(p).doubleValue();
+ y = y_s.get(p).doubleValue();
+ if (x < sx || x > ex) {
+ continue;
+ }
+ if (y < sy || y > ey) {
+ continue;
+ }
+
+ int j = (int) ((x - sx) / dX);
+ int i = (int) ((y - sy) / dY);
+ pNums[i][j] += 1;
+ r.setDouble(i * colNum + j, Math.max(r.getDouble(i * colNum + j), v));
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ if (pNums[i][j] == 0 || Double.isInfinite(r.getDouble(i * colNum + j))) {
+ r.setDouble(i * colNum + j, Double.NaN);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolate with inside method - The grid cell value is the minimum value
+ * of the inside points or fill value if no inside point.
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @param centerPoint points locate at center or border of grid
+ * @return grid data
+ */
+ public static Array interpolation_Inside_Min(List x_s, List y_s, Array a,
+ List X, List Y, boolean centerPoint) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{rowNum, colNum});
+ double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
+ double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
+ int[][] pNums = new int[rowNum][colNum];
+ double x, y, v, sx, sy, ex, ey;
+ double max = Double.MAX_VALUE;
+ if (centerPoint) {
+ sx = X.get(0).doubleValue() - dX * 0.5;
+ sy = Y.get(0).doubleValue() - dY * 0.5;
+ ex = X.get(colNum - 1).doubleValue() + dX * 0.5;
+ ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5;
+ } else {
+ sx = X.get(0).doubleValue();
+ sy = Y.get(0).doubleValue();
+ ex = X.get(colNum - 1).doubleValue();
+ ey = Y.get(rowNum - 1).doubleValue();
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ pNums[i][j] = 0;
+ r.setDouble(i * colNum + j, max);
+ }
+ }
+
+ for (int p = 0; p < pNum; p++) {
+ v = a.getDouble(p);
+ if (Double.isNaN(v)) {
+ continue;
+ }
+
+ x = x_s.get(p).doubleValue();
+ y = y_s.get(p).doubleValue();
+ if (x < sx || x > ex) {
+ continue;
+ }
+ if (y < sy || y > ey) {
+ continue;
+ }
+
+ int j = (int) ((x - sx) / dX);
+ int i = (int) ((y - sy) / dY);
+ pNums[i][j] += 1;
+ r.setDouble(i * colNum + j, Math.min(r.getDouble(i * colNum + j), v));
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ if (pNums[i][j] == 0 || r.getDouble(i * colNum + j) == Double.MAX_VALUE) {
+ r.setDouble(i * colNum + j, Double.NaN);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolate with inside method - The grid cell value is the count number
+ * of the inside points or fill value if no inside point.
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @param pointDensity If return point density value
+ * @param centerPoint points locate at center or border of grid
+ * @return grid data
+ */
+ public static Object interpolation_Inside_Count(List x_s, List y_s,
+ List X, List Y, boolean pointDensity, boolean centerPoint) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ Array r = Array.factory(DataType.INT, new int[]{rowNum, colNum});
+ double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
+ double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
+ int[][] pNums = new int[rowNum][colNum];
+ double x, y, sx, sy, ex, ey;
+ if (centerPoint) {
+ sx = X.get(0).doubleValue() - dX * 0.5;
+ sy = Y.get(0).doubleValue() - dY * 0.5;
+ ex = X.get(colNum - 1).doubleValue() + dX * 0.5;
+ ey = Y.get(rowNum - 1).doubleValue() + dY * 0.5;
+ } else {
+ sx = X.get(0).doubleValue();
+ sy = Y.get(0).doubleValue();
+ ex = X.get(colNum - 1).doubleValue();
+ ey = Y.get(rowNum - 1).doubleValue();
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ pNums[i][j] = 0;
+ //r.setInt(i * colNum + j, 0);
+ }
+ }
+
+ for (int p = 0; p < pNum; p++) {
+ x = x_s.get(p).doubleValue();
+ y = y_s.get(p).doubleValue();
+ if (x < sx || x > ex) {
+ continue;
+ }
+ if (y < sy || y > ey) {
+ continue;
+ }
+
+ int j = (int) ((x - sx) / dX);
+ int i = (int) ((y - sy) / dY);
+ pNums[i][j] += 1;
+ //r.setInt(i * colNum + j, r.getInt(i * colNum + j) + 1);
+ }
+
+ for (int i = 0; i < rowNum; i++) {
+ for (int j = 0; j < colNum; j++) {
+ r.setInt(i * colNum + j, pNums[i][j]);
+ }
+ }
+
+ if (pointDensity) {
+ Array pds = Array.factory(DataType.INT, new int[]{pNum});
+ for (int p = 0; p < pNum; p++) {
+ x = x_s.get(p).doubleValue();
+ y = y_s.get(p).doubleValue();
+ if (x < sx || x > ex) {
+ continue;
+ }
+ if (y < sy || y > ey) {
+ continue;
+ }
+
+ int j = (int) ((x - sx) / dX);
+ int i = (int) ((y - sy) / dY);
+ pds.setInt(p, pNums[i][j]);
+ }
+ return new Array[]{r, pds};
+ }
+
+ return r;
+ }
+
+ private static List getPointsIJ(List x_s, List y_s, List X, List Y) {
+ int rowNum, colNum, pNum;
+ colNum = X.size();
+ rowNum = Y.size();
+ pNum = x_s.size();
+ double dX = X.get(1).doubleValue() - X.get(0).doubleValue();
+ double dY = Y.get(1).doubleValue() - Y.get(0).doubleValue();
+ List pIndices = new ArrayList<>();
+ double x, y;
+ int i, j;
+ for (int p = 0; p < pNum; p++) {
+ x = x_s.get(p).doubleValue();
+ y = y_s.get(p).doubleValue();
+ if (x < X.get(0).doubleValue() || x > X.get(colNum - 1).doubleValue()) {
+ continue;
+ }
+ if (y < Y.get(0).doubleValue() || y > Y.get(rowNum - 1).doubleValue()) {
+ continue;
+ }
+
+ j = (int) ((x - X.get(0).doubleValue()) / dX);
+ i = (int) ((y - Y.get(0).doubleValue()) / dY);
+ pIndices.add(new int[]{i, j});
+ }
+
+ return pIndices;
+ }
+
+ private static List getPointsIdx(List pIJ, int ii, int jj, int radius) {
+ List pIdx = new ArrayList<>();
+ int[] ij;
+ int i, j;
+ for (int p = 0; p < pIJ.size(); p++) {
+ ij = pIJ.get(p);
+ i = ij[0];
+ j = ij[1];
+ if (Math.abs(i - ii) <= radius && Math.abs(j - jj) <= radius) {
+ pIdx.add(p);
+ }
+ }
+
+ return pIdx;
+ }
+
+ /**
+ * Interpolate with surface method
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @param unDefData undefine value
+ * @return grid data
+ */
+ public static Array interpolation_Surface_1(Array x_s, Array y_s, Array a, Array X, Array Y,
+ double unDefData) {
+ int rowNum, colNum, xn, yn;
+ int[] shape = x_s.getShape();
+ colNum = shape[1];
+ rowNum = shape[0];
+ xn = (int) X.getSize();
+ yn = (int) Y.getSize();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn});
+ double x, y;
+
+ PolygonShape[][] polygons = new PolygonShape[rowNum - 1][colNum - 1];
+ PolygonShape ps;
+ for (int i = 0; i < rowNum - 1; i++) {
+ for (int j = 0; j < colNum - 1; j++) {
+ ps = new PolygonShape();
+ List points = new ArrayList<>();
+ points.add(new PointD(x_s.getDouble(i * colNum + j), y_s.getDouble(i * colNum + j)));
+ points.add(new PointD(x_s.getDouble((i + 1) * colNum + j), y_s.getDouble((i + 1) * colNum + j)));
+ points.add(new PointD(x_s.getDouble((i + 1) * colNum + j + 1), y_s.getDouble((i + 1) * colNum + j + 1)));
+ points.add(new PointD(x_s.getDouble(i * colNum + j + 1), y_s.getDouble(i * colNum + j + 1)));
+ points.add((PointD) points.get(0).clone());
+ ps.setPoints(points);
+ polygons[i][j] = ps;
+ }
+ }
+
+ for (int i = 0; i < yn; i++) {
+ for (int j = 0; j < xn; j++) {
+ r.setDouble(i * xn + j, unDefData);
+ }
+ }
+
+ double v;
+ for (int i = 0; i < rowNum - 1; i++) {
+ for (int j = 0; j < colNum - 1; j++) {
+ ps = polygons[i][j];
+ v = a.getDouble(i * colNum + j);
+ for (int ii = 0; ii < yn; ii++) {
+ y = Y.getDouble(ii);
+ for (int jj = 0; jj < xn; jj++) {
+ x = X.getDouble(jj);
+ if (Double.isNaN(r.getDouble(ii * xn + jj)) || r.getDouble(ii * xn + jj) == unDefData) {
+ if (GeoComputation.pointInPolygon(ps, x, y)) {
+ r.setDouble(ii * xn + jj, v);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolate with surface method
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @return grid data
+ */
+ public static Array interpolation_Surface(Array x_s, Array y_s, Array a, Array X, Array Y) {
+ int rowNum, colNum, xn, yn;
+ int[] shape = x_s.getShape();
+ colNum = shape[1];
+ rowNum = shape[0];
+ xn = (int) X.getSize();
+ yn = (int) Y.getSize();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn});
+ for (int i = 0; i < r.getSize(); i++) {
+ r.setDouble(i, Double.NaN);
+ }
+
+ double x, y;
+ double v, xll, xtl, xtr, xlr, yll, ytl, ytr, ylr;
+ double dX = X.getDouble(1) - X.getDouble(0);
+ double dY = Y.getDouble(1) - Y.getDouble(0);
+ int minxi, maxxi, minyi, maxyi;
+ for (int i = 0; i < rowNum - 1; i++) {
+ for (int j = 0; j < colNum - 1; j++) {
+ v = a.getDouble(i * colNum + j);
+ if (Double.isNaN(v)) {
+ continue;
+ }
+ xll = x_s.getDouble(i * colNum + j);
+ xtl = x_s.getDouble((i + 1) * colNum + j);
+ xtr = x_s.getDouble((i + 1) * colNum + j + 1);
+ xlr = x_s.getDouble(i * colNum + j + 1);
+ yll = y_s.getDouble(i * colNum + j);
+ ytl = y_s.getDouble((i + 1) * colNum + j);
+ ytr = y_s.getDouble((i + 1) * colNum + j + 1);
+ ylr = y_s.getDouble(i * colNum + j + 1);
+ if (Double.isNaN(xll) || Double.isNaN(xtl) || Double.isNaN(xtr) || Double.isNaN(xlr)
+ || Double.isNaN(yll) || Double.isNaN(ytl) || Double.isNaN(ytr) || Double.isNaN(ylr)) {
+ continue;
+ }
+ PolygonShape ps = new PolygonShape();
+ List points = new ArrayList<>();
+ points.add(new PointD(xll, yll));
+ points.add(new PointD(xtl, ytl));
+ points.add(new PointD(xtr, ytr));
+ points.add(new PointD(xlr, ylr));
+ points.add((PointD) points.get(0).clone());
+ ps.setPoints(points);
+ minxi = (int) ((ps.getExtent().minX - X.getDouble(0)) / dX);
+ maxxi = (int) ((ps.getExtent().maxX - X.getDouble(0)) / dX);
+ minyi = (int) ((ps.getExtent().minY - Y.getDouble(0)) / dY);
+ maxyi = (int) ((ps.getExtent().maxY - Y.getDouble(0)) / dY);
+ maxxi += 1;
+ maxyi += 1;
+ if (maxxi < 0 || minxi >= xn) {
+ continue;
+ }
+ if (maxyi < 0 || minyi >= yn) {
+ continue;
+ }
+ if (minxi < 0) {
+ minxi = 0;
+ }
+ if (maxxi >= xn) {
+ maxxi = xn - 1;
+ }
+ if (maxyi >= yn) {
+ maxyi = yn - 1;
+ }
+ for (int m = minyi; m <= maxyi; m++) {
+ y = Y.getDouble(m);
+ for (int n = minxi; n <= maxxi; n++) {
+ x = X.getDouble(n);
+ if (GeoComputation.pointInPolygon(ps, x, y)) {
+ r.setDouble(m * xn + n, v);
+ }
+ }
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolate with surface method
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param a scatter value array
+ * @param X x coordinate
+ * @param Y y coordinate
+ * @return grid data
+ */
+ public static Array interpolation_Surface_bak(Array x_s, Array y_s, Array a, Array X, Array Y) {
+ int rowNum, colNum, xn, yn;
+ int[] shape = x_s.getShape();
+ colNum = shape[1];
+ rowNum = shape[0];
+ xn = (int) X.getSize();
+ yn = (int) Y.getSize();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn});
+ double x, y;
+ boolean isIn;
+
+ PolygonShape[][] polygons = new PolygonShape[rowNum - 1][colNum - 1];
+ for (int i = 0; i < rowNum - 1; i++) {
+ for (int j = 0; j < colNum - 1; j++) {
+ PolygonShape ps = new PolygonShape();
+ List points = new ArrayList<>();
+ points.add(new PointD(x_s.getDouble(i * colNum + j), y_s.getDouble(i * colNum + j)));
+ points.add(new PointD(x_s.getDouble((i + 1) * colNum + j), y_s.getDouble((i + 1) * colNum + j)));
+ points.add(new PointD(x_s.getDouble((i + 1) * colNum + j + 1), y_s.getDouble((i + 1) * colNum + j + 1)));
+ points.add(new PointD(x_s.getDouble(i * colNum + j + 1), y_s.getDouble(i * colNum + j + 1)));
+ points.add((PointD) points.get(0).clone());
+ ps.setPoints(points);
+ polygons[i][j] = ps;
+ }
+ }
+
+ for (int i = 0; i < yn; i++) {
+ y = Y.getDouble(i);
+ for (int j = 0; j < xn; j++) {
+ x = X.getDouble(j);
+ isIn = false;
+ for (int ii = 0; ii < rowNum - 1; ii++) {
+ for (int jj = 0; jj < colNum - 1; jj++) {
+ if (GeoComputation.pointInPolygon(polygons[ii][jj], x, y)) {
+ r.setDouble(i * xn + j, a.getDouble(ii * colNum + jj));
+ isIn = true;
+ break;
+ }
+ }
+ if (isIn) {
+ break;
+ }
+ }
+ if (!isIn) {
+ r.setDouble(i * xn + j, Double.NaN);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Cressman analysis
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param v_s scatter value array
+ * @param X x array
+ * @param Y y array
+ * @param radList radii list
+ * @return result grid data
+ */
+ public static Array cressman(List x_s, List y_s, Array v_s, List X, List Y,
+ List radList) {
+ int xNum = X.size();
+ int yNum = Y.size();
+ int pNum = x_s.size();
+ //double[][] gridData = new double[yNum][xNum];
+ Array r = Array.factory(DataType.DOUBLE, new int[]{yNum, xNum});
+ int irad = radList.size();
+ int i, j;
+
+ //Loop through each stn report and convert stn lat/lon to grid coordinates
+ double xMin = X.get(0).doubleValue();
+ double xMax = X.get(xNum - 1).doubleValue();
+ double yMin = Y.get(0).doubleValue();
+ double yMax = Y.get(yNum - 1).doubleValue();
+ double xDelt = X.get(1).doubleValue() - X.get(0).doubleValue();
+ double yDelt = Y.get(1).doubleValue() - Y.get(0).doubleValue();
+ double x, y;
+ double sum;
+ int stNum = 0;
+ double[][] stationData = new double[pNum][3];
+ for (i = 0; i < pNum; i++) {
+ x = x_s.get(i).doubleValue();
+ y = y_s.get(i).doubleValue();
+ stationData[i][0] = (x - xMin) / xDelt;
+ stationData[i][1] = (y - yMin) / yDelt;
+ stationData[i][2] = v_s.getDouble(i);
+ if (!Double.isNaN(stationData[i][2])) {
+ //total += stationData[i][2];
+ stNum += 1;
+ }
+ }
+ //total = total / stNum;
+
+ double HITOP = -999900000000000000000.0;
+ double HIBOT = 999900000000000000000.0;
+ double[][] TOP = new double[yNum][xNum];
+ double[][] BOT = new double[yNum][xNum];
+ for (i = 0; i < yNum; i++) {
+ for (j = 0; j < xNum; j++) {
+ TOP[i][j] = HITOP;
+ BOT[i][j] = HIBOT;
+ }
+ }
+
+ //Initial grid values are average of station reports within the first radius
+ double val, sx, sy, sxi, syi;
+ double rad;
+ if (radList.size() > 0) {
+ rad = radList.get(0).doubleValue();
+ } else {
+ rad = 4;
+ }
+ for (i = 0; i < yNum; i++) {
+ y = Y.get(i).doubleValue();
+ yMin = y - rad;
+ yMax = y + rad;
+ for (j = 0; j < xNum; j++) {
+ x = X.get(j).doubleValue();
+ xMin = x - rad;
+ xMax = x + rad;
+ stNum = 0;
+ sum = 0;
+ for (int s = 0; s < pNum; s++) {
+ val = stationData[s][2];
+ sx = x_s.get(s).doubleValue();
+ sy = y_s.get(s).doubleValue();
+ sxi = stationData[s][0];
+ syi = stationData[s][1];
+ if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
+ continue;
+ }
+
+ double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
+ if (dis > rad) {
+ continue;
+ }
+
+ sum += val;
+ stNum += 1;
+ if (TOP[i][j] < val) {
+ TOP[i][j] = val;
+ }
+ if (BOT[i][j] > val) {
+ BOT[i][j] = val;
+ }
+ }
+ if (stNum == 0) {
+ r.setDouble(i * xNum + j, Double.NaN);
+ } else {
+ r.setDouble(i * xNum + j, sum / stNum);
+ }
+ }
+ }
+
+ //Perform the objective analysis
+ for (int p = 0; p < irad; p++) {
+ rad = radList.get(p).doubleValue();
+ for (i = 0; i < yNum; i++) {
+ y = Y.get(i).doubleValue();
+ yMin = y - rad;
+ yMax = y + rad;
+ for (j = 0; j < xNum; j++) {
+ if (Double.isNaN(r.getDouble(i * xNum + j))) {
+ continue;
+ }
+
+ x = X.get(j).doubleValue();
+ xMin = x - rad;
+ xMax = x + rad;
+ sum = 0;
+ double wSum = 0;
+ for (int s = 0; s < pNum; s++) {
+ val = stationData[s][2];
+ sx = x_s.get(s).doubleValue();
+ sy = y_s.get(s).doubleValue();
+ sxi = stationData[s][0];
+ syi = stationData[s][1];
+ if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
+ continue;
+ }
+
+ double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
+ if (dis > rad) {
+ continue;
+ }
+
+ int i1 = (int) syi;
+ int j1 = (int) sxi;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+ double a = r.getDouble(i1 * xNum + j1);
+ double b = r.getDouble(i1 * xNum + j2);
+ double c = r.getDouble(i2 * xNum + j1);
+ double d = r.getDouble(i2 * xNum + j2);
+ List dList = new ArrayList<>();
+ if (!Double.isNaN(a)) {
+ dList.add(a);
+ }
+ if (!Double.isNaN(b)) {
+ dList.add(b);
+ }
+ if (!Double.isNaN(c)) {
+ dList.add(c);
+ }
+ if (Double.isNaN(d)) {
+ dList.add(d);
+ }
+
+ double calVal;
+ if (dList.isEmpty()) {
+ continue;
+ } else if (dList.size() == 1) {
+ calVal = dList.get(0);
+ } else if (dList.size() <= 3) {
+ double aSum = 0;
+ for (double dd : dList) {
+ aSum += dd;
+ }
+ calVal = aSum / dList.size();
+ } else {
+ double x1val = a + (c - a) * (syi - i1);
+ double x2val = b + (d - b) * (syi - i1);
+ calVal = x1val + (x2val - x1val) * (sxi - j1);
+ }
+ double eVal = val - calVal;
+ double w = (rad * rad - dis * dis) / (rad * rad + dis * dis);
+ sum += eVal * w;
+ wSum += w;
+ }
+// if (wSum < 0.000001) {
+// r.setDouble(i * xNum + j, Double.NaN);
+// } else {
+// double aData = r.getDouble(i * xNum + j) + sum / wSum;
+// r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData)));
+// }
+ if (wSum >= 0.000001) {
+ double aData = r.getDouble(i * xNum + j) + sum / wSum;
+ r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData)));
+ }
+ }
+ }
+ }
+
+ //Return
+ return r;
+ }
+
+ /**
+ * Cressman analysis
+ *
+ * @param x_s scatter X array
+ * @param y_s scatter Y array
+ * @param v_s scatter value array
+ * @param X x array
+ * @param Y y array
+ * @param radList radii list
+ * @return result grid data
+ */
+ public static Array cressman_bak(List x_s, List y_s, Array v_s, List X, List Y,
+ List radList) {
+ int xNum = X.size();
+ int yNum = Y.size();
+ int pNum = x_s.size();
+ //double[][] gridData = new double[yNum][xNum];
+ Array r = Array.factory(DataType.DOUBLE, new int[]{yNum, xNum});
+ int irad = radList.size();
+ int i, j;
+
+ //Loop through each stn report and convert stn lat/lon to grid coordinates
+ double xMin = X.get(0).doubleValue();
+ double xMax;
+ double yMin = Y.get(0).doubleValue();
+ double yMax;
+ double xDelt = X.get(1).doubleValue() - X.get(0).doubleValue();
+ double yDelt = Y.get(1).doubleValue() - Y.get(0).doubleValue();
+ double x, y;
+ double sum;
+ int stNum = 0;
+ double[][] stationData = new double[pNum][3];
+ for (i = 0; i < pNum; i++) {
+ x = x_s.get(i).doubleValue();
+ y = y_s.get(i).doubleValue();
+ stationData[i][0] = (x - xMin) / xDelt;
+ stationData[i][1] = (y - yMin) / yDelt;
+ stationData[i][2] = v_s.getDouble(i);
+ if (!Double.isNaN(stationData[i][2])) {
+ //total += stationData[i][2];
+ stNum += 1;
+ }
+ }
+ //total = total / stNum;
+
+ double HITOP = -999900000000000000000.0;
+ double HIBOT = 999900000000000000000.0;
+ double[][] TOP = new double[yNum][xNum];
+ double[][] BOT = new double[yNum][xNum];
+ for (i = 0; i < yNum; i++) {
+ for (j = 0; j < xNum; j++) {
+ TOP[i][j] = HITOP;
+ BOT[i][j] = HIBOT;
+ }
+ }
+
+ //Initial grid values are average of station reports within the first radius
+ double rad;
+ if (radList.size() > 0) {
+ rad = radList.get(0).doubleValue();
+ } else {
+ rad = 4;
+ }
+ for (i = 0; i < yNum; i++) {
+ y = (double) i;
+ yMin = y - rad;
+ yMax = y + rad;
+ for (j = 0; j < xNum; j++) {
+ x = (double) j;
+ xMin = x - rad;
+ xMax = x + rad;
+ stNum = 0;
+ sum = 0;
+ for (int s = 0; s < pNum; s++) {
+ double val = stationData[s][2];
+ double sx = stationData[s][0];
+ double sy = stationData[s][1];
+ if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) {
+ continue;
+ }
+
+ if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
+ continue;
+ }
+
+ double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
+ if (dis > rad) {
+ continue;
+ }
+
+ sum += val;
+ stNum += 1;
+ if (TOP[i][j] < val) {
+ TOP[i][j] = val;
+ }
+ if (BOT[i][j] > val) {
+ BOT[i][j] = val;
+ }
+ }
+ if (stNum == 0) {
+ r.setDouble(i * xNum + j, Double.NaN);
+ } else {
+ r.setDouble(i * xNum + j, sum / stNum);
+ }
+ }
+ }
+
+ //Perform the objective analysis
+ for (int p = 0; p < irad; p++) {
+ rad = radList.get(p).doubleValue();
+ for (i = 0; i < yNum; i++) {
+ y = (double) i;
+ yMin = y - rad;
+ yMax = y + rad;
+ for (j = 0; j < xNum; j++) {
+ if (Double.isNaN(r.getDouble(i * xNum + j))) {
+ continue;
+ }
+
+ x = (double) j;
+ xMin = x - rad;
+ xMax = x + rad;
+ sum = 0;
+ double wSum = 0;
+ for (int s = 0; s < pNum; s++) {
+ double val = stationData[s][2];
+ double sx = stationData[s][0];
+ double sy = stationData[s][1];
+ if (sx < 0 || sx >= xNum - 1 || sy < 0 || sy >= yNum - 1) {
+ continue;
+ }
+
+ if (Double.isNaN(val) || sx < xMin || sx > xMax || sy < yMin || sy > yMax) {
+ continue;
+ }
+
+ double dis = Math.sqrt(Math.pow(sx - x, 2) + Math.pow(sy - y, 2));
+ if (dis > rad) {
+ continue;
+ }
+
+ int i1 = (int) sy;
+ int j1 = (int) sx;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+ double a = r.getDouble(i1 * xNum + j1);
+ double b = r.getDouble(i1 * xNum + j2);
+ double c = r.getDouble(i2 * xNum + j1);
+ double d = r.getDouble(i2 * xNum + j2);
+ List dList = new ArrayList<>();
+ if (!Double.isNaN(a)) {
+ dList.add(a);
+ }
+ if (!Double.isNaN(b)) {
+ dList.add(b);
+ }
+ if (!Double.isNaN(c)) {
+ dList.add(c);
+ }
+ if (Double.isNaN(d)) {
+ dList.add(d);
+ }
+
+ double calVal;
+ if (dList.isEmpty()) {
+ continue;
+ } else if (dList.size() == 1) {
+ calVal = dList.get(0);
+ } else if (dList.size() <= 3) {
+ double aSum = 0;
+ for (double dd : dList) {
+ aSum += dd;
+ }
+ calVal = aSum / dList.size();
+ } else {
+ double x1val = a + (c - a) * (sy - i1);
+ double x2val = b + (d - b) * (sy - i1);
+ calVal = x1val + (x2val - x1val) * (sx - j1);
+ }
+ double eVal = val - calVal;
+ double w = (rad * rad - dis * dis) / (rad * rad + dis * dis);
+ sum += eVal * w;
+ wSum += w;
+ }
+ if (wSum < 0.000001) {
+ r.setDouble(i * xNum + j, Double.NaN);
+ } else {
+ double aData = r.getDouble(i * xNum + j) + sum / wSum;
+ r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData)));
+ }
+// if (wSum >= 0.000001) {
+// double aData = r.getDouble(i * xNum + j) + sum / wSum;
+// r.setDouble(i * xNum + j, Math.max(BOT[i][j], Math.min(TOP[i][j], aData)));
+// }
+ }
+ }
+ }
+
+ //Return
+ return r;
+ }
+
+ /**
+ * Interpolates from a rectilinear grid to another rectilinear grid using
+ * bilinear interpolation.
+ *
+ * @param a The sample array
+ * @param X X coordinate of the sample array
+ * @param Y Y coordinate of the sample array
+ * @param newX X coordinate of the query points
+ * @param newY Y coordinate of the query points
+ * @return Resampled array
+ */
+ public static Array linint2(Array a, Array X, Array Y, Array newX, Array newY) {
+ int xn = (int) newX.getSize();
+ int yn = (int) newY.getSize();
+ int[] shape = a.getShape();
+ int n = shape.length;
+ shape[n - 1] = xn;
+ shape[n - 2] = yn;
+ double x, y, v;
+ Array r = Array.factory(DataType.DOUBLE, shape);
+
+ Index index = r.getIndex();
+ int[] counter;
+ int yi, xi;
+ for (int k = 0; k < r.getSize(); k++) {
+ counter = index.getCurrentCounter();
+ yi = counter[n - 2];
+ xi = counter[n - 1];
+ y = newY.getDouble(yi);
+ x = newX.getDouble(xi);
+ v = bilinear(a, index, X, Y, x, y);
+ r.setDouble(index, v);
+ index.incr();
+ }
+
+ return r;
+ }
+
+ /**
+ * Resample grid array with bilinear method
+ *
+ * @param a The sample array
+ * @param X X coordinate of the sample array
+ * @param Y Y coordinate of the sample array
+ * @param newX X coordinate of the query points
+ * @param newY Y coordinate of the query points
+ * @return Resampled array
+ */
+ public static Array resample_Bilinear(Array a, List X, List Y, List newX, List newY) {
+ int i, j;
+ int xn = newX.size();
+ int yn = newY.size();
+ double x, y, v;
+ Array r = Array.factory(DataType.DOUBLE, new int[]{yn, xn});
+
+ for (i = 0; i < yn; i++) {
+ y = newY.get(i).doubleValue();
+ for (j = 0; j < xn; j++) {
+ x = newX.get(j).doubleValue();
+ if (x < X.get(0).doubleValue() || x > X.get(X.size() - 1).doubleValue()) {
+ r.setDouble(i * xn + j, Double.NaN);
+ } else if (y < Y.get(0).doubleValue() || y > Y.get(Y.size() - 1).doubleValue()) {
+ r.setDouble(i * xn + j, Double.NaN);
+ } else {
+ v = toStation(a, X, Y, x, y);
+ r.setDouble(i * xn + j, v);
+ }
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Resample grid array with bilinear method
+ *
+ * @param a The sample array
+ * @param X X coordinate of the sample array
+ * @param Y Y coordinate of the sample array
+ * @param newX X coordinate of the query points
+ * @param newY Y coordinate of the query points
+ * @return Resampled array
+ */
+ public static Array resample_Bilinear(Array a, Array X, Array Y, Array newX, Array newY) {
+ int i;
+ int n = (int) newX.getSize();
+ double x, y, v;
+ Array r = Array.factory(DataType.DOUBLE, newX.getShape());
+
+ for (i = 0; i < n; i++) {
+ x = newX.getDouble(i);
+ y = newY.getDouble(i);
+ if (x < X.getDouble(0) || x > X.getDouble((int) X.getSize() - 1)) {
+ r.setDouble(i, Double.NaN);
+ } else if (y < Y.getDouble(0) || y > Y.getDouble((int) Y.getSize() - 1)) {
+ r.setDouble(i, Double.NaN);
+ } else {
+ v = toStation(a, X, Y, x, y);
+ r.setDouble(i, v);
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Resample grid array with neighbor method
+ *
+ * @param a The sample array
+ * @param X X coordinate of the sample array
+ * @param Y Y coordinate of the sample array
+ * @param newX X coordinate of the query points
+ * @param newY Y coordinate of the query points
+ * @return Resampled array
+ */
+ public static Array resample_Neighbor(Array a, Array X, Array Y, Array newX, Array newY) {
+ int i;
+ int n = (int) newX.getSize();
+ double x, y, v;
+ Array r = Array.factory(DataType.DOUBLE, newX.getShape());
+
+ for (i = 0; i < n; i++) {
+ x = newX.getDouble(i);
+ y = newY.getDouble(i);
+ if (x < X.getDouble(0) || x > X.getDouble((int) X.getSize() - 1)) {
+ r.setDouble(i, Double.NaN);
+ } else if (y < Y.getDouble(0) || y > Y.getDouble((int) Y.getSize() - 1)) {
+ r.setDouble(i, Double.NaN);
+ } else {
+ v = toStation_Neighbor(a, X, Y, x, y);
+ r.setDouble(i, v);
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolate array data
+ *
+ * @param a Array
+ * @param X X coordinates
+ * @param Y Y coordinates
+ * @return Result array data
+ */
+ public Array interpolate(Array a, List X, List Y) {
+ int nxNum = X.size() * 2 - 1;
+ int nyNum = Y.size() * 2 - 1;
+ List newX = new ArrayList<>();
+ List newY = new ArrayList<>();
+ int i;
+
+ for (i = 0; i < nxNum; i++) {
+ if (i % 2 == 0) {
+ newX.add(X.get(i / 2).doubleValue());
+ } else {
+ newX.add((X.get((i - 1) / 2).doubleValue() + X.get((i - 1) / 2 + 1).doubleValue()) / 2);
+ }
+ }
+ for (i = 0; i < nyNum; i++) {
+ if (i % 2 == 0) {
+ newY.add(Y.get(i / 2).doubleValue());
+ } else {
+ newY.add((Y.get((i - 1) / 2).doubleValue() + Y.get((i - 1) / 2 + 1).doubleValue()) / 2);
+ }
+ }
+
+ return resample_Bilinear(a, X, Y, newX, newY);
+ }
+
+ /**
+ * Multidimensional interpolation on regular grids.
+ *
+ * @param points The points defining the regular grid in n dimensions.
+ * @param values The data on the regular grid in n dimensions.
+ * @param xi The coordinates to sample the gridded data at
+ * @return Interpolation value
+ */
+ public static double interpn_s(List> points, Array values, List xi) {
+ Object[] r = findIndices(points, xi);
+ boolean outBounds = (boolean) r[2];
+ if (outBounds) {
+ return Double.NaN;
+ } else {
+ double v, weight;
+ Index index = values.getIndex();
+ int[] indices = (int[]) r[0];
+ double[] distances = (double[]) r[1];
+ v = 0;
+ List ii = new ArrayList<>();
+ iterIndex(ii, index, indices, 0);
+ int n = indices.length;
+ for (Index idx : ii) {
+ weight = 1;
+ for (int i = 0; i < n; i++) {
+ weight *= idx.getCurrentCounter()[i] == indices[i] ? 1 - distances[i] : distances[i];
+ }
+ v += values.getDouble(idx) * weight;
+ }
+
+ return v;
+ }
+ }
+
+ /**
+ * Multidimensional interpolation on regular grids.
+ *
+ * @param points The points defining the regular grid in n dimensions.
+ * @param values The data on the regular grid in n dimensions.
+ * @param xi The coordinates to sample the gridded data at
+ * @return Interpolation value
+ */
+ public static double interpn_s(List points, Array values, Array xi) {
+ Object[] r = findIndices(points, xi);
+ boolean outBounds = (boolean) r[2];
+ if (outBounds) {
+ return Double.NaN;
+ } else {
+ double v, weight;
+ Index index = values.getIndex();
+ int[] indices = (int[]) r[0];
+ double[] distances = (double[]) r[1];
+ v = 0;
+ List ii = new ArrayList<>();
+ iterIndex(ii, index, indices, 0);
+ int n = indices.length;
+ for (Index idx : ii) {
+ weight = 1;
+ for (int i = 0; i < n; i++) {
+ weight *= idx.getCurrentCounter()[i] == indices[i] ? 1 - distances[i] : distances[i];
+ }
+ v += values.getDouble(idx) * weight;
+ }
+
+ return v;
+ }
+ }
+
+ /**
+ * Multidimensional interpolation on regular grids.
+ *
+ * @param points The points defining the regular grid in n dimensions.
+ * @param values The data on the regular grid in n dimensions.
+ * @param xi The coordinates to sample the gridded data at - 2D
+ * @return Interpolation value
+ */
+ public static Array interpn(List points, Array values, List xi) {
+ int n = xi.size();
+ Array r = Array.factory(DataType.DOUBLE, new int[]{n});
+ for (int i = 0; i < n; i++) {
+ Array x = xi.get(i);
+ r.setDouble(i, interpn_s(points, values, x));
+ }
+
+ return r;
+ }
+
+ /**
+ * Multidimensional interpolation on regular grids.
+ *
+ * @param points The points defining the regular grid in n dimensions.
+ * @param values The data on the regular grid in n dimensions.
+ * @param xi The coordinates to sample the gridded data at - 2D
+ * @return Interpolation value
+ * @throws org.meteoinfo.ndarray.InvalidRangeException
+ */
+ public static Object interpn(List points, Array values, Array xi) throws InvalidRangeException {
+ if (xi.getRank() == 1) {
+ return interpn_s(points, values, xi);
+ }
+
+ int n = xi.getShape()[0];
+ int m = xi.getShape()[1];
+ Array r = Array.factory(DataType.DOUBLE, new int[]{n});
+ for (int i = 0; i < n; i++) {
+ Array x = xi.section(new int[]{i, 0}, new int[]{1, m});
+ r.setDouble(i, interpn_s(points, values, x));
+ }
+
+ return r;
+ }
+
+ private static void iterIndex(List ii, Index index, int[] indices, int idx) {
+ int n = indices.length;
+ if (idx < n - 1) {
+ index.setDim(idx, indices[idx]);
+ iterIndex(ii, index, indices, idx + 1);
+ index.setDim(idx, indices[idx] + 1);
+ iterIndex(ii, index, indices, idx + 1);
+ } else {
+ index.setDim(idx, indices[idx]);
+ ii.add((Index) index.clone());
+ //System.out.println(index);
+ index.setDim(idx, indices[idx] + 1);
+ ii.add((Index) index.clone());
+ //System.out.println(index);
+ }
+ }
+
+ /**
+ * Find indices
+ *
+ * @param points The points defining the regular grid in n dimensions.
+ * @param xi The coordinates to sample the gridded data at
+ * @return Indices
+ */
+ public static Object[] findIndices(List> points, List xi) {
+ int n = points.size();
+ int[] indices = new int[n];
+ double[] distances = new double[n];
+ boolean outBounds = false;
+ double x;
+ List a;
+ for (int i = 0; i < n; i++) {
+ x = xi.get(i).doubleValue();
+ a = points.get(i);
+ int idx = searchSorted(a, x);
+ if (idx < 0) {
+ outBounds = true;
+ idx = 0;
+ }
+ indices[i] = idx;
+ distances[i] = (x - a.get(idx).doubleValue()) / (a.get(idx + 1).doubleValue() - a.get(idx).doubleValue());
+ }
+
+ return new Object[]{indices, distances, outBounds};
+ }
+
+ /**
+ * Find indices
+ *
+ * @param points The points defining the regular grid in n dimensions.
+ * @param xi The coordinates to sample the gridded data at
+ * @return Indices
+ */
+ public static Object[] findIndices(List points, Array xi) {
+ int n = points.size();
+ int[] indices = new int[n];
+ double[] distances = new double[n];
+ boolean outBounds = false;
+ double x;
+ Array a;
+ for (int i = 0; i < n; i++) {
+ x = xi.getDouble(i);
+ a = points.get(i);
+ int idx = searchSorted(a, x);
+ if (idx < 0) {
+ outBounds = true;
+ idx = 0;
+ }
+ indices[i] = idx;
+ distances[i] = (x - a.getDouble(idx)) / (a.getDouble(idx + 1) - a.getDouble(idx));
+ }
+
+ return new Object[]{indices, distances, outBounds};
+ }
+
+ /**
+ * Search sorted list index
+ *
+ * @param a Sorted list
+ * @param v value
+ * @return Index
+ */
+ public static int searchSorted(List a, double v) {
+ int idx = -1;
+ int n = a.size();
+ if (a.get(1).doubleValue() > a.get(0).doubleValue()) {
+ if (v < a.get(0).doubleValue()) {
+ return idx;
+ }
+
+ if (v > a.get(n - 1).doubleValue()) {
+ return idx;
+ }
+
+ for (int i = 1; i < n; i++) {
+ if (v < a.get(i).doubleValue()) {
+ idx = i - 1;
+ break;
+ }
+ }
+ } else {
+ if (v > a.get(0).doubleValue()) {
+ return idx;
+ }
+
+ if (v < a.get(n - 1).doubleValue()) {
+ return idx;
+ }
+
+ for (int i = 1; i < n; i++) {
+ if (v > a.get(i).doubleValue()) {
+ idx = i - 1;
+ break;
+ }
+ }
+ }
+
+ return idx;
+ }
+
+ /**
+ * Search sorted list index
+ *
+ * @param a Sorted list
+ * @param v value
+ * @return Index
+ */
+ public static int searchSorted(Array a, double v) {
+ int idx = -1;
+ int n = (int) a.getSize();
+ if (a.getDouble(1) > a.getDouble(0)) {
+ if (v < a.getDouble(0)) {
+ return idx;
+ }
+
+ if (v > a.getDouble(n - 1)) {
+ return idx;
+ }
+
+ for (int i = 1; i < n; i++) {
+ if (v < a.getDouble(i)) {
+ idx = i - 1;
+ break;
+ }
+ }
+ } else {
+ if (v > a.getDouble(0)) {
+ return idx;
+ }
+
+ if (v < a.getDouble(n - 1)) {
+ return idx;
+ }
+
+ for (int i = 1; i < n; i++) {
+ if (v > a.getDouble(i)) {
+ idx = i - 1;
+ break;
+ }
+ }
+ }
+
+ return idx;
+ }
+
+// /**
+// * Search sorted list index
+// *
+// * @param a Sorted list
+// * @param v value
+// * @return Index
+// */
+// public static int searchSorted(Array a, double v) {
+// if (v < a.getDouble(0) || v > a.getDouble((int)a.getSize() - 1)) {
+// return -1;
+// }
+//
+// int idx = Arrays.binarySearch((double[])a.get1DJavaArray(double.class), v);
+// if (idx < 0) {
+// idx = -idx - 1;
+// }
+// return idx;
+// }
+ /**
+ * Interpolates data with any shape over a specified axis.
+ *
+ * @param x Desired interpolated value
+ * @param xp The x-coordinates of the data points.
+ * @param a The data to be interpolated.
+ * @param axis The axis to interpolate over.
+ * @return Interpolated data
+ * @throws InvalidRangeException
+ */
+ public static Array interpolate_1d(double x, Array xp, Array a, int axis) throws InvalidRangeException {
+ int[] dataShape = xp.getShape();
+ int[] shape = new int[dataShape.length - 1];
+ for (int i = 0; i < dataShape.length; i++) {
+ if (i < axis) {
+ shape[i] = dataShape[i];
+ } else if (i > axis) {
+ shape[i - 1] = dataShape[i];
+ }
+ }
+
+ Array r = Array.factory(a.getDataType(), shape);
+ Index indexr = r.getIndex();
+ Index indexa = a.getIndex();
+ int[] current, dcurrent = new int[dataShape.length];
+ int idx;
+ Array tArray;
+ double belowp, abovep, belowa, abovea;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = indexr.getCurrentCounter();
+ List ranges = new ArrayList<>();
+ for (int j = 0; j < dataShape.length; j++) {
+ if (j == axis) {
+ ranges.add(new Range(0, dataShape[j] - 1, 1));
+ } else {
+ idx = j;
+ if (idx > axis) {
+ idx -= 1;
+ }
+ ranges.add(new Range(current[idx], current[idx], 1));
+ dcurrent[j] = current[idx];
+ }
+ }
+ tArray = ArrayMath.section(xp, ranges);
+ idx = searchSorted(tArray, x);
+ if (idx < 0) {
+ r.setDouble(i, Double.NaN);
+ } else if (idx == dataShape[axis] - 1) {
+ dcurrent[axis] = idx;
+ r.setObject(i, a.getObject(indexa.set(dcurrent)));
+ } else {
+ dcurrent[axis] = idx;
+ indexa.set(dcurrent);
+ belowp = xp.getDouble(indexa);
+ belowa = a.getDouble(indexa);
+ dcurrent[axis] = idx + 1;
+ indexa.set(dcurrent);
+ abovep = xp.getDouble(indexa);
+ abovea = a.getDouble(indexa);
+ r.setDouble(i, (x - belowp) / (abovep - belowp) * (abovea - belowa) + belowa);
+ }
+ indexr.incr();
+ }
+
+ return r;
+ }
+
+ /**
+ * Interpolates data with any shape over a specified axis.
+ *
+ * @param xa Desired interpolated values
+ * @param xp The x-coordinates of the data points.
+ * @param a The data to be interpolated.
+ * @param axis The axis to interpolate over.
+ * @return Interpolated data
+ * @throws InvalidRangeException
+ */
+ public static Array interpolate_1d(Array xa, Array xp, Array a, int axis) throws InvalidRangeException {
+ int[] dataShape = xp.getShape();
+ int[] shape = new int[dataShape.length];
+ int[] tshape = new int[shape.length - 1];
+ for (int i = 0; i < dataShape.length; i++) {
+ if (i == axis) {
+ shape[i] = xa.getShape()[0];
+ } else {
+ shape[i] = dataShape[i];
+ if (i < axis) {
+ tshape[i] = dataShape[i];
+ } else {
+ tshape[i - 1] = dataShape[i];
+ }
+ }
+ }
+
+ Array r = Array.factory(a.getDataType(), shape);
+ Array rr = Array.factory(DataType.BYTE, tshape);
+ Index indexrr = rr.getIndex();
+ Index indexr = r.getIndex();
+ Index indexa = a.getIndex();
+ int[] currentrr, currenta = new int[dataShape.length], currentr = new int[shape.length];
+ int idx;
+ Array tArray;
+ double belowp, abovep, belowa, abovea, x;
+ for (int i = 0; i < rr.getSize(); i++) {
+ currentrr = indexrr.getCurrentCounter();
+ List ranges = new ArrayList<>();
+ for (int j = 0; j < dataShape.length; j++) {
+ if (j == axis) {
+ ranges.add(new Range(0, dataShape[j] - 1, 1));
+ } else {
+ idx = j;
+ if (idx > axis) {
+ idx -= 1;
+ }
+ ranges.add(new Range(currentrr[idx], currentrr[idx], 1));
+ currenta[j] = currentrr[idx];
+ currentr[j] = currentrr[idx];
+ }
+ }
+ tArray = ArrayMath.section(xp, ranges);
+ for (int j = 0; j < xa.getSize(); j++) {
+ x = xa.getDouble(j);
+ idx = searchSorted(tArray, x);
+ currentr[axis] = j;
+ indexr.set(currentr);
+ if (idx < 0) {
+ r.setDouble(indexr, Double.NaN);
+ } else if (idx == dataShape[axis] - 1) {
+ currenta[axis] = idx;
+ r.setObject(indexr, a.getObject(indexa.set(currenta)));
+ } else {
+ currenta[axis] = idx;
+ indexa.set(currenta);
+ belowp = xp.getDouble(indexa);
+ belowa = a.getDouble(indexa);
+ currenta[axis] = idx + 1;
+ indexa.set(currenta);
+ abovep = xp.getDouble(indexa);
+ abovea = a.getDouble(indexa);
+ r.setDouble(indexr, (x - belowp) / (abovep - belowp) * (abovea - belowa) + belowa);
+ }
+ }
+ indexrr.incr();
+ }
+
+ return r;
+ }
+
+ //
+ //
+ /**
+ * Reproject
+ *
+ * @param x X array
+ * @param y Y array
+ * @param toProj To projection
+ * @return Result arrays
+ */
+ public static Array[] reproject(Array x, Array y, ProjectionInfo toProj) {
+ ProjectionInfo fromProj = KnownCoordinateSystems.geographic.world.WGS1984;
+ return reproject(x, y, fromProj, toProj);
+ }
+
+ /**
+ * Reproject
+ *
+ * @param x X array
+ * @param y Y array
+ * @param fromProj From projection
+ * @param toProj To projection
+ * @return Result arrays
+ */
+ public static Array[] reproject(Array x, Array y, ProjectionInfo fromProj, ProjectionInfo toProj) {
+ Array rx = Array.factory(DataType.DOUBLE, x.getShape());
+ Array ry = Array.factory(DataType.DOUBLE, x.getShape());
+ int n = (int) x.getSize();
+ double[][] points = new double[n][];
+ for (int i = 0; i < n; i++) {
+ points[i] = new double[]{x.getDouble(i), y.getDouble(i)};
+ }
+ Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length);
+ for (int i = 0; i < n; i++) {
+ rx.setDouble(i, points[i][0]);
+ ry.setDouble(i, points[i][1]);
+ }
+
+ return new Array[]{rx, ry};
+ }
+
+ /**
+ * Interpolate data to a station point
+ *
+ * @param data Data array
+ * @param xArray X array
+ * @param yArray Y array
+ * @param x X coordinate of the station
+ * @param y Y coordinate of the station
+ * @param missingValue Missing value
+ * @return Interpolated value
+ */
+ public static double toStation(Array data, List xArray, List yArray, double x, double y,
+ double missingValue) {
+ double iValue = Double.NaN;
+ int nx = xArray.size();
+ int ny = yArray.size();
+ if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue()
+ || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) {
+ return iValue;
+ }
+
+ //Get x/y index
+ int xIdx = 0, yIdx = 0;
+ int i;
+ boolean isIn = false;
+ for (i = 1; i < nx; i++) {
+ if (x < xArray.get(i).doubleValue()) {
+ xIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ xIdx = nx - 2;
+ }
+ isIn = false;
+ for (i = 1; i < ny; i++) {
+ if (y < yArray.get(i).doubleValue()) {
+ yIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ yIdx = ny - 2;
+ }
+
+ int i1 = yIdx;
+ int j1 = xIdx;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+ Index index = data.getIndex();
+ double a = data.getDouble(index.set(i1, j1));
+ double b = data.getDouble(index.set(i1, j2));
+ double c = data.getDouble(index.set(i2, j1));
+ double d = data.getDouble(index.set(i2, j2));
+ List dList = new ArrayList<>();
+ if (!Double.isNaN(a) && !MIMath.doubleEquals(a, missingValue)) {
+ dList.add(a);
+ }
+ if (!Double.isNaN(b) && !MIMath.doubleEquals(b, missingValue)) {
+ dList.add(b);
+ }
+ if (!Double.isNaN(c) && !MIMath.doubleEquals(c, missingValue)) {
+ dList.add(c);
+ }
+ if (!Double.isNaN(d) && !MIMath.doubleEquals(d, missingValue)) {
+ dList.add(d);
+ }
+
+ if (dList.isEmpty()) {
+ return iValue;
+ } else if (dList.size() == 1) {
+ iValue = dList.get(0);
+ } else if (dList.size() <= 3) {
+ double aSum = 0;
+ for (double dd : dList) {
+ aSum += dd;
+ }
+ iValue = aSum / dList.size();
+ } else {
+ double dx = xArray.get(xIdx + 1).doubleValue() - xArray.get(xIdx).doubleValue();
+ double dy = yArray.get(yIdx + 1).doubleValue() - yArray.get(yIdx).doubleValue();
+ double x1val = a + (c - a) * (y - yArray.get(i1).doubleValue()) / dy;
+ double x2val = b + (d - b) * (y - yArray.get(i1).doubleValue()) / dy;
+ iValue = x1val + (x2val - x1val) * (x - xArray.get(j1).doubleValue()) / dx;
+ }
+
+ return iValue;
+ }
+
+ /**
+ * Interpolate data to a station point
+ *
+ * @param data Data array
+ * @param xArray X array
+ * @param yArray Y array
+ * @param x X coordinate of the station
+ * @param y Y coordinate of the station
+ * @return Interpolated value
+ */
+ public static double toStation(Array data, List xArray, List yArray, double x, double y) {
+ double iValue = Double.NaN;
+ int nx = xArray.size();
+ int ny = yArray.size();
+ if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue()
+ || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) {
+ return iValue;
+ }
+
+ //Get x/y index
+ int xIdx = 0, yIdx = 0;
+ int i;
+ boolean isIn = false;
+ for (i = 1; i < nx; i++) {
+ if (x < xArray.get(i).doubleValue()) {
+ xIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ xIdx = nx - 2;
+ }
+ isIn = false;
+ for (i = 1; i < ny; i++) {
+ if (y < yArray.get(i).doubleValue()) {
+ yIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ yIdx = ny - 2;
+ }
+
+ int i1 = yIdx;
+ int j1 = xIdx;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+ Index index = data.getIndex();
+ double a = data.getDouble(index.set(i1, j1));
+ double b = data.getDouble(index.set(i1, j2));
+ double c = data.getDouble(index.set(i2, j1));
+ double d = data.getDouble(index.set(i2, j2));
+ List dList = new ArrayList<>();
+ if (!Double.isNaN(a)) {
+ dList.add(a);
+ }
+ if (!Double.isNaN(b)) {
+ dList.add(b);
+ }
+ if (!Double.isNaN(c)) {
+ dList.add(c);
+ }
+ if (!Double.isNaN(d)) {
+ dList.add(d);
+ }
+
+ if (dList.isEmpty()) {
+ return iValue;
+ } else if (dList.size() == 1) {
+ iValue = dList.get(0);
+ } else if (dList.size() <= 3) {
+ double aSum = 0;
+ for (double dd : dList) {
+ aSum += dd;
+ }
+ iValue = aSum / dList.size();
+ } else {
+ double dx = xArray.get(xIdx + 1).doubleValue() - xArray.get(xIdx).doubleValue();
+ double dy = yArray.get(yIdx + 1).doubleValue() - yArray.get(yIdx).doubleValue();
+ double x1val = a + (c - a) * (y - yArray.get(i1).doubleValue()) / dy;
+ double x2val = b + (d - b) * (y - yArray.get(i1).doubleValue()) / dy;
+ iValue = x1val + (x2val - x1val) * (x - xArray.get(j1).doubleValue()) / dx;
+ }
+
+ return iValue;
+ }
+
+ /**
+ * Get value index in a dimension array
+ *
+ * @param dim Dimension array
+ * @param v The value
+ * @return value index
+ */
+ public static int getDimIndex(Array dim, double v) {
+ int n = (int) dim.getSize();
+ if (v < dim.getDouble(0) || v > dim.getDouble(n - 1)) {
+ return -1;
+ }
+
+ int idx = n - 1;
+ for (int i = 1; i < n; i++) {
+ if (v < dim.getDouble(i)) {
+ idx = i - 1;
+ break;
+ }
+ }
+ return idx;
+ }
+
+ private static int[] gridIndex(Array xdim, Array ydim, double x, double y) {
+ int xn = (int) xdim.getSize();
+ int yn = (int) ydim.getSize();
+ int xIdx = getDimIndex(xdim, x);
+ if (xIdx < 0) {
+ return null;
+ }
+
+ int yIdx = getDimIndex(ydim, y);
+ if (yIdx < 0) {
+ return null;
+ }
+
+ if (xIdx == xn - 1) {
+ xIdx = xn - 2;
+ }
+ if (yIdx == yn - 1) {
+ yIdx = yn - 2;
+ }
+ int i1 = yIdx;
+ int j1 = xIdx;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+
+ return new int[]{i1, j1, i2, j2};
+ }
+
+ private static double bilinear(Array data, Index dindex, Array xdim, Array ydim, double x, double y) {
+ double iValue = Double.NaN;
+ int[] xyIdx = gridIndex(xdim, ydim, x, y);
+ if (xyIdx == null) {
+ return iValue;
+ }
+
+ int i1 = xyIdx[0];
+ int j1 = xyIdx[1];
+ int i2 = xyIdx[2];
+ int j2 = xyIdx[3];
+ Index index = Index.factory(data.getShape());
+ int n = index.getRank();
+ for (int i = 0; i < n - 2; i++) {
+ index.setDim(i, dindex.getCurrentCounter()[i]);
+ }
+ index.setDim(n - 2, i1);
+ index.setDim(n - 1, j1);
+ double a = data.getDouble(index);
+ index.setDim(n - 1, j2);
+ double b = data.getDouble(index);
+ index.setDim(n - 2, i2);
+ index.setDim(n - 1, j1);
+ double c = data.getDouble(index);
+ index.setDim(n - 2, i2);
+ index.setDim(n - 1, j2);
+ double d = data.getDouble(index);
+ List dList = new ArrayList<>();
+ if (!Double.isNaN(a)) {
+ dList.add(a);
+ }
+ if (!Double.isNaN(b)) {
+ dList.add(b);
+ }
+ if (!Double.isNaN(c)) {
+ dList.add(c);
+ }
+ if (!Double.isNaN(d)) {
+ dList.add(d);
+ }
+
+ if (dList.isEmpty()) {
+ return iValue;
+ } else if (dList.size() == 1) {
+ iValue = dList.get(0);
+ } else if (dList.size() <= 3) {
+ double aSum = 0;
+ for (double dd : dList) {
+ aSum += dd;
+ }
+ iValue = aSum / dList.size();
+ } else {
+ double dx = xdim.getDouble(j1 + 1) - xdim.getDouble(j1);
+ double dy = ydim.getDouble(i1 + 1) - ydim.getDouble(i1);
+ double x1val = a + (c - a) * (y - ydim.getDouble(i1)) / dy;
+ double x2val = b + (d - b) * (y - ydim.getDouble(i1)) / dy;
+ iValue = x1val + (x2val - x1val) * (x - xdim.getDouble(j1)) / dx;
+ }
+
+ return iValue;
+ }
+
+ /**
+ * Interpolate data to a station point
+ *
+ * @param data Data array
+ * @param xArray X array
+ * @param yArray Y array
+ * @param x X coordinate of the station
+ * @param y Y coordinate of the station
+ * @return Interpolated value
+ */
+ public static double toStation(Array data, Array xArray, Array yArray, double x, double y) {
+ double iValue = Double.NaN;
+ int nx = (int) xArray.getSize();
+ int ny = (int) yArray.getSize();
+ if (x < xArray.getDouble(0) || x > xArray.getDouble(nx - 1)
+ || y < yArray.getDouble(0) || y > yArray.getDouble(ny - 1)) {
+ return iValue;
+ }
+
+ //Get x/y index
+ int xIdx = 0, yIdx = 0;
+ int i;
+ boolean isIn = false;
+ for (i = 1; i < nx; i++) {
+ if (x < xArray.getDouble(i)) {
+ xIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ xIdx = nx - 2;
+ }
+ isIn = false;
+ for (i = 1; i < ny; i++) {
+ if (y < yArray.getDouble(i)) {
+ yIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ yIdx = ny - 2;
+ }
+
+ int i1 = yIdx;
+ int j1 = xIdx;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+ Index index = data.getIndex();
+ double a = data.getDouble(index.set(i1, j1));
+ double b = data.getDouble(index.set(i1, j2));
+ double c = data.getDouble(index.set(i2, j1));
+ double d = data.getDouble(index.set(i2, j2));
+ List dList = new ArrayList<>();
+ if (!Double.isNaN(a)) {
+ dList.add(a);
+ }
+ if (!Double.isNaN(b)) {
+ dList.add(b);
+ }
+ if (!Double.isNaN(c)) {
+ dList.add(c);
+ }
+ if (!Double.isNaN(d)) {
+ dList.add(d);
+ }
+
+ if (dList.isEmpty()) {
+ return iValue;
+ } else if (dList.size() == 1) {
+ iValue = dList.get(0);
+ } else if (dList.size() <= 3) {
+ double aSum = 0;
+ for (double dd : dList) {
+ aSum += dd;
+ }
+ iValue = aSum / dList.size();
+ } else {
+ double dx = xArray.getDouble(xIdx + 1) - xArray.getDouble(xIdx);
+ double dy = yArray.getDouble(yIdx + 1) - yArray.getDouble(yIdx);
+ double x1val = a + (c - a) * (y - yArray.getDouble(i1)) / dy;
+ double x2val = b + (d - b) * (y - yArray.getDouble(i1)) / dy;
+ iValue = x1val + (x2val - x1val) * (x - xArray.getDouble(j1)) / dx;
+ }
+
+ return iValue;
+ }
+
+ /**
+ * Interpolate data to a station point
+ *
+ * @param data Data array
+ * @param xArray X array
+ * @param yArray Y array
+ * @param x X coordinate of the station
+ * @param y Y coordinate of the station
+ * @param missingValue Missing value
+ * @return Interpolated value
+ */
+ public static double toStation_Neighbor(Array data, List xArray, List yArray, double x, double y,
+ double missingValue) {
+ double iValue = Double.NaN;
+ int nx = xArray.size();
+ int ny = yArray.size();
+ if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue()
+ || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) {
+ return iValue;
+ }
+
+ //Get x/y index
+ int xIdx = 0, yIdx = 0;
+ int i;
+ boolean isIn = false;
+ for (i = 1; i < nx; i++) {
+ if (x < xArray.get(i).doubleValue()) {
+ xIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ xIdx = nx - 2;
+ }
+ isIn = false;
+ for (i = 1; i < ny; i++) {
+ if (y < yArray.get(i).doubleValue()) {
+ yIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ yIdx = ny - 2;
+ }
+
+ int i1 = yIdx;
+ int j1 = xIdx;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+ Index index = data.getIndex();
+ double a = data.getDouble(index.set(i1, j1));
+ double b = data.getDouble(index.set(i1, j2));
+ double c = data.getDouble(index.set(i2, j1));
+ double d = data.getDouble(index.set(i2, j2));
+
+ if (Math.abs(x - xArray.get(j1).doubleValue()) < Math.abs(xArray.get(j2).doubleValue() - x)) {
+ if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) {
+ iValue = a;
+ } else {
+ iValue = c;
+ }
+ } else if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) {
+ iValue = b;
+ } else {
+ iValue = d;
+ }
+
+ return iValue;
+ }
+
+ /**
+ * Interpolate data to a station point
+ *
+ * @param data Data array
+ * @param xArray X array
+ * @param yArray Y array
+ * @param x X coordinate of the station
+ * @param y Y coordinate of the station
+ * @return Interpolated value
+ */
+ public static double toStation_Neighbor(Array data, List xArray, List yArray, double x, double y) {
+ //ouble iValue = Double.NaN;
+ int nx = xArray.size();
+ int ny = yArray.size();
+ if (x < xArray.get(0).doubleValue() || x > xArray.get(nx - 1).doubleValue()
+ || y < yArray.get(0).doubleValue() || y > yArray.get(ny - 1).doubleValue()) {
+ return Double.NaN;
+ }
+
+ //Get x/y index
+ int xIdx = 0, yIdx = 0;
+ int i;
+ boolean isIn = false;
+ for (i = 1; i < nx; i++) {
+ if (x < xArray.get(i).doubleValue()) {
+ xIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ xIdx = nx - 2;
+ }
+ isIn = false;
+ for (i = 1; i < ny; i++) {
+ if (y < yArray.get(i).doubleValue()) {
+ yIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ yIdx = ny - 2;
+ }
+
+ int i1 = yIdx;
+ int j1 = xIdx;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+ Index index = data.getIndex();
+ double a = data.getDouble(index.set(i1, j1));
+ double b = data.getDouble(index.set(i1, j2));
+ double c = data.getDouble(index.set(i2, j1));
+ double d = data.getDouble(index.set(i2, j2));
+
+ double iValue;
+ if (Math.abs(x - xArray.get(j1).doubleValue()) < Math.abs(xArray.get(j2).doubleValue() - x)) {
+ if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) {
+ iValue = a;
+ } else {
+ iValue = c;
+ }
+ } else if (Math.abs(y - yArray.get(i1).doubleValue()) < Math.abs(yArray.get(i2).doubleValue() - y)) {
+ iValue = b;
+ } else {
+ iValue = d;
+ }
+
+ return iValue;
+ }
+
+ /**
+ * Interpolate data to a station point
+ *
+ * @param data Data array
+ * @param xArray X array
+ * @param yArray Y array
+ * @param x X coordinate of the station
+ * @param y Y coordinate of the station
+ * @return Interpolated value
+ */
+ public static double toStation_Neighbor(Array data, Array xArray, Array yArray, double x, double y) {
+ //ouble iValue = Double.NaN;
+ int nx = (int) xArray.getSize();
+ int ny = (int) yArray.getSize();
+ if (x < xArray.getDouble(0) || x > xArray.getDouble(nx - 1)
+ || y < yArray.getDouble(0) || y > yArray.getDouble(ny - 1)) {
+ return Double.NaN;
+ }
+
+ //Get x/y index
+ int xIdx = 0, yIdx = 0;
+ int i;
+ boolean isIn = false;
+ for (i = 1; i < nx; i++) {
+ if (x < xArray.getDouble(i)) {
+ xIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ xIdx = nx - 2;
+ }
+ isIn = false;
+ for (i = 1; i < ny; i++) {
+ if (y < yArray.getDouble(i)) {
+ yIdx = i - 1;
+ isIn = true;
+ break;
+ }
+ }
+ if (!isIn) {
+ yIdx = ny - 2;
+ }
+
+ int i1 = yIdx;
+ int j1 = xIdx;
+ int i2 = i1 + 1;
+ int j2 = j1 + 1;
+ Index index = data.getIndex();
+ double a = data.getDouble(index.set(i1, j1));
+ double b = data.getDouble(index.set(i1, j2));
+ double c = data.getDouble(index.set(i2, j1));
+ double d = data.getDouble(index.set(i2, j2));
+
+ double iValue;
+ if (Math.abs(x - xArray.getDouble(j1)) < Math.abs(xArray.getDouble(j2) - x)) {
+ if (Math.abs(y - yArray.getDouble(i1)) < Math.abs(yArray.getDouble(i2) - y)) {
+ iValue = a;
+ } else {
+ iValue = c;
+ }
+ } else if (Math.abs(y - yArray.getDouble(i1)) < Math.abs(yArray.getDouble(i2) - y)) {
+ iValue = b;
+ } else {
+ iValue = d;
+ }
+
+ return iValue;
+ }
+
+ /**
+ * Project grid data
+ *
+ * @param data Data array
+ * @param xx X array
+ * @param yy Y array
+ * @param fromProj From projection
+ * @param toProj To projection
+ * @return Porjected grid data
+ * @throws org.meteoinfo.ndarray.InvalidRangeException
+ */
+ public static Object[] reproject_back(Array data, List xx, List yy, ProjectionInfo fromProj, ProjectionInfo toProj) throws InvalidRangeException {
+ Extent aExtent;
+ int xnum = xx.size();
+ int ynum = yy.size();
+ double xdelta = xx.get(1).doubleValue() - xx.get(0).doubleValue();
+ double ydelta = yy.get(1).doubleValue() - yy.get(0).doubleValue();
+ aExtent = ProjectionUtil.getProjectionExtent(fromProj, toProj, xx, yy);
+
+ double xDelt = (aExtent.maxX - aExtent.minX) / (xnum - 1);
+ double yDelt = (aExtent.maxY - aExtent.minY) / (ynum - 1);
+ Array rx = Array.factory(DataType.DOUBLE, new int[]{xnum});
+ Array ry = Array.factory(DataType.DOUBLE, new int[]{ynum});
+ int i, j, xIdx, yIdx;
+ for (i = 0; i < xnum; i++) {
+ rx.setDouble(i, aExtent.minX + i * xDelt);
+ }
+
+ for (i = 0; i < ynum; i++) {
+ ry.setDouble(i, aExtent.minY + i * yDelt);
+ }
+
+ double x, y;
+ Array r = Array.factory(data.getDataType(), data.getShape());
+ double[][] points = new double[1][];
+ Object fill_value = Double.NaN;
+ switch (data.getDataType()) {
+ case INT:
+ fill_value = Integer.MIN_VALUE;
+ break;
+ case FLOAT:
+ fill_value = Float.NaN;
+ break;
+ }
+ for (i = 0; i < ynum; i++) {
+ for (j = 0; j < xnum; j++) {
+ points[0] = new double[]{rx.getDouble(j), ry.getDouble(i)};
+ try {
+ Reproject.reprojectPoints(points, toProj, fromProj, 0, 1);
+ x = points[0][0];
+ y = points[0][1];
+
+ if (x < xx.get(0).doubleValue() || x > xx.get(xx.size() - 1).doubleValue()) {
+ r.setObject(i * xnum + j, fill_value);
+ } else if (y < yy.get(0).doubleValue() || y > yy.get(yy.size() - 1).doubleValue()) {
+ r.setObject(i * xnum + j, fill_value);
+ } else {
+ xIdx = (int) ((x - xx.get(0).doubleValue()) / xdelta);
+ yIdx = (int) ((y - yy.get(0).doubleValue()) / ydelta);
+ r.setObject(i * xnum + j, data.getObject(yIdx * xnum + xIdx));
+ }
+ } catch (Exception e) {
+ r.setObject(i * xnum + j, fill_value);
+ j++;
+ }
+ }
+ }
+
+ return new Object[]{r, rx, ry};
+ }
+
+ /**
+ * Project grid data
+ *
+ * @param data Data array
+ * @param xx X array
+ * @param yy Y array
+ * @param fromProj From projection
+ * @param toProj To projection
+ * @param method Resample method
+ * @return Porjected grid data
+ * @throws org.meteoinfo.ndarray.InvalidRangeException
+ */
+ public static Object[] reproject(Array data, List xx, List yy, ProjectionInfo fromProj,
+ ProjectionInfo toProj, ResampleMethods method) throws InvalidRangeException {
+ Extent aExtent;
+ int xnum = xx.size();
+ int ynum = yy.size();
+ aExtent = ProjectionUtil.getProjectionExtent(fromProj, toProj, xx, yy);
+
+ double xDelt = (aExtent.maxX - aExtent.minX) / (xnum - 1);
+ double yDelt = (aExtent.maxY - aExtent.minY) / (ynum - 1);
+ int i;
+ Array rx = Array.factory(DataType.DOUBLE, new int[]{xnum});
+ Array ry = Array.factory(DataType.DOUBLE, new int[]{ynum});
+ for (i = 0; i < xnum; i++) {
+ rx.setDouble(i, aExtent.minX + i * xDelt);
+ }
+
+ for (i = 0; i < ynum; i++) {
+ ry.setDouble(i, aExtent.minY + i * yDelt);
+ }
+
+ Array[] rr = ArrayUtil.meshgrid(rx, ry);
+
+ Array r = ArrayUtil.reproject(data, xx, yy, rr[0], rr[1], fromProj, toProj, method);
+
+ return new Object[]{r, rx, ry};
+ }
+
+ /**
+ * Project grid data
+ *
+ * @param data Data array
+ * @param xx X array
+ * @param yy Y array
+ * @param fromProj From projection
+ * @param toProj To projection
+ * @return Porjected grid data
+ * @throws org.meteoinfo.ndarray.InvalidRangeException
+ */
+ public static Object[] reproject(Array data, List xx, List yy, ProjectionInfo fromProj,
+ ProjectionInfo toProj) throws InvalidRangeException {
+ return reproject(data, xx, yy, fromProj, toProj, ResampleMethods.NearestNeighbor);
+ }
+
+ /**
+ * Reproject
+ *
+ * @param data Data array
+ * @param x X array
+ * @param y Y array
+ * @param rx Result x array
+ * @param ry Result y array
+ * @param fromProj From projection
+ * @param toProj To projection
+ * @param fill_value Fill value
+ * @param resampleMethod Resample method
+ * @return Result arrays
+ * @throws org.meteoinfo.ndarray.InvalidRangeException
+ */
+ public static Array reproject(Array data, List x, List y, Array rx, Array ry,
+ ProjectionInfo fromProj, ProjectionInfo toProj, double fill_value, ResampleMethods resampleMethod) throws InvalidRangeException {
+ int n = (int) rx.getSize();
+ int[] dshape = data.getShape();
+ int[] shape;
+ if (rx.getRank() == 1) {
+ shape = new int[1];
+ shape[0] = rx.getShape()[0];
+ } else {
+ shape = new int[data.getRank()];
+ for (int i = 0; i < shape.length; i++) {
+ if (i == shape.length - 2) {
+ shape[i] = rx.getShape()[0];
+ } else if (i == shape.length - 1) {
+ shape[i] = rx.getShape()[1];
+ } else {
+ shape[i] = data.getShape()[i];
+ }
+ }
+ }
+ Array r = Array.factory(data.getDataType(), shape);
+
+ double[][] points = new double[n][];
+ for (int i = 0; i < n; i++) {
+ points[i] = new double[]{rx.getDouble(i), ry.getDouble(i)};
+ }
+ if (!fromProj.equals(toProj)) {
+ Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length);
+ }
+ double xx, yy;
+ if (resampleMethod == ResampleMethods.Bilinear) {
+ if (shape.length <= 2) {
+ for (int i = 0; i < n; i++) {
+ xx = points[i][0];
+ yy = points[i][1];
+ if (Double.isNaN(xx) || Double.isNaN(yy)) {
+ r.setObject(i, Double.NaN);
+ } else {
+ r.setObject(i, toStation(data, x, y, xx, yy, fill_value));
+ }
+ }
+ } else {
+ Index indexr = r.getIndex();
+ int[] current, cc = null;
+ boolean isNew;
+ Array ndata = null;
+ int k;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = indexr.getCurrentCounter();
+ isNew = true;
+ if (i > 0) {
+ for (int j = 0; j < shape.length - 2; j++) {
+ if (cc[j] != current[j]) {
+ isNew = false;
+ break;
+ }
+ }
+ }
+ cc = Arrays.copyOf(current, current.length);
+ if (isNew) {
+ List ranges = new ArrayList<>();
+ for (int j = 0; j < shape.length - 2; j++) {
+ ranges.add(new Range(current[j], current[j], 1));
+ }
+ ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1));
+ ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1));
+ ndata = data.section(ranges).reduce();
+ }
+ k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1];
+ xx = points[k][0];
+ yy = points[k][1];
+ if (Double.isNaN(xx) || Double.isNaN(yy)) {
+ r.setObject(i, Double.NaN);
+ } else {
+ r.setObject(i, toStation(ndata, x, y, xx, yy, fill_value));
+ }
+ indexr.incr();
+ }
+ }
+ } else if (shape.length <= 2) {
+ for (int i = 0; i < n; i++) {
+ xx = points[i][0];
+ yy = points[i][1];
+ if (Double.isNaN(xx) || Double.isNaN(yy)) {
+ r.setObject(i, Double.NaN);
+ } else {
+ r.setObject(i, toStation_Neighbor(data, x, y, xx, yy, fill_value));
+ }
+ }
+ } else {
+ Index indexr = r.getIndex();
+ int[] current, cc = null;
+ boolean isNew;
+ Array ndata = null;
+ int k;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = indexr.getCurrentCounter();
+ isNew = true;
+ if (i > 0) {
+ for (int j = 0; j < shape.length - 2; j++) {
+ if (cc[j] != current[j]) {
+ isNew = false;
+ break;
+ }
+ }
+ }
+ cc = Arrays.copyOf(current, current.length);
+ if (isNew) {
+ List ranges = new ArrayList<>();
+ for (int j = 0; j < shape.length - 2; j++) {
+ ranges.add(new Range(current[j], current[j], 1));
+ }
+ ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1));
+ ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1));
+ ndata = data.section(ranges).reduce();
+ }
+ k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1];
+ xx = points[k][0];
+ yy = points[k][1];
+ if (Double.isNaN(xx) || Double.isNaN(yy)) {
+ r.setObject(i, Double.NaN);
+ } else {
+ r.setObject(i, toStation_Neighbor(ndata, x, y, xx, yy, fill_value));
+ }
+ indexr.incr();
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Reproject
+ *
+ * @param data Data array
+ * @param x X array
+ * @param y Y array
+ * @param rx Result x array
+ * @param ry Result y array
+ * @param fromProj From projection
+ * @param toProj To projection
+ * @param resampleMethod Resample method
+ * @return Result arrays
+ * @throws org.meteoinfo.ndarray.InvalidRangeException
+ */
+ public static Array reproject(Array data, List x, List y, Array rx, Array ry,
+ ProjectionInfo fromProj, ProjectionInfo toProj, ResampleMethods resampleMethod) throws InvalidRangeException {
+ int n = (int) rx.getSize();
+ int[] dshape = data.getShape();
+ int[] shape;
+ if (rx.getRank() == 1) {
+ shape = new int[1];
+ shape[0] = rx.getShape()[0];
+ } else {
+ shape = new int[data.getRank()];
+ for (int i = 0; i < shape.length; i++) {
+ if (i == shape.length - 2) {
+ shape[i] = rx.getShape()[0];
+ } else if (i == shape.length - 1) {
+ shape[i] = rx.getShape()[1];
+ } else {
+ shape[i] = data.getShape()[i];
+ }
+ }
+ }
+ Array r = Array.factory(data.getDataType(), shape);
+
+ double[][] points = new double[n][];
+ for (int i = 0; i < n; i++) {
+ points[i] = new double[]{rx.getDouble(i), ry.getDouble(i)};
+ }
+ if (!fromProj.equals(toProj)) {
+ Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length);
+ }
+ double xx, yy;
+ if (resampleMethod == ResampleMethods.Bilinear) {
+ if (shape.length <= 2) {
+ for (int i = 0; i < n; i++) {
+ xx = points[i][0];
+ yy = points[i][1];
+ r.setObject(i, toStation(data, x, y, xx, yy));
+ }
+ } else {
+ Index indexr = r.getIndex();
+ int[] current, cc = null;
+ boolean isNew;
+ Array ndata = null;
+ int k;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = indexr.getCurrentCounter();
+ isNew = true;
+ if (i > 0) {
+ for (int j = 0; j < shape.length - 2; j++) {
+ if (cc[j] != current[j]) {
+ isNew = false;
+ break;
+ }
+ }
+ }
+ cc = Arrays.copyOf(current, current.length);
+ if (isNew) {
+ List ranges = new ArrayList<>();
+ for (int j = 0; j < shape.length - 2; j++) {
+ ranges.add(new Range(current[j], current[j], 1));
+ }
+ ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1));
+ ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1));
+ ndata = data.section(ranges).reduce();
+ }
+ k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1];
+ xx = points[k][0];
+ yy = points[k][1];
+ r.setObject(i, toStation(ndata, x, y, xx, yy));
+ indexr.incr();
+ }
+ }
+ } else if (shape.length == 2) {
+ for (int i = 0; i < n; i++) {
+ xx = points[i][0];
+ yy = points[i][1];
+ r.setObject(i, toStation_Neighbor(data, x, y, xx, yy));
+ }
+ } else {
+ Index indexr = r.getIndex();
+ int[] current, cc = null;
+ boolean isNew;
+ Array ndata = null;
+ int k;
+ for (int i = 0; i < r.getSize(); i++) {
+ current = indexr.getCurrentCounter();
+ isNew = true;
+ if (i > 0) {
+ for (int j = 0; j < shape.length - 2; j++) {
+ if (cc[j] != current[j]) {
+ isNew = false;
+ break;
+ }
+ }
+ }
+ cc = Arrays.copyOf(current, current.length);
+ if (isNew) {
+ List ranges = new ArrayList<>();
+ for (int j = 0; j < shape.length - 2; j++) {
+ ranges.add(new Range(current[j], current[j], 1));
+ }
+ ranges.add(new Range(0, dshape[dshape.length - 2] - 1, 1));
+ ranges.add(new Range(0, dshape[dshape.length - 1] - 1, 1));
+ ndata = data.section(ranges).reduce();
+ }
+ k = current[shape.length - 2] * shape[shape.length - 1] + current[shape.length - 1];
+ xx = points[k][0];
+ yy = points[k][1];
+ r.setObject(i, toStation_Neighbor(ndata, x, y, xx, yy));
+ indexr.incr();
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Reproject
+ *
+ * @param data Data array
+ * @param x X array
+ * @param y Y array
+ * @param rx Result x array
+ * @param ry Result y array
+ * @param fromProj From projection
+ * @param toProj To projection
+ * @param fill_value Fill value
+ * @param resampleMethod Resample method
+ * @return Result arrays
+ */
+ public static Array reproject(Array data, List x, List y, List rx, List ry,
+ ProjectionInfo fromProj, ProjectionInfo toProj, double fill_value, ResampleMethods resampleMethod) {
+ int n = rx.size() * ry.size();
+ int[] shape = new int[]{ry.size(), rx.size()};
+ Array r = Array.factory(data.getDataType(), shape);
+
+ double[][] points = new double[n][];
+ for (int i = 0; i < ry.size(); i++) {
+ for (int j = 0; j < rx.size(); j++) {
+ points[i * rx.size() + j] = new double[]{rx.get(j).doubleValue(), ry.get(i).doubleValue()};
+ }
+ }
+ if (!fromProj.equals(toProj)) {
+ Reproject.reprojectPoints(points, toProj, fromProj, 0, points.length);
+ }
+ double xx, yy;
+ if (resampleMethod == ResampleMethods.Bilinear) {
+ for (int i = 0; i < n; i++) {
+ xx = points[i][0];
+ yy = points[i][1];
+ r.setObject(i, toStation(data, x, y, xx, yy, fill_value));
+ }
+ } else {
+ for (int i = 0; i < n; i++) {
+ xx = points[i][0];
+ yy = points[i][1];
+ r.setObject(i, toStation_Neighbor(data, x, y, xx, yy, fill_value));
+ }
+ }
+
+ return r;
+ }
+
+ /**
+ * Computes the smallest convex Polygon that contains all the
+ * points
+ *
+ * @param x X array
+ * @param y Y array
+ * @return PolygonShape
+ */
+ public static PolygonShape convexHull(Array x, Array y) {
+ int n = (int) x.getSize();
+ Geometry[] geos = new Geometry[n];
+ GeometryFactory factory = new GeometryFactory();
+ for (int i = 0; i < n; i++) {
+ Coordinate c = new Coordinate(x.getDouble(i), y.getDouble(i));
+ geos[i] = factory.createPoint(c);
+ }
+ Geometry gs = factory.createGeometryCollection(geos);
+ Geometry ch = gs.convexHull();
+ return new PolygonShape(ch);
+ }
+
+ //
+ //
+ //
+}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/Axis.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/Axis.java
index a1f2736e..30cf6687 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/Axis.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/axis/Axis.java
@@ -26,10 +26,9 @@ import org.meteoinfo.chart.plot.YAlign;
import org.meteoinfo.drawing.Draw;
import org.meteoinfo.global.DataConvert;
import org.meteoinfo.global.MIMath;
-import org.meteoinfo.global.util.BigDecimalUtil;
-import org.meteoinfo.global.util.DateUtil;
import org.meteoinfo.global.util.JDateUtil;
import org.meteoinfo.legend.LineStyles;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
/**
*
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/GraphicFactory.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/GraphicFactory.java
index e04bd34b..631a6090 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/GraphicFactory.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/GraphicFactory.java
@@ -17,7 +17,6 @@ import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
import org.meteoinfo.chart.ChartText;
-import org.meteoinfo.chart.jogl.SurfaceGraphics;
import org.meteoinfo.chart.plot3d.GraphicCollection3D;
import org.meteoinfo.math.ArrayMath;
import org.meteoinfo.math.ArrayUtil;
@@ -33,7 +32,6 @@ import org.meteoinfo.global.Extent;
import org.meteoinfo.global.Extent3D;
import org.meteoinfo.global.MIMath;
import org.meteoinfo.global.PointD;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.layer.ImageLayer;
import org.meteoinfo.layer.VectorLayer;
import org.meteoinfo.legend.ArrowLineBreak;
@@ -52,6 +50,7 @@ import org.meteoinfo.legend.PolylineBreak;
import org.meteoinfo.legend.StreamlineBreak;
import org.meteoinfo.math.meteo.MeteoMath;
import org.meteoinfo.ndarray.*;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.shape.*;
import wcontour.Contour;
import wcontour.global.Point3D;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PolarPlot.java b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PolarPlot.java
index 72811cbe..a3b4c9d2 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PolarPlot.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/chart/plot/PolarPlot.java
@@ -21,10 +21,10 @@ import static org.meteoinfo.drawing.Draw.getDashPattern;
import org.meteoinfo.global.DataConvert;
import org.meteoinfo.global.Extent;
import org.meteoinfo.global.MIMath;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.legend.LineStyles;
import org.meteoinfo.shape.Graphic;
import org.meteoinfo.shape.GraphicCollection;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
/**
*
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridArray.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridArray.java
index a3e3b86b..31bab42f 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridArray.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridArray.java
@@ -32,9 +32,9 @@ import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.meteoinfo.ndarray.*;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.data.meteodata.GridDataSetting;
import org.meteoinfo.geoprocess.analysis.ResampleMethods;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.legend.LegendManage;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.info.ProjectionInfo;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridData.java
index 569e842b..ad5dcfa2 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridData.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/GridData.java
@@ -37,7 +37,6 @@ import org.meteoinfo.ndarray.DimensionType;
import org.meteoinfo.data.meteodata.GridDataSetting;
import org.meteoinfo.geoprocess.analysis.ResampleMethods;
import org.meteoinfo.global.DataConvert;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.layer.VectorLayer;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.info.ProjectionInfo;
@@ -48,6 +47,7 @@ import org.meteoinfo.shape.ShapeTypes;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.DataType;
import org.meteoinfo.ndarray.IndexIterator;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
/**
*
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/geotiff/GeoTiff.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/geotiff/GeoTiff.java
index 6bf0d121..fc348fb9 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/geotiff/GeoTiff.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/mapdata/geotiff/GeoTiff.java
@@ -34,7 +34,7 @@ import org.meteoinfo.data.mapdata.geotiff.compression.CompressionDecoder;
import org.meteoinfo.data.mapdata.geotiff.compression.DeflateCompression;
import org.meteoinfo.data.mapdata.geotiff.compression.LZWCompression;
import org.meteoinfo.global.DataConvert;
-import org.meteoinfo.global.util.BigDecimalUtil;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.info.ProjectionInfo;
import org.meteoinfo.ndarray.Array;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/StationInfoData.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/StationInfoData.java
index 454fb99a..54da0ea7 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/StationInfoData.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/StationInfoData.java
@@ -24,8 +24,6 @@ import org.meteoinfo.data.dataframe.DataFrame;
import org.meteoinfo.table.DataTable;
import org.meteoinfo.ndarray.DataType;
-import javax.xml.crypto.Data;
-
/**
*
* @author yaqiang
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/arl/ARLDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/arl/ARLDataInfo.java
index b4a67a8c..9b4f938a 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/arl/ARLDataInfo.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/arl/ARLDataInfo.java
@@ -19,6 +19,7 @@ import org.meteoinfo.data.meteodata.DataInfo;
import org.meteoinfo.global.util.JDateUtil;
import org.meteoinfo.ndarray.Dimension;
import org.meteoinfo.ndarray.DimensionType;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.data.meteodata.IGridDataInfo;
import org.meteoinfo.data.meteodata.Variable;
import org.meteoinfo.global.DataConvert;
@@ -40,7 +41,6 @@ import java.util.logging.Logger;
import org.meteoinfo.data.GridArray;
import org.meteoinfo.data.meteodata.MeteoDataType;
import org.meteoinfo.global.MIMath;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.locationtech.proj4j.proj.Projection;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.info.ProjectionInfo;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/ASCIIGridDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/ASCIIGridDataInfo.java
index 3d7e8626..7d18e0cf 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/ASCIIGridDataInfo.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/ascii/ASCIIGridDataInfo.java
@@ -34,7 +34,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import org.meteoinfo.data.GridArray;
import org.meteoinfo.data.meteodata.MeteoDataType;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.DataType;
import org.meteoinfo.ndarray.IndexIterator;
@@ -42,6 +41,7 @@ import org.meteoinfo.ndarray.InvalidRangeException;
import org.meteoinfo.ndarray.Range;
import org.meteoinfo.ndarray.Section;
import org.meteoinfo.data.meteodata.Attribute;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
/**
*
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grads/GrADSDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grads/GrADSDataInfo.java
index db622ec5..d56d8396 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grads/GrADSDataInfo.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/grads/GrADSDataInfo.java
@@ -21,6 +21,7 @@ import org.meteoinfo.data.meteodata.IGridDataInfo;
import org.meteoinfo.data.meteodata.Variable;
import org.meteoinfo.global.DataConvert;
import org.meteoinfo.io.EndianDataOutputStream;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.info.ProjectionInfo;
import org.meteoinfo.projection.Reproject;
@@ -51,7 +52,6 @@ import org.meteoinfo.data.meteodata.StationInfoData;
import org.meteoinfo.data.meteodata.StationModelData;
import org.meteoinfo.data.meteodata.arl.ARLDataInfo;
import org.meteoinfo.global.Extent;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.DataType;
import org.meteoinfo.ndarray.IndexIterator;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITConcDataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITConcDataInfo.java
index f981eb48..03b5b69a 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITConcDataInfo.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/hysplit/HYSPLITConcDataInfo.java
@@ -35,7 +35,6 @@ import org.meteoinfo.data.GridArray;
import org.meteoinfo.data.meteodata.MeteoDataType;
import org.meteoinfo.data.meteodata.arl.ARLDataInfo;
import org.meteoinfo.global.DataConvert;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.DataType;
import org.meteoinfo.ndarray.IndexIterator;
@@ -43,8 +42,9 @@ import org.meteoinfo.ndarray.InvalidRangeException;
import org.meteoinfo.ndarray.Range;
import org.meteoinfo.ndarray.Section;
import org.meteoinfo.data.meteodata.Attribute;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
-/**
+ /**
*
* @author yaqiang
*/
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS131DataInfo.java b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS131DataInfo.java
index b70a15db..781fbec8 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS131DataInfo.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/data/meteodata/micaps/MICAPS131DataInfo.java
@@ -33,7 +33,6 @@ import org.meteoinfo.data.meteodata.IGridDataInfo;
import org.meteoinfo.data.meteodata.MeteoDataType;
import org.meteoinfo.data.meteodata.Variable;
import org.meteoinfo.global.DataConvert;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.DataType;
import org.meteoinfo.ndarray.IndexIterator;
@@ -41,6 +40,7 @@ import org.meteoinfo.ndarray.InvalidRangeException;
import org.meteoinfo.ndarray.Range;
import org.meteoinfo.ndarray.Section;
import org.meteoinfo.data.meteodata.Attribute;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
/**
*
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/MIMath.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/MIMath.java
index f64b9e18..929ea850 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/MIMath.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/global/MIMath.java
@@ -13,12 +13,12 @@
*/
package org.meteoinfo.global;
-import org.meteoinfo.data.mapdata.Field;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;
-import org.meteoinfo.global.util.BigDecimalUtil;
+
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.shape.PointZ;
import org.meteoinfo.shape.Shape;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/DateUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/DateUtil.java
index 9d5a4637..f072860c 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/DateUtil.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/DateUtil.java
@@ -20,6 +20,7 @@ import java.util.List;
import org.joda.time.*;
import org.joda.time.format.DateTimeFormatter;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
/**
*
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/JDateUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/JDateUtil.java
index 982f9ea4..417a091f 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/JDateUtil.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/JDateUtil.java
@@ -1,5 +1,7 @@
package org.meteoinfo.global.util;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
+
import java.time.*;
import java.time.chrono.ChronoPeriod;
import java.time.format.DateTimeFormatter;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmLegendBreaks.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmLegendBreaks.java
index 46176435..bb741243 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmLegendBreaks.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/FrmLegendBreaks.java
@@ -5,6 +5,7 @@
package org.meteoinfo.legend;
import org.meteoinfo.layer.FrmLayerProperty;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.shape.ShapeTypes;
import java.awt.Color;
import java.awt.Dimension;
@@ -16,7 +17,6 @@ import java.util.logging.Logger;
import javax.swing.JOptionPane;
import org.meteoinfo.global.colors.ColorMap;
import org.meteoinfo.global.colors.ColorUtil;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.ui.ColorComboBoxModel;
import org.meteoinfo.ui.ColorListCellRender;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendManage.java b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendManage.java
index 038ed641..46335336 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendManage.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/legend/LegendManage.java
@@ -17,6 +17,7 @@ import org.meteoinfo.data.GridData;
import org.meteoinfo.data.StationData;
import org.meteoinfo.drawing.ContourDraw;
import org.meteoinfo.global.MIMath;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.shape.ShapeTypes;
import java.awt.Color;
import java.io.IOException;
@@ -26,16 +27,13 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.meteoinfo.data.GridArray;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.global.DataConvert;
import org.meteoinfo.global.colors.ColorMap;
-import org.meteoinfo.global.colors.ColorUtil;
import org.meteoinfo.layer.VectorLayer;
import org.meteoinfo.shape.PointShape;
import org.meteoinfo.shape.PolygonShape;
import org.meteoinfo.shape.PolylineShape;
import org.meteoinfo.shape.Shape;
-import wcontour.Legend;
/**
* Legend manage class
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapView.java b/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapView.java
index b340c895..44281733 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapView.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/map/MapView.java
@@ -41,6 +41,7 @@ import org.meteoinfo.global.MIMath;
import org.meteoinfo.global.PointD;
import org.meteoinfo.global.PointF;
import org.meteoinfo.ndarray.DataType;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.layer.ChartSet;
import org.meteoinfo.layer.ImageLayer;
import org.meteoinfo.layer.LabelSet;
@@ -167,7 +168,6 @@ import org.meteoinfo.global.event.IShapeSelectedListener;
import org.meteoinfo.global.event.IUndoEditListener;
import org.meteoinfo.global.event.ShapeSelectedEvent;
import org.meteoinfo.global.event.UndoEditEvent;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.global.util.GeoUtil;
import org.meteoinfo.image.ImageUtil;
import org.meteoinfo.layer.VisibleScale;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayUtil.java b/MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayUtil.java
index 2e53e715..ae975748 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayUtil.java
+++ b/MeteoInfoLib/src/main/java/org/meteoinfo/math/ArrayUtil.java
@@ -36,14 +36,13 @@ import org.meteoinfo.geoprocess.GeoComputation;
import org.meteoinfo.global.DataConvert;
import org.meteoinfo.global.MIMath;
import org.meteoinfo.global.PointD;
-import org.meteoinfo.global.util.BigDecimalUtil;
import org.meteoinfo.global.util.GlobalUtil;
import org.meteoinfo.global.util.JDateUtil;
import org.meteoinfo.io.EndianDataOutputStream;
-import org.meteoinfo.layer.ChartSet;
import org.meteoinfo.math.spatial.KDTree;
import org.meteoinfo.math.spatial.KDTree.SearchResult;
import org.meteoinfo.ndarray.*;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
import org.meteoinfo.shape.PolygonShape;
/**
diff --git a/MeteoInfoMap/MeteoInfoMap.iml b/MeteoInfoMap/MeteoInfoMap.iml
index c21638c1..90c2e067 100644
--- a/MeteoInfoMap/MeteoInfoMap.iml
+++ b/MeteoInfoMap/MeteoInfoMap.iml
@@ -12,6 +12,8 @@
+
+
diff --git a/MeteoInfoMap/pom.xml b/MeteoInfoMap/pom.xml
index 3dfebcdf..c94d219d 100644
--- a/MeteoInfoMap/pom.xml
+++ b/MeteoInfoMap/pom.xml
@@ -4,7 +4,7 @@
org.meteothink
MeteoInfo
- 2.4.6
+ 3.0.0
MeteoInfoMap
jar
diff --git a/meteoinfo-console/pom.xml b/meteoinfo-console/pom.xml
index ff7b0e9c..5f17cc51 100644
--- a/meteoinfo-console/pom.xml
+++ b/meteoinfo-console/pom.xml
@@ -5,7 +5,7 @@
MeteoInfo
org.meteothink
- 2.4.6
+ 3.0.0
4.0.0
diff --git a/meteoinfo-ndarray/meteoinfo-ndarray.iml b/meteoinfo-ndarray/meteoinfo-ndarray.iml
new file mode 100644
index 00000000..fdf32413
--- /dev/null
+++ b/meteoinfo-ndarray/meteoinfo-ndarray.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/meteoinfo-ndarray/pom.xml b/meteoinfo-ndarray/pom.xml
new file mode 100644
index 00000000..8e603762
--- /dev/null
+++ b/meteoinfo-ndarray/pom.xml
@@ -0,0 +1,34 @@
+
+
+
+ org.meteothink
+ MeteoInfo
+ 3.0.0
+
+ 4.0.0
+
+ meteoinfo-ndarray
+ jar
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+
+
+
+ org.apache.commons
+ commons-math3
+ 3.6.1
+
+
+ com.google.code.findbugs
+ jsr305
+ 3.0.2
+
+
+
+
\ No newline at end of file
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Array.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Array.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Array.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Array.java
index 548a7012..94389e1c 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Array.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Array.java
@@ -33,11 +33,11 @@
package org.meteoinfo.ndarray;
import java.math.BigInteger;
+import java.nio.*;
import java.time.LocalDateTime;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.ArrayList;
-import java.nio.*;
/**
* Superclass for implementations of multidimensional arrays. An Array has a
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java
index e7258b06..c9e252db 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayBoolean.java
@@ -60,21 +60,21 @@ public class ArrayBoolean extends Array {
static ArrayBoolean factory(Index index, boolean[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayBoolean.D0(index, storage);
+ return new D0(index, storage);
case 1:
- return new ArrayBoolean.D1(index, storage);
+ return new D1(index, storage);
case 2:
- return new ArrayBoolean.D2(index, storage);
+ return new D2(index, storage);
case 3:
- return new ArrayBoolean.D3(index, storage);
+ return new D3(index, storage);
case 4:
- return new ArrayBoolean.D4(index, storage);
+ return new D4(index, storage);
case 5:
- return new ArrayBoolean.D5(index, storage);
+ return new D5(index, storage);
case 6:
- return new ArrayBoolean.D6(index, storage);
+ return new D6(index, storage);
case 7:
- return new ArrayBoolean.D7(index, storage);
+ return new D7(index, storage);
default:
return new ArrayBoolean(index, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayByte.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayByte.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayByte.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayByte.java
index 2f016c26..1947dc3f 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayByte.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayByte.java
@@ -62,21 +62,21 @@ public class ArrayByte extends Array {
static ArrayByte factory(Index index, boolean isUnsigned, byte[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayByte.D0(index, isUnsigned, storage);
+ return new D0(index, isUnsigned, storage);
case 1:
- return new ArrayByte.D1(index, isUnsigned, storage);
+ return new D1(index, isUnsigned, storage);
case 2:
- return new ArrayByte.D2(index, isUnsigned, storage);
+ return new D2(index, isUnsigned, storage);
case 3:
- return new ArrayByte.D3(index, isUnsigned, storage);
+ return new D3(index, isUnsigned, storage);
case 4:
- return new ArrayByte.D4(index, isUnsigned, storage);
+ return new D4(index, isUnsigned, storage);
case 5:
- return new ArrayByte.D5(index, isUnsigned, storage);
+ return new D5(index, isUnsigned, storage);
case 6:
- return new ArrayByte.D6(index, isUnsigned, storage);
+ return new D6(index, isUnsigned, storage);
case 7:
- return new ArrayByte.D7(index, isUnsigned, storage);
+ return new D7(index, isUnsigned, storage);
default:
return new ArrayByte(index, isUnsigned, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayChar.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayChar.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayChar.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayChar.java
index c706e65e..693c4298 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayChar.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayChar.java
@@ -63,21 +63,21 @@ public class ArrayChar extends Array {
static ArrayChar factory(Index index, char[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayChar.D0(index, storage);
+ return new D0(index, storage);
case 1:
- return new ArrayChar.D1(index, storage);
+ return new D1(index, storage);
case 2:
- return new ArrayChar.D2(index, storage);
+ return new D2(index, storage);
case 3:
- return new ArrayChar.D3(index, storage);
+ return new D3(index, storage);
case 4:
- return new ArrayChar.D4(index, storage);
+ return new D4(index, storage);
case 5:
- return new ArrayChar.D5(index, storage);
+ return new D5(index, storage);
case 6:
- return new ArrayChar.D6(index, storage);
+ return new D6(index, storage);
case 7:
- return new ArrayChar.D7(index, storage);
+ return new D7(index, storage);
default:
return new ArrayChar(index, storage);
}
@@ -909,10 +909,10 @@ public class ArrayChar extends Array {
*/
public ArrayObject make1DStringArray() {
int nelems = (getRank() == 0) ? 1 : (int) getSize() / indexCalc.getShape(getRank() - 1);
- Array sarr = Array.factory(String.class, new int[]{nelems});
+ Array sarr = factory(String.class, new int[]{nelems});
IndexIterator newsiter = sarr.getIndexIterator();
- ArrayChar.StringIterator siter = getStringIterator();
+ StringIterator siter = getStringIterator();
while (siter.hasNext()) {
newsiter.setObjectNext(siter.next());
}
@@ -927,7 +927,7 @@ public class ArrayChar extends Array {
* @return equivilent ArrayChar
*/
public static ArrayChar makeFromString(String s, int max) {
- ArrayChar result = new ArrayChar.D1(max);
+ ArrayChar result = new D1(max);
for (int i = 0; i < max && i < s.length(); i++) {
result.setChar(i, s.charAt(i));
}
@@ -985,7 +985,7 @@ public class ArrayChar extends Array {
}
// ready to create the char Array
- Array carr = Array.factory(char.class, shape, cdata);
+ Array carr = factory(char.class, shape, cdata);
return (ArrayChar) carr;
} catch (InvalidRangeException e) {
e.printStackTrace(); // cant happen.
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayComplex.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayComplex.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayComplex.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayComplex.java
index 1f6a304b..5da170ac 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayComplex.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayComplex.java
@@ -61,21 +61,21 @@ public class ArrayComplex extends Array {
static ArrayComplex factory(Index index, Complex[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayComplex.D0(index, storage);
+ return new D0(index, storage);
case 1:
- return new ArrayComplex.D1(index, storage);
+ return new D1(index, storage);
case 2:
- return new ArrayComplex.D2(index, storage);
+ return new D2(index, storage);
case 3:
- return new ArrayComplex.D3(index, storage);
+ return new D3(index, storage);
case 4:
- return new ArrayComplex.D4(index, storage);
+ return new D4(index, storage);
case 5:
- return new ArrayComplex.D5(index, storage);
+ return new D5(index, storage);
case 6:
- return new ArrayComplex.D6(index, storage);
+ return new D6(index, storage);
case 7:
- return new ArrayComplex.D7(index, storage);
+ return new D7(index, storage);
default:
return new ArrayComplex(index, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayDate.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDate.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayDate.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDate.java
index b8c72aa9..fc07cf79 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayDate.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDate.java
@@ -61,21 +61,21 @@ public class ArrayDate extends Array {
static ArrayDate factory(Index index, LocalDateTime[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayDate.D0(index, storage);
+ return new D0(index, storage);
case 1:
- return new ArrayDate.D1(index, storage);
+ return new D1(index, storage);
case 2:
- return new ArrayDate.D2(index, storage);
+ return new D2(index, storage);
case 3:
- return new ArrayDate.D3(index, storage);
+ return new D3(index, storage);
case 4:
- return new ArrayDate.D4(index, storage);
+ return new D4(index, storage);
case 5:
- return new ArrayDate.D5(index, storage);
+ return new D5(index, storage);
case 6:
- return new ArrayDate.D6(index, storage);
+ return new D6(index, storage);
case 7:
- return new ArrayDate.D7(index, storage);
+ return new D7(index, storage);
default:
return new ArrayDate(index, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java
index 8c98acff..e9c81c9f 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayDouble.java
@@ -61,21 +61,21 @@ public class ArrayDouble extends Array {
static ArrayDouble factory(Index index, double[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayDouble.D0(index, storage);
+ return new D0(index, storage);
case 1:
- return new ArrayDouble.D1(index, storage);
+ return new D1(index, storage);
case 2:
- return new ArrayDouble.D2(index, storage);
+ return new D2(index, storage);
case 3:
- return new ArrayDouble.D3(index, storage);
+ return new D3(index, storage);
case 4:
- return new ArrayDouble.D4(index, storage);
+ return new D4(index, storage);
case 5:
- return new ArrayDouble.D5(index, storage);
+ return new D5(index, storage);
case 6:
- return new ArrayDouble.D6(index, storage);
+ return new D6(index, storage);
case 7:
- return new ArrayDouble.D7(index, storage);
+ return new D7(index, storage);
default:
return new ArrayDouble(index, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayFloat.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayFloat.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayFloat.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayFloat.java
index f8f5411a..53adb578 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayFloat.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayFloat.java
@@ -64,21 +64,21 @@ public class ArrayFloat extends Array {
static ArrayFloat factory(Index index, float[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayFloat.D0(index, storage);
+ return new D0(index, storage);
case 1:
- return new ArrayFloat.D1(index, storage);
+ return new D1(index, storage);
case 2:
- return new ArrayFloat.D2(index, storage);
+ return new D2(index, storage);
case 3:
- return new ArrayFloat.D3(index, storage);
+ return new D3(index, storage);
case 4:
- return new ArrayFloat.D4(index, storage);
+ return new D4(index, storage);
case 5:
- return new ArrayFloat.D5(index, storage);
+ return new D5(index, storage);
case 6:
- return new ArrayFloat.D6(index, storage);
+ return new D6(index, storage);
case 7:
- return new ArrayFloat.D7(index, storage);
+ return new D7(index, storage);
default:
return new ArrayFloat(index, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayInt.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayInt.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayInt.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayInt.java
index a08011c6..b9462484 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayInt.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayInt.java
@@ -64,21 +64,21 @@ public class ArrayInt extends Array {
static ArrayInt factory(Index index, boolean isUnsigned, int[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayInt.D0(index, isUnsigned, storage);
+ return new D0(index, isUnsigned, storage);
case 1:
- return new ArrayInt.D1(index, isUnsigned, storage);
+ return new D1(index, isUnsigned, storage);
case 2:
- return new ArrayInt.D2(index, isUnsigned, storage);
+ return new D2(index, isUnsigned, storage);
case 3:
- return new ArrayInt.D3(index, isUnsigned, storage);
+ return new D3(index, isUnsigned, storage);
case 4:
- return new ArrayInt.D4(index, isUnsigned, storage);
+ return new D4(index, isUnsigned, storage);
case 5:
- return new ArrayInt.D5(index, isUnsigned, storage);
+ return new D5(index, isUnsigned, storage);
case 6:
- return new ArrayInt.D6(index, isUnsigned, storage);
+ return new D6(index, isUnsigned, storage);
case 7:
- return new ArrayInt.D7(index, isUnsigned, storage);
+ return new D7(index, isUnsigned, storage);
default:
return new ArrayInt(index, isUnsigned, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayLong.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayLong.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayLong.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayLong.java
index f90ac62a..a2530261 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayLong.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayLong.java
@@ -65,21 +65,21 @@ public class ArrayLong extends Array {
static ArrayLong factory(Index index, boolean isUnsigned, long[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayLong.D0(index, isUnsigned, storage);
+ return new D0(index, isUnsigned, storage);
case 1:
- return new ArrayLong.D1(index, isUnsigned, storage);
+ return new D1(index, isUnsigned, storage);
case 2:
- return new ArrayLong.D2(index, isUnsigned, storage);
+ return new D2(index, isUnsigned, storage);
case 3:
- return new ArrayLong.D3(index, isUnsigned, storage);
+ return new D3(index, isUnsigned, storage);
case 4:
- return new ArrayLong.D4(index, isUnsigned, storage);
+ return new D4(index, isUnsigned, storage);
case 5:
- return new ArrayLong.D5(index, isUnsigned, storage);
+ return new D5(index, isUnsigned, storage);
case 6:
- return new ArrayLong.D6(index, isUnsigned, storage);
+ return new D6(index, isUnsigned, storage);
case 7:
- return new ArrayLong.D7(index, isUnsigned, storage);
+ return new D7(index, isUnsigned, storage);
default:
return new ArrayLong(index, isUnsigned, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayObject.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayObject.java
similarity index 96%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayObject.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayObject.java
index 54910eef..3bac1d71 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayObject.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayObject.java
@@ -60,21 +60,21 @@ public class ArrayObject extends Array {
*/
static ArrayObject factory(DataType dtype, Class elemType, boolean isVlen, Index index, Object[] storage) {
if (index instanceof Index0D) {
- return new ArrayObject.D0(dtype, elemType, isVlen, index, storage);
+ return new D0(dtype, elemType, isVlen, index, storage);
} else if (index instanceof Index1D) {
- return new ArrayObject.D1(dtype, elemType, isVlen, index, storage);
+ return new D1(dtype, elemType, isVlen, index, storage);
} else if (index instanceof Index2D) {
- return new ArrayObject.D2(dtype, elemType, isVlen, index, storage);
+ return new D2(dtype, elemType, isVlen, index, storage);
} else if (index instanceof Index3D) {
- return new ArrayObject.D3(dtype, elemType, isVlen, index, storage);
+ return new D3(dtype, elemType, isVlen, index, storage);
} else if (index instanceof Index4D) {
- return new ArrayObject.D4(dtype, elemType, isVlen, index, storage);
+ return new D4(dtype, elemType, isVlen, index, storage);
} else if (index instanceof Index5D) {
- return new ArrayObject.D5(dtype, elemType, isVlen, index, storage);
+ return new D5(dtype, elemType, isVlen, index, storage);
} else if (index instanceof Index6D) {
- return new ArrayObject.D6(dtype, elemType, isVlen, index, storage);
+ return new D6(dtype, elemType, isVlen, index, storage);
} else if (index instanceof Index7D) {
- return new ArrayObject.D7(dtype, elemType, isVlen, index, storage);
+ return new D7(dtype, elemType, isVlen, index, storage);
} else {
return new ArrayObject(dtype, elemType, isVlen, index, storage);
}
@@ -138,7 +138,7 @@ public class ArrayObject extends Array {
* create new Array with given indexImpl and the same backing store
*/
protected Array createView(Index index) {
- return ArrayObject.factory(elementType, index, storage);
+ return factory(elementType, index, storage);
}
/**
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayRagged.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayRagged.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayRagged.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayRagged.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayScalar.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayScalar.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayScalar.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayScalar.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArraySequence.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArraySequence.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArraySequence.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArraySequence.java
index 6d4e619c..8d3ba542 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArraySequence.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArraySequence.java
@@ -32,7 +32,7 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.util.Indent;
+import org.meteoinfo.ndarray.util.Indent;
import java.io.IOException;
import java.util.ArrayList;
@@ -122,7 +122,7 @@ public class ArraySequence extends ArrayStructureBak {
StructureMembers membersw = new StructureMembers(proxym.getStructureMembers()); // no data arrays get propagated
result = new ArrayStructureW(membersw, rshape);
} else {
- result = Array.factory(dataType.getPrimitiveClassType(), rshape);
+ result = factory(dataType.getPrimitiveClassType(), rshape);
}
StructureDataIterator sdataIter = getStructureDataIterator();
@@ -357,7 +357,7 @@ public class ArraySequence extends ArrayStructureBak {
}
// create an array to hold the result
rshape[0] = count;
- return Array.factory(dataType.getPrimitiveClassType(), rshape, dataArray);
+ return factory(dataType.getPrimitiveClassType(), rshape, dataArray);
}
@Override
@@ -369,8 +369,8 @@ public class ArraySequence extends ArrayStructureBak {
public void showInternal(Formatter f, Indent indent) {
super.showInternal(f, indent);
f.format("%sStructureDataIterator Class=%s hash=0x%x%n", indent, iter.getClass().getName(), iter.hashCode());
- if (iter instanceof ArrayStructureBak.ArrayStructureIterator) {
- ArrayStructureBak.ArrayStructureIterator ii = (ArrayStructureBak.ArrayStructureIterator) iter;
+ if (iter instanceof ArrayStructureIterator) {
+ ArrayStructureIterator ii = (ArrayStructureIterator) iter;
ii.getArrayStructure().showInternal(f, indent.incr());
indent.decr();
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArraySequenceNested.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArraySequenceNested.java
similarity index 98%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArraySequenceNested.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArraySequenceNested.java
index e4385b65..79dc451e 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArraySequenceNested.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArraySequenceNested.java
@@ -64,7 +64,7 @@ public class ArraySequenceNested extends ArrayStructureBak {
}
// not sure how this is used
- protected StructureData makeStructureData( ArrayStructureBak as, int index) {
+ protected StructureData makeStructureData(ArrayStructureBak as, int index) {
return new StructureDataA( as, index);
}
@@ -123,7 +123,7 @@ public class ArraySequenceNested extends ArrayStructureBak {
System.arraycopy(mShape, 0, shape, 1, mShape.length);
// LOOK not doing nested structures
- Array data = Array.factory(m.getDataType(), shape);
+ Array data = factory(m.getDataType(), shape);
m.setDataArray(data);
}
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayShort.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayShort.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayShort.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayShort.java
index bf98af47..3df56a23 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayShort.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayShort.java
@@ -63,21 +63,21 @@ public class ArrayShort extends Array {
static ArrayShort factory(Index index, boolean isUnsigned, short[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayShort.D0(index, isUnsigned, storage);
+ return new D0(index, isUnsigned, storage);
case 1:
- return new ArrayShort.D1(index, isUnsigned, storage);
+ return new D1(index, isUnsigned, storage);
case 2:
- return new ArrayShort.D2(index, isUnsigned, storage);
+ return new D2(index, isUnsigned, storage);
case 3:
- return new ArrayShort.D3(index, isUnsigned, storage);
+ return new D3(index, isUnsigned, storage);
case 4:
- return new ArrayShort.D4(index, isUnsigned, storage);
+ return new D4(index, isUnsigned, storage);
case 5:
- return new ArrayShort.D5(index, isUnsigned, storage);
+ return new D5(index, isUnsigned, storage);
case 6:
- return new ArrayShort.D6(index, isUnsigned, storage);
+ return new D6(index, isUnsigned, storage);
case 7:
- return new ArrayShort.D7(index, isUnsigned, storage);
+ return new D7(index, isUnsigned, storage);
default:
return new ArrayShort(index, isUnsigned, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayString.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayString.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayString.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayString.java
index 9d433975..ba9722a9 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayString.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayString.java
@@ -61,21 +61,21 @@ public class ArrayString extends Array {
static ArrayString factory(Index index, String[] storage) {
switch (index.getRank()) {
case 0:
- return new ArrayString.D0(index, storage);
+ return new D0(index, storage);
case 1:
- return new ArrayString.D1(index, storage);
+ return new D1(index, storage);
case 2:
- return new ArrayString.D2(index, storage);
+ return new D2(index, storage);
case 3:
- return new ArrayString.D3(index, storage);
+ return new D3(index, storage);
case 4:
- return new ArrayString.D4(index, storage);
+ return new D4(index, storage);
case 5:
- return new ArrayString.D5(index, storage);
+ return new D5(index, storage);
case 6:
- return new ArrayString.D6(index, storage);
+ return new D6(index, storage);
case 7:
- return new ArrayString.D7(index, storage);
+ return new D7(index, storage);
default:
return new ArrayString(index, storage);
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructure.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructure.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructure.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructure.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBB.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBB.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBB.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBB.java
index 02a81e4a..885f739c 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBB.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBB.java
@@ -32,14 +32,14 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.ndarry.constants.CDM;
-import org.meteoinfo.util.Indent;
+import org.meteoinfo.ndarray.constants.CDM;
+import org.meteoinfo.ndarray.util.Indent;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
-import java.util.ArrayList;
/**
* Concrete implementation of ArrayStructure, data storage is in a ByteBuffer, which is converted to member data on the fly.
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBBpos.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBBpos.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBBpos.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBBpos.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBBsection.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBBsection.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBBsection.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBBsection.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBak.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBak.java
similarity index 98%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBak.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBak.java
index 59ac2b10..8ea7c762 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureBak.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureBak.java
@@ -32,13 +32,13 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.util.Indent;
+import org.meteoinfo.ndarray.util.Indent;
import java.io.IOException;
+import java.nio.ByteBuffer;
import java.time.LocalDateTime;
import java.util.Formatter;
import java.util.List;
-import java.nio.ByteBuffer;
/**
* Superclass for implementations of Array of StructureData.
@@ -319,35 +319,35 @@ public abstract class ArrayStructureBak extends Array {
if (dataType == DataType.DOUBLE) {
double[] pa = getJavaArrayDouble(recno, m);
- return Array.factory(double.class, m.getShape(), pa);
+ return factory(double.class, m.getShape(), pa);
} else if (dataType == DataType.FLOAT) {
float[] pa = getJavaArrayFloat(recno, m);
- return Array.factory(float.class, m.getShape(), pa);
+ return factory(float.class, m.getShape(), pa);
} else if ((dataType == DataType.BYTE) || (dataType == DataType.ENUM1)) {
byte[] pa = getJavaArrayByte(recno, m);
- return Array.factory(byte.class, m.getShape(), pa);
+ return factory(byte.class, m.getShape(), pa);
} else if ((dataType == DataType.SHORT) || (dataType == DataType.ENUM2)) {
short[] pa = getJavaArrayShort(recno, m);
- return Array.factory(short.class, m.getShape(), pa);
+ return factory(short.class, m.getShape(), pa);
} else if ((dataType == DataType.INT) || (dataType == DataType.ENUM4)) {
int[] pa = getJavaArrayInt(recno, m);
- return Array.factory(int.class, m.getShape(), pa);
+ return factory(int.class, m.getShape(), pa);
} else if (dataType == DataType.LONG) {
long[] pa = getJavaArrayLong(recno, m);
- return Array.factory(long.class, m.getShape(), pa);
+ return factory(long.class, m.getShape(), pa);
} else if (dataType == DataType.CHAR) {
char[] pa = getJavaArrayChar(recno, m);
- return Array.factory(char.class, m.getShape(), pa);
+ return factory(char.class, m.getShape(), pa);
} else if (dataType == DataType.STRING) {
String[] pa = getJavaArrayString(recno, m);
- return Array.factory(String.class, m.getShape(), pa);
+ return factory(String.class, m.getShape(), pa);
} else if (dataType == DataType.STRUCTURE) {
return getArrayStructure(recno, m);
@@ -382,7 +382,7 @@ public abstract class ArrayStructureBak extends Array {
*
* @param m get data from this StructureMembers.Member.
* @return Array values.
- * @throws java.io.IOException on read error (only happens for Sequences, otherwise data is already read)
+ * @throws IOException on read error (only happens for Sequences, otherwise data is already read)
*/
public Array extractMemberArray(StructureMembers.Member m) throws IOException {
if (m.getDataArray() != null)
@@ -421,7 +421,7 @@ public abstract class ArrayStructureBak extends Array {
result = new ArrayObject(dataType, ByteBuffer.class, false, rshape);
} else {
- result = Array.factory(dataType.getPrimitiveClassType(), rshape);
+ result = factory(dataType.getPrimitiveClassType(), rshape);
}
IndexIterator resultIter = result.getIndexIterator();
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureComposite.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureComposite.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureComposite.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureComposite.java
index 957e5165..7145108d 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureComposite.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureComposite.java
@@ -33,8 +33,8 @@
package org.meteoinfo.ndarray;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
/**
* An ArrayStructure compose of other ArrayStructures.
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureMA.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureMA.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureMA.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureMA.java
index c2284769..0b5694c3 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureMA.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureMA.java
@@ -210,7 +210,7 @@ public class ArrayStructureMA extends ArrayStructureBak {
* Turn any ArrayStructure into a ArrayStructureMA
* @param from copy from here. If from is a ArrayStructureMA, return it.
* @return equivilent ArrayStructureMA
- * @throws java.io.IOException on error reading a sequence
+ * @throws IOException on error reading a sequence
*/
static public ArrayStructureMA factoryMA(ArrayStructureBak from) throws IOException {
if (from instanceof ArrayStructureMA)
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureW.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureW.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ArrayStructureW.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ArrayStructureW.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Complex.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Complex.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Complex.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Complex.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/DataType.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/DataType.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/DataType.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/DataType.java
index 621d229d..c1d5cd36 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/DataType.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/DataType.java
@@ -32,8 +32,6 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.data.meteodata.arl.DataLabel;
-
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.time.LocalDateTime;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/DimArray.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/DimArray.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/DimArray.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/DimArray.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Dimension.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Dimension.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Dimension.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Dimension.java
index 738fc8af..7022626f 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Dimension.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Dimension.java
@@ -13,9 +13,10 @@
*/
package org.meteoinfo.ndarray;
+import org.meteoinfo.ndarray.util.BigDecimalUtil;
+
import java.util.ArrayList;
import java.util.List;
-import org.meteoinfo.global.util.BigDecimalUtil;
/**
* Template
@@ -563,9 +564,9 @@ public class Dimension {
}
}
- if (this.reverse) {
+ /*if (this.reverse) {
idx = this.getLength() - idx - 1;
- }
+ }*/
return idx;
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/DimensionType.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/DimensionType.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/DimensionType.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/DimensionType.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ForbiddenConversionException.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ForbiddenConversionException.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/ForbiddenConversionException.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/ForbiddenConversionException.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index0D.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index0D.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index0D.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index0D.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index1D.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index1D.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index1D.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index1D.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index2D.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index2D.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index2D.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index2D.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index3D.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index3D.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index3D.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index3D.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index4D.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index4D.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index4D.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index4D.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index5D.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index5D.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index5D.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index5D.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index6D.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index6D.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index6D.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index6D.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index7D.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index7D.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Index7D.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Index7D.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/IndexConstant.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/IndexConstant.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/IndexConstant.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/IndexConstant.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/IndexIterator.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/IndexIterator.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/IndexIterator.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/IndexIterator.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/InvalidRangeException.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/InvalidRangeException.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/InvalidRangeException.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/InvalidRangeException.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/IsMissingEvaluator.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/IsMissingEvaluator.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/IsMissingEvaluator.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/IsMissingEvaluator.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/IteratorFast.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/IteratorFast.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/IteratorFast.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/IteratorFast.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/MAMath.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MAMath.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/MAMath.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MAMath.java
index 982b5969..7f353531 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/MAMath.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MAMath.java
@@ -32,7 +32,7 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.util.Misc;
+import org.meteoinfo.ndarray.util.Misc;
/**
* Element by element algebra on Arrays
@@ -481,7 +481,7 @@ public class MAMath {
* @param a the array.
* @return MinMax
*/
- public static MAMath.MinMax getMinMax(Array a) {
+ public static MinMax getMinMax(Array a) {
IndexIterator iter = a.getIndexIterator();
double max = -Double.MAX_VALUE;
double min = Double.MAX_VALUE;
@@ -496,7 +496,7 @@ public class MAMath {
return new MinMax(min, max);
}
- public static MAMath.MinMax getMinMaxSkipMissingData(Array a, IsMissingEvaluator eval) {
+ public static MinMax getMinMaxSkipMissingData(Array a, IsMissingEvaluator eval) {
if (!eval.hasMissing())
return MAMath.getMinMax(a);
@@ -512,7 +512,7 @@ public class MAMath {
if (val < min)
min = val;
}
- return new MAMath.MinMax(min, max);
+ return new MinMax(min, max);
}
@@ -538,7 +538,7 @@ public class MAMath {
return max;
}
- public static MAMath.MinMax getMinMaxSkipMissingData(Array a, double missingValue) {
+ public static MinMax getMinMaxSkipMissingData(Array a, double missingValue) {
IndexIterator iter = a.getIndexIterator();
double max = -Double.MAX_VALUE;
double min = Double.MAX_VALUE;
@@ -648,8 +648,8 @@ public class MAMath {
* @param isUnsigned use signed or unsigned packed values
* @return ScaleOffset, calculated as above.
*/
- public static MAMath.ScaleOffset calcScaleOffsetSkipMissingData(Array a, double missingValue, int nbits, boolean isUnsigned) {
- MAMath.MinMax minmax = getMinMaxSkipMissingData(a, missingValue);
+ public static ScaleOffset calcScaleOffsetSkipMissingData(Array a, double missingValue, int nbits, boolean isUnsigned) {
+ MinMax minmax = getMinMaxSkipMissingData(a, missingValue);
if (isUnsigned) {
long size = (1L << nbits) - 1;
@@ -666,7 +666,7 @@ public class MAMath {
}
public static Array convert2packed(Array unpacked, double missingValue, int nbits, boolean isUnsigned, DataType packedType) {
- MAMath.ScaleOffset scaleOffset = calcScaleOffsetSkipMissingData(unpacked, missingValue, nbits, isUnsigned);
+ ScaleOffset scaleOffset = calcScaleOffsetSkipMissingData(unpacked, missingValue, nbits, isUnsigned);
Array result = Array.factory(packedType, unpacked.getShape());
IndexIterator riter = result.getIndexIterator();
while (unpacked.hasNext()) {
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/MAMatrix.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MAMatrix.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/MAMatrix.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MAMatrix.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/MAVector.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MAVector.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/MAVector.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/MAVector.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Range.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Range.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Range.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Range.java
index b80ac88a..50cccbdc 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Range.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Range.java
@@ -34,9 +34,8 @@
package org.meteoinfo.ndarray;
import javax.annotation.concurrent.Immutable;
-
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
import java.util.StringTokenizer;
/**
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Section.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Section.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Section.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Section.java
index 119826c7..e9757971 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/Section.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/Section.java
@@ -33,7 +33,10 @@
package org.meteoinfo.ndarray;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.StringTokenizer;
/**
* A section of multidimensional array indices.
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/SequenceIterator.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/SequenceIterator.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/SequenceIterator.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/SequenceIterator.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureData.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureData.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureData.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureData.java
index 1d1a7aed..e5defc8b 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureData.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureData.java
@@ -32,7 +32,7 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.util.Indent;
+import org.meteoinfo.ndarray.util.Indent;
import java.util.Formatter;
import java.util.List;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataA.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataA.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataA.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataA.java
index dbaff74d..4897fef3 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataA.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataA.java
@@ -32,7 +32,7 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.util.Indent;
+import org.meteoinfo.ndarray.util.Indent;
import java.util.Formatter;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataComposite.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataComposite.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataComposite.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataComposite.java
index 665a9528..f37826d4 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataComposite.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataComposite.java
@@ -32,8 +32,8 @@
*/
package org.meteoinfo.ndarray;
-import java.util.Map;
import java.util.HashMap;
+import java.util.Map;
/**
* A composite of other StructureData.
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java
index c42d9a6d..53db7cbc 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataDeep.java
@@ -33,10 +33,11 @@
package org.meteoinfo.ndarray;
+import org.meteoinfo.ndarray.util.Converter;
+
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import org.meteoinfo.util.Converter;
/**
* Make a deep copy of an existing StructureData, so that all the data is contained in this object
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataFactory.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataFactory.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataFactory.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataFactory.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataIterator.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataIterator.java
similarity index 97%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataIterator.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataIterator.java
index 4b739478..b02244af 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataIterator.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataIterator.java
@@ -56,7 +56,7 @@ public interface StructureDataIterator {
* You must always call this before calling next().
*
* @return true if more records are available
- * @throws java.io.IOException on read error
+ * @throws IOException on read error
*/
public boolean hasNext() throws IOException;
@@ -64,7 +64,7 @@ public interface StructureDataIterator {
* Get the next StructureData in the iteration.
*
* @return next StructureData record.
- * @throws java.io.IOException on read error
+ * @throws IOException on read error
*/
public StructureData next() throws IOException;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataIteratorLimited.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataIteratorLimited.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataIteratorLimited.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataIteratorLimited.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataIteratorMediated.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataIteratorMediated.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataIteratorMediated.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataIteratorMediated.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataMediator.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataMediator.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataMediator.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataMediator.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataProxy.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataProxy.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataProxy.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataProxy.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataScalar.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataScalar.java
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataScalar.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataScalar.java
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataW.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataW.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataW.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataW.java
index 0e83a552..9ac2205c 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureDataW.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureDataW.java
@@ -32,7 +32,7 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.util.Indent;
+import org.meteoinfo.ndarray.util.Indent;
import java.util.Formatter;
import java.util.HashMap;
@@ -47,7 +47,7 @@ import java.util.Map;
*/
public class StructureDataW extends StructureData {
- protected final Map memberData;
+ protected final Map memberData;
/**
* Constructor.
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureMembers.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureMembers.java
similarity index 98%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureMembers.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureMembers.java
index 886d4d6a..73bea837 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/StructureMembers.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/StructureMembers.java
@@ -32,7 +32,7 @@
*/
package org.meteoinfo.ndarray;
-import org.meteoinfo.util.Indent;
+import org.meteoinfo.ndarray.util.Indent;
import java.util.*;
@@ -147,7 +147,7 @@ public class StructureMembers {
*
* @return the list of Member objects.
*/
- public java.util.List getMembers() {
+ public List getMembers() {
return members;
}
@@ -157,7 +157,7 @@ public class StructureMembers {
*
* @return List of type String.
*/
- public java.util.List getMemberNames() {
+ public List getMemberNames() {
List memberNames = new ArrayList<>();
for (Member m : members) {
memberNames.add(m.getName());
@@ -411,7 +411,7 @@ public class StructureMembers {
if (members != null) {
indent.incr();
f.format("%n%sNested members %s%n", indent, members.getName());
- for (StructureMembers.Member m : members.getMembers())
+ for (Member m : members.getMembers())
m.showInternal(f, indent);
indent.decr();
}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarry/constants/CDM.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/constants/CDM.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarry/constants/CDM.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/constants/CDM.java
index 6f875b19..de3182ad 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarry/constants/CDM.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/constants/CDM.java
@@ -31,7 +31,7 @@
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-package org.meteoinfo.ndarry.constants;
+package org.meteoinfo.ndarray.constants;
import java.nio.charset.Charset;
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/package.html b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/package.html
similarity index 100%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/ndarray/package.html
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/package.html
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/BigDecimalUtil.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/BigDecimalUtil.java
similarity index 95%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/global/util/BigDecimalUtil.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/BigDecimalUtil.java
index c04ef583..43316ca1 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/global/util/BigDecimalUtil.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/BigDecimalUtil.java
@@ -1,142 +1,142 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.meteoinfo.global.util;
-
-import java.math.BigDecimal;
-import java.math.MathContext;
-
-/**
- *
- * @author wyq
- */
-public class BigDecimalUtil {
- /**
- * Float to double
- * @param v Float value
- * @return Double value
- */
- public static double toDouble(float v){
- return Double.parseDouble(Float.toString(v));
- }
-
- /**
- * Double to float
- * @param v Double value
- * @return Float value
- */
- public static float toFloat(double v) {
- BigDecimal b = new BigDecimal(v);
- return b.floatValue();
- }
-
- /**
- * Add
- * @param d1 Value1
- * @param d2 Value2
- * @return Add result
- */
- public static double add(double d1,double d2){
- BigDecimal b1=new BigDecimal(Double.toString(d1));
- BigDecimal b2=new BigDecimal(Double.toString(d2));
- return b1.add(b2).doubleValue();
- }
-
- /**
- * Add
- * @param d1 Value1
- * @param d2 Value2
- * @return Add result
- */
- public static double add(float d1,float d2){
- BigDecimal b1=new BigDecimal(Float.toString(d1));
- BigDecimal b2=new BigDecimal(Float.toString(d2));
- return b1.add(b2).doubleValue();
- }
-
- /**
- * Substract
- * @param d1 Value1
- * @param d2 Value2
- * @return Substract result
- */
- public static double sub(double d1,double d2){
- BigDecimal b1=new BigDecimal(Double.toString(d1));
- BigDecimal b2=new BigDecimal(Double.toString(d2));
- return b1.subtract(b2).doubleValue();
- }
-
- /**
- * Multiply
- * @param d1 Value1
- * @param d2 Value2
- * @return Multiply result
- */
- public static double mul(double d1,double d2){
- BigDecimal b1=new BigDecimal(Double.toString(d1));
- BigDecimal b2=new BigDecimal(Double.toString(d2));
- return b1.multiply(b2).doubleValue();
- }
-
- /**
- * Multiply
- * @param d1 Value1
- * @param d2 Value2
- * @return Multiply result
- */
- public static double mul(float d1,float d2){
- BigDecimal b1=new BigDecimal(Float.toString(d1));
- BigDecimal b2=new BigDecimal(Float.toString(d2));
- return b1.multiply(b2).doubleValue();
- }
-
- /**
- * Divide
- * @param d1 Value1
- * @param d2 Value2
- * @return Divide result
- */
- public static double div(double d1,double d2){
- return div(d1,d2,20);
- }
-
- /**
- * Divide
- * @param d1 Value1
- * @param d2 Value2
- * @param scale Scale
- * @return Divide result
- */
- public static double div(double d1,double d2,int scale){
- if(scale<0){
- throw new IllegalArgumentException("The scale must be a positive integer or zero");
- }
- BigDecimal b1=new BigDecimal(Double.toString(d1));
- BigDecimal b2=new BigDecimal(Double.toString(d2));
- return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
- }
-
- /**
- * Power
- * @param d1 Value1
- * @param d2 Value2
- * @return Power value
- */
- public static double pow(double d1,int d2){
- BigDecimal b1=new BigDecimal(Double.toString(d1));
- return b1.pow(d2, new MathContext(10)).doubleValue();
- }
-
- /**
- * Mod
- * @param d1 Value 1
- * @param d2 Value 2
- * @return Mod value
- */
- public static double mod(double d1, double d2) {
- BigDecimal b1=new BigDecimal(Double.toString(d1));
- BigDecimal b2=new BigDecimal(Double.toString(d2));
- return b1.divideAndRemainder(b2)[1].doubleValue();
- }
-}
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.meteoinfo.ndarray.util;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+/**
+ *
+ * @author wyq
+ */
+public class BigDecimalUtil {
+ /**
+ * Float to double
+ * @param v Float value
+ * @return Double value
+ */
+ public static double toDouble(float v){
+ return Double.parseDouble(Float.toString(v));
+ }
+
+ /**
+ * Double to float
+ * @param v Double value
+ * @return Float value
+ */
+ public static float toFloat(double v) {
+ BigDecimal b = new BigDecimal(v);
+ return b.floatValue();
+ }
+
+ /**
+ * Add
+ * @param d1 Value1
+ * @param d2 Value2
+ * @return Add result
+ */
+ public static double add(double d1,double d2){
+ BigDecimal b1=new BigDecimal(Double.toString(d1));
+ BigDecimal b2=new BigDecimal(Double.toString(d2));
+ return b1.add(b2).doubleValue();
+ }
+
+ /**
+ * Add
+ * @param d1 Value1
+ * @param d2 Value2
+ * @return Add result
+ */
+ public static double add(float d1,float d2){
+ BigDecimal b1=new BigDecimal(Float.toString(d1));
+ BigDecimal b2=new BigDecimal(Float.toString(d2));
+ return b1.add(b2).doubleValue();
+ }
+
+ /**
+ * Substract
+ * @param d1 Value1
+ * @param d2 Value2
+ * @return Substract result
+ */
+ public static double sub(double d1,double d2){
+ BigDecimal b1=new BigDecimal(Double.toString(d1));
+ BigDecimal b2=new BigDecimal(Double.toString(d2));
+ return b1.subtract(b2).doubleValue();
+ }
+
+ /**
+ * Multiply
+ * @param d1 Value1
+ * @param d2 Value2
+ * @return Multiply result
+ */
+ public static double mul(double d1,double d2){
+ BigDecimal b1=new BigDecimal(Double.toString(d1));
+ BigDecimal b2=new BigDecimal(Double.toString(d2));
+ return b1.multiply(b2).doubleValue();
+ }
+
+ /**
+ * Multiply
+ * @param d1 Value1
+ * @param d2 Value2
+ * @return Multiply result
+ */
+ public static double mul(float d1,float d2){
+ BigDecimal b1=new BigDecimal(Float.toString(d1));
+ BigDecimal b2=new BigDecimal(Float.toString(d2));
+ return b1.multiply(b2).doubleValue();
+ }
+
+ /**
+ * Divide
+ * @param d1 Value1
+ * @param d2 Value2
+ * @return Divide result
+ */
+ public static double div(double d1,double d2){
+ return div(d1,d2,20);
+ }
+
+ /**
+ * Divide
+ * @param d1 Value1
+ * @param d2 Value2
+ * @param scale Scale
+ * @return Divide result
+ */
+ public static double div(double d1,double d2,int scale){
+ if(scale<0){
+ throw new IllegalArgumentException("The scale must be a positive integer or zero");
+ }
+ BigDecimal b1=new BigDecimal(Double.toString(d1));
+ BigDecimal b2=new BigDecimal(Double.toString(d2));
+ return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
+ }
+
+ /**
+ * Power
+ * @param d1 Value1
+ * @param d2 Value2
+ * @return Power value
+ */
+ public static double pow(double d1,int d2){
+ BigDecimal b1=new BigDecimal(Double.toString(d1));
+ return b1.pow(d2, new MathContext(10)).doubleValue();
+ }
+
+ /**
+ * Mod
+ * @param d1 Value 1
+ * @param d2 Value 2
+ * @return Mod value
+ */
+ public static double mod(double d1, double d2) {
+ BigDecimal b1=new BigDecimal(Double.toString(d1));
+ BigDecimal b2=new BigDecimal(Double.toString(d2));
+ return b1.divideAndRemainder(b2)[1].doubleValue();
+ }
+}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/util/Converter.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Converter.java
similarity index 92%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/util/Converter.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Converter.java
index 384e95f5..c325e518 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/util/Converter.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Converter.java
@@ -1,53 +1,54 @@
-/*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.meteoinfo.util;
-
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import org.meteoinfo.ndarry.constants.CDM;
-import org.meteoinfo.ndarray.DataType;
-
-/**
- *
- * @author wyq
- */
-public class Converter {
- // convert byte array to char array, assuming UTF-8 encoding
-
- static public char[] convertByteToCharUTF(byte[] byteArray) {
- Charset c = CDM.utf8Charset;
- CharBuffer output = c.decode(ByteBuffer.wrap(byteArray));
- return output.array();
- }
-
- // convert char array to byte array, assuming UTF-8 encoding
- static public byte[] convertCharToByteUTF(char[] from) {
- Charset c = CDM.utf8Charset;
- ByteBuffer output = c.encode(CharBuffer.wrap(from));
- return output.array();
- }
-
- // convert byte array to char array
- static public char[] convertByteToChar(byte[] byteArray) {
- int size = byteArray.length;
- char[] cbuff = new char[size];
- for (int i = 0; i < size; i++) {
- cbuff[i] = (char) DataType.unsignedByteToShort(byteArray[i]); // NOTE: not Unicode !
- }
- return cbuff;
- }
-
- // convert char array to byte array
- static public byte[] convertCharToByte(char[] from) {
- int size = from.length;
- byte[] to = new byte[size];
- for (int i = 0; i < size; i++) {
- to[i] = (byte) from[i]; // LOOK wrong, convert back to unsigned byte ???
- }
- return to;
- }
-}
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.meteoinfo.ndarray.util;
+
+import org.meteoinfo.ndarray.DataType;
+import org.meteoinfo.ndarray.constants.CDM;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+
+/**
+ *
+ * @author wyq
+ */
+public class Converter {
+ // convert byte array to char array, assuming UTF-8 encoding
+
+ static public char[] convertByteToCharUTF(byte[] byteArray) {
+ Charset c = CDM.utf8Charset;
+ CharBuffer output = c.decode(ByteBuffer.wrap(byteArray));
+ return output.array();
+ }
+
+ // convert char array to byte array, assuming UTF-8 encoding
+ static public byte[] convertCharToByteUTF(char[] from) {
+ Charset c = CDM.utf8Charset;
+ ByteBuffer output = c.encode(CharBuffer.wrap(from));
+ return output.array();
+ }
+
+ // convert byte array to char array
+ static public char[] convertByteToChar(byte[] byteArray) {
+ int size = byteArray.length;
+ char[] cbuff = new char[size];
+ for (int i = 0; i < size; i++) {
+ cbuff[i] = (char) DataType.unsignedByteToShort(byteArray[i]); // NOTE: not Unicode !
+ }
+ return cbuff;
+ }
+
+ // convert char array to byte array
+ static public byte[] convertCharToByte(char[] from) {
+ int size = from.length;
+ byte[] to = new byte[size];
+ for (int i = 0; i < size; i++) {
+ to[i] = (byte) from[i]; // LOOK wrong, convert back to unsigned byte ???
+ }
+ return to;
+ }
+}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/util/Indent.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Indent.java
similarity index 96%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/util/Indent.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Indent.java
index 2b80a914..ed81fcea 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/util/Indent.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Indent.java
@@ -1,82 +1,82 @@
-/*
- * Copyright (c) 1998 - 2009. University Corporation for Atmospheric Research/Unidata
- * Portions of this software were developed by the Unidata Program at the
- * University Corporation for Atmospheric Research.
- *
- * Access and use of this software shall impose the following obligations
- * and understandings on the user. The user is granted the right, without
- * any fee or cost, to use, copy, modify, alter, enhance and distribute
- * this software, and any derivative works thereof, and its supporting
- * documentation for any purpose whatsoever, provided that this entire
- * notice appears in all copies of the software, derivative works and
- * supporting documentation. Further, UCAR requests that the user credit
- * UCAR/Unidata in any publications that result from the use of this
- * software or in any product that includes this software. The names UCAR
- * and/or Unidata, however, may not be used in any advertising or publicity
- * to endorse or promote any products or commercial entity unless specific
- * written permission is obtained from UCAR/Unidata. The user also
- * understands that UCAR/Unidata is not obligated to provide the user with
- * any support, consulting, training or assistance of any kind with regard
- * to the use, operation and performance of this software nor to provide
- * the user with any updates, revisions, new versions or "bug fixes."
- *
- * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
- * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
- * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-package org.meteoinfo.util;
-
-/**
- * Maintains indentation level for printing nested structures.
- */
-public class Indent {
- private int nspaces = 0;
-
- private int level = 0;
- private StringBuilder blanks;
- private String indent = "";
-
- // nspaces = how many spaces each level adds.
- // max 100 levels
- public Indent(int nspaces) {
- this.nspaces = nspaces;
- blanks = new StringBuilder();
- for (int i = 0; i < 100 * nspaces; i++)
- blanks.append(" ");
- }
-
- public Indent incr() {
- level++;
- setIndentLevel(level);
- return this;
- }
-
- public Indent decr() {
- level--;
- setIndentLevel(level);
- return this;
- }
-
- public int level() {
- return level;
- }
-
- @Override
- public String toString() {
- return indent;
- }
-
- public void setIndentLevel(int level) {
- this.level = level;
- if (level * nspaces >= blanks.length())
- System.out.printf("HEY setIndentLevel!%n");
- int end = Math.min(level * nspaces, blanks.length());
- indent = blanks.substring(0, end);
- }
-}
+/*
+ * Copyright (c) 1998 - 2009. University Corporation for Atmospheric Research/Unidata
+ * Portions of this software were developed by the Unidata Program at the
+ * University Corporation for Atmospheric Research.
+ *
+ * Access and use of this software shall impose the following obligations
+ * and understandings on the user. The user is granted the right, without
+ * any fee or cost, to use, copy, modify, alter, enhance and distribute
+ * this software, and any derivative works thereof, and its supporting
+ * documentation for any purpose whatsoever, provided that this entire
+ * notice appears in all copies of the software, derivative works and
+ * supporting documentation. Further, UCAR requests that the user credit
+ * UCAR/Unidata in any publications that result from the use of this
+ * software or in any product that includes this software. The names UCAR
+ * and/or Unidata, however, may not be used in any advertising or publicity
+ * to endorse or promote any products or commercial entity unless specific
+ * written permission is obtained from UCAR/Unidata. The user also
+ * understands that UCAR/Unidata is not obligated to provide the user with
+ * any support, consulting, training or assistance of any kind with regard
+ * to the use, operation and performance of this software nor to provide
+ * the user with any updates, revisions, new versions or "bug fixes."
+ *
+ * THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+package org.meteoinfo.ndarray.util;
+
+/**
+ * Maintains indentation level for printing nested structures.
+ */
+public class Indent {
+ private int nspaces = 0;
+
+ private int level = 0;
+ private StringBuilder blanks;
+ private String indent = "";
+
+ // nspaces = how many spaces each level adds.
+ // max 100 levels
+ public Indent(int nspaces) {
+ this.nspaces = nspaces;
+ blanks = new StringBuilder();
+ for (int i = 0; i < 100 * nspaces; i++)
+ blanks.append(" ");
+ }
+
+ public Indent incr() {
+ level++;
+ setIndentLevel(level);
+ return this;
+ }
+
+ public Indent decr() {
+ level--;
+ setIndentLevel(level);
+ return this;
+ }
+
+ public int level() {
+ return level;
+ }
+
+ @Override
+ public String toString() {
+ return indent;
+ }
+
+ public void setIndentLevel(int level) {
+ this.level = level;
+ if (level * nspaces >= blanks.length())
+ System.out.printf("HEY setIndentLevel!%n");
+ int end = Math.min(level * nspaces, blanks.length());
+ indent = blanks.substring(0, end);
+ }
+}
diff --git a/MeteoInfoLib/src/main/java/org/meteoinfo/util/Misc.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Misc.java
similarity index 99%
rename from MeteoInfoLib/src/main/java/org/meteoinfo/util/Misc.java
rename to meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Misc.java
index 22be419e..250439df 100644
--- a/MeteoInfoLib/src/main/java/org/meteoinfo/util/Misc.java
+++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/util/Misc.java
@@ -31,9 +31,7 @@
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-package org.meteoinfo.util;
-
-import com.google.common.primitives.Floats;
+package org.meteoinfo.ndarray.util;
import java.io.File;
import java.io.FileInputStream;
diff --git a/pom.xml b/pom.xml
index dc341db0..02465bfa 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,7 +3,7 @@
4.0.0
org.meteothink
MeteoInfo
- 2.4.6
+ 3.0.0
pom
@@ -17,6 +17,7 @@
MeteoInfoMap
MeteoInfoLab
meteoinfo-console
+ meteoinfo-ndarray