mirror of
https://github.com/meteoinfo/MeteoInfo.git
synced 2025-12-08 20:36:05 +00:00
add ColorTransferFunction class
This commit is contained in:
parent
0e4757e8fe
commit
f2441b13a7
@ -1,8 +1,7 @@
|
||||
package org.meteoinfo.chart.graphic;
|
||||
|
||||
import com.jogamp.common.nio.Buffers;
|
||||
import org.meteoinfo.chart.jogl.Transform;
|
||||
import org.meteoinfo.chart.render.TransferFunction;
|
||||
import org.meteoinfo.geometry.colors.TransferFunction;
|
||||
import org.meteoinfo.chart.render.jogl.RayCastingType;
|
||||
import org.meteoinfo.common.Extent3D;
|
||||
import org.meteoinfo.common.MIMath;
|
||||
@ -12,10 +11,8 @@ import org.meteoinfo.geometry.colors.Normalize;
|
||||
import org.meteoinfo.geometry.legend.LegendScheme;
|
||||
import org.meteoinfo.geometry.shape.ShapeTypes;
|
||||
import org.meteoinfo.ndarray.Array;
|
||||
import org.meteoinfo.ndarray.math.ArrayMath;
|
||||
|
||||
import java.awt.*;
|
||||
import java.nio.Buffer;
|
||||
import java.util.List;
|
||||
|
||||
import static org.joml.Math.clamp;
|
||||
|
||||
@ -19,7 +19,7 @@ import org.meteoinfo.chart.graphic.VolumeGraphics;
|
||||
import org.meteoinfo.chart.jogl.mc.CallbackMC;
|
||||
import org.meteoinfo.chart.jogl.mc.MarchingCubes;
|
||||
import org.meteoinfo.chart.graphic.GraphicCollection3D;
|
||||
import org.meteoinfo.chart.render.TransferFunction;
|
||||
import org.meteoinfo.geometry.colors.TransferFunction;
|
||||
import org.meteoinfo.chart.shape.TextureShape;
|
||||
import org.meteoinfo.common.Extent;
|
||||
import org.meteoinfo.common.Extent3D;
|
||||
@ -47,7 +47,6 @@ import javax.imageio.*;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
import javax.swing.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
@ -261,6 +261,39 @@ public class ColorUtil {
|
||||
|
||||
return ncts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color maps
|
||||
*
|
||||
* @return Color maps
|
||||
* @throws IOException
|
||||
*/
|
||||
public static ColorMap[] getColorMaps(String path) throws IOException {
|
||||
File pathDir = new File(path);
|
||||
if (!pathDir.isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
File[] files = pathDir.listFiles();
|
||||
List<ColorMap> cts = new ArrayList<>();
|
||||
for (File file : files) {
|
||||
ColorMap ct = new ColorMap();
|
||||
ct.readFromFile(file);
|
||||
if (ct.getColorCount() > 0) {
|
||||
String name = file.getName();
|
||||
name = name.substring(0, name.lastIndexOf("."));
|
||||
ct.setName(name);
|
||||
cts.add(ct);
|
||||
}
|
||||
}
|
||||
|
||||
ColorMap[] ncts = new ColorMap[cts.size()];
|
||||
for (int i = 0; i < cts.size(); i++) {
|
||||
ncts[i] = cts.get(i);
|
||||
}
|
||||
|
||||
return ncts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load color map from rgb file
|
||||
|
||||
@ -223,6 +223,25 @@ public class DimArray {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change all dimensions to be ascending
|
||||
*/
|
||||
public void asAscending() {
|
||||
boolean changed = false;
|
||||
int i = 0;
|
||||
for (Dimension dimension : this.dimensions) {
|
||||
if (dimension.isDescending()) {
|
||||
dimension.reverse();
|
||||
array = array.flip(i);
|
||||
changed = true;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if (changed) {
|
||||
array = array.copy();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Section
|
||||
* @param origin Origin
|
||||
|
||||
@ -658,12 +658,47 @@ public class Dimension {
|
||||
return idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the dimension values are ascending
|
||||
* @return Ascending or not
|
||||
*/
|
||||
public boolean isAscending() {
|
||||
for (int i = 0; i < this.dimValue.getSize() - 1; i++) {
|
||||
if (dimValue.getDouble(i) >= dimValue.getDouble(i + 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the dimension values are descending
|
||||
* @return Descending or not
|
||||
*/
|
||||
public boolean isDescending() {
|
||||
for (int i = 0; i < this.dimValue.getSize() - 1; i++) {
|
||||
if (dimValue.getDouble(i) <= dimValue.getDouble(i + 1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the dimension values are ordered
|
||||
* @return Ordered or not
|
||||
*/
|
||||
public boolean isOrdered() {
|
||||
return isAscending() || isDescending();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the dimension values
|
||||
*/
|
||||
public void reverse() {
|
||||
this.dimValue = this.dimValue.flip(0);
|
||||
//Collections.reverse(this.dimValue);
|
||||
this.dimValue = this.dimValue.flip(0).copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -0,0 +1,110 @@
|
||||
package org.meteoinfo.geometry.colors;
|
||||
|
||||
import org.meteoinfo.common.colors.ColorMap;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class ColorTransferFunction {
|
||||
private TransferFunction transferFunction;
|
||||
private ColorMap colorMap;
|
||||
private Normalize normalize;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param transferFunction Transfer function
|
||||
* @param colorMap Color map
|
||||
* @param normalize Normalize
|
||||
*/
|
||||
public ColorTransferFunction(TransferFunction transferFunction, ColorMap colorMap, Normalize normalize) {
|
||||
this.transferFunction = transferFunction;
|
||||
this.colorMap = colorMap;
|
||||
this.normalize = normalize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param transferFunction Transfer function
|
||||
* @param colorMap Color map
|
||||
*/
|
||||
public ColorTransferFunction(TransferFunction transferFunction, ColorMap colorMap) {
|
||||
this(transferFunction, colorMap, new Normalize());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param colorMap Color map
|
||||
* @param normalize Normalize
|
||||
*/
|
||||
public ColorTransferFunction(ColorMap colorMap, Normalize normalize) {
|
||||
this(new TransferFunction(), colorMap, normalize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param colorMap Color map
|
||||
*/
|
||||
public ColorTransferFunction(ColorMap colorMap) {
|
||||
this(colorMap, new Normalize());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transfer function
|
||||
* @return Transfer function
|
||||
*/
|
||||
public TransferFunction getTransferFunction() {
|
||||
return this.transferFunction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transfer function
|
||||
* @param value Transfer function
|
||||
*/
|
||||
public void setTransferFunction(TransferFunction value) {
|
||||
this.transferFunction = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color map
|
||||
* @return Color map
|
||||
*/
|
||||
public ColorMap getColorMap() {
|
||||
return this.colorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set color map
|
||||
* @param value Color map
|
||||
*/
|
||||
public void setColorMap(ColorMap value) {
|
||||
this.colorMap = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get normalize
|
||||
* @return Normalize
|
||||
*/
|
||||
public Normalize getNormalize() {
|
||||
return this.normalize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set normalize
|
||||
* @param value Normalize
|
||||
*/
|
||||
public void setNormalize(Normalize value) {
|
||||
this.normalize = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get color with a data value
|
||||
* @param v The data value
|
||||
* @return The color
|
||||
*/
|
||||
public Color getColor(double v) {
|
||||
float ratio = this.normalize.apply(v).floatValue();
|
||||
Color c = this.colorMap.getColor(ratio);
|
||||
float alpha = this.transferFunction.getOpacity(ratio);
|
||||
|
||||
return new Color(c.getRed(), c.getGreen(), c.getBlue(), (int) alpha * 255);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package org.meteoinfo.chart.render;
|
||||
package org.meteoinfo.geometry.colors;
|
||||
|
||||
import org.meteoinfo.geometry.colors.Normalize;
|
||||
|
||||
@ -34,5 +34,5 @@
|
||||
</Font>
|
||||
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
|
||||
<Figure DoubleBuffering="true"/>
|
||||
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
|
||||
<Startup MainFormLocation="-7,0" MainFormSize="1391,812"/>
|
||||
</MeteoInfo>
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package org.meteoinfo.math;
|
||||
|
||||
public class Constants {
|
||||
public static double P0 = 1000.; //reference pressure for potential temperature (hPa)
|
||||
public static double R = 8.3144598; //molar gas constant (J / K / mol)
|
||||
public static double Mw = 18.01528; //Molecular weight of water (g / mol)
|
||||
public static double Md = 28.9644; //Nominal molecular weight of dry air at the surface of th Earth (g / mol)
|
||||
public static double Rd = R / Md; //Gas constant for dry air at the surface of the Earth (J (K kg)^-1)
|
||||
public static double Lv = 2.501e6; //Latent heat of vaporization for liquid water at 0C (J kg^-1)
|
||||
public static double Cp_d = 1005; //Specific heat at constant pressure for dry air (J kg^-1)
|
||||
public static double epsilon = Mw / Md;
|
||||
public static double kappa = 0.286;
|
||||
public static double degCtoK = 273.15; //Temperature offset between K and C (deg C)
|
||||
public static double g = 9.8; //Gravitational acceleration (m / s^2)
|
||||
public static double sat_pressure_0c = 6.112; //Saturation pressure at 0 degree (hPa)
|
||||
public static double T_BASE = 300.;
|
||||
public static double omega = 7292115e-11; //Avg. angular velocity of Earth (rad / s)
|
||||
}
|
||||
@ -5,6 +5,7 @@
|
||||
*/
|
||||
package org.meteoinfo.math.meteo;
|
||||
|
||||
import org.meteoinfo.math.Constants;
|
||||
import org.meteoinfo.ndarray.math.ArrayMath;
|
||||
import org.meteoinfo.ndarray.Array;
|
||||
import org.meteoinfo.ndarray.DataType;
|
||||
@ -238,6 +239,38 @@ public class MeteoMath {
|
||||
return (rh * es) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pressure data to heights using the U.S. standard atmosphere.
|
||||
*
|
||||
* @param p Pressure - hPa
|
||||
* @return Height - meter
|
||||
*/
|
||||
public static double pressure2Height(double p) {
|
||||
double t0 = 288.;
|
||||
double gamma = 6.5;
|
||||
double p0 = 1013.25;
|
||||
double h = (t0 / gamma) * (1 - Math.pow(p / p0, Constants.Rd * gamma / Constants.g)) * 1000;
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert pressure data to heights using the U.S. standard atmosphere.
|
||||
*
|
||||
* @param p Pressure - hPa
|
||||
* @return Height - meter
|
||||
*/
|
||||
public static Array pressure2Height(Array press) {
|
||||
Array r = Array.factory(DataType.DOUBLE, press.getShape());
|
||||
IndexIterator iter = press.getIndexIterator();
|
||||
IndexIterator iterR = r.getIndexIterator();
|
||||
while (iter.hasNext()) {
|
||||
iterR.setDoubleNext(pressure2Height(iter.getDoubleNext()));
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate height from pressure
|
||||
*
|
||||
|
||||
@ -457,6 +457,135 @@ public class Reproject {
|
||||
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 InvalidRangeException
|
||||
*/
|
||||
public static Array reproject(Array data, Array x, Array 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, ArrayUtil.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<Range> 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, ArrayUtil.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, ArrayUtil.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<Range> 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, ArrayUtil.toStation_Neighbor(ndata, x, y, xx, yy));
|
||||
indexr.incr();
|
||||
}
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reproject
|
||||
*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user