netcdf流场展示

来源:互联网 发布:可爱p图软件 编辑:程序博客网 时间:2024/05/16 17:32

说明

        海洋数值预报里面,数据格式一般都为nc文件格式,存储的为科学数据,这些数据都是网格化的数据。由于有些网格点是陆地,如果用图片方式去展示流场的化,合理的方式是将这些陆地剔除。由于一些客户端软件可以做到,这里不考虑。这里提供两个软件可供参考。

       一个是jzy3d , 里面使用ContourPictureGenerator可生成想要的等值面,返回的为BufferedImage,当然流场方向还需自己处理。

另外一个是wcontour,可生成等值面,需要自己生成BufferedImage,再利用Contour.tracingStreamline获取流场曲线,再自己在BufferedImage上绘制。


代码

@Overrideprotected Object wrapperRaw(CacheDataStore dataStore) {double[] lons = Arrays.copyOf(dataStore.windLons, dataStore.windLons.length);double[] lats = Arrays.copyOf(dataStore.windLats, dataStore.windLats.length);// double[] lf, double[] rt,double[] lf = getLfAndRtPts(lons, lats).get(0);double[] rt = getLfAndRtPts(lons, lats).get(1);// int rows, int cols, double[] contourVals,int rows = lons.length;int cols = lats.length;double[][] data = genNorm(dataStore.wind_u, dataStore.wind_v, lons.length, lats.length, 10000, _undefData);lons = initArr(rows);lats = initArr(cols);List<PolyLine> lines = Contour.tracingStreamline(maskTable(dataStore.wind_u, 10000, _undefData), maskTable(dataStore.wind_v, 10000, _undefData), lons, lats, _undefData, 1);BufferedImage img = ImgContourUtils.drawContourImage(maskTableEq(data, Math.abs(_undefData), Double.NaN), lons.length, lats.length, "");ImgContourUtils.drawLines(img, lines);//ImgContourUtils.drawArc(img, dataStore.wind_u, dataStore.wind_v, lons.length, lats.length, _undefData);ImgContourUtils.saveImage(img, "d:\\temp\\flow2.png");return img;}

import java.awt.Graphics2D;import java.awt.image.BufferedImage;import java.awt.image.ColorModel;import java.awt.image.DirectColorModel;import java.io.File;import java.util.ArrayList;import java.util.List;import javax.imageio.ImageIO;import org.jzy3d.colors.Color;import org.jzy3d.colors.ColorMapper;import org.jzy3d.colors.colormaps.ColorMapRainbow;import org.jzy3d.contour.AbstractContourGenerator;import org.jzy3d.contour.DefaultContourColoringPolicy;import org.jzy3d.contour.IContourColoringPolicy;import org.jzy3d.contour.IContourPictureGenerator;import org.jzy3d.maths.Coord3d;import org.jzy3d.maths.Range;import org.jzy3d.plot3d.builder.Mapper;import org.jzy3d.plot3d.builder.concrete.OrthonormalTessellator;import org.jzy3d.plot3d.primitives.Shape;import wContour.Global.PointD;import wContour.Global.PolyLine;public class ImgContourUtils {public static BufferedImage getContourFilledImage(double[][] data, int m, int n, String path) {OrthonormalTessellator tesselator = new OrthonormalTessellator();// bottom, top, mid surfaceShape surface = (Shape) tesselator.build(toCoordList(data, n, m));ColorMapper localColorMapper = new ColorMapper(new ColorMapRainbow(), surface.getBounds().getZmin(), surface.getBounds().getZmax(), new Color(1.0F, 1.0F, 1.0F, 1.0F));System.out.println("max=" + surface.getBounds().getZmax());System.out.println("min=" + surface.getBounds().getZmin());CustomMapperContourPictureGenerator a = new CustomMapperContourPictureGenerator(new CustomMapper(data, n, m), new Range(0, n), new Range(0, m));IContourColoringPolicy policy = new DefaultContourColoringPolicy(localColorMapper);// BufferedImage img = a.getContourImage(policy, n, m, 10);// BufferedImage img = a.getFilledContourImage(policy, n, m, new// double[]{-10,30,40,50,60,70,80,90});BufferedImage img = a.getFilledContourImage(policy, n, m, 10);System.out.println(img);updateAlpha(m, n, data, Double.NaN, img);saveImage(img, path);return img;}public static BufferedImage drawContourImage(double[][] data, int m, int n, String path) {OrthonormalTessellator tesselator = new OrthonormalTessellator();Shape surface = (Shape) tesselator.build(toCoordList(data, n, m));ColorMapper localColorMapper = new ColorMapper(new ColorMapRainbow(), surface.getBounds().getZmin(), surface.getBounds().getZmax(), new Color(1.0F, 1.0F, 1.0F, 1.0F));System.out.println("max=" + surface.getBounds().getZmax());System.out.println("min=" + surface.getBounds().getZmin());CustomMapperContourPictureGenerator a = new CustomMapperContourPictureGenerator(new CustomMapper(data, n, m), new Range(0, n), new Range(0, m));IContourColoringPolicy policy = new DefaultContourColoringPolicy(localColorMapper);BufferedImage img = a.getFilledContourImage(policy, n, m, 10);updateAlpha(m, n, data, Double.NaN, img);return img;}public static class CustomMapper extends Mapper {private double[][] data;private int m;private int n;public CustomMapper(double[][] data, int m, int n) {this.data = data;this.m = m;this.n = n;}public final double f(double x, double y) {if (x >= m || x < 0 || y >= n || y < 0) {// System.out.println(x + "," + y);}return this.data[(int) Math.min(data.length - 1, Math.max(0, x))][(int) Math.min(data[0].length - 1, Math.max(0, y))];}}public static List<Coord3d> toCoordList(double[][] z, int m, int n) {List<Coord3d> ret = new ArrayList<Coord3d>();for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {ret.add(new Coord3d(i, j, z[i][j]));}}return ret;}public static void saveImage(BufferedImage img, String path) {try {File outputfile = new File(path);ImageIO.write(img, "png", outputfile);} catch (Exception ex) {ex.printStackTrace();}}public static BufferedImage drawLines(int xRes, int yRes, double[][] vals, double _undef, List<PolyLine> polyLines) {BufferedImage img = buildImage(xRes, yRes, vals, _undef);drawLines(img, polyLines);return img;}public static void drawLines(BufferedImage img, List<PolyLine> polyLines) {Graphics2D g2d = img.createGraphics();List<int[]> xs = toIntArrsX(polyLines, img.getWidth());List<int[]> ys = toIntArrsY(polyLines, img.getHeight());g2d.setColor(java.awt.Color.blue);for (int i = 0; i < xs.size(); i = i + 12) {g2d.drawPolyline(xs.get(i), ys.get(i), xs.get(i).length);int[] xPoints = xs.get(i);int[] yPoints = ys.get(i);int alen = xs.get(i).length;// break;{int len = 12;for (int j = 0; j < alen; j = j + 50) {if (j > 0 && j < alen - 2 && j % len == 0) {// Draw arrawjava.awt.Point aP = new java.awt.Point(xPoints[j], yPoints[j]);java.awt.Point bPoint = new java.awt.Point(xPoints[j + 1], yPoints[j + 1]);double U = bPoint.x - aP.x;double V = bPoint.y - aP.y;double angle = Math.atan((V) / (U)) * 180 / Math.PI;angle = angle + 90;if (U < 0) {angle = angle + 180;}if (angle >= 360) {angle = angle - 360;}if (Double.isNaN(angle)) {continue;}java.awt.Point eP1 = new java.awt.Point();double aSize = 8;eP1.x = (int) (aP.x - aSize * Math.sin((angle + 20.0) * Math.PI / 180));eP1.y = (int) (aP.y + aSize * Math.cos((angle + 20.0) * Math.PI / 180));g2d.drawLine(aP.x, aP.y, eP1.x, eP1.y);eP1.x = (int) (aP.x - aSize * Math.sin((angle - 20.0) * Math.PI / 180));eP1.y = (int) (aP.y + aSize * Math.cos((angle - 20.0) * Math.PI / 180));g2d.drawLine(aP.x, aP.y, eP1.x, eP1.y);// System.out.println(Math.abs(aP.x - eP1.x) + "," +// Math.abs(aP.y - eP1.y));}}}}g2d.dispose();}public static void drawArc(BufferedImage img, double[][] windU, double[][] windV, int m, int n, double mask) {Graphics2D g2d = img.createGraphics();g2d.setColor(java.awt.Color.yellow);for (int i = 0; i < m; i = i + 24) {for (int j = 0; j < n; j = j + 24) {double u = windU[j][i];double v = windV[j][i];if (Double.isNaN(u) || Double.isNaN(v) || Math.abs(u) == Math.abs(mask) || Math.abs(v) == Math.abs(mask)) {continue;}g2d.drawString(getStringByAngle(u, v), i, n - 1 -j);}}g2d.dispose();}public static void drawArc(BufferedImage img, double[][] data, int m, int n, double mask) {Graphics2D g2d = img.createGraphics();g2d.setColor(java.awt.Color.yellow);for (int i = 0; i < m; i = i + 24) {for (int j = 0; j < n; j = j + 24) {double u = data[j][i];if (Double.isNaN(u) ||  Math.abs(u) == Math.abs(mask) ) {continue;}u = 360 -data[j][i] * 0.1;g2d.drawString(getAngleByVal(u), i, n - 1 -j);}}g2d.dispose();}private static String getStringByAngle(double x, double y) {if (x > 0) {if (y == 0) {return "→";} else if (y > 0) {return "↗";}return "↘";} else if (x < 0) {if (y == 0) {return "←";} else if (y > 0) {return "↖";}return "↙";} else {if (y >= 0) {return "↑";}return "↓";}}static String getAngleByVal(double v){if( v < 0){return "→";}if( v >= 0 && v < 45){return "→";}else if( v <= 90){if( v == 90){return "↑";}return "↗";}else if( v <= 180){if( v == 180){return "←";}return "↖";}else if( v <= 270){if( v == 270){return "↓";}return "↙";}else{if( v == 360){return "→";}return "↘";}}static List<int[]> toIntArrsX(List<PolyLine> polyLines, int max) {List<int[]> xs = new ArrayList<int[]>();for (int i = 0; i < polyLines.size(); i++) {PolyLine pl = polyLines.get(i);List<Integer> is = new ArrayList<Integer>();for (PointD d : pl.PointList) {int x = (int) Math.round(d.X);if (x >= max) {x = max - 1;}is.add(x);}xs.add(toIntArr(is));}return xs;}static List<int[]> toIntArrsY(List<PolyLine> polyLines, int max) {List<int[]> ys = new ArrayList<int[]>();for (int i = 0; i < polyLines.size(); i++) {PolyLine pl = polyLines.get(i);List<Integer> is = new ArrayList<Integer>();for (PointD d : pl.PointList) {int y = (int) Math.round(d.Y);y = max - 1 - y;if (y >= max) {y = max - 1;}if (y < 0) {y = 0;}is.add(y);}ys.add(toIntArr(is));}return ys;}static int[] toIntArr(List<Integer> iList) {int[] xs = new int[iList.size()];for (int i = 0; i < iList.size(); i++) {xs[i] = iList.get(i);}return xs;}static int getLocalRgb(int rgb) {DirectColorModel dcm = (DirectColorModel) ColorModel.getRGBdefault();// DirectColorModel类用来将ARGB值独立分解出来int red = dcm.getRed(rgb);int green = dcm.getGreen(rgb);int blue = dcm.getBlue(rgb);int alpha;if (red == 255 && blue == 255 && green == 255) {// 如果像素为白色,则让它透明alpha = 0;} else {alpha = 0;}return alpha << 24 | red << 16 | green << 8 | blue;}static BufferedImage buildImage(int xRes, int yRes, double[][] vals, double _undef) {BufferedImage image = new BufferedImage(yRes, xRes, BufferedImage.TYPE_4BYTE_ABGR);for (int x = 0; x < yRes; x++) {for (int y = 0; y < xRes; y++) {if (vals[y][x] == _undef) {int rgb = -123;rgb = getLocalRgb(rgb);image.setRGB(x, y, rgb);} else {image.setRGB(x, y, java.awt.Color.lightGray.getRGB());}}}return image;}static BufferedImage updateAlpha(int xRes, int yRes, double[][] vals, double _undef, BufferedImage img) {for (int x = 0; x < xRes; x++) {for (int y = 0; y < yRes; y++) {if (vals[y][x] == _undef || Double.isNaN(vals[y][x])) {int rgb = -16777088;rgb = getLocalRgb(rgb);img.setRGB(x, yRes - 1 - y, rgb);} else {}}}return img;}public static BufferedImage rotateImg(int xRes, int yRes, BufferedImage image) {BufferedImage imageRotate = new BufferedImage(yRes, xRes, BufferedImage.TYPE_4BYTE_ABGR);for (int x = 0; x < yRes; x++) {for (int y = 0; y < xRes; y++) {imageRotate.setRGB(x, y, image.getRGB(y, yRes - 1 - x));}}return imageRotate;}public static class CustomMapperContourPictureGenerator extends AbstractContourGenerator implements IContourPictureGenerator {public static int PIXEL_NEIGHBOUR_THRESHOLD = 2;public static float LINE_STRIP_WIDTH = 2.0F;public static int MERGE_STRIP_DIST = 1;protected Mapper mapper;protected Range xrange;protected Range yrange;public CustomMapperContourPictureGenerator(Mapper mapper, Range xrange, Range yrange) {this.mapper = mapper;this.xrange = xrange;this.yrange = yrange;}public double[][] getContourMatrix(int xRes, int yRes, int nLevels) {return computeContour(xRes, yRes, nLevels);}public BufferedImage getContourImage(IContourColoringPolicy policy, int xRes, int yRes, int nLevels) {double[][] contours = computeContour(xRes, yRes, nLevels);return buildImage(xRes, yRes, contours, policy);}public BufferedImage getContourImage(IContourColoringPolicy policy, int xRes, int yRes, double[] sortedLevels) {double[][] contours = computeContour(xRes, yRes, sortedLevels);return buildImage(xRes, yRes, contours, policy);}public BufferedImage getFilledContourImage(IContourColoringPolicy policy, int xRes, int yRes, int nLevels) {double[][] contours = computeFilledContour(xRes, yRes, nLevels);return buildImage(xRes, yRes, contours, policy);}public BufferedImage getFilledContourImage(IContourColoringPolicy policy, int xRes, int yRes, double[] sortedLevels) {double[][] contours = computeFilledContour(xRes, yRes, sortedLevels);return buildImage(xRes, yRes, contours, policy);}public BufferedImage getHeightMap(IContourColoringPolicy policy, int xRes, int yRes, int nLevels) {double[][] contours = computeXYColors(xRes, yRes, nLevels);return buildImage(xRes, yRes, contours, policy);}protected BufferedImage buildImage(int xRes, int yRes, double[][] contours, IContourColoringPolicy policy) {BufferedImage image = new BufferedImage(xRes, yRes, BufferedImage.TYPE_4BYTE_ABGR);for (int x = 0; x < xRes; x++) {for (int y = 0; y < yRes; y++) {image.setRGB(x, y, policy.getRGB(contours[x][y]));}}// rotateBufferedImage imageRotate = new BufferedImage(yRes, xRes, BufferedImage.TYPE_4BYTE_ABGR);for (int x = 0; x < yRes; x++) {for (int y = 0; y < xRes; y++) {imageRotate.setRGB(x, y, image.getRGB(xRes - 1 - y, yRes - 1 - x));}}return imageRotate;}protected double[][] computeFilledContour(int xRes, int yRes, double[] sortedLevels) {double[][] matrix = new double[xRes][yRes];computeHeightMatrix(matrix, xRes, yRes);quantizeMatrix(matrix, sortedLevels);return matrix;}protected void computeHeightMatrix(double[][] matrix, int xRes, int yRes) {this.minValue = Double.MAX_VALUE;this.maxValue = -1.7976931348623157E308D;double xstep = this.xrange.getRange() / (xRes - 1);double ystep = this.yrange.getRange() / (yRes - 1);for (int xi = 0; xi < xRes; xi++) {for (int yi = 0; yi < yRes; yi++) {double x = this.xrange.getMin() + xi * xstep;double y = this.yrange.getMin() + yi * ystep;double value = this.mapper.f(x, y);matrix[xi][(yRes - 1 - yi)] = value;if (value < this.minValue) {this.minValue = value;}if (value > this.maxValue) {this.maxValue = value;}}}}}}

图片

两个不同的效果:


原创粉丝点击