diff --git a/.idea/libraries/Maven__org_apache_commons_commons_math4_core_4_0_SNAPSHOT.xml b/.idea/libraries/Maven__org_apache_commons_commons_math4_core_4_0_SNAPSHOT.xml
index 8a3fe527..99855144 100644
--- a/.idea/libraries/Maven__org_apache_commons_commons_math4_core_4_0_SNAPSHOT.xml
+++ b/.idea/libraries/Maven__org_apache_commons_commons_math4_core_4_0_SNAPSHOT.xml
@@ -1,13 +1,13 @@
-
+
-
+
-
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_4_0_SNAPSHOT.xml b/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_4_0_SNAPSHOT.xml
index 85b95758..4d9cd944 100644
--- a/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_4_0_SNAPSHOT.xml
+++ b/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_4_0_SNAPSHOT.xml
@@ -1,13 +1,13 @@
-
+
-
+
-
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_core_4_0_SNAPSHOT.xml b/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_core_4_0_SNAPSHOT.xml
index 6bd6f5d4..1d619a58 100644
--- a/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_core_4_0_SNAPSHOT.xml
+++ b/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_core_4_0_SNAPSHOT.xml
@@ -1,13 +1,13 @@
-
+
-
+
-
+
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_exception_4_0_SNAPSHOT.xml b/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_exception_4_0_SNAPSHOT.xml
index b5980b99..492065a1 100644
--- a/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_exception_4_0_SNAPSHOT.xml
+++ b/.idea/libraries/Maven__org_apache_commons_commons_math4_legacy_exception_4_0_SNAPSHOT.xml
@@ -1,13 +1,13 @@
-
+
-
+
-
+
\ No newline at end of file
diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/GLChartPanel.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/GLChartPanel.java
index ecc670d0..292a1e40 100644
--- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/GLChartPanel.java
+++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/GLChartPanel.java
@@ -1647,7 +1647,12 @@ public class GLChartPanel extends GLJPanel implements IChartPanel{
* @return View image
*/
public BufferedImage paintViewImage(int width, int height) {
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ BufferedImage image;
+ if (this.chart.containsGLPlot()) {
+ image = JOGLUtil.paintViewImage(this.chart, width, height);
+ } else {
+ image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ }
Graphics2D g = image.createGraphics();
paintGraphics(g);
@@ -1682,8 +1687,12 @@ public class GLChartPanel extends GLJPanel implements IChartPanel{
*/
public BufferedImage paintViewImage(int width, int height, int dpi) {
double scaleFactor = dpi / 72.0;
- BufferedImage image = new BufferedImage((int)(width * scaleFactor), (int)(height * scaleFactor),
- BufferedImage.TYPE_INT_ARGB);
+ BufferedImage image;
+ if (this.chart.containsGLPlot()) {
+ image = JOGLUtil.paintViewImage(this.chart, width, height, dpi);
+ } else {
+ image = new BufferedImage((int)(width * scaleFactor), (int)(height * scaleFactor), BufferedImage.TYPE_INT_ARGB);
+ }
Graphics2D g = image.createGraphics();
AffineTransform at = g.getTransform();
at.scale(scaleFactor, scaleFactor);
diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/EarthGLPlot.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/EarthGLPlot.java
index fecc03ca..f330136a 100644
--- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/EarthGLPlot.java
+++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/EarthGLPlot.java
@@ -268,6 +268,8 @@ public class EarthGLPlot extends GLPlot {
this.setLight(gl);
+ this.updateTextRender(this.xAxis.getTickLabelFont());
+
//Draw graphics
for (int m = 0; m < this.graphics.getNumGraphics(); m++) {
Graphic graphic = this.graphics.get(m);
@@ -314,6 +316,9 @@ public class EarthGLPlot extends GLPlot {
//Draw title
this.drawTitle();
+ this.textRenderer.dispose();
+ this.textRenderer = null;
+
gl.glFlush();
//Do screen-shot
diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java
index cd111cf4..b9a4a217 100644
--- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java
+++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java
@@ -23,10 +23,7 @@ import org.meteoinfo.chart.jogl.tessellator.TessPolygon;
import org.meteoinfo.chart.plot.GridLine;
import org.meteoinfo.chart.plot.Plot;
import org.meteoinfo.chart.plot.PlotType;
-import org.meteoinfo.chart.render.jogl.JOGLGraphicRender;
-import org.meteoinfo.chart.render.jogl.MeshRender;
-import org.meteoinfo.chart.render.jogl.TriMeshRender;
-import org.meteoinfo.chart.render.jogl.VolumeRender;
+import org.meteoinfo.chart.render.jogl.*;
import org.meteoinfo.chart.shape.TextureShape;
import org.meteoinfo.common.*;
import org.meteoinfo.common.colors.ColorMap;
@@ -2444,87 +2441,121 @@ public class GLPlot extends Plot {
}
}
- if (graphic.getNumGraphics() == 1) {
- Graphic gg = graphic.getGraphicN(0);
- this.drawGraphic(gl, gg);
+ if (graphic instanceof MeshGraphic) {
+ if (!this.renderMap.containsKey(graphic)) {
+ renderMap.put(graphic, new MeshRender(gl, (MeshGraphic) graphic));
+ }
+ MeshRender meshRender = (MeshRender) renderMap.get(graphic);
+ meshRender.setTransform(this.transform, this.alwaysUpdateBuffers);
+ meshRender.setOrthographic(this.orthographic);
+ meshRender.setLighting(this.lighting);
+ meshRender.updateMatrix();
+ meshRender.draw();
+ } else if (graphic instanceof IsosurfaceGraphics) {
+ this.drawIsosurface(gl, (IsosurfaceGraphics) graphic);
+ } else if (graphic instanceof ParticleGraphics) {
+ this.drawParticles(gl, (ParticleGraphics) graphic);
+ } else if (graphic instanceof TriMeshGraphic) {
+ if (!this.renderMap.containsKey(graphic)) {
+ renderMap.put(graphic, new TriMeshRender(gl, (TriMeshGraphic) graphic));
+ }
+ TriMeshRender triMeshRender = (TriMeshRender) renderMap.get(graphic);
+ triMeshRender.setTransform(this.transform, this.alwaysUpdateBuffers);
+ triMeshRender.setOrthographic(this.orthographic);
+ triMeshRender.setLighting(this.lighting);
+ triMeshRender.updateMatrix();
+ triMeshRender.draw();
+ } else if (graphic instanceof VolumeGraphic) {
+ try {
+ if (this.clipPlane)
+ this.disableClipPlane(gl);
+ if (!this.renderMap.containsKey(graphic)) {
+ renderMap.put(graphic, new VolumeRender(gl, (VolumeGraphic) graphic));
+ }
+ VolumeRender volumeRender = (VolumeRender) renderMap.get(graphic);
+ volumeRender.setTransform(this.transform, this.alwaysUpdateBuffers);
+ volumeRender.setOrthographic(this.orthographic);
+ volumeRender.updateMatrix();
+ volumeRender.draw();
+ if (this.clipPlane)
+ this.enableClipPlane(gl);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
} else {
- if (graphic instanceof MeshGraphic) {
- //this.drawSurface(gl, (SurfaceGraphics) graphic);
- if (!this.renderMap.containsKey(graphic)) {
- renderMap.put(graphic, new MeshRender(gl, (MeshGraphic) graphic));
- }
- MeshRender meshRender = (MeshRender) renderMap.get(graphic);
- meshRender.setTransform(this.transform, this.alwaysUpdateBuffers);
- meshRender.setOrthographic(this.orthographic);
- meshRender.setLighting(this.lighting);
- meshRender.updateMatrix();
- meshRender.draw();
- } else if (graphic instanceof IsosurfaceGraphics) {
- this.drawIsosurface(gl, (IsosurfaceGraphics) graphic);
- } else if (graphic instanceof ParticleGraphics) {
- this.drawParticles(gl, (ParticleGraphics) graphic);
- } else if (graphic instanceof TriMeshGraphic) {
- if (!this.renderMap.containsKey(graphic)) {
- renderMap.put(graphic, new TriMeshRender(gl, (TriMeshGraphic) graphic));
- }
- TriMeshRender triMeshRender = (TriMeshRender) renderMap.get(graphic);
- triMeshRender.setTransform(this.transform, this.alwaysUpdateBuffers);
- triMeshRender.setOrthographic(this.orthographic);
- triMeshRender.setLighting(this.lighting);
- triMeshRender.updateMatrix();
- triMeshRender.draw();
- } else if (graphic instanceof VolumeGraphic) {
- try {
- if (this.clipPlane)
- this.disableClipPlane(gl);
- if (!this.renderMap.containsKey(graphic)) {
- renderMap.put(graphic, new VolumeRender(gl, (VolumeGraphic) graphic));
- }
- VolumeRender volumeRender = (VolumeRender) renderMap.get(graphic);
- volumeRender.setTransform(this.transform, this.alwaysUpdateBuffers);
- volumeRender.setOrthographic(this.orthographic);
- volumeRender.updateMatrix();
- volumeRender.draw();
- if (this.clipPlane)
- this.enableClipPlane(gl);
- } catch (Exception e) {
- e.printStackTrace();
- }
- } else {
- boolean isDraw = true;
- if (graphic instanceof GraphicCollection3D) {
- if (graphic.getNumGraphics() == 0) {
+ boolean isDraw = true;
+ if (graphic instanceof GraphicCollection3D) {
+ if (graphic.getNumGraphics() == 0) {
+ isDraw = false;
+ } else {
+ GraphicCollection3D gg = (GraphicCollection3D) graphic;
+ if (gg.isAllQuads()) {
+ this.drawQuadsPolygons(gl, gg);
+ isDraw = false;
+ } else if (gg.isAllTriangle()) {
+ this.drawTrianglePolygons(gl, gg);
isDraw = false;
- } else {
- GraphicCollection3D gg = (GraphicCollection3D) graphic;
- if (gg.isAllQuads()) {
- this.drawQuadsPolygons(gl, gg);
- isDraw = false;
- } else if (gg.isAllTriangle()) {
- this.drawTrianglePolygons(gl, gg);
- isDraw = false;
- }
}
}
- if (isDraw) {
- switch (graphic.getGraphicN(0).getShape().getShapeType()) {
- case POINT_Z:
- if (((GraphicCollection3D) graphic).isSphere()) {
- this.drawSpheres(gl, graphic);
- } else {
- this.drawPoints(gl, graphic);
+ }
+ if (isDraw) {
+ switch (graphic.getGraphicN(0).getShape().getShapeType()) {
+ case POINT_Z:
+ if (((GraphicCollection3D) graphic).isSphere()) {
+ this.drawSpheres(gl, graphic);
+ } else {
+ this.drawPoints(gl, graphic);
+ }
+ break;
+ case POLYLINE_Z:
+ boolean useRender = true;
+ ColorBreak cb = graphic.getGraphicN(0).getLegend();
+ if (cb instanceof StreamlineBreak) {
+ useRender = false;
+ } else if (cb instanceof ColorBreakCollection) {
+ if (((ColorBreakCollection) cb).get(0) instanceof StreamlineBreak) {
+ useRender = false;
}
- break;
- default:
+ }
+ if (useRender) {
+ if (graphic.getGraphicN(0).getShape() instanceof PipeShape) {
+ if (!this.renderMap.containsKey(graphic)) {
+ renderMap.put(graphic, new PipeRender(gl, (GraphicCollection3D) graphic));
+ }
+ PipeRender pipeRender = (PipeRender) renderMap.get(graphic);
+ pipeRender.setTransform(this.transform, this.alwaysUpdateBuffers);
+ pipeRender.setOrthographic(this.orthographic);
+ pipeRender.setLighting(this.lighting);
+ pipeRender.updateMatrix();
+ pipeRender.draw();
+ } else {
+ if (!this.renderMap.containsKey(graphic)) {
+ renderMap.put(graphic, new LineRender(gl, (GraphicCollection3D) graphic));
+ }
+ LineRender lineRender = (LineRender) renderMap.get(graphic);
+ lineRender.setTransform(this.transform, this.alwaysUpdateBuffers);
+ lineRender.setOrthographic(this.orthographic);
+ lineRender.setLighting(this.lighting);
+ lineRender.updateMatrix();
+ lineRender.draw();
+ }
+ } else {
for (int i = 0; i < graphic.getNumGraphics(); i++) {
Graphic gg = graphic.getGraphicN(i);
this.drawGraphic(gl, gg);
}
- break;
- }
+ }
+ break;
+ default:
+ for (int i = 0; i < graphic.getNumGraphics(); i++) {
+ Graphic gg = graphic.getGraphicN(i);
+ this.drawGraphic(gl, gg);
+ }
+ break;
}
}
}
+
if (graphic instanceof GraphicCollection3D) {
if (lightEnabled && !((GraphicCollection3D)graphic).isUsingLight()) {
this.lighting.start(gl);
@@ -2878,7 +2909,7 @@ public class GLPlot extends Plot {
Vector n1 = pipe.getNormal(i);
Vector n2 = pipe.getNormal(i+1);
gl.glBegin(GL_TRIANGLE_STRIP);
- for(int j = 0; j < (int)c2.size(); ++j)
+ for(int j = 0; j < c2.size(); ++j)
{
gl.glNormal3fv(JOGLUtil.toArray(n2.get(j)), 0);
gl.glVertex3fv(JOGLUtil.toArray(c2.get(j)), 0);
diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/pipe/Pipe.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/pipe/Pipe.java
index e97aae93..a2b4b328 100644
--- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/pipe/Pipe.java
+++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/pipe/Pipe.java
@@ -110,6 +110,14 @@ public class Pipe {
return this.contours.size();
}
+ /**
+ * Get vertex number
+ * @return Vertex number
+ */
+ public int getVertexCount() {
+ return this.path.size() * this.contour.size();
+ }
+
/**
* Get normal
* @param idx Index
diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/pipe/PipeShape.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/pipe/PipeShape.java
index 26269053..f922e3fb 100644
--- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/pipe/PipeShape.java
+++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/pipe/PipeShape.java
@@ -60,6 +60,10 @@ public class PipeShape extends PolylineZShape {
return this.steps;
}
+ public int getVertexCount() {
+ return this.getPointNum() * (this.steps + 1);
+ }
+
void generatePipe() {
Vector path = new Vector<>();
for (PointZ p : (List) this.getPoints()) {
diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/LineRender.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/LineRender.java
new file mode 100644
index 00000000..22439ea3
--- /dev/null
+++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/LineRender.java
@@ -0,0 +1,198 @@
+package org.meteoinfo.chart.render.jogl;
+
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.util.GLBuffers;
+import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
+import org.meteoinfo.chart.graphic.GraphicCollection3D;
+import org.meteoinfo.chart.jogl.Program;
+import org.meteoinfo.chart.jogl.Transform;
+import org.meteoinfo.chart.jogl.Utils;
+import org.meteoinfo.geometry.graphic.Graphic;
+import org.meteoinfo.geometry.legend.*;
+import org.meteoinfo.geometry.shape.PointZ;
+import org.meteoinfo.geometry.shape.Polyline;
+import org.meteoinfo.geometry.shape.PolylineZ;
+import org.meteoinfo.geometry.shape.PolylineZShape;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.jogamp.opengl.GL.GL_TEXTURE_2D;
+
+public class LineRender extends JOGLGraphicRender {
+
+ private GraphicCollection3D graphics;
+ private IntBuffer vbo;
+ private Program program;
+ private int vertexNum;
+ private int sizePosition;
+ private int sizeColor;
+ private int sizeNormal;
+ private float[] vertexColor;
+ private float lineWidth = 1.0f;
+ private List linePointNumbers;
+
+ /**
+ * Constructor
+ *
+ * @param gl The JOGL GL2 object
+ */
+ public LineRender(GL2 gl) {
+ super(gl);
+
+ if (useShader) {
+ try {
+ this.compileShaders();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ initVertexBuffer();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param gl The JOGL GL2 object
+ * @param graphics Linestring 3D graphics
+ */
+ public LineRender(GL2 gl, GraphicCollection3D graphics) {
+ this(gl);
+
+ this.graphics = graphics;
+ this.updateVertexColor();
+ }
+
+ void compileShaders() throws Exception {
+ String vertexShaderCode = Utils.loadResource("/shaders/surface/vertex.vert");
+ String fragmentShaderCode = Utils.loadResource("/shaders/surface/surface.frag");
+ program = new Program("surface", vertexShaderCode, fragmentShaderCode);
+ }
+
+ private void initVertexBuffer() {
+ vbo = GLBuffers.newDirectIntBuffer(1);
+ }
+
+ private void updateVertexColor() {
+ this.vertexNum = 0;
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ this.vertexNum += graphic.getShape().getPointNum();
+ }
+
+ this.vertexColor = new float[this.vertexNum * 4];
+ int i = 0;
+ float[] color;
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ int n = graphic.getShape().getPointNum();
+ ColorBreak cb = graphic.getLegend();
+ if (cb.getBreakType() == BreakTypes.COLOR_BREAK_COLLECTION) {
+ PolylineBreak lineBreak;
+ for (int j = 0; j < n; j++) {
+ lineBreak = (PolylineBreak) ((ColorBreakCollection) cb).get(j);
+ this.lineWidth = lineBreak.getWidth();
+ color = lineBreak.getColor().getRGBComponents(null);
+ System.arraycopy(color, 0, vertexColor, i * 4, 4);
+ i++;
+ }
+ } else {
+ this.lineWidth = ((PolylineBreak) cb).getWidth();
+ color = cb.getColor().getRGBComponents(null);
+ for (int j = 0; j < n; j++) {
+ System.arraycopy(color, 0, vertexColor, i * 4, 4);
+ i++;
+ }
+ }
+ }
+ }
+
+ private float[] getVertexPosition() {
+ float[] vertexData = new float[this.vertexNum * 3];
+ int i = 0;
+ linePointNumbers = new ArrayList<>();
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ PolylineZShape shape = (PolylineZShape) graphic.getShape();
+ for (Polyline line : shape.getPolylines()) {
+ List ps = (List) line.getPointList();
+ linePointNumbers.add(ps.size());
+ for (PointZ p : ps) {
+ vertexData[i] = transform.transform_x((float) p.X);
+ vertexData[i + 1] = transform.transform_y((float) p.Y);
+ vertexData[i + 2] = transform.transform_z((float) p.Z);
+ i += 3;
+ }
+ }
+ }
+
+ return vertexData;
+ }
+
+ @Override
+ public void setTransform(Transform transform, boolean alwaysUpdateBuffers) {
+ boolean updateBuffer = true;
+ if (!alwaysUpdateBuffers && this.transform != null && this.transform.equals(transform))
+ updateBuffer = false;
+
+ super.setTransform((Transform) transform.clone());
+
+ if (updateBuffer) {
+ float[] vertexData = this.getVertexPosition();
+ FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(vertexData);
+ sizePosition = vertexBuffer.capacity() * Float.BYTES;
+
+ FloatBuffer colorBuffer = GLBuffers.newDirectFloatBuffer(vertexColor);
+ sizeColor = colorBuffer.capacity() * Float.BYTES;
+ int totalSize = sizePosition + sizeColor;
+
+ gl.glGenBuffers(1, vbo);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0));
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, totalSize, null, GL.GL_STATIC_DRAW);
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, 0, sizePosition, vertexBuffer);
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, sizePosition, sizeColor, colorBuffer);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ }
+ }
+
+ void setUniforms() {
+
+ }
+
+ @Override
+ public void draw() {
+ if (useShader) { // not working now
+ program.use(gl);
+ setUniforms();
+
+ gl.glUseProgram(0);
+ } else {
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0));
+
+ // enable vertex arrays
+ gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
+ gl.glEnableClientState(GL2.GL_COLOR_ARRAY);
+ gl.glColorPointer(4, GL.GL_FLOAT, 0, sizePosition);
+
+ boolean lightEnabled = this.lighting.isEnable();
+ if (lightEnabled) {
+ this.lighting.stop(gl);
+ }
+ gl.glLineWidth(this.lineWidth * this.dpiScale);
+ int sIdx = 0;
+ for (int np : linePointNumbers) {
+ gl.glDrawArrays(GL.GL_LINE_STRIP, sIdx, np);
+ sIdx += np;
+ }
+ if (lightEnabled) {
+ this.lighting.start(gl);
+ }
+
+ gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
+ gl.glDisableClientState(GL2.GL_COLOR_ARRAY);
+
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ }
+ }
+}
diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/PipeRender.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/PipeRender.java
new file mode 100644
index 00000000..37b24816
--- /dev/null
+++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/render/jogl/PipeRender.java
@@ -0,0 +1,263 @@
+package org.meteoinfo.chart.render.jogl;
+
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GL2;
+import com.jogamp.opengl.util.GLBuffers;
+import org.joml.Vector3f;
+import org.meteoinfo.chart.graphic.GraphicCollection3D;
+import org.meteoinfo.chart.jogl.Program;
+import org.meteoinfo.chart.jogl.Transform;
+import org.meteoinfo.chart.jogl.Utils;
+import org.meteoinfo.chart.jogl.pipe.Pipe;
+import org.meteoinfo.chart.jogl.pipe.PipeShape;
+import org.meteoinfo.geometry.graphic.Graphic;
+import org.meteoinfo.geometry.legend.BreakTypes;
+import org.meteoinfo.geometry.legend.ColorBreak;
+import org.meteoinfo.geometry.legend.ColorBreakCollection;
+import org.meteoinfo.geometry.legend.PolylineBreak;
+import org.meteoinfo.geometry.shape.PointZ;
+import org.meteoinfo.geometry.shape.Polyline;
+import org.meteoinfo.geometry.shape.PolylineZShape;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+public class PipeRender extends JOGLGraphicRender{
+
+ private GraphicCollection3D graphics;
+ private IntBuffer vbo;
+ private Program program;
+ private int vertexNum;
+ private int sizePosition;
+ private int sizeColor;
+ private int sizeNormal;
+ private float[] vertexColor;
+ private int[] vertexIndices;
+ private List linePointNumbers;
+
+ /**
+ * Constructor
+ *
+ * @param gl The JOGL GL2 object
+ */
+ public PipeRender(GL2 gl) {
+ super(gl);
+
+ if (useShader) {
+ try {
+ this.compileShaders();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ initVertexBuffer();
+ }
+
+ /**
+ * Constructor
+ *
+ * @param gl The JOGL GL2 object
+ * @param graphics Linestring 3D graphics
+ */
+ public PipeRender(GL2 gl, GraphicCollection3D graphics) {
+ this(gl);
+
+ this.graphics = graphics;
+ this.vertexNum = 0;
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ this.vertexNum += ((PipeShape) graphic.getShape()).getVertexCount();
+ }
+ }
+
+ void compileShaders() throws Exception {
+ String vertexShaderCode = Utils.loadResource("/shaders/surface/vertex.vert");
+ String fragmentShaderCode = Utils.loadResource("/shaders/surface/surface.frag");
+ program = new Program("surface", vertexShaderCode, fragmentShaderCode);
+ }
+
+ private void initVertexBuffer() {
+ vbo = GLBuffers.newDirectIntBuffer(2);
+ }
+
+ private void updateVertexColor() {
+ this.vertexColor = new float[this.vertexNum * 4];
+ int i = 0;
+ float[] color;
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ PipeShape shape = (PipeShape) graphic.getShape();
+ Pipe pipe = shape.getPipe();
+ int n = pipe.getContourCount();
+ int m = pipe.getContour().size();
+ ColorBreak cb = graphic.getLegend();
+ if (cb.getBreakType() == BreakTypes.COLOR_BREAK_COLLECTION) {
+ ColorBreak lineBreak;
+ for (int j = 0; j < n; j++) {
+ lineBreak = ((ColorBreakCollection) cb).get(j);
+ color = lineBreak.getColor().getRGBComponents(null);
+ for (int k = 0; k < m; k++) {
+ System.arraycopy(color, 0, vertexColor, i * 4, 4);
+ i++;
+ }
+ }
+ } else {
+ color = cb.getColor().getRGBComponents(null);
+ for (int j = 0; j < n * m; j++) {
+ System.arraycopy(color, 0, vertexColor, i * 4, 4);
+ i++;
+ }
+ }
+ }
+ }
+
+ private float[] getVertexPosition() {
+ float[] vertexData = new float[this.vertexNum * 3];
+ int i = 0;
+ linePointNumbers = new ArrayList<>();
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ PipeShape shape = (PipeShape) graphic.getShape();
+ shape.transform(transform);
+ Pipe pipe = shape.getPipe();
+ linePointNumbers.add(pipe.getVertexCount());
+ for (int j = 0; j < pipe.getContourCount(); j++) {
+ for (Vector3f vector3f : shape.getPipe().getContour(j)) {
+ vertexData[i] = vector3f.x;
+ vertexData[i + 1] = vector3f.y;
+ vertexData[i + 2] = vector3f.z;
+ i += 3;
+ }
+ }
+ }
+
+ return vertexData;
+ }
+
+ private void updateVertexIndices() {
+ int idxNum = 0;
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ PipeShape shape = (PipeShape) graphic.getShape();
+ Pipe pipe = shape.getPipe();
+ idxNum += (pipe.getContourCount() - 1) * (pipe.getContour().size() - 1) * 6;
+ }
+
+ vertexIndices = new int[idxNum];
+ int i = 0;
+ int b = 0;
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ PipeShape shape = (PipeShape) graphic.getShape();
+ Pipe pipe = shape.getPipe();
+ int n = pipe.getContour().size();
+ for (int j = 0; j < pipe.getContourCount() - 1; j++) {
+ Vector c1 = pipe.getContour(j);
+ Vector c2 = pipe.getContour(j + 1);
+ for (int k = 0; k < n - 1; k++) {
+ vertexIndices[i++] = b + j * n + k;
+ vertexIndices[i++] = b + j * n + k + 1;
+ vertexIndices[i++] = b + (j + 1) * n + k;
+
+ vertexIndices[i++] = b + j * n + k + 1;
+ vertexIndices[i++] = b + (j + 1) * n + k + 1;
+ vertexIndices[i++] = b + (j + 1) * n + k;
+ }
+ }
+ b += pipe.getVertexCount();
+ }
+ }
+
+ private float[] getVertexNormal() {
+ float[] vertexNormal = new float[this.vertexNum * 3];
+ int i = 0;
+ for (Graphic graphic : this.graphics.getGraphics()) {
+ PipeShape shape = (PipeShape) graphic.getShape();
+ Pipe pipe = shape.getPipe();
+ for (int j = 0; j < pipe.getContourCount(); j++) {
+ for (Vector3f vector3f : shape.getPipe().getNormal(j)) {
+ vertexNormal[i] = vector3f.x;
+ vertexNormal[i + 1] = vector3f.y;
+ vertexNormal[i + 2] = vector3f.z;
+ i += 3;
+ }
+ }
+ }
+
+ return vertexNormal;
+ }
+
+ @Override
+ public void setTransform(Transform transform, boolean alwaysUpdateBuffers) {
+ boolean updateBuffer = true;
+ if (!alwaysUpdateBuffers && this.transform != null && this.transform.equals(transform))
+ updateBuffer = false;
+
+ super.setTransform((Transform) transform.clone());
+
+ if (updateBuffer) {
+ float[] vertexData = this.getVertexPosition();
+ FloatBuffer vertexBuffer = GLBuffers.newDirectFloatBuffer(vertexData);
+ sizePosition = vertexBuffer.capacity() * Float.BYTES;
+
+ float[] vertexNormal = this.getVertexNormal();
+ FloatBuffer normalBuffer = GLBuffers.newDirectFloatBuffer(vertexNormal);
+ sizeNormal = normalBuffer.capacity() * Float.BYTES;
+
+ if (vertexColor == null) {
+ this.updateVertexColor();
+ }
+ FloatBuffer colorBuffer = GLBuffers.newDirectFloatBuffer(vertexColor);
+ sizeColor = colorBuffer.capacity() * Float.BYTES;
+ int totalSize = sizePosition + sizeNormal + sizeColor;
+
+ gl.glGenBuffers(2, vbo);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0));
+ gl.glBufferData(GL.GL_ARRAY_BUFFER, totalSize, null, GL.GL_STATIC_DRAW);
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, 0, sizePosition, vertexBuffer);
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, sizePosition, sizeNormal, normalBuffer);
+ gl.glBufferSubData(GL.GL_ARRAY_BUFFER, sizePosition + sizeNormal, sizeColor, colorBuffer);
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+
+ if (vertexIndices == null) {
+ this.updateVertexIndices();
+ }
+ IntBuffer indexBuffer = GLBuffers.newDirectIntBuffer(vertexIndices);
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, vbo.get(1));
+ gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, indexBuffer.capacity() * Integer.BYTES, indexBuffer, GL.GL_STATIC_DRAW);
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+ }
+
+ void setUniforms() {
+
+ }
+
+ @Override
+ public void draw() {
+ if (useShader) { // not working now
+ program.use(gl);
+ setUniforms();
+
+ gl.glUseProgram(0);
+ } else {
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vbo.get(0));
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, vbo.get(1));
+
+ // enable vertex arrays
+ gl.glEnableClientState(GL2.GL_VERTEX_ARRAY);
+ gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
+ gl.glEnableClientState(GL2.GL_NORMAL_ARRAY);
+ gl.glNormalPointer(GL.GL_FLOAT, 0, sizePosition);
+ gl.glEnableClientState(GL2.GL_COLOR_ARRAY);
+ gl.glColorPointer(4, GL.GL_FLOAT, 0, sizePosition + sizeNormal);
+
+ gl.glDrawElements(GL2.GL_TRIANGLES, vertexIndices.length, GL.GL_UNSIGNED_INT, 0);
+
+ gl.glDisableClientState(GL2.GL_VERTEX_ARRAY);
+ gl.glDisableClientState(GL2.GL_NORMAL_ARRAY);
+ gl.glDisableClientState(GL2.GL_COLOR_ARRAY);
+
+ gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
+ gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+ }
+}
diff --git a/meteoinfo-geo/meteoinfo-geo.iml b/meteoinfo-geo/meteoinfo-geo.iml
index 49d4882b..7398874d 100644
--- a/meteoinfo-geo/meteoinfo-geo.iml
+++ b/meteoinfo-geo/meteoinfo-geo.iml
@@ -12,19 +12,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
@@ -33,28 +65,15 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -70,7 +89,6 @@
-
@@ -86,49 +104,31 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/analysis/GeometryUtil.java b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/analysis/GeometryUtil.java
index 19e47e3c..73e60e52 100644
--- a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/analysis/GeometryUtil.java
+++ b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/analysis/GeometryUtil.java
@@ -800,7 +800,7 @@ public class GeometryUtil {
}
if (isZ) {
- return new Array[]{xArray, yArray, zArray};
+ return new Array[]{xArray, yArray, zArray, mArray};
} else {
return new Array[]{xArray, yArray};
}
diff --git a/meteoinfo-lab/milconfig.xml b/meteoinfo-lab/milconfig.xml
index 635cb15d..916aa9e1 100644
--- a/meteoinfo-lab/milconfig.xml
+++ b/meteoinfo-lab/milconfig.xml
@@ -1,32 +1,32 @@
-
-
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
-
+
-
+
diff --git a/meteoinfo-lab/pylib/mipylib/numeric/core/_ndarray.py b/meteoinfo-lab/pylib/mipylib/numeric/core/_ndarray.py
index a8fb76df..cdf985f5 100644
--- a/meteoinfo-lab/pylib/mipylib/numeric/core/_ndarray.py
+++ b/meteoinfo-lab/pylib/mipylib/numeric/core/_ndarray.py
@@ -6,7 +6,7 @@ NDArray class - multiple dimensional array
from org.meteoinfo.data import GridArray
from org.meteoinfo.ndarray.math import ArrayMath, ArrayUtil
from org.meteoinfo.math.linalg import LinalgUtil
-from org.meteoinfo.ndarray import Array, Range, MAMath, Complex
+from org.meteoinfo.ndarray import Array, Range, MAMath, Complex, DataType
import datetime
@@ -20,7 +20,7 @@ class NDArray(object):
if not isinstance(array, Array):
array = ArrayUtil.array(array, None)
- if array.getRank() == 0:
+ if array.getRank() == 0 and array.getDataType() != DataType.STRUCTURE:
array = ArrayUtil.array([array.getIndexIterator().getObjectNext()])
self._array = array
diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/miplot$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/miplot$py.class
index 7baa6fbf..98498494 100644
Binary files a/meteoinfo-lab/pylib/mipylib/plotlib/miplot$py.class and b/meteoinfo-lab/pylib/mipylib/plotlib/miplot$py.class differ
diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/miplot.py b/meteoinfo-lab/pylib/mipylib/plotlib/miplot.py
index 4d68dd57..76a43ec5 100644
--- a/meteoinfo-lab/pylib/mipylib/plotlib/miplot.py
+++ b/meteoinfo-lab/pylib/mipylib/plotlib/miplot.py
@@ -974,7 +974,7 @@ def savefig(fname, width=None, height=None, dpi=None, sleep=None):
Save the current figure.
:param fname: (*string*) A string containing a path to a filename. The output format
- is deduced from the extention of the filename. Supported format: 'png', 'bmp',
+ is deduced from the extension of the filename. Supported format: 'png', 'bmp',
'jpg', 'gif', 'tif', 'eps' and 'pdf'.
:param width: (*int*) Optional, width of the output figure with pixel units. Default
is None, the output figure size is same as *figures* window.
@@ -2129,7 +2129,7 @@ def gifanimation(filename, repeat=0, delay=1000):
def gifaddframe(animation, width=None, height=None, dpi=None):
"""
- Add a frame to an gif animation object
+ Add a frame to a gif animation object
:param animation: Gif animation object
:param width: (*int*) Image width
diff --git a/meteoinfo-map/config.xml b/meteoinfo-map/config.xml
index b9693bdd..6e50fc10 100644
--- a/meteoinfo-map/config.xml
+++ b/meteoinfo-map/config.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/meteoinfo-map/default.mip b/meteoinfo-map/default.mip
index eb142490..af14e48a 100644
--- a/meteoinfo-map/default.mip
+++ b/meteoinfo-map/default.mip
@@ -2,15 +2,12 @@
-
+
-
+
-
-
-
@@ -27,7 +24,7 @@
-
+