add Transform for graphics

This commit is contained in:
wyq 2024-06-19 00:02:00 +08:00
parent 1cee1c2994
commit c3f4e3b526
17 changed files with 472 additions and 107 deletions

View File

@ -18,6 +18,8 @@ import org.meteoinfo.data.mapdata.webmap.GeoPosition;
import org.meteoinfo.data.mapdata.webmap.GeoUtil; import org.meteoinfo.data.mapdata.webmap.GeoUtil;
import org.meteoinfo.data.mapdata.webmap.IWebMapPanel; import org.meteoinfo.data.mapdata.webmap.IWebMapPanel;
import org.meteoinfo.data.mapdata.webmap.TileLoadListener; import org.meteoinfo.data.mapdata.webmap.TileLoadListener;
import org.meteoinfo.geometry.graphic.Transform;
import org.meteoinfo.projection.*;
import org.meteoinfo.render.java2d.Draw; import org.meteoinfo.render.java2d.Draw;
import org.meteoinfo.chart.graphic.GeoGraphicCollection; import org.meteoinfo.chart.graphic.GeoGraphicCollection;
import org.meteoinfo.geometry.graphic.Graphic; import org.meteoinfo.geometry.graphic.Graphic;
@ -25,10 +27,6 @@ import org.meteoinfo.geometry.graphic.GraphicCollection;
import org.meteoinfo.chart.graphic.GraphicProjectionUtil; import org.meteoinfo.chart.graphic.GraphicProjectionUtil;
import org.meteoinfo.geometry.legend.*; import org.meteoinfo.geometry.legend.*;
import org.meteoinfo.geometry.shape.*; import org.meteoinfo.geometry.shape.*;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.ProjectionInfo;
import org.meteoinfo.projection.ProjectionUtil;
import org.meteoinfo.projection.Reproject;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -646,6 +644,41 @@ public class MapPlot extends Plot2D implements IWebMapPanel {
graphic.draw(g, area, this.tileLoadListener); graphic.draw(g, area, this.tileLoadListener);
} }
/**
* Add a graphic
*
* @param g Graphic
*/
@Override
public Graphic addGraphic(Graphic graphic) {
Transform transform = graphic.getTransform();
if (transform != null && transform.isValid()) {
GeoTransform geoTransform = (GeoTransform) transform;
graphic = GraphicProjectionUtil.projectClipGraphic(graphic, geoTransform.getSourceProj(),
geoTransform.getTargetProj());
}
return super.addGraphic(graphic);
}
/**
* Add a graphic by index
*
* @param idx Index
* @param g Graphic
*/
@Override
public Graphic addGraphic(int idx, Graphic graphic) {
Transform transform = graphic.getTransform();
if (transform != null && transform.isValid()) {
GeoTransform geoTransform = (GeoTransform) transform;
GraphicProjectionUtil.projectClipGraphic(graphic, geoTransform.getSourceProj(),
geoTransform.getTargetProj());
}
return super.addGraphic(idx, graphic);
}
/** /**
* Add a graphic * Add a graphic
* *
@ -656,12 +689,12 @@ public class MapPlot extends Plot2D implements IWebMapPanel {
public Graphic addGraphic(Graphic graphic, ProjectionInfo proj) { public Graphic addGraphic(Graphic graphic, ProjectionInfo proj) {
ProjectionInfo toProj = this.getProjInfo(); ProjectionInfo toProj = this.getProjInfo();
if (proj.equals(toProj)) { if (proj.equals(toProj)) {
this.addGraphic(graphic); super.addGraphic(graphic);
return graphic; return graphic;
} else { } else {
Graphic nGraphic = GraphicProjectionUtil.projectClipGraphic(graphic, proj, toProj); Graphic nGraphic = GraphicProjectionUtil.projectClipGraphic(graphic, proj, toProj);
if (nGraphic != null) { if (nGraphic != null) {
this.addGraphic(nGraphic); super.addGraphic(nGraphic);
} }
return nGraphic; return nGraphic;
} }

View File

@ -7,10 +7,7 @@ import org.meteoinfo.chart.graphic.GeoGraphicCollection;
import org.meteoinfo.geometry.geoprocess.GeoComputation; import org.meteoinfo.geometry.geoprocess.GeoComputation;
import org.meteoinfo.geometry.graphic.Graphic; import org.meteoinfo.geometry.graphic.Graphic;
import org.meteoinfo.geometry.shape.Shape; import org.meteoinfo.geometry.shape.Shape;
import org.meteoinfo.projection.ProjectionInfo; import org.meteoinfo.projection.*;
import org.meteoinfo.projection.ProjectionNames;
import org.meteoinfo.projection.ProjectionUtil;
import org.meteoinfo.projection.Reproject;
import org.meteoinfo.table.DataColumn; import org.meteoinfo.table.DataColumn;
import org.meteoinfo.table.DataRow; import org.meteoinfo.table.DataRow;
import org.meteoinfo.table.DataTable; import org.meteoinfo.table.DataTable;
@ -21,6 +18,7 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public class GraphicProjectionUtil extends ProjectionUtil { public class GraphicProjectionUtil extends ProjectionUtil {
/** /**
* Project graphic * Project graphic
* *

View File

@ -39,6 +39,7 @@ package org.meteoinfo.geometry.graphic;
protected ColorBreak legend; protected ColorBreak legend;
protected GeneralPath clipPath; protected GeneralPath clipPath;
protected Graphic clipGraphic; protected Graphic clipGraphic;
protected Transform transform;
private ResizeAbility _resizeAbility = ResizeAbility.RESIZE_ALL; private ResizeAbility _resizeAbility = ResizeAbility.RESIZE_ALL;
protected int handle; protected int handle;
// </editor-fold> // </editor-fold>
@ -101,6 +102,22 @@ package org.meteoinfo.geometry.graphic;
updateResizeAbility(); updateResizeAbility();
} }
/**
* Get transform
* @return Transform
*/
public Transform getTransform() {
return this.transform;
}
/**
* Set transform
* @param value Transform
*/
public void setTransform(Transform value) {
this.transform = value;
}
/** /**
* Get clip path * Get clip path
* @return Clip path * @return Clip path

View File

@ -100,6 +100,7 @@ public class GraphicCollection extends Graphic implements Iterator {
*/ */
public void setGraphics(List<Graphic> value) { public void setGraphics(List<Graphic> value) {
this.graphics = value; this.graphics = value;
this.updateExtent();
} }
/** /**

View File

@ -167,10 +167,10 @@ public class Line2DGraphic extends Graphic {
} }
/** /**
* Get data * Get color data array
* @return Data * @return Color data array
*/ */
public Array getData() { public Array getColorData() {
return this.cData; return this.cData;
} }

View File

@ -8,6 +8,7 @@ import org.meteoinfo.geometry.legend.PointBreak;
import org.meteoinfo.geometry.shape.PointShape; import org.meteoinfo.geometry.shape.PointShape;
import org.meteoinfo.geometry.shape.PolylineShape; import org.meteoinfo.geometry.shape.PolylineShape;
import org.meteoinfo.geometry.shape.Shape; import org.meteoinfo.geometry.shape.Shape;
import org.meteoinfo.geometry.shape.ShapeTypes;
import org.meteoinfo.ndarray.Array; import org.meteoinfo.ndarray.Array;
import org.meteoinfo.ndarray.IndexIterator; import org.meteoinfo.ndarray.IndexIterator;
@ -47,7 +48,6 @@ public class Point2DGraphicCollection extends GraphicCollection {
this(); this();
this.xData = xData; this.xData = xData;
this.yData = yData; this.yData = yData;
this.legend = pointBreak;
this.updateGraphics(pointBreak); this.updateGraphics(pointBreak);
} }
@ -55,6 +55,20 @@ public class Point2DGraphicCollection extends GraphicCollection {
* Constructor * Constructor
* @param xData X data * @param xData X data
* @param yData Y data * @param yData Y data
* @param pointBreak Point break
*/
public Point2DGraphicCollection(Array xData, Array yData, List<ColorBreak> cbs) {
this();
this.xData = xData;
this.yData = yData;
this.updateGraphics(cbs);
}
/**
* Constructor
*
* @param xData X data
* @param yData Y data
* @param cData Color data * @param cData Color data
* @param ls Legend scheme * @param ls Legend scheme
*/ */
@ -63,10 +77,18 @@ public class Point2DGraphicCollection extends GraphicCollection {
this.xData = xData; this.xData = xData;
this.yData = yData; this.yData = yData;
this.cData = cData; this.cData = cData;
this.legendScheme = ls;
this.updateGraphics(ls); this.updateGraphics(ls);
} }
/**
* Return has color data array or not
*
* @return Has color data array of not
*/
public boolean hasColorData() {
return this.cData != null;
}
/** /**
* Get x data * Get x data
* @return X data * @return X data
@ -75,6 +97,15 @@ public class Point2DGraphicCollection extends GraphicCollection {
return this.xData; return this.xData;
} }
/**
* Set x data
* @param xData X data
*/
public void setXData(Array xData) {
this.xData = xData;
updateShape();
}
/** /**
* Get y data * Get y data
* @return Y data * @return Y data
@ -84,18 +115,36 @@ public class Point2DGraphicCollection extends GraphicCollection {
} }
/** /**
* Set data * Set y data
* @return Data * @param yData Y data
*/ */
public Array getData() { public void setYData(Array yData) {
this.yData = yData;
updateShape();
}
/**
* Get color data
* @return Color data
*/
public Array getColorData() {
return this.cData; return this.cData;
} }
protected void updateShape() {
if (this.hasColorData()) {
updateGraphics(this.legendScheme);
} else {
updateGraphics((PointBreak) this.legend);
}
}
protected void updateGraphics() { protected void updateGraphics() {
updateGraphics((PointBreak) this.legend); updateGraphics((PointBreak) this.legend);
} }
protected void updateGraphics(PointBreak pointBreak) { protected void updateGraphics(PointBreak pointBreak) {
this.legend = pointBreak;
this.graphics = new ArrayList<>(); this.graphics = new ArrayList<>();
List<PointD> points = new ArrayList<>(); List<PointD> points = new ArrayList<>();
IndexIterator xIter = this.xData.getIndexIterator(); IndexIterator xIter = this.xData.getIndexIterator();
@ -112,6 +161,35 @@ public class Point2DGraphicCollection extends GraphicCollection {
} }
} }
protected void updateGraphics(List<ColorBreak> cbs) {
this.graphics = new ArrayList<>();
List<PointD> points = new ArrayList<>();
IndexIterator xIter = this.xData.getIndexIterator();
IndexIterator yIter = this.yData.getIndexIterator();
double x, y;
if (cbs.size() == this.xData.getSize()) {
int i = 0;
while (xIter.hasNext()) {
x = xIter.getDoubleNext();
y = yIter.getDoubleNext();
if (Double.isNaN(x) || Double.isNaN(y)) {
continue;
}
PointShape shape = new PointShape(new PointD(x, y));
this.add(new Point2DGraphic(shape, (PointBreak) cbs.get(i)));
i += 1;
}
LegendScheme ls = new LegendScheme();
ls.setLegendBreaks(cbs);
ls.setLegendType(LegendType.UNIQUE_VALUE);
ls.setShapeType(ShapeTypes.POINT);
this.singleLegend = false;
this.legendScheme = ls;
} else {
updateGraphics((PointBreak) cbs.get(0));
}
}
protected void updateGraphics(LegendScheme ls) { protected void updateGraphics(LegendScheme ls) {
this.graphics = new ArrayList<Graphic>(); this.graphics = new ArrayList<Graphic>();
PointShape ps; PointShape ps;
@ -143,7 +221,7 @@ public class Point2DGraphicCollection extends GraphicCollection {
} }
} }
} }
this.setSingleLegend(false); this.singleLegend = false;
this.setLegendScheme(ls); this.legendScheme = ls;
} }
} }

View File

@ -0,0 +1,12 @@
package org.meteoinfo.geometry.graphic;
import org.meteoinfo.common.PointD;
public abstract class Transform {
public abstract boolean isValid();
public abstract PointD transform(double x, double y);
public abstract Transform inverted();
}

View File

@ -1,32 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile"> <MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\common_math\interpolate"> <Path OpenPath="D:\Working\MIScript\Jython\mis\plot_types\pcolor">
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\gridshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\plot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\radar\cinrad"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\dataframe"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\wind"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\arrow"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\arrow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\matlab"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\matlab"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo\calc"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo\calc"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\interpolate"/> <RecentFolder Folder="D:\Working\MIScript\Jython\mis\common_math\interpolate"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\scatter"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\geoshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\wind"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\contour"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\pcolor"/>
</Path> </Path>
<File> <File>
<OpenedFiles> <OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_1.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\scatter\scatterm_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_2.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\scatter\scatter_map_proj.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_3.py"/> <OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\contour\contourf_hatch.py"/>
</OpenedFiles> </OpenedFiles>
<RecentFiles> <RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_1.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\scatter\scatterm_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\velocity_potential_2.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\scatter\scatter_map_proj.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\calc\stream_function_3.py"/> <RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\contour\contourf_hatch.py"/>
</RecentFiles> </RecentFiles>
</File> </File>
<Font> <Font>

View File

@ -34,7 +34,7 @@ from mipylib.geolib.milayer import MILayer, MIXYListData
import plotutil import plotutil
import colors import colors
import mipylib.miutil as miutil import mipylib.miutil as miutil
from .graphic import Line2D, Artist from .graphic import Line2D, Artist, Point2DCollection
__all__ = ['Axes', 'PolarAxes'] __all__ = ['Axes', 'PolarAxes']
@ -1087,12 +1087,12 @@ class Axes(object):
#self._axes.setAutoExtent() #self._axes.setAutoExtent()
self.stale = True self.stale = True
def add_graphic(self, graphic, projection=None, zorder=None): def add_graphic(self, graphic, transform=None, zorder=None):
""" """
Add a graphic Add a graphic
:param graphic: (*Graphic*) The graphic to be added. :param graphic: (*Graphic*) The graphic to be added.
:param projection: (*Projection*) The projection. :param transform: (*Transform*) The transform. Default is `None`.
:param zorder: (*int*) Z order of the graphic. Default is `None` that the graphic added :param zorder: (*int*) Z order of the graphic. Default is `None` that the graphic added
to the end. to the end.
""" """
@ -1103,16 +1103,16 @@ class Axes(object):
if zorder > self.num_graphics(): if zorder > self.num_graphics():
zorder = self.num_graphics() zorder = self.num_graphics()
if projection is None: if transform is None:
if zorder is None: if zorder is None:
rGraphic = self._axes.addGraphic(graphic) rGraphic = self._axes.addGraphic(graphic)
else: else:
rGraphic = self._axes.addGraphic(zorder, graphic) rGraphic = self._axes.addGraphic(zorder, graphic)
else: else:
if zorder is None: if zorder is None:
rGraphic = self._axes.addGraphic(graphic, projection) rGraphic = self._axes.addGraphic(graphic, transform)
else: else:
rGraphic = self._axes.addGraphic(zorder, graphic, projection) rGraphic = self._axes.addGraphic(zorder, graphic, transform)
#self._axes.setAutoExtent() #self._axes.setAutoExtent()
self.stale = True self.stale = True
@ -1578,8 +1578,8 @@ class Axes(object):
for i in range(0, n): for i in range(0, n):
ls.getLegendBreaks()[i].setSize(s[i]) ls.getLegendBreaks()[i].setSize(s[i])
# Create graphics # Create graphics
graphics = GraphicFactory.createPoints(xdata, ydata, c.asarray(), ls) #graphics = GraphicFactory.createPoints(xdata, ydata, c.asarray(), ls)
graphics = Point2DCollection(xdata, ydata, c._array, legend=ls)
else: else:
alpha = kwargs.pop('alpha', None) alpha = kwargs.pop('alpha', None)
colors = plotutil.getcolors(c, alpha) colors = plotutil.getcolors(c, alpha)
@ -1614,8 +1614,8 @@ class Axes(object):
plotutil.setpointlegendbreak(npb, **kwargs) plotutil.setpointlegendbreak(npb, **kwargs)
pbs.append(npb) pbs.append(npb)
# Create graphics # Create graphics
graphics = GraphicFactory.createPoints(xdata, ydata, pbs) #graphics = GraphicFactory.createPoints(xdata, ydata, pbs)
graphics = Point2DCollection(x._array, y._array, legend=ls.getLegendBreak(0)) graphics = Point2DCollection(xdata, ydata, legend=pbs)
antialias = kwargs.pop('antialias', None) antialias = kwargs.pop('antialias', None)
if antialias is not None: if antialias is not None:

View File

@ -8,6 +8,7 @@
import os import os
import numbers import numbers
import functools
from org.meteoinfo.chart import ChartScaleBar, ChartNorthArrow from org.meteoinfo.chart import ChartScaleBar, ChartNorthArrow
from org.meteoinfo.chart.plot import GridLabelPosition from org.meteoinfo.chart.plot import GridLabelPosition
@ -19,7 +20,7 @@ from org.meteoinfo.geo.io import GraphicUtil
from org.meteoinfo.geometry.legend import BreakTypes, LegendScheme, LegendType, LegendManage from org.meteoinfo.geometry.legend import BreakTypes, LegendScheme, LegendType, LegendManage
from org.meteoinfo.geometry.shape import Shape, PolylineShape, PolygonShape, ShapeTypes from org.meteoinfo.geometry.shape import Shape, PolylineShape, PolygonShape, ShapeTypes
from org.meteoinfo.geometry.graphic import Graphic from org.meteoinfo.geometry.graphic import Graphic
from org.meteoinfo.projection import ProjectionInfo from org.meteoinfo.projection import ProjectionInfo, GeoTransform
from org.meteoinfo.common import Extent from org.meteoinfo.common import Extent
from org.meteoinfo.geo.layer import LayerTypes, WebMapLayer from org.meteoinfo.geo.layer import LayerTypes, WebMapLayer
from org.meteoinfo.data.mapdata.webmap import WebMapProvider, DefaultTileFactory, TileFactoryInfo from org.meteoinfo.data.mapdata.webmap import WebMapProvider, DefaultTileFactory, TileFactoryInfo
@ -40,6 +41,20 @@ import mipylib.miutil as miutil
__all__ = ['MapAxes','WebMapProvider'] __all__ = ['MapAxes','WebMapProvider']
def _add_transform(func):
"""A decorator that adds and validates the transform keyword argument."""
@functools.wraps(func)
def wrapper(self, *args, **kwargs):
data_proj = kwargs.get('transform', None)
if data_proj is None:
data_proj = kwargs.pop('proj', None)
if data_proj is not None:
transform = GeoTransform(data_proj, self.projection)
kwargs['transform'] = transform
return func(self, *args, **kwargs)
return wrapper
############################################## ##############################################
class MapAxes(Axes): class MapAxes(Axes):
""" """
@ -93,7 +108,7 @@ class MapAxes(Axes):
if not cutoff is None: if not cutoff is None:
projinfo.setCutoff(cutoff) projinfo.setCutoff(cutoff)
self._axes.setProjInfo(projinfo) self._axes.setProjInfo(projinfo)
self.proj = self._axes.getProjInfo() self.projection = self._axes.getProjInfo()
xyscale = kwargs.pop('xyscale', 1) xyscale = kwargs.pop('xyscale', 1)
self._axes.setAspect(xyscale) self._axes.setAspect(xyscale)
@ -123,7 +138,7 @@ class MapAxes(Axes):
:returns: (*boolean*) Is lonlat projection or not. :returns: (*boolean*) Is lonlat projection or not.
""" """
return self.proj.isLonLat() return self.projection.isLonLat()
def add_layer(self, layer, zorder=None, select=None): def add_layer(self, layer, zorder=None, select=None):
""" """
@ -386,7 +401,7 @@ class MapAxes(Axes):
:param z: (*float*) Z coordinate - only used for 3-D axes. :param z: (*float*) Z coordinate - only used for 3-D axes.
""" """
if not self._axes.isLonLatMap(): if not self._axes.isLonLatMap():
x, y = migeo.project(x, y, toproj=self.proj) x, y = migeo.project(x, y, toproj=self.projection)
rect = self._axes.getPositionArea() rect = self._axes.getPositionArea()
r = self._axes.projToScreen(x, y, rect) r = self._axes.projToScreen(x, y, rect)
@ -530,7 +545,9 @@ class MapAxes(Axes):
if antialias is not None: if antialias is not None:
graphics.setAntiAlias(antialias) graphics.setAntiAlias(antialias)
graphics = self.add_graphic(graphics, projection=layer.proj, zorder=zorder) transform = GeoTransform(layer.proj, self.projection)
graphics.setTransform(transform)
graphics = self.add_graphic(graphics, zorder=zorder)
graphics.setVisible(visible) graphics.setVisible(visible)
return GeoGraphicCollection(graphics) return GeoGraphicCollection(graphics)
else: else:
@ -587,21 +604,15 @@ class MapAxes(Axes):
if graphic.getNumGraphics() == 1: if graphic.getNumGraphics() == 1:
graphic = graphic.getGraphicN(0) graphic = graphic.getGraphicN(0)
if graphic.isCollection(): transform = GeoTransform(migeo.projinfo(), self.projection)
if self.islonlat(): graphic.setTransform(transform)
self._axes.addGraphics(graphic) graphic = self._axes.addGraphic(graphic)
else:
graphic = self._axes.addGraphics(graphic, migeo.projinfo())
else:
if self.islonlat():
self._axes.addGraphic(graphic)
else:
graphic = self._axes.addGraphic(graphic, migeo.projinfo())
graphic.setVisible(visible) graphic.setVisible(visible)
return graphic return graphic
@_add_transform
def plot(self, *args, **kwargs): def plot(self, *args, **kwargs):
""" """
Plot lines and/or markers to the map. Plot lines and/or markers to the map.
@ -615,7 +626,7 @@ class MapAxes(Axes):
:returns: (*VectorLayer*) Line VectorLayer. :returns: (*VectorLayer*) Line VectorLayer.
""" """
fill_value = kwargs.pop('fill_value', -9999.0) fill_value = kwargs.pop('fill_value', -9999.0)
proj = kwargs.pop('proj', migeo.projinfo()) transform = kwargs.pop('transform', None)
is_lonlat = proj.isLonLat() is_lonlat = proj.isLonLat()
n = len(args) n = len(args)
xdatalist = [] xdatalist = []
@ -735,7 +746,8 @@ class MapAxes(Axes):
graphic = GraphicFactory.createLineString(xdata, ydata, lines[0], iscurve) graphic = GraphicFactory.createLineString(xdata, ydata, lines[0], iscurve)
else: #>1 else: #>1
graphic = GraphicFactory.createLineString(xdata, ydata, lines, iscurve) graphic = GraphicFactory.createLineString(xdata, ydata, lines, iscurve)
graphic = self.add_graphic(graphic, proj) graphic.transform = transform
graphic = self.add_graphic(graphic)
graphics.append(graphic) graphics.append(graphic)
else: else:
for i in range(0, snum): for i in range(0, snum):
@ -743,14 +755,16 @@ class MapAxes(Axes):
xdata = plotutil.getplotdata(xdatalist[i]) xdata = plotutil.getplotdata(xdatalist[i])
ydata = plotutil.getplotdata(ydatalist[i]) ydata = plotutil.getplotdata(ydatalist[i])
graphic = GraphicFactory.createLineString(xdata, ydata, lines[i], iscurve) graphic = GraphicFactory.createLineString(xdata, ydata, lines[i], iscurve)
graphic = self.add_graphic(graphic, proj) graphic.transform = transform
graphic = self.add_graphic(graphic)
graphics.append(graphic) graphics.append(graphic)
else: else:
xdata = plotutil.getplotdata(xdatalist[0]) xdata = plotutil.getplotdata(xdatalist[0])
ydata = plotutil.getplotdata(ydatalist[0]) ydata = plotutil.getplotdata(ydatalist[0])
zdata = plotutil.getplotdata(cdata) zdata = plotutil.getplotdata(cdata)
graphic = GraphicFactory.createLineString(xdata, ydata, zdata, ls, iscurve) graphic = GraphicFactory.createLineString(xdata, ydata, zdata, ls, iscurve)
graphic = self.add_graphic(graphic, proj) graphic.transform = transform
graphic = self.add_graphic(graphic)
graphics.append(graphic) graphics.append(graphic)
antialias = kwargs.pop('antialias', None) antialias = kwargs.pop('antialias', None)
@ -764,6 +778,7 @@ class MapAxes(Axes):
return graphics[0] return graphics[0]
@_add_transform
def scatter(self, *args, **kwargs): def scatter(self, *args, **kwargs):
""" """
Make a scatter plot on a map. Make a scatter plot on a map.
@ -783,10 +798,10 @@ class MapAxes(Axes):
:param edge: (*boolean*) Draw edge of markers or not. Default is True. :param edge: (*boolean*) Draw edge of markers or not. Default is True.
:param facecolor: (*Color*) Fill color of markers. Default is black. :param facecolor: (*Color*) Fill color of markers. Default is black.
:param edgecolor: (*Color*) Edge color of markers. Default is black. :param edgecolor: (*Color*) Edge color of markers. Default is black.
:param proj: (*ProjectionInfo*) Map projection of the data. Default is None. :param transform: (*ProjectionInfo*) Map projection transform of the data. Default is same with the axes.
:param zorder: (*int*) Z-order of created layer for display. :param zorder: (*int*) Z-order of created layer for display.
:returns: (*VectoryLayer*) Point VectoryLayer. :returns: (*graphic collection*) Graphic collection.
""" """
n = len(args) n = len(args)
if n == 1: if n == 1:
@ -836,14 +851,16 @@ class MapAxes(Axes):
ls = plotutil.getlegendscheme(args, a.min(), a.max(), **kwargs) ls = plotutil.getlegendscheme(args, a.min(), a.max(), **kwargs)
ls = plotutil.setlegendscheme_point(ls, **kwargs) ls = plotutil.setlegendscheme_point(ls, **kwargs)
proj = kwargs.pop('proj', migeo.projinfo())
# Create graphics # Create graphics
if a.ndim == 0: if a.ndim == 0:
graphics = GraphicFactory.createPoints(x._array, y._array, ls.getLegendBreak(0)) #graphics = GraphicFactory.createPoints(x._array, y._array, ls.getLegendBreak(0))
#graphics = Point2DCollection(x._array, y._array, legend=ls.getLegendBreak(0)) graphics = Point2DCollection(x._array, y._array, legend=ls.getLegendBreak(0))
else: else:
graphics = GraphicFactory.createPoints(x._array, y._array, a._array, ls) #graphics = GraphicFactory.createPoints(x._array, y._array, a._array, ls)
#graphics = Point2DCollection(x._array, y._array, a._array, ls) graphics = Point2DCollection(x._array, y._array, a._array, ls)
transform = kwargs.pop('transform', None)
graphics.transform = transform
antialias = kwargs.pop('antialias', None) antialias = kwargs.pop('antialias', None)
if antialias is not None: if antialias is not None:
@ -851,7 +868,7 @@ class MapAxes(Axes):
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)
@ -872,13 +889,14 @@ class MapAxes(Axes):
:param coordinates=['axes'|'figure'|'data'|'inches']: (*string*) Coordinate system and units for :param coordinates=['axes'|'figure'|'data'|'inches']: (*string*) Coordinate system and units for
*X, Y*. 'axes' and 'figure' are normalized coordinate system with 0,0 in the lower left and *X, Y*. 'axes' and 'figure' are normalized coordinate system with 0,0 in the lower left and
1,1 in the upper right, 'data' are the axes data coordinates (Default value); 'inches' is 1,1 in the upper right, 'data' are the axes data coordinates (Default value); 'inches' is
position in the figure in inches, with 0,0 at the lower left corner. position in the figure in inches, with 0,0 in the lower left corner.
""" """
ctext = plotutil.text(x, y, s, **kwargs) ctext = plotutil.text(x, y, s, **kwargs)
islonlat = kwargs.pop('islonlat', True) islonlat = kwargs.pop('islonlat', True)
self._axes.addText(ctext, islonlat) self._axes.addText(ctext, islonlat)
return ctext return ctext
@_add_transform
def contour(self, *args, **kwargs): def contour(self, *args, **kwargs):
""" """
Plot contours on the map. Plot contours on the map.
@ -922,7 +940,8 @@ class MapAxes(Axes):
graphics = GraphicFactory.createContourLines(x.asarray(), y.asarray(), a.asarray(), ls, smooth) graphics = GraphicFactory.createContourLines(x.asarray(), y.asarray(), a.asarray(), ls, smooth)
proj = kwargs.pop('proj', migeo.projinfo()) transform = kwargs.pop('transform', None)
graphics.transform = transform
# Add graphics # Add graphics
antialias = kwargs.pop('antialias', None) antialias = kwargs.pop('antialias', None)
@ -931,12 +950,13 @@ class MapAxes(Axes):
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)
return graphics return graphics
@_add_transform
def contourf(self, *args, **kwargs): def contourf(self, *args, **kwargs):
""" """
Plot filled contours on the map. Plot filled contours on the map.
@ -984,7 +1004,8 @@ class MapAxes(Axes):
a, x, y = np.griddata((x,y), a, **griddata_props) a, x, y = np.griddata((x,y), a, **griddata_props)
graphics = GraphicFactory.createContourPolygons(x.asarray(), y.asarray(), a.asarray(), ls, smooth) graphics = GraphicFactory.createContourPolygons(x.asarray(), y.asarray(), a.asarray(), ls, smooth)
proj = kwargs.pop('proj', migeo.projinfo()) transform = kwargs.pop('transform', None)
graphics.transform = transform
# Add graphics # Add graphics
antialias = kwargs.pop('antialias', None) antialias = kwargs.pop('antialias', None)
@ -995,12 +1016,13 @@ class MapAxes(Axes):
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
if zorder is None: if zorder is None:
zorder = 0 zorder = 0
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)
return graphics return graphics
@_add_transform
def imshow(self, *args, **kwargs): def imshow(self, *args, **kwargs):
""" """
Display an image on the map. Display an image on the map.
@ -1066,7 +1088,7 @@ class MapAxes(Axes):
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
interpolation = kwargs.pop('interpolation', None) interpolation = kwargs.pop('interpolation', None)
proj = kwargs.pop('proj', migeo.projinfo()) transform = kwargs.pop('transform', None)
if isrgb: if isrgb:
if isinstance(rgbdata, (list, tuple)): if isinstance(rgbdata, (list, tuple)):
rgbd = [] rgbd = []
@ -1120,8 +1142,8 @@ class MapAxes(Axes):
if cb.isNoData(): if cb.isNoData():
cb.setColor(plotutil.getcolor(fill_color)) cb.setColor(plotutil.getcolor(fill_color))
if not proj.equals(self.proj): if not transform.equals(self.projection):
arr, x, y = migeo.reproject(arr, x, y, fromproj=proj, toproj=self.proj) arr, x, y = migeo.reproject(arr, x, y, fromproj=transform, toproj=self.projection)
extent = [x[0],x[-1],y[0],y[-1]] extent = [x[0],x[-1],y[0],y[-1]]
igraphic = GraphicFactory.createImage(arr._array, x._array, y._array, ls, extent) igraphic = GraphicFactory.createImage(arr._array, x._array, y._array, ls, extent)
@ -1142,7 +1164,8 @@ class MapAxes(Axes):
gridline.setTop(True) gridline.setTop(True)
return igraphic return igraphic
@_add_transform
def pcolor(self, *args, **kwargs): def pcolor(self, *args, **kwargs):
""" """
Create a pseudocolor plot of a 2-D array in a MapAxes. Create a pseudocolor plot of a 2-D array in a MapAxes.
@ -1165,7 +1188,6 @@ class MapAxes(Axes):
:returns: (*VectoryLayer*) Polygon VectoryLayer created from array data. :returns: (*VectoryLayer*) Polygon VectoryLayer created from array data.
""" """
proj = kwargs.pop('proj', migeo.projinfo())
n = len(args) n = len(args)
if n <= 2: if n <= 2:
a = args[0] a = args[0]
@ -1186,26 +1208,29 @@ class MapAxes(Axes):
if not kwargs.has_key('edgecolor'): if not kwargs.has_key('edgecolor'):
kwargs['edgecolor'] = None kwargs['edgecolor'] = None
plotutil.setlegendscheme(ls, **kwargs) plotutil.setlegendscheme(ls, **kwargs)
if proj is None or proj.isLonLat(): transform = kwargs.pop('transform', None)
if transform is None or transform.isLonLat():
lonlim = 90 lonlim = 90
else: else:
lonlim = 0 lonlim = 0
#x, y = np.project(x, y, toproj=proj) #x, y = np.project(x, y, toproj=proj)
graphics = GraphicFactory.createPColorPolygons(x.asarray(), y.asarray(), a.asarray(), ls) graphics = GraphicFactory.createPColorPolygons(x.asarray(), y.asarray(), a.asarray(), ls)
graphics.transform = transform
antialias = kwargs.pop('antialias', None) antialias = kwargs.pop('antialias', None)
if antialias is not None: if antialias is not None:
graphics.setAntiAlias(antialias) graphics.setAntiAlias(antialias)
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)
return graphics return graphics
@_add_transform
def gridshow(self, *args, **kwargs): def gridshow(self, *args, **kwargs):
""" """
Create a grid plot of a 2-D array in a MapAxes. Create a grid plot of a 2-D array in a MapAxes.
@ -1251,17 +1276,20 @@ class MapAxes(Axes):
if antialias is not None: if antialias is not None:
graphics.setAntiAlias(antialias) graphics.setAntiAlias(antialias)
proj = kwargs.pop('proj', migeo.projinfo()) transform = kwargs.pop('transform', None)
graphics.transform = transform
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
if zorder is None: if zorder is None:
zorder = 0 zorder = 0
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)
return graphics return graphics
@_add_transform
def quiver(self, *args, **kwargs): def quiver(self, *args, **kwargs):
""" """
Plot a 2-D field of quiver in a map. Plot a 2-D field of quiver in a map.
@ -1285,7 +1313,7 @@ class MapAxes(Axes):
""" """
cmap = plotutil.getcolormap(**kwargs) cmap = plotutil.getcolormap(**kwargs)
fill_value = kwargs.pop('fill_value', -9999.0) fill_value = kwargs.pop('fill_value', -9999.0)
proj = kwargs.pop('proj', migeo.projinfo()) transform = kwargs.pop('transform', None)
order = kwargs.pop('order', None) order = kwargs.pop('order', None)
isuv = kwargs.pop('isuv', True) isuv = kwargs.pop('isuv', True)
n = len(args) n = len(args)
@ -1342,7 +1370,8 @@ class MapAxes(Axes):
x, y = np.meshgrid(x, y) x, y = np.meshgrid(x, y)
graphics = GraphicFactory.createArrows(x._array, y._array, u._array, v._array, cdata, ls, isuv) graphics = GraphicFactory.createArrows(x._array, y._array, u._array, v._array, cdata, ls, isuv)
graphics.transform = transform
# Add graphics # Add graphics
antialias = kwargs.pop('antialias', None) antialias = kwargs.pop('antialias', None)
if antialias is not None: if antialias is not None:
@ -1354,12 +1383,13 @@ class MapAxes(Axes):
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)
return graphics return graphics
@_add_transform
def barbs(self, *args, **kwargs): def barbs(self, *args, **kwargs):
""" """
Plot a 2-D field of barbs in a map. Plot a 2-D field of barbs in a map.
@ -1447,15 +1477,18 @@ class MapAxes(Axes):
if avoidcoll is not None: if avoidcoll is not None:
graphics.setAvoidCollision(avoidcoll) graphics.setAvoidCollision(avoidcoll)
proj = kwargs.pop('proj', migeo.projinfo()) transform = kwargs.pop('transform', None)
graphics.transform = transform
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)
return graphics return graphics
@_add_transform
def streamplot(self, *args, **kwargs): def streamplot(self, *args, **kwargs):
""" """
Plot streamline in a map. Plot streamline in a map.
@ -1475,7 +1508,6 @@ class MapAxes(Axes):
:returns: (*VectoryLayer*) Created streamline VectoryLayer. :returns: (*VectoryLayer*) Created streamline VectoryLayer.
""" """
proj = kwargs.pop('proj', migeo.projinfo())
isuv = kwargs.pop('isuv', True) isuv = kwargs.pop('isuv', True)
density = kwargs.pop('density', 4) density = kwargs.pop('density', 4)
n = len(args) n = len(args)
@ -1528,12 +1560,15 @@ class MapAxes(Axes):
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) transform = kwargs.pop('transform', None)
graphics.transform = transform
graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)
return graphics return graphics
@_add_transform
def stationmodel(self, smdata, **kwargs): def stationmodel(self, smdata, **kwargs):
""" """
Plot station model data on the map. Plot station model data on the map.
@ -1547,13 +1582,14 @@ class MapAxes(Axes):
:returns: (*graphics*) Station model graphics. :returns: (*graphics*) Station model graphics.
""" """
proj = kwargs.pop('proj', migeo.projinfo()) transform = kwargs.pop('transform', None)
size = kwargs.pop('size', 12) size = kwargs.pop('size', 12)
surface = kwargs.pop('surface', True) surface = kwargs.pop('surface', True)
color = kwargs.pop('color', 'b') color = kwargs.pop('color', 'b')
color = plotutil.getcolor(color) color = plotutil.getcolor(color)
ls = LegendManage.createSingleSymbolLegendScheme(ShapeTypes.POINT, color, size) ls = LegendManage.createSingleSymbolLegendScheme(ShapeTypes.POINT, color, size)
graphics = GraphicFactory.createStationModel(smdata, ls, surface) graphics = GraphicFactory.createStationModel(smdata, ls, surface)
graphics.transform = transform
# Add graphics # Add graphics
antialias = kwargs.pop('antialias', None) antialias = kwargs.pop('antialias', None)
@ -1566,7 +1602,7 @@ class MapAxes(Axes):
visible = kwargs.pop('visible', True) visible = kwargs.pop('visible', True)
zorder = kwargs.pop('zorder', None) zorder = kwargs.pop('zorder', None)
graphics = self.add_graphic(graphics, projection=proj, zorder=zorder) graphics = self.add_graphic(graphics, zorder=zorder)
self.set_draw_extent(graphics.getExtent()) self.set_draw_extent(graphics.getExtent())
graphics.setVisible(visible) graphics.setVisible(visible)

View File

@ -1,4 +1,5 @@
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from org.meteoinfo.geometry.graphic import Graphic
__all__ = ['Artist'] __all__ = ['Artist']
@ -21,6 +22,7 @@ class Artist(object):
self._stale = True self._stale = True
self.stale_callback = None self.stale_callback = None
self._animated = False self._animated = False
self._transform = None
@property @property
def axes(self): def axes(self):
@ -57,4 +59,14 @@ class Artist(object):
return return
if val and self.stale_callback is not None: if val and self.stale_callback is not None:
self.stale_callback(self, val) self.stale_callback(self, val)
@property
def transform(self):
return self._transform
@transform.setter
def transform(self, val):
self._transform = val
if isinstance(self, Graphic):
self.setTransform(val)

View File

@ -82,3 +82,84 @@ class Point2DCollection(Collection, Point2DGraphicCollection):
Point2DGraphicCollection.__init__(self, self._x._array, self._y._array, legend) Point2DGraphicCollection.__init__(self, self._x._array, self._y._array, legend)
else: else:
Point2DGraphicCollection.__init__(self, self._x._array, self._y._array, self._cdata._array, legend) Point2DGraphicCollection.__init__(self, self._x._array, self._y._array, self._cdata._array, legend)
@property
def visible(self):
"""
The artist is visible or not.
"""
return self.isVisible()
@visible.setter
def visible(self, val):
self.setVisible(val)
self.stale = True
@property
def xdata(self):
"""
Return the xdata.
:return: (*array*) xdata.
"""
return self._x
@xdata.setter
def xdata(self, xdata):
"""
Set the xdata.
:param xdata: (*array*) The xdata.
"""
self._x = xdata
self.setXData(xdata._array)
self.stale = True
@property
def ydata(self):
"""
Return the ydata.
:return: (*array*) ydata.
"""
return self._y
@ydata.setter
def ydata(self, ydata):
"""
Set the ydata.
:param ydata: (*array*) The ydata.
"""
self._y = ydata
self.setYData(ydata._array)
self.stale = True
@property
def data(self):
"""
Get x, y data.
:return: x, y data.
"""
return (self._x, self._y)
@data.setter
def data(self, *args):
"""
Set x, y data.
:param xdata: (*array*) X data.
:param ydata: (*array*) Y data.
"""
if len(args) == 1:
xdata = args[0][0]
ydata = args[0][1]
else:
xdata = args[0]
ydata = args[1]
self._x = xdata
self._y = ydata
self.setData(xdata._array, ydata._array)
self.stale = True

View File

@ -0,0 +1,60 @@
package org.meteoinfo.projection;
import org.locationtech.proj4j.BasicCoordinateTransform;
import org.locationtech.proj4j.CoordinateTransform;
import org.locationtech.proj4j.ProjCoordinate;
import org.meteoinfo.common.PointD;
import org.meteoinfo.geometry.graphic.Transform;
public class GeoTransform extends Transform {
protected CoordinateTransform coordinateTransform;
protected ProjectionInfo sourceProj;
protected ProjectionInfo targetProj;
/**
* Constructor
* @param source Source projection info
* @param target Target projection info
*/
public GeoTransform(ProjectionInfo source, ProjectionInfo target) {
this.sourceProj = source;
this.targetProj = target;
this.coordinateTransform = new BasicCoordinateTransform(source.getCoordinateReferenceSystem(),
target.getCoordinateReferenceSystem());
}
/**
* Get source projection
* @return Source projection
*/
public ProjectionInfo getSourceProj() {
return this.sourceProj;
}
/**
* Get target projection
* @return Target projection
*/
public ProjectionInfo getTargetProj() {
return this.targetProj;
}
@Override
public boolean isValid() {
return !sourceProj.equals(targetProj);
}
@Override
public PointD transform(double x, double y) {
ProjCoordinate s = new ProjCoordinate(x, y);
ProjCoordinate t = new ProjCoordinate();
this.coordinateTransform.transform(s, t);
return new PointD(t.x, t.y);
}
@Override
public Transform inverted() {
return new GeoTransform(this.targetProj, this.sourceProj);
}
}

View File

@ -946,6 +946,43 @@ public class ProjectionUtil {
* @return Projected graphic * @return Projected graphic
*/ */
public static Graphic projectClipGraphic(Graphic graphic, ProjectionInfo fromProj, ProjectionInfo toProj) { public static Graphic projectClipGraphic(Graphic graphic, ProjectionInfo fromProj, ProjectionInfo toProj) {
if (graphic instanceof GraphicCollection) {
try {
List<Graphic> graphics = new ArrayList<>();
for (Graphic aGraphic : ((GraphicCollection) graphic).getGraphics()) {
List<? extends Shape> shapes = projectClipShape(aGraphic.getShape(), fromProj, toProj);
if (shapes != null && shapes.size() > 0) {
aGraphic.setShape(shapes.get(0));
graphics.add(aGraphic);
}
}
((GraphicCollection) graphic).setGraphics(graphics);
return graphic;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
} else {
List<? extends Shape> shapes = projectClipShape(graphic.getShape(), fromProj, toProj);
if (shapes != null && shapes.size() > 0) {
graphic.setShape(shapes.get(0));
return graphic;
} else {
return null;
}
}
}
/**
* Project graphic
*
* @param graphic The graphic
* @param fromProj From projection
* @param toProj To projection
* @return Projected graphic
*/
public static Graphic projectClipGraphic_old(Graphic graphic, ProjectionInfo fromProj, ProjectionInfo toProj) {
if (graphic instanceof GraphicCollection) { if (graphic instanceof GraphicCollection) {
try { try {
Graphic newGCollection = graphic.getClass().getDeclaredConstructor().newInstance(); Graphic newGCollection = graphic.getClass().getDeclaredConstructor().newInstance();