Add MapGLPlot class

This commit is contained in:
wyq 2022-08-25 23:15:52 +08:00
parent 4d0facb9a2
commit 05610158f2
8 changed files with 422 additions and 33 deletions

View File

@ -281,7 +281,7 @@ public class GLChartPanel extends GLJPanel implements IChartPanel{
}
/**
* Get if using off screen image double buffering.
* Get if using off-screen image double buffering.
* Using double buffering will be faster but lower view quality in
* high dpi screen computer.
*
@ -292,7 +292,7 @@ public class GLChartPanel extends GLJPanel implements IChartPanel{
}
/**
* Set using off screen image double buffering or not.
* Set using off-screen image double buffering or not.
* @param value Boolean
*/
public void setDoubleBuffer(boolean value) {

View File

@ -0,0 +1,390 @@
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.*;
import org.meteoinfo.geometry.graphic.Graphic;
import org.meteoinfo.projection.ProjectionInfo;
import java.awt.geom.Rectangle2D;
import java.util.List;
public class MapGLPlot extends GLPlot {
private ProjectionInfo projInfo;
/**
* Constructor
*/
public MapGLPlot() {
this(ProjectionInfo.LONG_LAT);
}
/**
* Constructor
* @param projInfo Projection info
*/
public MapGLPlot(ProjectionInfo projInfo) {
super();
this.gridLine = new MapGridLine3D();
this.projInfo = projInfo;
updateExtent();
}
/**
* Get projection info
* @return Projection info
*/
public ProjectionInfo getProjInfo() {
return this.projInfo;
}
/**
* Set projection info
* @param value Projection info
*/
public void setProjInfo(ProjectionInfo value) {
this.projInfo = value;
if (!projInfo.isLonLat())
((MapGridLine3D) this.gridLine).setProjInfo(projInfo);
}
/**
* Add a graphic
*
* @param graphic The graphic
* @param proj The graphic projection
*/
@Override
public void addGraphic(Graphic graphic, ProjectionInfo proj) {
if (proj.equals(this.projInfo)) {
super.addGraphic(graphic);
} else {
Graphic nGraphic = GraphicProjectionUtil.projectClipGraphic(graphic, proj, this.projInfo);
super.addGraphic(nGraphic);
}
}
/**
* Add a graphic
*
* @param index The index
* @param graphic The graphic
* @param proj The graphic projection
*/
@Override
public void addGraphic(int index, Graphic graphic, ProjectionInfo proj) {
if (proj.equals(this.projInfo)) {
super.addGraphic(index, graphic);
} else {
Graphic nGraphic = GraphicProjectionUtil.projectClipGraphic(graphic, proj, this.projInfo);
super.addGraphic(index, nGraphic);
}
}
/**
* Set draw extent
*
* @param value Extent
*/
@Override
public void setDrawExtent(Extent3D value) {
super.setDrawExtent(value);
if (!this.projInfo.isLonLat()) {
((MapGridLine3D) this.gridLine).setExtent(value);
}
}
@Override
protected void updateExtent() {
super.updateExtent();
if (!this.projInfo.isLonLat()) {
((MapGridLine3D) this.gridLine).setExtent(this.drawExtent);
}
}
@Override
protected void drawXYGridLine(GL2 gl) {
if (this.projInfo.isLonLat()) {
super.drawXYGridLine(gl);
} else {
MapGridLine mapGridLine = (MapGridLine3D) gridLine;
//Longitude
if (mapGridLine.isDrawXLine()) {
if (mapGridLine.getLongitudeLines() != null) {
this.drawGraphics(gl, mapGridLine.getLongitudeLines());
}
}
//Latitude
if (mapGridLine.isDrawYLine()) {
if (mapGridLine.getLatitudeLines() != null) {
this.drawGraphics(gl, mapGridLine.getLatitudeLines());
}
}
}
}
@Override
protected void drawAxis(GL2 gl) {
if (this.projInfo.isLonLat()) {
super.drawAxis(gl);
} else {
float xMin, xMax, yMin, yMax, zMin, zMax;
xMin = this.transform.transform_x((float) axesExtent.minX);
xMax = this.transform.transform_x((float) axesExtent.maxX);
yMin = this.transform.transform_y((float) axesExtent.minY);
yMax = this.transform.transform_y((float) axesExtent.maxY);
zMin = this.transform.transform_z((float) axesExtent.minZ);
zMax = this.transform.transform_z((float) axesExtent.maxZ);
gl.glDepthFunc(GL.GL_ALWAYS);
//Draw axis
float[] rgba;
float x, y;
int skip;
XAlign xAlign;
YAlign yAlign;
Rectangle2D rect;
float strWidth, strHeight;
MapGridLine3D mapGridLine = (MapGridLine3D) gridLine;
if (this.displayXY) {
//Draw x/y axis lines
//x axis line
if (this.angleY >= 90 && this.angleY < 270) {
y = yMax;
} else {
y = yMin;
}
rgba = this.xAxis.getLineColor().getRGBComponents(null);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
gl.glLineWidth(this.xAxis.getLineWidth() * this.dpiScale);
gl.glBegin(GL2.GL_LINES);
gl.glVertex3f(xMin, y, zMin);
gl.glVertex3f(xMax, y, zMin);
gl.glEnd();
//Longitude axis ticks
float tickLen = this.xAxis.getTickLength() * this.lenScale;
float axisLen = this.toScreenLength(xMin, y, zMin, xMax, y, zMin);
float y1 = y > 0 ? y + tickLen : y - tickLen;
if (this.angleY < 90 || (this.angleY >= 180 && this.angleY < 270)) {
xAlign = XAlign.LEFT;
} else {
xAlign = XAlign.RIGHT;
}
if (this.angleX > -120) {
yAlign = YAlign.TOP;
} else {
yAlign = YAlign.BOTTOM;
}
strWidth = 0.0f;
strHeight = 0.0f;
List<GridLabel> lonLabels = mapGridLine.getLongitudeLabels();
for (int i = 0; i < lonLabels.size(); i++) {
GridLabel gridLabel = lonLabels.get(i);
PointD point = gridLabel.getCoord();
x = (float) point.X;
if (x < axesExtent.minX || x > axesExtent.maxX) {
continue;
}
x = this.transform.transform_x(x);
//Draw tick line
rgba = this.xAxis.getLineColor().getRGBComponents(null);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
gl.glLineWidth(this.xAxis.getLineWidth() * this.dpiScale);
gl.glBegin(GL2.GL_LINES);
gl.glVertex3f(x, y, zMin);
gl.glVertex3f(x, y1, zMin);
gl.glEnd();
//Draw tick label
rect = drawString(gl, gridLabel.getLabString(), this.xAxis.getTickLabelFont(),
this.xAxis.getTickLabelColor(), x, y1, zMin, xAlign, yAlign);
if (strWidth < rect.getWidth()) {
strWidth = (float) rect.getWidth();
}
if (strHeight < rect.getHeight()) {
strHeight = (float) rect.getHeight();
}
}
//Draw x axis label
ChartText label = this.xAxis.getLabel();
if (label != null) {
strWidth += this.tickSpace;
float angle = this.toScreenAngle(xMin, y, zMin, xMax, y, zMin);
angle = y < 0 ? 270 - angle : 90 - angle;
float yShift = Math.min(-strWidth, -strWidth);
if (this.angleX <= -120) {
yShift = -yShift;
}
drawString(gl, label, 0.0f, y1, zMin, XAlign.CENTER, yAlign, angle, 0, yShift);
}
////////////////////////////////////////////
//y axis line
if (this.angleY >= 180 && this.angleY < 360) {
x = xMax;
} else {
x = xMin;
}
rgba = this.yAxis.getLineColor().getRGBComponents(null);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
gl.glLineWidth(this.yAxis.getLineWidth() * this.dpiScale);
gl.glBegin(GL2.GL_LINES);
gl.glVertex3f(x, yMin, zMin);
gl.glVertex3f(x, yMax, zMin);
gl.glEnd();
//y axis ticks
axisLen = this.toScreenLength(x, yMin, zMin, x, yMax, zMin);
tickLen = this.yAxis.getTickLength() * this.lenScale;
float x1 = x > 0 ? x + tickLen : x - tickLen;
if (this.angleY < 90 || (this.angleY >= 180 && this.angleY < 270)) {
xAlign = XAlign.RIGHT;
} else {
xAlign = XAlign.LEFT;
}
if (this.angleX > -120) {
yAlign = YAlign.TOP;
} else {
yAlign = YAlign.BOTTOM;
}
strWidth = 0.0f;
strHeight = 0.0f;
List<GridLabel> latLabels = mapGridLine.getLatitudeLabels();
for (int i = 0; i < latLabels.size(); i++) {
GridLabel gridLabel = latLabels.get(i);
PointD point = gridLabel.getCoord();
y = (float) point.Y;
if (y < axesExtent.minY || y > axesExtent.maxY) {
continue;
}
y = this.transform.transform_y(y);
//Draw tick line
rgba = this.yAxis.getLineColor().getRGBComponents(null);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
gl.glLineWidth(this.yAxis.getLineWidth() * this.dpiScale);
gl.glBegin(GL2.GL_LINES);
gl.glVertex3f(x, y, zMin);
gl.glVertex3f(x1, y, zMin);
gl.glEnd();
//Draw tick label
rect = drawString(gl, gridLabel.getLabString(), this.yAxis.getTickLabelFont(),
this.yAxis.getTickLabelColor(), x1, y, zMin, xAlign, yAlign);
if (strWidth < rect.getWidth()) {
strWidth = (float) rect.getWidth();
}
if (strHeight < rect.getHeight()) {
strHeight = (float) rect.getHeight();
}
}
//Draw y axis label
label = this.yAxis.getLabel();
if (label != null) {
strWidth += this.tickSpace;
float angle = this.toScreenAngle(x, yMin, zMin, x, yMax, xMin);
angle = x > 0 ? 270 - angle : 90 - angle;
float yShift = Math.min(-strWidth, -strWidth);
if (this.angleX <= -120) {
yShift = -yShift;
}
drawString(gl, label, x1, 0.0f, zMin, XAlign.CENTER, yAlign, angle, 0, yShift);
}
}
//Draw z axis
if (this.displayZ) {
//z axis line
if (this.angleY < 90) {
x = xMin;
y = yMax;
} else if (this.angleY < 180) {
x = xMax;
y = yMax;
} else if (this.angleY < 270) {
x = xMax;
y = yMin;
} else {
x = xMin;
y = yMin;
}
rgba = this.zAxis.getLineColor().getRGBComponents(null);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
gl.glLineWidth(this.zAxis.getLineWidth() * this.dpiScale);
gl.glBegin(GL2.GL_LINES);
gl.glVertex3f(x, y, zMin);
gl.glVertex3f(x, y, zMax);
gl.glEnd();
//z axis ticks
this.zAxis.updateTickLabels();
List<ChartText> tlabs = this.zAxis.getTickLabels();
float axisLen = this.toScreenLength(x, y, zMin, x, y, zMax);
skip = getLabelGap(this.zAxis.getTickLabelFont(), tlabs, axisLen);
float x1 = x;
float y1 = y;
float tickLen = this.zAxis.getTickLength() * this.lenScale;
if (x < 0) {
if (y > 0) {
y1 += tickLen;
} else {
x1 -= tickLen;
}
} else {
if (y > 0) {
x1 += tickLen;
} else {
y1 -= tickLen;
}
}
xAlign = XAlign.RIGHT;
yAlign = YAlign.CENTER;
strWidth = 0.0f;
float v;
for (int i = 0; i < this.zAxis.getTickValues().length; i += skip) {
v = (float) this.zAxis.getTickValues()[i];
if (v < axesExtent.minZ || v > axesExtent.maxZ) {
continue;
}
v = this.transform.transform_z(v);
if (i == tlabs.size()) {
break;
}
//Draw tick line
rgba = this.zAxis.getLineColor().getRGBComponents(null);
gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);
gl.glLineWidth(this.zAxis.getLineWidth() * this.dpiScale);
gl.glBegin(GL2.GL_LINES);
gl.glVertex3f(x, y, v);
gl.glVertex3f(x1, y1, v);
gl.glEnd();
//Draw tick label
rect = drawString(gl, tlabs.get(i), x1, y1, v, xAlign, yAlign, -this.tickSpace, 0);
if (strWidth < rect.getWidth()) {
strWidth = (float) rect.getWidth();
}
}
//Draw z axis label
ChartText label = this.zAxis.getLabel();
if (label != null) {
float yShift = strWidth + this.tickSpace * 3;
drawString(gl, label, x1, y1, 0.0f, XAlign.CENTER, YAlign.BOTTOM, 90.f, 0, yShift);
}
}
gl.glDepthFunc(GL2.GL_LEQUAL);
}
}
}

View File

@ -1,34 +1,34 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\interpolate"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\bar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\contour"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\imshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\isosurface"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\particles"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\plot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\volume"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\contour"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\3d_earth"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\isosurface\fimplicit3_gyroid.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\subplot_3d_cylinder.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\subplot_2_3d_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf\surf_flower_2.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\MyProgram\java\MeteoInfoDev\toolbox\meteoview3d\mainGUI.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\isosurface\fimplicit3_gyroid.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\subplot_3d_cylinder.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\subplot_2_3d_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\surf\surf_flower_2.py"/>
</RecentFiles>
</File>
<Font>
@ -36,5 +36,5 @@
</Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,0" MainFormSize="1408,828"/>
<Startup MainFormLocation="-7,-7" MainFormSize="1293,685"/>
</MeteoInfo>

View File

@ -13,7 +13,7 @@ from org.meteoinfo.geo.legend import LegendManage
from org.meteoinfo.geo.layer import LayerTypes
from org.meteoinfo.geometry.shape import ShapeTypes
from org.meteoinfo.geometry.graphic import Graphic, GraphicCollection
from org.meteoinfo.chart.jogl import Plot3DGL, GLPlot, GLForm, JOGLUtil, EarthPlot3D, MapPlot3D
from org.meteoinfo.chart.jogl import GLPlot, GLForm, JOGLUtil, EarthGLPlot, MapGLPlot
from org.meteoinfo.math.interpolate import InterpolationMethod
from org.meteoinfo.image import ImageUtil
from org.meteoinfo.common import Extent3D
@ -1465,7 +1465,7 @@ class MapAxes3D(Axes3DGL):
:param plot: (*EarthPlot3D*) Plot.
"""
if plot is None:
self._axes = MapPlot3D()
self._axes = MapGLPlot()
else:
self._axes = plot
@ -1506,7 +1506,7 @@ class EarthAxes3D(Axes3DGL):
:param plot: (*EarthPlot3D*) Plot.
"""
if plot is None:
self._axes = EarthPlot3D()
self._axes = EarthGLPlot()
else:
self._axes = plot

View File

@ -847,9 +847,9 @@ def axes3d_map(*args, **kwargs):
g_axes = ax
if not batchmode:
if g_figure is None or isinstance(g_figure, Figure):
glfigure(**kwargs)
g_figure.set_axes(ax)
if g_figure is None:
figure(**kwargs)
g_figure.add_axes(ax)
draw_if_interactive()
return ax
@ -866,9 +866,9 @@ def axes3d_earth(*args, **kwargs):
g_axes = ax
if not batchmode:
if g_figure is None or isinstance(g_figure, Figure):
glfigure(**kwargs)
g_figure.set_axes(ax)
if g_figure is None:
figure(**kwargs)
g_figure.add_axes(ax)
draw_if_interactive()
return ax

View File

@ -21,10 +21,9 @@ import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import org.meteoinfo.chart.ChartPanel;
import org.meteoinfo.chart.GLChartPanel;
import org.meteoinfo.chart.IChartPanel;
import org.meteoinfo.chart.MouseMode;
//import org.meteoinfo.chart.jogl.GLChartPanel;
import org.meteoinfo.console.jython.PythonInteractiveInterpreter;
import org.meteoinfo.ui.ButtonTabComponent;
@ -192,8 +191,8 @@ public class FigureDockable extends DefaultSingleCDockable {
* @return Figure chart panel
*/
public final IChartPanel addNewFigure(String title, final JPanel cp) {
if (cp instanceof ChartPanel) {
((ChartPanel)cp).setDoubleBuffer(this.doubleBuffer);
if (cp instanceof GLChartPanel) {
((GLChartPanel)cp).setDoubleBuffer(this.doubleBuffer);
}
final JScrollPane sp = new JScrollPane(cp);
this.tabbedPanel.add(sp, title);
@ -220,8 +219,8 @@ public class FigureDockable extends DefaultSingleCDockable {
public final IChartPanel addFigure(final JPanel ncp) {
((IChartPanel) ncp).setLoading(true);
if (ncp instanceof ChartPanel) {
((ChartPanel) ncp).setDoubleBuffer(this.doubleBuffer);
if (ncp instanceof GLChartPanel) {
((GLChartPanel) ncp).setDoubleBuffer(this.doubleBuffer);
}
int idx = 1;
if (this.tabbedPanel.getTabCount() > 0) {
@ -319,10 +318,10 @@ public class FigureDockable extends DefaultSingleCDockable {
* @param idx Figure index
* @return Figure
*/
public ChartPanel getFigure(int idx) {
public GLChartPanel getFigure(int idx) {
if (this.tabbedPanel.getTabCount() > idx) {
JScrollPane sp = (JScrollPane) this.tabbedPanel.getComponentAt(idx);
return (ChartPanel) sp.getViewport().getView();
return (GLChartPanel) sp.getViewport().getView();
} else {
return null;
}
@ -340,8 +339,8 @@ public class FigureDockable extends DefaultSingleCDockable {
* Get figures
* @return Figures
*/
public List<ChartPanel> getFigures() {
List<ChartPanel> figures = new ArrayList<>();
public List<GLChartPanel> getFigures() {
List<GLChartPanel> figures = new ArrayList<>();
for (int i = 0; i < this.tabbedPanel.getTabCount(); i++) {
figures.add(this.getFigure(i));
}
@ -353,7 +352,7 @@ public class FigureDockable extends DefaultSingleCDockable {
*
* @param cp ChartPanel
*/
public void setCurrentFigure(ChartPanel cp) {
public void setCurrentFigure(GLChartPanel cp) {
if (this.tabbedPanel.getTabCount() > 0) {
JScrollPane sp = new JScrollPane(cp);
this.tabbedPanel.setComponentAt(this.tabbedPanel.getSelectedIndex(), sp);
@ -375,8 +374,8 @@ public class FigureDockable extends DefaultSingleCDockable {
*/
public void setDoubleBuffer(boolean doubleBuffer) {
this.doubleBuffer = doubleBuffer;
List<ChartPanel> figures = this.getFigures();
for (ChartPanel figure : figures) {
List<GLChartPanel> figures = this.getFigures();
for (GLChartPanel figure : figures) {
figure.setDoubleBuffer(this.doubleBuffer);
figure.repaintNew();
}