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) 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); - } - - // - // - // -} +/* + * 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