diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/ChartWindArrow.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/ChartWindArrow.java index 4ee2c851..e0cb87e8 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/ChartWindArrow.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/ChartWindArrow.java @@ -408,8 +408,7 @@ public class ChartWindArrow { g.draw(rect); } } - //Draw.drawArraw(this.color, new PointF(x, y), this.windArrow, g, zoom); - Draw.drawArraw(new PointF(x, y), windArrow, arrowBreak, g, zoom); + Draw.drawArrow(new PointF(x, y), windArrow, arrowBreak, g, zoom); g.setColor(this.labelColor); Draw.drawString(g, this.label, x, y + dim.height + this.labelSep); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, rendering); 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 282779ee..b288506d 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 @@ -1,10 +1,58 @@ package org.meteoinfo.chart.jogl; +import org.meteoinfo.geometry.graphic.Graphic; import org.meteoinfo.projection.KnownCoordinateSystems; import org.meteoinfo.projection.ProjectionInfo; +import org.meteoinfo.projection.ProjectionUtil; public class MapPlot3D extends Plot3DGL { - private ProjectionInfo projInfo = KnownCoordinateSystems.geographic.world.WGS1984; + private ProjectionInfo projInfo; + /** + * Constructor + */ + public MapPlot3D() { + super(); + this.projInfo = KnownCoordinateSystems.geographic.world.WGS1984; + } + /** + * Constructor + * @param projInfo Projection info + */ + public MapPlot3D(ProjectionInfo projInfo) { + super(); + this.projInfo = projInfo; + } + + /** + * 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; + } + + /** + * Add a graphic + * + * @param graphic The graphic + * @param proj The graphic projection + */ + public void addGraphic(Graphic graphic, ProjectionInfo proj) { + if (proj.equals(this.projInfo)) { + super.addGraphic(graphic); + } else { + Graphic nGraphic = ProjectionUtil.projectGraphic(graphic, proj, this.projInfo); + super.addGraphic(nGraphic); + } + } } diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/Plot3DGL.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/Plot3DGL.java index 62a5f49f..94c2a5a1 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/Plot3DGL.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/Plot3DGL.java @@ -44,6 +44,8 @@ import org.meteoinfo.geometry.legend.*; import org.meteoinfo.geometry.shape.Shape; import org.meteoinfo.geometry.shape.*; import org.meteoinfo.math.meteo.MeteoMath; +import org.meteoinfo.projection.ProjectionInfo; +import org.meteoinfo.projection.ProjectionUtil; import javax.imageio.ImageIO; import javax.swing.*; @@ -73,6 +75,7 @@ import static com.jogamp.opengl.GL2ES3.GL_TEXTURE_BASE_LEVEL; public class Plot3DGL extends Plot implements GLEventListener { // + protected ProjectionInfo projInfo; protected boolean sampleBuffers = false; protected Color background = Color.white; protected boolean doScreenShot; @@ -130,6 +133,7 @@ public class Plot3DGL extends Plot implements GLEventListener { * Constructor */ public Plot3DGL() { + this.projInfo = null; this.doScreenShot = false; this.legends = new ArrayList<>(); //this.legends.add(new ChartColorBar(new LegendScheme(ShapeTypes.Polygon, 5))); @@ -173,6 +177,21 @@ public class Plot3DGL extends Plot implements GLEventListener { // // + /** + * 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; + } /** * Get is sample buffers or not @@ -967,6 +986,21 @@ public class Plot3DGL extends Plot implements GLEventListener { this.setDrawExtent((Extent3D) this.extent.clone()); } + /** + * Add a graphic + * + * @param graphic The graphic + * @param proj The graphic projection + */ + public void addGraphic(Graphic graphic, ProjectionInfo proj) { + if (proj == null || proj.equals(this.projInfo)) { + addGraphic(graphic); + } else { + Graphic nGraphic = ProjectionUtil.projectGraphic(graphic, proj, this.projInfo); + addGraphic(nGraphic); + } + } + /** * Remove a graphic by index * diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/plot/Plot2D.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/plot/Plot2D.java index e475cb03..48a47621 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/plot/Plot2D.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/plot/Plot2D.java @@ -430,7 +430,7 @@ public class Plot2D extends AbstractPlot2D { double[] sXY = projToScreen(p.X, p.Y, area); PointF pf = new PointF((float) sXY[0], (float) sXY[1]); float zoom = aPB.getSize() / 10; - Draw.drawArraw(pf, aPS, aPB, g, zoom); + Draw.drawArrow(pf, aPS, aPB, g, zoom); } private void drawPolyline(Graphics2D g, PolylineShape aPLS, PointBreak aPB, Rectangle2D area) { diff --git a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/drawing/Draw.java b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/drawing/Draw.java index cf4408e0..00f1494e 100644 --- a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/drawing/Draw.java +++ b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/drawing/Draw.java @@ -631,7 +631,7 @@ public class Draw { g.setColor(aColor); g.draw(new Line2D.Float(sP.X, sP.Y, eP.X, eP.Y)); - drawArraw(g, eP, angle); + drawArrow(g, eP, angle); return new Rectangle2D.Double(Math.min(sP.X, eP.X), Math.min(sP.Y, eP.Y), Math.abs(eP.X - sP.X), Math.abs(eP.Y - sP.Y)); @@ -656,17 +656,17 @@ public class Draw { * Draw wind arrow * * @param sP Start point - * @param aArraw The arrow + * @param arrow The arrow * @param pb PointBreak * @param g Graphics2D * @param zoom Zoom * @return Border rectangle */ - public static Rectangle2D drawArraw(PointF sP, WindArrow aArraw, ArrowBreak pb, Graphics2D g, double zoom) { + public static Rectangle2D drawArrow(PointF sP, WindArrow arrow, ArrowBreak pb, Graphics2D g, double zoom) { PointF eP = new PointF(0, 0); //PointF eP1 = new PointF(0, 0); - double len = aArraw.length; - double angle = aArraw.angle + 180; + double len = arrow.length; + double angle = arrow.angle + 180; if (angle >= 360) { angle -= 360; } @@ -686,19 +686,23 @@ public class Draw { g.draw(new Line2D.Float(sP.X, sP.Y, eP.X, eP.Y)); float headWidth = pb.getHeadWidth(); float headLength = pb.getHeadLength(); + if (len < headLength && pb.isAutoScale()) { + headWidth = headWidth * (float) len / headLength; + headLength = (float) len; + } drawArraw(g, eP, angle, headLength, headWidth, pb.getOverhang()); return new Rectangle2D.Double(Math.min(sP.X, eP.X), Math.min(sP.Y, eP.Y), Math.abs(eP.X - sP.X), Math.abs(eP.Y - sP.Y)); } /** - * Draw arraw + * Draw arrow * * @param g Graphics2D * @param sP Start point * @param angle Angle */ - public static void drawArraw(Graphics2D g, PointF sP, double angle) { + public static void drawArrow(Graphics2D g, PointF sP, double angle) { GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD, 5); Rectangle.Float rect = new Rectangle.Float(-4, -4, 8, 8); PointF[] pt = new PointF[5]; diff --git a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/mapview/MapView.java b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/mapview/MapView.java index 78a45215..a4368758 100644 --- a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/mapview/MapView.java +++ b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/mapview/MapView.java @@ -4826,7 +4826,7 @@ public class MapView extends JPanel implements IWebMapPanel { sPoint.X = (float) xy[0]; sPoint.Y = (float) xy[1]; //Draw.drawArraw(aColor, sPoint, aArraw, g, zoom); - Draw.drawArraw(sPoint, aArraw, aPB, g, zoom); + Draw.drawArrow(sPoint, aArraw, aPB, g, zoom); } break; case UNIQUE_VALUE: @@ -4843,7 +4843,7 @@ public class MapView extends JPanel implements IWebMapPanel { sPoint.Y = (float) xy[1]; aPB = (ArrowBreak) aLS.getLegendBreak(aArraw.getLegendIndex()); - Draw.drawArraw(sPoint, aArraw, aPB, g, zoom); + Draw.drawArrow(sPoint, aArraw, aPB, g, zoom); /*String vStr = aLayer.getCellValue(aLS.getFieldName(), shapeIdx).toString().trim(); if (vStr.isEmpty()) { diff --git a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/util/GeoProjectionUtil.java b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/util/GeoProjectionUtil.java index 3f39dae6..75828b01 100644 --- a/meteoinfo-geo/src/main/java/org/meteoinfo/geo/util/GeoProjectionUtil.java +++ b/meteoinfo-geo/src/main/java/org/meteoinfo/geo/util/GeoProjectionUtil.java @@ -405,7 +405,7 @@ public class GeoProjectionUtil { if (oLayer.getLabelPoints().size() > 0) { if (projectLabels) { - oLayer.setLabelPoints(ProjectionUtil.projectGraphics(oLayer.getLabelPoints(), fromProj, toProj)); + oLayer.setLabelPoints(ProjectionUtil.projectGraphic(oLayer.getLabelPoints(), fromProj, toProj)); } else { oLayer.setLabelPoints(new ArrayList<>(oLayer.getLabelPoints())); } @@ -639,7 +639,7 @@ public class GeoProjectionUtil { oLayer.getAttributeTable().setTable(aTable); if (oLayer.getLabelPoints().size() > 0) { - oLayer.setLabelPoints(ProjectionUtil.projectGraphics(oLayer.getLabelPoints(), fromProj, toProj)); + oLayer.setLabelPoints(ProjectionUtil.projectGraphic(oLayer.getLabelPoints(), fromProj, toProj)); } } diff --git a/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/legend/ArrowBreak.java b/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/legend/ArrowBreak.java index 7d5518be..5a7919cd 100644 --- a/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/legend/ArrowBreak.java +++ b/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/legend/ArrowBreak.java @@ -15,6 +15,7 @@ public class ArrowBreak extends PointBreak { private float headWidth; private float headLength; private float overhang; + private boolean autoScale; // // /** @@ -23,10 +24,9 @@ public class ArrowBreak extends PointBreak { public ArrowBreak() { super(); this.outlineColor = null; - this.width = 1; - this.headWidth = this.width * 5; - this.headLength = this.headWidth * 1.5f; + this.initWidth(1); this.overhang = 0; + this.autoScale = true; } /** @@ -55,6 +55,7 @@ public class ArrowBreak extends PointBreak { this.headWidth = this.width * 5; this.headLength = this.headWidth * 1.5f; this.overhang = 0; + this.autoScale = true; } // // @@ -121,7 +122,33 @@ public class ArrowBreak extends PointBreak { public void setOverhang(float value) { this.overhang = value; } + + /** + * Get whether automatically scale the arrow size + * @return Whether automatically scale the arrow size + */ + public boolean isAutoScale() { + return this.autoScale; + } + + /** + * Set whether automatically scale the arrow size + * @param value Whether automatically scale the arrow size + */ + public void setAutoScale(boolean value) { + this.autoScale = value; + } // // + + /** + * Initialize width + * @param width Width + */ + public void initWidth(float width) { + this.width = width; + this.headWidth = this.width * 5; + this.headLength = this.headWidth * 5 / 3; + } // } diff --git a/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/shape/PolygonShape.java b/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/shape/PolygonShape.java index 7ec2d22d..b4b2d019 100644 --- a/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/shape/PolygonShape.java +++ b/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/shape/PolygonShape.java @@ -284,7 +284,7 @@ public class PolygonShape extends Shape implements Cloneable { * * @param polygons polygon list */ - public void setPolygons(List polygons) { + public void setPolygons(List polygons) { _polygons = polygons; updatePartsPoints(); } diff --git a/meteoinfo-lab/milconfig.xml b/meteoinfo-lab/milconfig.xml index a919c2b6..4f6bef2d 100644 --- a/meteoinfo-lab/milconfig.xml +++ b/meteoinfo-lab/milconfig.xml @@ -1,30 +1,32 @@ - - - - - - - + - - + + + + + + + + + + diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/_axes$py.class index b18dcd84..ab2c4f87 100644 Binary files a/meteoinfo-lab/pylib/mipylib/plotlib/_axes$py.class and b/meteoinfo-lab/pylib/mipylib/plotlib/_axes$py.class differ diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes.py b/meteoinfo-lab/pylib/mipylib/plotlib/_axes.py index 6e031a49..8bd66ef1 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/_axes.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/_axes.py @@ -692,6 +692,7 @@ class Axes(object): ax2.axes.getAxis(Location.LEFT).setVisible(False) ax2.axes.getAxis(Location.TOP).setVisible(False) axis = ax2.axes.getAxis(Location.RIGHT) + axis.setDrawTickLine(True) axis.setDrawTickLabel(True) axis.setDrawLabel(True) return ax2 @@ -952,13 +953,17 @@ class Axes(object): self.axes.addGraphic(patch) self.axes.setAutoExtent() - def add_graphic(self, graphic): + def add_graphic(self, graphic, projection=None): ''' Add a graphic :param graphic: (*Graphic*) The graphic to be added. + :param projection: (*Projection*) The projection ''' - self.axes.addGraphic(graphic) + if projection is None: + self.axes.addGraphic(graphic) + else: + self.axes.addGraphic(graphic, projection) def get_graphics(self): ''' diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class index 0dbe8343..9b5da2e7 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 43f771de..70f9d780 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py @@ -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, GLForm, JOGLUtil, EarthPlot3D +from org.meteoinfo.chart.jogl import Plot3DGL, GLForm, JOGLUtil, EarthPlot3D, MapPlot3D from org.meteoinfo.math.interpolate import InterpolationMethod from org.meteoinfo.image import ImageUtil from org.meteoinfo.common import Extent3D @@ -33,7 +33,7 @@ import mipylib.numeric as np from mipylib import migl from mipylib.geolib import migeo -__all__ = ['Axes3DGL','EarthAxes3D'] +__all__ = ['Axes3DGL','MapAxes3D','EarthAxes3D'] class Axes3DGL(Axes3D): @@ -653,7 +653,8 @@ class Axes3DGL(Axes3D): visible = kwargs.pop('visible', True) if visible: - self.add_graphic(graphics) + projection = kwargs.pop('projection', migeo.projinfo()) + self.add_graphic(graphics, projection) return graphics def plot_layer(self, layer, **kwargs): @@ -1556,6 +1557,37 @@ class Axes3DGL(Axes3D): form.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE) form.setVisible(True) +class MapAxes3D(Axes3DGL): + """ + Map 3D axes. + """ + + def __init__(self, *args, **kwargs): + super(MapAxes3D, self).__init__(*args, **kwargs) + + projection = kwargs.pop('projection', None) + if not projection is None: + self.axes.setProjInfo(projection) + + def _set_plot(self, plot): + """ + Set plot. + + :param plot: (*EarthPlot3D*) Plot. + """ + if plot is None: + self.axes = MapPlot3D() + else: + self.axes = plot + + @property + def axestype(self): + return '3d_Map' + + @property + def projection(self): + return self.axes.getProjInfo() + class EarthAxes3D(Axes3DGL): """ Earth spherical 3D axes. diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/miplot$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/miplot$py.class index bb3784b4..e39bd940 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 8540c82c..aa883a99 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/miplot.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/miplot.py @@ -26,7 +26,7 @@ from org.meteoinfo.chart.form import ChartForm from org.meteoinfo.geometry.shape import ShapeTypes from ._axes import Axes, PolarAxes from ._axes3d import Axes3D -from ._axes3dgl import Axes3DGL, EarthAxes3D +from ._axes3dgl import Axes3DGL, MapAxes3D, EarthAxes3D from ._figure import Figure from ._glfigure import GLFigure from ._mapaxes import MapAxes @@ -1329,15 +1329,18 @@ def axes3d(*args, **kwargs): """ opengl = kwargs.pop('opengl', True) if opengl: - projection = kwargs.pop('projection', None) + projection = kwargs.get('projection', None) if projection is None: earth = kwargs.pop('earth', False) - else: - earth = projection == 'earth' - if earth: + if earth: + projection == 'earth' + + if projection is None: + return axes3dgl(*args, **kwargs) + elif projection == 'earth': return axes3d_earth(*args, **kwargs) else: - return axes3dgl(*args, **kwargs) + return axes3d_map(*args, **kwargs) else: kwargs['axestype'] = '3d' return axes(*args, **kwargs) @@ -1361,6 +1364,25 @@ def axes3dgl(*args, **kwargs): draw_if_interactive() return ax +def axes3d_map(*args, **kwargs): + """ + Add an map 3d axes with JOGL to the figure. + + :returns: The axes. + """ + global g_axes + + ax = MapAxes3D(*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) + + draw_if_interactive() + return ax + def axes3d_earth(*args, **kwargs): """ Add an earth 3d axes with JOGL to the figure. diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/plotutil$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/plotutil$py.class index d0fed57d..450397fd 100644 Binary files a/meteoinfo-lab/pylib/mipylib/plotlib/plotutil$py.class and b/meteoinfo-lab/pylib/mipylib/plotlib/plotutil$py.class differ diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/plotutil.py b/meteoinfo-lab/pylib/mipylib/plotlib/plotutil.py index c0c40645..129c9fde 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/plotutil.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/plotutil.py @@ -654,11 +654,13 @@ def point2arrow(pb, **kwargs): ''' arrowbreak = ArrowBreak(pb) width = kwargs.pop('width', 1.) - arrowbreak.setWidth(width) - headwidth = kwargs.pop('headwidth', width * 5.) - arrowbreak.setHeadWidth(headwidth) - headlength = kwargs.pop('headlength', headwidth * 1.5) - arrowbreak.setHeadLength(headlength) + arrowbreak.initWidth(width) + headwidth = kwargs.pop('headwidth', None) + if not headwidth is None: + arrowbreak.setHeadWidth(headwidth) + headlength = kwargs.pop('headlength', None) + if not headlength is None: + arrowbreak.setHeadLength(headlength) overhang = kwargs.pop('overhang', None) if not overhang is None: arrowbreak.setOverhang(overhang) diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionUtil.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionUtil.java index 532330c0..2675d91e 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionUtil.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionUtil.java @@ -529,55 +529,109 @@ public class ProjectionUtil { * @return Projected polygon shape */ public static PolygonShape projectPolygonShape(PolygonShape aPGS, ProjectionInfo fromProj, ProjectionInfo toProj) { - List polygons = new ArrayList<>(); - for (int i = 0; i < aPGS.getPolygons().size(); i++) { - Polygon aPG = aPGS.getPolygons().get(i); - Polygon bPG = null; - for (int r = 0; r < aPG.getRingNumber(); r++) { - List pList = (List) aPG.getRings().get(r); - List newPoints = new ArrayList<>(); - for (int j = 0; j < pList.size(); j++) { - double[][] points = new double[1][]; - PointD wPoint = pList.get(j); - points[0] = new double[]{wPoint.X, wPoint.Y}; - try { - Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); - if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { - wPoint = new PointD(); - wPoint.X = points[0][0]; - wPoint.Y = points[0][1]; - newPoints.add(wPoint); + if (aPGS instanceof PolygonZShape) { + List polygons = new ArrayList<>(); + for (int i = 0; i < aPGS.getPolygons().size(); i++) { + PolygonZ aPG = (PolygonZ) aPGS.getPolygons().get(i); + PolygonZ bPG = null; + for (int r = 0; r < aPG.getRingNumber(); r++) { + List pList = (List) aPG.getRings().get(r); + List newPoints = new ArrayList<>(); + for (int j = 0; j < pList.size(); j++) { + double[][] points = new double[1][]; + PointZ wPoint = pList.get(j); + points[0] = new double[]{wPoint.X, wPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) || !Double.isInfinite(points[0][0]) || + !Double.isNaN(points[0][1]) || !Double.isInfinite(points[0][1])) { + wPoint = new PointZ(); + wPoint.X = points[0][0]; + wPoint.Y = points[0][1]; + newPoints.add(wPoint); + } + } catch (Exception e) { + break; } - } catch (Exception e) { - break; } - } - if (r == 0) { - if (newPoints.size() > 2) { - bPG = new Polygon(); - bPG.setOutLine(newPoints); + if (r == 0) { + if (newPoints.size() > 2) { + bPG = new PolygonZ(); + bPG.setOutLine(newPoints); + } else { + break; + } } else { - break; - } - } else { - if (newPoints.size() > 2) { - bPG.addHole(newPoints); + if (newPoints.size() > 2) { + bPG.addHole(newPoints); + } } } + + if (bPG != null) { + polygons.add(bPG); + } } - if (bPG != null) { - polygons.add(bPG); + if (polygons.size() > 0) { + ((PolygonZShape) aPGS).setPolygons(polygons); + + return aPGS; + } else { + return null; } - } - - if (polygons.size() > 0) { - aPGS.setPolygons(polygons); - - return aPGS; } else { - return null; + List polygons = new ArrayList<>(); + for (int i = 0; i < aPGS.getPolygons().size(); i++) { + Polygon aPG = aPGS.getPolygons().get(i); + Polygon bPG = null; + for (int r = 0; r < aPG.getRingNumber(); r++) { + List pList = (List) aPG.getRings().get(r); + List newPoints = new ArrayList<>(); + for (int j = 0; j < pList.size(); j++) { + double[][] points = new double[1][]; + PointD wPoint = pList.get(j); + points[0] = new double[]{wPoint.X, wPoint.Y}; + try { + Reproject.reprojectPoints(points, fromProj, toProj, 0, points.length); + if (!Double.isNaN(points[0][0]) && !Double.isNaN(points[0][1])) { + wPoint = new PointD(); + wPoint.X = points[0][0]; + wPoint.Y = points[0][1]; + newPoints.add(wPoint); + } + } catch (Exception e) { + break; + } + } + + if (r == 0) { + if (newPoints.size() > 2) { + bPG = new Polygon(); + bPG.setOutLine(newPoints); + } else { + break; + } + } else { + if (newPoints.size() > 2) { + bPG.addHole(newPoints); + } + } + } + + if (bPG != null) { + polygons.add(bPG); + } + } + + if (polygons.size() > 0) { + aPGS.setPolygons(polygons); + + return aPGS; + } else { + return null; + } } } @@ -590,11 +644,23 @@ public class ProjectionUtil { * @return Projected graphic */ public static Graphic projectGraphic(Graphic graphic, ProjectionInfo fromProj, ProjectionInfo toProj) { - Shape shape = projectShape(graphic.getShape(), fromProj, toProj); - return new Graphic(shape, graphic.getLegend()); + if (graphic instanceof GraphicCollection) { + GraphicCollection newGCollection = new GraphicCollection(); + for (Graphic aGraphic : ((GraphicCollection) graphic).getGraphics()) { + aGraphic.setShape(projectShape(aGraphic.getShape(), fromProj, toProj)); + if (aGraphic.getShape() != null) { + newGCollection.add(aGraphic); + } + } + + return newGCollection; + } else { + Shape shape = projectShape(graphic.getShape(), fromProj, toProj); + return new Graphic(shape, graphic.getLegend()); + } } - public static GraphicCollection projectGraphics(GraphicCollection aGCollection, ProjectionInfo fromProj, ProjectionInfo toProj) { + public static GraphicCollection projectGraphic(GraphicCollection aGCollection, ProjectionInfo fromProj, ProjectionInfo toProj) { GraphicCollection newGCollection = new GraphicCollection(); for (Graphic aGraphic : aGCollection.getGraphics()) { aGraphic.setShape(projectShape(aGraphic.getShape(), fromProj, toProj)); @@ -606,7 +672,7 @@ public class ProjectionUtil { return newGCollection; } - public static List projectGraphics(List graphics, ProjectionInfo fromProj, ProjectionInfo toProj) { + public static List projectGraphic(List graphics, ProjectionInfo fromProj, ProjectionInfo toProj) { List newGraphics = new ArrayList<>(); for (Graphic aGraphic : graphics) { Shape aShape = projectShape(aGraphic.getShape(), fromProj, toProj); @@ -634,6 +700,7 @@ public class ProjectionUtil { break; case POLYGON: case POLYGON_M: + case POLYGON_Z: case RECTANGLE: newShape = projectPolygonShape((PolygonShape) aShape, fromProj, toProj); break;