diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/GraphicFactory.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/GraphicFactory.java index 5c47d41c..b927da05 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/GraphicFactory.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/GraphicFactory.java @@ -11,6 +11,7 @@ import org.meteoinfo.chart.ChartText3D; import org.meteoinfo.chart.jogl.mc.CallbackMC; import org.meteoinfo.chart.jogl.mc.MarchingCubes; import org.meteoinfo.chart.jogl.pipe.PipeShape; +import org.meteoinfo.chart.shape.TextureShape; import org.meteoinfo.common.*; import org.meteoinfo.common.colors.ColorMap; import org.meteoinfo.data.GridArray; @@ -41,6 +42,7 @@ import org.meteoinfo.ndarray.*; import org.meteoinfo.ndarray.math.ArrayMath; import org.meteoinfo.ndarray.math.ArrayUtil; import org.meteoinfo.ndarray.util.BigDecimalUtil; +import org.meteoinfo.projection.ProjectionInfo; import wcontour.Contour; import wcontour.global.Point3D; import wcontour.global.PolyLine; @@ -49,6 +51,7 @@ import wcontour.global.PolyLine3D; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; +import java.io.IOException; import java.util.List; import java.util.*; @@ -3292,6 +3295,45 @@ public class GraphicFactory { return graphics; } + /** + * Create Texture + * + * @param gl GL2 + * @param layer Image layer + * @param offset Offset of z axis + * @param xshift X shift - to shift the grahpics in x direction, normally + * for map in 180 - 360 degree east + * @param interpolation Interpolation + * @return Graphics + * @throws IOException + */ + public static GraphicCollection createTexture(ImageLayer layer, double offset, double xshift, + String interpolation) throws IOException { + GraphicCollection3D graphics = new GraphicCollection3D(); + graphics.setFixZ(true); + graphics.setZDir("z"); + graphics.setZValue(offset); + TextureShape ishape = new TextureShape(); + ishape.setFileName(layer.getFileName()); + ishape.setImage(layer.getImage()); + Extent extent = layer.getExtent(); + Extent3D ex3 = new Extent3D(extent.minX + xshift, extent.maxX + xshift, extent.minY, extent.maxY, offset, offset); + List coords = new ArrayList<>(); + coords.add(new PointZ(extent.minX + xshift, extent.minY, offset)); + coords.add(new PointZ(extent.maxX + xshift, extent.minY, offset)); + coords.add(new PointZ(extent.maxX + xshift, extent.maxY, offset)); + coords.add(new PointZ(extent.minX + xshift, extent.maxY, offset)); + ishape.setExtent(ex3); + ishape.setCoords(coords); + Graphic gg = new Graphic(ishape, new ColorBreak()); + if (interpolation != null) { + ((ImageShape) gg.getShape()).setInterpolation(interpolation); + } + graphics.add(gg); + + return graphics; + } + /** * Create contour lines * @@ -7281,6 +7323,200 @@ public class GraphicFactory { return surfaceGraphic; } + /** + * Create surface graphic + * + * @param layer Image layer + * @param offset Offset of z axis + * @param xShift X shift - to shift the graphics in x direction, normally + * for map in 180 - 360 degree east + * @param nLon Number of longitude + * @param nLat Number of latitude + * @return Graphics + * @throws IOException + */ + public static MeshGraphic geoSurface(ImageLayer layer, double offset, double xShift, + int nLon, int nLat) throws IOException { + Extent extent = layer.getExtent(); + Array lon = ArrayUtil.lineSpace(extent.minX + xShift, extent.maxX + xShift, nLon + 1, true); + Array lat = ArrayUtil.lineSpace(extent.minY, extent.maxY, nLat + 1, true); + lat = lat.flip(0).copy(); + Array[] lonlat = ArrayUtil.meshgrid(lon, lat); + lon = lonlat[0]; + lat = lonlat[1]; + Array alt = ArrayUtil.zeros(lon.getShape(), DataType.FLOAT); + alt = ArrayMath.add(alt, offset); + LegendScheme ls = LegendManage.createSingleSymbolLegendScheme(ShapeTypes.POLYGON, Color.cyan, 1); + ((PolygonBreak) ls.getLegendBreak(0)).setDrawOutline(false); + ((PolygonBreak) ls.getLegendBreak(0)).setOutlineColor(Color.white); + + MeshGraphic graphic = GraphicFactory.surface(lon, lat, alt, ls); + graphic.setImage(layer.getImage()); + + return graphic; + } + + /** + * Create surface graphic + * + * @param layer Image layer + * @param offset Offset of z axis + * @param xShift X shift - to shift the graphics in x direction, normally + * for map in 180 - 360 degree east + * @param nLon Number of longitude + * @param nLat Number of latitude + * @param toProj Destination projection + * @return Graphics + * @throws IOException + */ + public static MeshGraphic geoSurface(ImageLayer layer, double offset, double xShift, + int nLon, int nLat, ProjectionInfo toProj) throws IOException { + Extent layerExtent = layer.getExtent(); + Extent extent = (Extent) layerExtent.clone(); + double width = extent.getWidth(); + double height = extent.getHeight(); + float cutoff = toProj.getCutoff(); + double cLon = toProj.getCenterLon(); + boolean extentChanged = false; + switch (toProj.getProjectionName()) { + case Lambert_Conformal_Conic: + if (extent.minY < cutoff) { + extent.minY = cutoff; + extentChanged = true; + } + break; + case North_Polar_Stereographic_Azimuthal: + if (extent.minY < cutoff) { + extent.minY = cutoff; + extentChanged = true; + } + break; + case South_Polar_Stereographic_Azimuthal: + if (extent.maxY > cutoff) { + extent.maxY = cutoff; + extentChanged = true; + } + break; + case Mercator: + if (extent.maxY > cutoff) { + extent.maxY = cutoff; + extentChanged = true; + } + if (extent.minY < -cutoff) { + extent.minY = -cutoff; + extentChanged = true; + } + break; + } + + if (cLon != 0) { + extent.minX = cLon - 180 + 0.1; + extent.maxX = cLon + 180 - 0.1; + extentChanged = true; + } + + BufferedImage image = layer.getImage(); + if (extentChanged) { + int x = (int) ((extent.minX - layerExtent.minX) / width * image.getWidth()); + int y = (int) ((layerExtent.maxY - extent.maxY) / height * image.getHeight()); + int w = (int) (extent.getWidth() / layerExtent.getWidth() * image.getWidth()); + int h = (int) (extent.getHeight() / layerExtent.getHeight() * image.getHeight()); + BufferedImage nImage = new BufferedImage(w, h, image.getType()); + if (cLon == 0) { + int[] rgb = new int[w * h]; + rgb = image.getRGB(x, y, w, h, rgb, 0, w); + nImage.setRGB(0, 0, w, h, rgb, 0, w); + } + else { + if (cLon > 0) { + int w1 = (int) ((layerExtent.maxX - extent.minX) / extent.getWidth() * w); + int[] rgb1 = new int[w1 * h]; + rgb1 = image.getRGB(x, y, w1, h, rgb1, 0, w1); + int[] rgb2 = new int[(w - w1) * h]; + rgb2 = image.getRGB(0, y, w - w1, h, rgb2, 0, w - w1); + nImage.setRGB(0, 0, w1, h, rgb1, 0, w1); + nImage.setRGB(w1, 0, w - w1, h, rgb2, 0, w - w1); + } else { + int w1 = (int) ((extent.maxX - layerExtent.minX) / extent.getWidth() * w); + int[] rgb1 = new int[w1 * h]; + rgb1 = image.getRGB(x, y, w1, h, rgb1, 0, w1); + int[] rgb2 = new int[(w - w1) * h]; + rgb2 = image.getRGB(x + w1, y, w - w1, h, rgb2, 0, w - w1); + nImage.setRGB(w - w1, 0, w1, h, rgb1, 0, w1); + nImage.setRGB(0, 0, w - w1, h, rgb2, 0, w - w1); + } + } + image = nImage; + } + + Array lon = ArrayUtil.lineSpace(extent.minX + xShift, extent.maxX + xShift, nLon + 1, true); + Array lat = ArrayUtil.lineSpace(extent.minY, extent.maxY, nLat + 1, true); + lat = lat.flip(0).copy(); + Array[] lonlat = ArrayUtil.meshgrid(lon, lat); + lon = lonlat[0]; + lat = lonlat[1]; + Array alt = ArrayUtil.zeros(lon.getShape(), DataType.FLOAT); + alt = ArrayMath.add(alt, offset); + LegendScheme ls = LegendManage.createSingleSymbolLegendScheme(ShapeTypes.POLYGON, Color.cyan, 1); + ((PolygonBreak) ls.getLegendBreak(0)).setDrawOutline(false); + ((PolygonBreak) ls.getLegendBreak(0)).setOutlineColor(Color.white); + + MeshGraphic graphic = GraphicFactory.surface(lon, lat, alt, ls); + graphic.setImage(image); + + return graphic; + } + + /** + * Create surface graphic + * + * @param layer Image layer + * @param offset Offset of z axis + * @param xShift X shift - to shift the graphics in x direction, normally + * for map in 180 - 360 degree east + * @param nLon Number of longitude + * @param nLat Number of latitude + * @param toProj Destination projection + * @param limits Image extent limitations + * @return Graphics + * @throws IOException + */ + public static MeshGraphic geoSurface(ImageLayer layer, double offset, double xShift, + int nLon, int nLat, ProjectionInfo toProj, List limits) throws IOException { + Extent layerExtent = layer.getExtent(); + Extent extent = new Extent(limits.get(0).doubleValue(), limits.get(1).doubleValue(), + limits.get(2).doubleValue(), limits.get(3).doubleValue()); + double width = layerExtent.getWidth(); + double height = layerExtent.getHeight(); + + BufferedImage image = layer.getImage(); + int x = (int) ((extent.minX - layerExtent.minX) / width * image.getWidth()); + int y = (int) ((layerExtent.maxY - extent.maxY) / height * image.getHeight()); + int w = (int)(extent.getWidth() / layerExtent.getWidth() * image.getWidth()); + int h = (int)(extent.getHeight() / layerExtent.getHeight() * image.getHeight()); + BufferedImage nImage = new BufferedImage(w, h, image.getType()); + Graphics2D g2 = nImage.createGraphics(); + g2.drawImage(image.getSubimage(x, y, w, h), 0, 0, null); + image = nImage; + + Array lon = ArrayUtil.lineSpace(extent.minX + xShift, extent.maxX + xShift, nLon + 1, true); + Array lat = ArrayUtil.lineSpace(extent.minY, extent.maxY, nLat + 1, true); + lat = lat.flip(0).copy(); + Array[] lonlat = ArrayUtil.meshgrid(lon, lat); + lon = lonlat[0]; + lat = lonlat[1]; + Array alt = ArrayUtil.zeros(lon.getShape(), DataType.FLOAT); + alt = ArrayMath.add(alt, offset); + LegendScheme ls = LegendManage.createSingleSymbolLegendScheme(ShapeTypes.POLYGON, Color.cyan, 1); + ((PolygonBreak) ls.getLegendBreak(0)).setDrawOutline(false); + ((PolygonBreak) ls.getLegendBreak(0)).setOutlineColor(Color.white); + + MeshGraphic graphic = GraphicFactory.surface(lon, lat, alt, ls); + graphic.setImage(image); + + return graphic; + } + /** * Create slice graphics * diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/GraphicProjectionUtil.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/GraphicProjectionUtil.java new file mode 100644 index 00000000..33627cd2 --- /dev/null +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/GraphicProjectionUtil.java @@ -0,0 +1,40 @@ +package org.meteoinfo.chart.graphic; + +import org.locationtech.proj4j.CoordinateTransform; +import org.locationtech.proj4j.CoordinateTransformFactory; +import org.locationtech.proj4j.ProjCoordinate; +import org.meteoinfo.geometry.geoprocess.GeoComputation; +import org.meteoinfo.geometry.graphic.Graphic; +import org.meteoinfo.projection.ProjectionInfo; +import org.meteoinfo.projection.ProjectionNames; +import org.meteoinfo.projection.ProjectionUtil; +import org.meteoinfo.projection.Reproject; + +public class GraphicProjectionUtil extends ProjectionUtil { + /** + * Project graphic + * + * @param graphic The graphic + * @param fromProj From projection + * @param toProj To projection + * @return Projected graphic + */ + public static Graphic projectClipGraphic(Graphic graphic, ProjectionInfo fromProj, ProjectionInfo toProj) { + if (graphic instanceof MeshGraphic) { + CoordinateTransform trans = new CoordinateTransformFactory().createTransform(fromProj.getCoordinateReferenceSystem(), + toProj.getCoordinateReferenceSystem()); + float[] vertex = ((MeshGraphic) graphic).getVertexPosition(); + for (int i = 0; i < vertex.length; i+=3) { + ProjCoordinate p1 = new ProjCoordinate(vertex[i], vertex[i + 1]); + ProjCoordinate p2 = new ProjCoordinate(); + trans.transform(p1, p2); + vertex[i] = (float) p2.x; + vertex[i + 1] = (float) p2.y; + } + ((MeshGraphic) graphic).setVertexPosition(vertex); + return graphic; + } else { + return ProjectionUtil.projectClipGraphic(graphic, fromProj, toProj); + } + } +} diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/JOGLUtil.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/JOGLUtil.java index b168c62a..bb33b8af 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/JOGLUtil.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/JOGLUtil.java @@ -164,45 +164,6 @@ public class JOGLUtil { return cb.getColor().getRGBComponents(null); } - /** - * Create Texture - * - * @param gl GL2 - * @param layer Image layer - * @param offset Offset of z axis - * @param xshift X shift - to shift the grahpics in x direction, normally - * for map in 180 - 360 degree east - * @param interpolation Interpolation - * @return Graphics - * @throws IOException - */ - public static GraphicCollection createTexture(ImageLayer layer, double offset, double xshift, - String interpolation) throws IOException { - GraphicCollection3D graphics = new GraphicCollection3D(); - graphics.setFixZ(true); - graphics.setZDir("z"); - graphics.setZValue(offset); - TextureShape ishape = new TextureShape(); - ishape.setFileName(layer.getFileName()); - ishape.setImage(layer.getImage()); - Extent extent = layer.getExtent(); - Extent3D ex3 = new Extent3D(extent.minX + xshift, extent.maxX + xshift, extent.minY, extent.maxY, offset, offset); - List coords = new ArrayList<>(); - coords.add(new PointZ(extent.minX + xshift, extent.minY, offset)); - coords.add(new PointZ(extent.maxX + xshift, extent.minY, offset)); - coords.add(new PointZ(extent.maxX + xshift, extent.maxY, offset)); - coords.add(new PointZ(extent.minX + xshift, extent.maxY, offset)); - ishape.setExtent(ex3); - ishape.setCoords(coords); - Graphic gg = new Graphic(ishape, new ColorBreak()); - if (interpolation != null) { - ((ImageShape) gg.getShape()).setInterpolation(interpolation); - } - graphics.add(gg); - - return graphics; - } - /** * Create isosurface graphics * diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/MapPlot3D.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/MapPlot3D.java index 76969ebf..fce5360c 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/MapPlot3D.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/MapPlot3D.java @@ -3,6 +3,7 @@ package org.meteoinfo.chart.jogl; import com.jogamp.opengl.GL; import com.jogamp.opengl.GL2; import org.meteoinfo.chart.ChartText; +import org.meteoinfo.chart.graphic.GraphicProjectionUtil; import org.meteoinfo.chart.plot.MapGridLine; import org.meteoinfo.chart.plot.MapGridLine3D; import org.meteoinfo.common.*; @@ -64,7 +65,7 @@ public class MapPlot3D extends Plot3DGL { if (proj.equals(this.projInfo)) { super.addGraphic(graphic); } else { - Graphic nGraphic = ProjectionUtil.projectClipGraphic(graphic, proj, this.projInfo); + Graphic nGraphic = GraphicProjectionUtil.projectClipGraphic(graphic, proj, this.projInfo); super.addGraphic(nGraphic); } } @@ -81,7 +82,7 @@ public class MapPlot3D extends Plot3DGL { if (proj.equals(this.projInfo)) { super.addGraphic(index, graphic); } else { - Graphic nGraphic = ProjectionUtil.projectClipGraphic(graphic, proj, this.projInfo); + Graphic nGraphic = GraphicProjectionUtil.projectClipGraphic(graphic, proj, this.projInfo); super.addGraphic(index, nGraphic); } } diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/MeshRender.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/MeshRender.java index 68bf61dc..ca88a90d 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/MeshRender.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/MeshRender.java @@ -111,6 +111,12 @@ public class MeshRender extends JOGLGraphicRender { gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Integer.BYTES, indexBuffer, GL.GL_STATIC_DRAW); gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0); } + + if (alwaysUpdateBuffers) { + texture = AWTTextureIO.newTexture(gl.getGLProfile(), meshGraphic.getImage(), true); + this.textureID = texture.getTextureObject(gl); + this.bindingTextures(); + } } void bindingTextures() { diff --git a/meteoinfo-lab/milconfig.xml b/meteoinfo-lab/milconfig.xml index d0b512a1..ca057c39 100644 --- a/meteoinfo-lab/milconfig.xml +++ b/meteoinfo-lab/milconfig.xml @@ -1,34 +1,32 @@ - - - - - - - - - - - + - + + + + + + + + + + + - - - - + + + - - - - + + + @@ -36,5 +34,5 @@
- + diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class index abc474ac..967b03be 100644 Binary files a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class and b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class differ diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py index 4b9fb302..75c3e99f 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py @@ -653,9 +653,19 @@ class Axes3DGL(Axes3D): layer.setLegendScheme(ls) graphics = GraphicFactory.createGraphicsFromLayer(layer, offset, xshift) else: - interpolation = kwargs.pop('interpolation', None) - graphics = JOGLUtil.createTexture(layer, offset, xshift, interpolation) - #graphics = GraphicFactory.createImage(layer, offset, xshift, interpolation) + #interpolation = kwargs.pop('interpolation', None) + #graphics = GraphicFactory.createTexture(layer, offset, xshift, interpolation) + nlat = kwargs.pop('nlat', 180) + nlon = kwargs.pop('nlon', 360) + if self._axes.getProjInfo() is None: + graphics = GraphicFactory.geoSurface(layer, offset, xshift, nlon, nlat) + else: + limits = kwargs.pop('limits', None) + if limits is None: + graphics = GraphicFactory.geoSurface(layer, offset, xshift, nlon, nlat, self._axes.getProjInfo()) + else: + graphics = GraphicFactory.geoSurface(layer, offset, xshift, nlon, nlat, self._axes.getProjInfo(), + limits) lighting = kwargs.pop('lighting', None) if not lighting is None: @@ -663,7 +673,7 @@ class Axes3DGL(Axes3D): visible = kwargs.pop('visible', True) if visible: - projection = kwargs.pop('projection', migeo.projinfo()) + projection = kwargs.pop('projection', layer.getProjInfo()) self.add_graphic(graphics, projection) return graphics @@ -1609,7 +1619,7 @@ class MapAxes3D(Axes3DGL): @property def axestype(self): - return '3d_Map' + return '3d' @property def projection(self): @@ -1650,7 +1660,7 @@ class EarthAxes3D(Axes3DGL): @property def axestype(self): - return '3d_Earth' + return '3d' def earth_image(self, image): """ diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java index 3ce8bf93..96d36153 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java @@ -36,7 +36,7 @@ public class LambertConformalConic extends ProjectionInfo { /** * Construction * - * @param crs Coorinate reference system + * @param crs Coordinate reference system */ public LambertConformalConic(CoordinateReferenceSystem crs) { this.crs = crs;