add crs and common used projections

This commit is contained in:
wyq 2024-06-29 23:44:03 +08:00
parent 570f28d5e2
commit 6d444c7bce
39 changed files with 1573 additions and 123 deletions

View File

@ -287,7 +287,7 @@ public class MapGridLine extends GridLine {
points.add(new PointD(lon, lat));
lat += delta;
}
points.add((new PointD(lon, lat)));
points.add((new PointD(lon, latMax)));
PolylineShape line = new PolylineShape();
line.setPoints(points);
Graphic graphic = new Graphic(line, this.lineBreak);
@ -320,6 +320,7 @@ public class MapGridLine extends GridLine {
points.add(new PointD(lon, lat));
lon += delta;
}
//points.add(new PointD(lonMax, lat));
PolylineShape line = new PolylineShape();
line.setPoints(points);
Graphic graphic = new Graphic(line, this.lineBreak);

View File

@ -651,12 +651,7 @@ public class MapPlot extends Plot2D implements IWebMapPanel {
*/
@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());
}
graphic.doTransform();
return super.addGraphic(graphic);
}
@ -669,12 +664,7 @@ public class MapPlot extends Plot2D implements IWebMapPanel {
*/
@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());
}
graphic.doTransform();
return super.addGraphic(idx, graphic);
}
@ -745,7 +735,7 @@ public class MapPlot extends Plot2D implements IWebMapPanel {
public Extent getFullExtent() {
Extent ext = this.getExtent();
if (this.boundary != null) {
ext = ext.union(this.boundary.getExtent().extend(0.01));
ext = ext.union(this.boundary.getExtent().extend(0.015));
}
return ext;

View File

@ -7,6 +7,7 @@ import org.meteoinfo.geometry.legend.LegendManage;
import org.meteoinfo.geometry.colors.TransferFunction;
import org.meteoinfo.geometry.graphic.GraphicCollection3D;
import org.meteoinfo.geometry.legend.LegendScheme;
import org.meteoinfo.projection.GeoTransform;
import java.awt.*;
import java.awt.image.BufferedImage;
@ -430,4 +431,18 @@ public class MeshGraphic extends GraphicCollection3D {
public Color getColor() {
return Color.red;
}
/**
* Transform the graphic
*/
@Override
public void doTransform() {
if (this.transform != null && this.transform.isValid()) {
if (this.transform instanceof GeoTransform) {
GeoTransform geoTransform = (GeoTransform) this.transform;
GraphicProjectionUtil.projectClipGraphic(this, geoTransform.getSourceProj(),
geoTransform.getTargetProj());
}
}
}
}

View File

@ -1127,12 +1127,7 @@ public class GLPlot extends Plot {
* @param graphic Graphic
*/
public void addGraphic(Graphic graphic) {
org.meteoinfo.geometry.graphic.Transform transform = graphic.getTransform();
if (transform != null && transform.isValid()) {
GeoTransform geoTransform = (GeoTransform) transform;
GraphicProjectionUtil.projectClipGraphic(graphic, geoTransform.getSourceProj(),
geoTransform.getTargetProj());
}
graphic.doTransform();
this.graphics.add(graphic);
Extent ex = this.graphics.getExtent();
if (!ex.is3D()) {
@ -1153,12 +1148,7 @@ public class GLPlot extends Plot {
* @param graphic Graphic
*/
public void addGraphic(int index, Graphic graphic) {
org.meteoinfo.geometry.graphic.Transform transform = graphic.getTransform();
if (transform != null && transform.isValid()) {
GeoTransform geoTransform = (GeoTransform) transform;
GraphicProjectionUtil.projectClipGraphic(graphic, geoTransform.getSourceProj(),
geoTransform.getTargetProj());
}
graphic.doTransform();
this.graphics.add(index, graphic);
Extent ex = this.graphics.getExtent();
if (!ex.is3D()) {

View File

@ -116,6 +116,33 @@ public class Line2DGraphic extends Graphic {
this.legend = cbc;
}
protected void updateShapeLegend(List<ColorBreak> cbs) {
List<PointD> points = new ArrayList<>();
IndexIterator xIter = this.xData.getIndexIterator();
IndexIterator yIter = this.yData.getIndexIterator();
ColorBreakCollection cbc = new ColorBreakCollection();
ColorBreak cb;
double x, y, c;
int i = 0;
while (xIter.hasNext()) {
x = xIter.getDoubleNext();
y = yIter.getDoubleNext();
cb = cbs.get(i);
if (Double.isNaN(x) || Double.isNaN(y)) {
continue;
}
points.add(new PointD(x, y));
cbc.add(cb);
i += 1;
}
if (this.shape == null) {
this.shape = new PolylineShape();
}
this.shape.setPoints(points);
this.legend = cbc;
}
/**
* Return plot as curve line or not
* @return Curve line or not

View File

@ -1,30 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MeteoInfo File="milconfig.xml" Type="configurefile">
<Path OpenPath="D:\Working\MIScript\Jython\mis\io\netcdf">
<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\plot_types\scatter"/>
<Path OpenPath="D:\Working\MIScript\Jython\mis\map\projection">
<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\pcolor"/>
<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\geoshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\netcdf"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl\geoshow"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\contour"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
<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\plot"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\projection"/>
</Path>
<File>
<OpenedFiles>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\scatter\scatterm_2.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\netcdf\test_sub.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\plot\plot_cdata_1.py"/>
<OpenedFile File="D:\Working\MIScript\Jython\mis\map\projection\wag3_proj.py"/>
</OpenedFiles>
<RecentFiles>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\scatter\scatterm_2.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\io\netcdf\test_sub.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\plot\plot_cdata_1.py"/>
<RecentFile File="D:\Working\MIScript\Jython\mis\map\projection\wag3_proj.py"/>
</RecentFiles>
</File>
<Font>
@ -32,5 +34,5 @@
</Font>
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
<Figure DoubleBuffering="true"/>
<Startup MainFormLocation="-7,-7" MainFormSize="1293,765"/>
<Startup MainFormLocation="-7,0" MainFormSize="1293,765"/>
</MeteoInfo>

View File

@ -1,9 +1,11 @@
from .crs import *
from .migeo import *
from .geoutil import *
from .topology import *
from .geod import *
__all__ = []
__all__ += crs.__all__
__all__ += migeo.__all__
__all__ += geoutil.__all__
__all__ += topology.__all__

View File

@ -0,0 +1,763 @@
from org.meteoinfo.projection import ProjectionInfo
from org.meteoinfo.projection.info import LongLat, Albers, LambertConformalConic, LambertEqualAreaConic, \
GeostationarySatellite, OrthographicAzimuthal, StereographicAzimuthal
from org.meteoinfo.projection.info import TransverseMercator as JTransverseMercator
from org.meteoinfo.projection.info import Mercator as JMercator
from org.meteoinfo.projection.info import AzimuthEquidistant as JAzimuthEquidistant
from org.meteoinfo.projection.info import EquidistantConic as JEquidistantConic
from org.meteoinfo.projection.info import Hammer as JHammer
from org.meteoinfo.projection.info import LambertAzimuthalEqualArea as JLambertAzimuthalEqualArea
from org.meteoinfo.projection.info import Mollweide as JMollweide
from org.meteoinfo.projection.info import Robinson as JRobinson
from org.meteoinfo.projection.info import Sinusoidal as JSinusoidal
from org.meteoinfo.projection.info import Wagner3 as JWagner3
from org.meteoinfo.projection.info import Airy as JAiry
from org.meteoinfo.projection.info import Aitoff as JAitoff
from org.meteoinfo.projection.info import August as JAugust
from org.locationtech.proj4j import CRSFactory
__all__ = ['AlbersEqualArea','Airy','Aitoff','August','AzimuthalEquidistant','EquidistantConic',
'Geostationary','Hammer','LambertAzimuthalEqualArea','LambertConformal','LambertEqualArea',
'Mercator','Mollweide','NorthPolarStereo','Orthographic',
'PlateCarree','Robinson','Sinusoidal','SouthPolarStereo','Stereographic',
'TransverseMercator','Wagner3']
crs_factory = CRSFactory()
class PlateCarree(LongLat):
def __init__(self, central_longitude=0.0):
proj4_params = ['+proj=longlat', '+lon_0=' + str(central_longitude)]
crs = crs_factory.createFromParameters('custom', proj4_params)
LongLat.__init__(self, crs)
class TransverseMercator(JTransverseMercator):
"""
A Transverse Mercator projection.
"""
def __init__(self, central_longitude=0.0, central_latitude=0.0,
false_easting=0.0, false_northing=0.0, scale_factor=1.0):
"""
Parameters
----------
central_longitude: optional
The true longitude of the central meridian in degrees.
Defaults to 0.
central_latitude: optional
The true latitude of the planar origin in degrees. Defaults to 0.
false_easting: optional
X offset from the planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from the planar origin in metres. Defaults to 0.
scale_factor: optional
Scale factor at the central meridian. Defaults to 1.
"""
proj4_params = ['+proj=tmerc',
'+lon_0=' + str(central_longitude),
'+lat_0=' + str(central_latitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing),
'+k=' + str(scale_factor)]
crs = crs_factory.createFromParameters('custom', proj4_params)
JTransverseMercator.__init__(self, crs)
class Mercator(JMercator):
"""
A Transverse Mercator projection.
"""
def __init__(self, central_longitude=0.0, latitude_true_scale=None,
false_easting=0.0, false_northing=0.0, scale_factor=1.0):
"""
Parameters
----------
central_longitude: optional
The true longitude of the central meridian in degrees.
Defaults to 0.
latitude_true_scale: optional
The latitude where the scale is 1. Defaults to 0 degrees.
false_easting: optional
X offset from the planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from the planar origin in metres. Defaults to 0.
scale_factor: optional
Scale factor at the central meridian. Defaults to 1.
"""
proj4_params = ['+proj=merc',
'+lon_0=' + str(central_longitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
# If it's None, we don't pass it to Proj4, in which case its default
# of 0.0 will be used.
if latitude_true_scale is not None:
proj4_params.append('+lat_ts=' + str(latitude_true_scale))
if scale_factor is not None:
if latitude_true_scale is not None:
raise ValueError('It does not make sense to provide both '
'"scale_factor" and "latitude_true_scale". ')
else:
proj4_params.append('+k_0=' + str(scale_factor))
crs = crs_factory.createFromParameters('custom', proj4_params)
JMercator.__init__(self, crs)
class AlbersEqualArea(Albers):
"""
An Albers Equal Area projection.
This projection is conic and equal-area.
"""
def __init__(self, central_longitude=0.0, central_latitude=0.0,
false_easting=0.0, false_northing=0.0,
standard_parallels=(20.0, 50.0)):
"""
Parameters
----------
central_longitude: optional
The central longitude. Defaults to 0.
central_latitude: optional
The central latitude. Defaults to 0.
false_easting: optional
X offset from planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from planar origin in metres. Defaults to 0.
standard_parallels: optional
The one or two latitudes of correct scale. Defaults to (20, 50).
"""
proj4_params = ['+proj=' + 'aea',
'+lon_0=' + str(central_longitude),
'+lat_0=' + str(central_latitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
if standard_parallels is not None:
try:
proj4_params.append('+lat_1=' + str(standard_parallels[0]))
try:
proj4_params.append('+lat_2=' + str(standard_parallels[1]))
except IndexError:
pass
except TypeError:
proj4_params.append('+lat_1=' + str(standard_parallels))
crs = crs_factory.createFromParameters('custom', proj4_params)
Albers.__init__(self, crs)
class AzimuthalEquidistant(JAzimuthEquidistant):
"""
An Azimuthal Equidistant projection
This projection provides accurate angles about and distances through the
central position. Other angles, distances, or areas may be distorted.
"""
def __init__(self, central_longitude=0.0, central_latitude=0.0,
false_easting=0.0, false_northing=0.0):
"""
Parameters
----------
central_longitude: optional
The true longitude of the central meridian in degrees.
Defaults to 0.
central_latitude: optional
The true latitude of the planar origin in degrees.
Defaults to 0.
false_easting: optional
X offset from the planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from the planar origin in metres. Defaults to 0.
"""
proj4_params = ['+proj=' + 'aeqd',
'+lon_0=' + str(central_longitude),
'+lat_0=' + str(central_latitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
crs = crs_factory.createFromParameters('custom', proj4_params)
JAzimuthEquidistant.__init__(self, crs)
class EquidistantConic(JEquidistantConic):
"""
An Equidistant Conic projection.
This projection is conic and equidistant, and the scale is true along all
meridians and along one or two specified standard parallels.
"""
def __init__(self, central_longitude=0.0, central_latitude=0.0,
false_easting=0.0, false_northing=0.0,
standard_parallels=(20.0, 50.0)):
"""
Parameters
----------
central_longitude: optional
The central longitude. Defaults to 0.
central_latitude: optional
The true latitude of the planar origin in degrees. Defaults to 0.
false_easting: optional
X offset from planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from planar origin in metres. Defaults to 0.
standard_parallels: optional
The one or two latitudes of correct scale. Defaults to (20, 50).
"""
proj4_params = ['+proj=' + 'eqdc',
'+lon_0=' + str(central_longitude),
'+lat_0=' + str(central_latitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
if standard_parallels is not None:
try:
proj4_params.append('+lat_1=', str(standard_parallels[0]))
try:
proj4_params.append('+lat_2=' + str(standard_parallels[1]))
except IndexError:
pass
except TypeError:
proj4_params.append('+lat_1=' + str(standard_parallels))
crs = crs_factory.createFromParameters('custom', proj4_params)
JEquidistantConic.__init__(self, crs)
class Geostationary(GeostationarySatellite):
"""
A view appropriate for satellites in Geostationary Earth orbit.
Perspective view looking directly down from above a point on the equator.
In this projection, the projected coordinates are scanning angles measured
from the satellite looking directly downward, multiplied by the height of
the satellite.
"""
def __init__(self, central_longitude=0.0, satellite_height=35785831,
false_easting=0, false_northing=0, semi_major_axis=None,
semi_minor_axis=None):
"""
Parameters
----------
central_longitude: float, optional
The central longitude. Defaults to 0.
satellite_height: float, optional
The height of the satellite. Defaults to 35785831 metres
(true geostationary orbit).
false_easting:
X offset from planar origin in metres. Defaults to 0.
false_northing:
Y offset from planar origin in metres. Defaults to 0.
semi_major_axis:
Semi-major axis of the ellipsoid, `a`.
semi_minor_axis:
Semi-minor axis of the ellipsoid, `b`.
"""
proj4_params = ['+proj=' + 'geos',
'+lon_0=' + str(central_longitude),
'+h=' + str(satellite_height),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
if semi_major_axis is not None:
proj4_params.append('+a=' + str(semi_major_axis))
if semi_minor_axis is not None:
proj4_params.append('+b=' + str(semi_minor_axis))
crs = crs_factory.createFromParameters('custom', proj4_params)
GeostationarySatellite.__init__(self, crs)
class Hammer(JHammer):
"""
A Hammer projection.
This projection is a modified `.LambertAzimuthalEqualArea` projection,
similar to `.Aitoff`, and intended to reduce distortion in the outer
meridians compared to `.Mollweide`. There are no standard lines and only
the central point is free of distortion.
"""
_handles_ellipses = False
def __init__(self, central_longitude=0, false_easting=None,
false_northing=None):
"""
Parameters
----------
central_longitude: float, optional
The central longitude. Defaults to 0.
false_easting: float, optional
X offset from planar origin in metres. Defaults to 0.
false_northing: float, optional
Y offset from planar origin in metres. Defaults to 0.
.. note::
This projection does not handle elliptical globes.
"""
proj4_params = ['+proj=' + 'hammer',
'+lon_0=' + str(central_longitude)]
if false_easting is not None:
proj4_params.append('+x_0=' + str(false_easting))
if false_northing is not None:
proj4_params.append('+y_0=' + str(false_northing))
crs = crs_factory.createFromParameters('custom', proj4_params)
JHammer.__init__(self, crs)
class LambertConformal(LambertConformalConic):
"""
A Lambert Conformal conic projection.
"""
def __init__(self, central_longitude=-96.0, central_latitude=39.0,
false_easting=0.0, false_northing=0.0,
standard_parallels=(33, 45), cutoff=-30):
"""
Parameters
----------
central_longitude: optional
The central longitude. Defaults to -96.
central_latitude: optional
The central latitude. Defaults to 39.
false_easting: optional
X offset from planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from planar origin in metres. Defaults to 0.
standard_parallels: optional
Standard parallel latitude(s). Defaults to (33, 45).
cutoff: optional
Latitude of map cutoff.
The map extends to infinity opposite the central pole
so we must cut off the map drawing before then.
A value of 0 will draw half the globe. Defaults to -30.
"""
proj4_params = ['+proj=' + 'lcc',
'+lon_0=' + str(central_longitude),
'+lat_0=' + str(central_latitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
n_parallels = len(standard_parallels)
if not 1 <= n_parallels <= 2:
raise ValueError('1 or 2 standard parallels must be specified. '
'Got {} ({})'.format(n_parallels, standard_parallels))
proj4_params.append('+lat_1=' + str(standard_parallels[0]))
if n_parallels == 2:
proj4_params.append('+lat_2=' + str(standard_parallels[1]))
crs = crs_factory.createFromParameters('custom', proj4_params)
LambertConformalConic.__init__(self, crs, cutoff)
class LambertAzimuthalEqualArea(JLambertAzimuthalEqualArea):
"""
A Lambert Azimuthal Equal-Area projection.
"""
def __init__(self, central_longitude=0.0, central_latitude=0.0,
false_easting=0.0, false_northing=0.0):
"""
Parameters
----------
central_longitude: optional
The central longitude. Defaults to 0.
central_latitude: optional
The central latitude. Defaults to 0.
false_easting: optional
X offset from planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from planar origin in metres. Defaults to 0.
"""
proj4_params = ['+proj=' + 'laea',
'+lon_0=' + str(central_longitude),
'+lat_0=' + str(central_latitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
crs = crs_factory.createFromParameters('custom', proj4_params)
JLambertAzimuthalEqualArea.__init__(self, crs)
class LambertEqualArea(LambertEqualAreaConic):
"""
A Lambert Equal-Area Conic projection.
"""
def __init__(self, central_longitude=0.0, central_latitude=0.0,
false_easting=0.0, false_northing=0.0):
"""
Parameters
----------
central_longitude: optional
The central longitude. Defaults to 0.
central_latitude: optional
The central latitude. Defaults to 0.
false_easting: optional
X offset from planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from planar origin in metres. Defaults to 0.
"""
proj4_params = ['+proj=' + 'leac',
'+lon_0=' + str(central_longitude),
'+lat_0=' + str(central_latitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
crs = crs_factory.createFromParameters('custom', proj4_params)
LambertEqualAreaConic.__init__(self, crs)
class Mollweide(JMollweide):
"""
A Mollweide projection.
This projection is pseudocylindrical, and equal area. Parallels are
unequally-spaced straight lines, while meridians are elliptical arcs up to
semicircles on the edges. Poles are points.
It is commonly used for world maps, or interrupted with several central
meridians.
"""
_handles_ellipses = False
def __init__(self, central_longitude=0,
false_easting=None, false_northing=None):
"""
Parameters
----------
central_longitude: float, optional
The central longitude. Defaults to 0.
false_easting: float, optional
X offset from planar origin in metres. Defaults to 0.
false_northing: float, optional
Y offset from planar origin in metres. Defaults to 0.
.. note::
This projection does not handle elliptical globes.
"""
proj4_params = ['+proj=' + 'moll',
'+lon_0=' + str(central_longitude)]
if false_easting is not None:
proj4_params.append('+x_0=' + str(false_easting))
if false_northing is not None:
proj4_params.append('+y_0=' + str(false_northing))
crs = crs_factory.createFromParameters('custom', proj4_params)
JMollweide.__init__(self, crs)
class Orthographic(OrthographicAzimuthal):
"""
Am orthographic azimuthal projection.
"""
_handles_ellipses = False
def __init__(self, central_longitude=0.0, central_latitude=0.0):
"""
Parameters
----------
central_longitude: optional
The central longitude. Defaults to 0.
central_latitude: optional
The central latitude. Defaults to 0.
"""
proj4_params = ['+proj=' + 'ortho',
'+lon_0=' + str(central_longitude),
'+lat_0=' + str(central_latitude)]
crs = crs_factory.createFromParameters('custom', proj4_params)
OrthographicAzimuthal.__init__(self, crs)
class Robinson(JRobinson):
"""
A Robinson projection.
This projection is pseudocylindrical, and a compromise that is neither
equal-area nor conformal. Parallels are unequally-spaced straight lines,
and meridians are curved lines of no particular form.
It is commonly used for "visually-appealing" world maps.
"""
_handles_ellipses = False
def __init__(self, central_longitude=0,
false_easting=None, false_northing=None):
"""
Parameters
----------
central_longitude: float, optional
The central longitude. Defaults to 0.
false_easting: float, optional
X offset from planar origin in metres. Defaults to 0.
false_northing: float, optional
Y offset from planar origin in metres. Defaults to 0.
.. note::
This projection does not handle elliptical globes.
"""
proj4_params = ['+proj=' + 'robin',
'+lon_0=' + str(central_longitude)]
if false_easting is not None:
proj4_params.append('+x_0=' + str(false_easting))
if false_northing is not None:
proj4_params.append('+y_0=' + str(false_northing))
crs = crs_factory.createFromParameters('custom', proj4_params)
JRobinson.__init__(self, crs)
class Sinusoidal(JSinusoidal):
"""
A Sinusoidal projection.
This projection is equal-area.
"""
def __init__(self, central_longitude=0.0, false_easting=0.0,
false_northing=0.0):
"""
Parameters
----------
central_longitude: optional
The central longitude. Defaults to 0.
false_easting: optional
X offset from planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from planar origin in metres. Defaults to 0.
"""
proj4_params = ['+proj=' + 'sinu',
'+lon_0=' + str(central_longitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
crs = crs_factory.createFromParameters('custom', proj4_params)
JSinusoidal.__init__(self, crs)
class Stereographic(StereographicAzimuthal):
"""
A stereographic azimuthal projection.
"""
_wrappable = True
def __init__(self, central_latitude=0.0, central_longitude=0.0,
false_easting=0.0, false_northing=0.0,
true_scale_latitude=None, scale_factor=None, cutoff=0):
proj4_params = ['+proj=' + 'stere',
'+lat_0=' + str(central_latitude),
'+lon_0=' + str(central_longitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
if true_scale_latitude is not None:
if central_latitude not in (-90., 90.):
warnings.warn('"true_scale_latitude" parameter is only used '
'for polar stereographic projections. Consider '
'the use of "scale_factor" instead.',
stacklevel=2)
proj4_params.append('+lat_ts=' + str(true_scale_latitude))
if scale_factor is not None:
if true_scale_latitude is not None:
raise ValueError('It does not make sense to provide both '
'"scale_factor" and "true_scale_latitude". '
'Ignoring "scale_factor".')
else:
proj4_params.append('+k_0=' + str(scale_factor))
crs = crs_factory.createFromParameters('custom', proj4_params)
StereographicAzimuthal.__init__(self, crs, cutoff)
class NorthPolarStereo(Stereographic):
def __init__(self, central_longitude=0.0, true_scale_latitude=None, cutoff=0):
Stereographic.__init__(self,
central_latitude=90,
central_longitude=central_longitude,
true_scale_latitude=true_scale_latitude, # None is +90
cutoff=cutoff)
class SouthPolarStereo(Stereographic):
def __init__(self, central_longitude=0.0, true_scale_latitude=None, cutoff=0):
Stereographic.__init__(self,
central_latitude=-90,
central_longitude=central_longitude,
true_scale_latitude=true_scale_latitude, # None is -90
cutoff=cutoff)
class Wagner3(JWagner3):
"""
A Wagner 3 projection.
"""
def __init__(self, central_longitude=0.0, latitude_true_scale=None,
false_easting=0.0, false_northing=0.0):
"""
Parameters
----------
central_longitude: optional
The true longitude of the central meridian in degrees.
Defaults to 0.
latitude_true_scale: optional
The latitude where the scale is 1. Defaults to 0 degrees.
false_easting: optional
X offset from the planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from the planar origin in metres. Defaults to 0.
"""
proj4_params = ['+proj=wag3',
'+lon_0=' + str(central_longitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
# If it's None, we don't pass it to Proj4, in which case its default
# of 0.0 will be used.
if latitude_true_scale is not None:
proj4_params.append('+lat_ts=' + str(latitude_true_scale))
crs = crs_factory.createFromParameters('custom', proj4_params)
JWagner3.__init__(self, crs)
class Airy(JAiry):
"""
An Airy projection.
"""
def __init__(self, central_longitude=0.0, central_latitude=0.0,
false_easting=0.0, false_northing=0.0):
"""
Parameters
----------
central_longitude: optional
The central longitude. Defaults to 0.
central_latitude: optional
The central latitude. Defaults to 0.
false_easting: optional
X offset from planar origin in metres. Defaults to 0.
false_northing: optional
Y offset from planar origin in metres. Defaults to 0.
"""
proj4_params = ['+proj=' + 'airy',
'+lat_0=' + str(central_latitude),
'+lon_0=' + str(central_longitude),
'+x_0=' + str(false_easting),
'+y_0=' + str(false_northing)]
crs = crs_factory.createFromParameters('custom', proj4_params)
JAiry.__init__(self, crs)
class Aitoff(JAitoff):
"""
An Aitoff projection.
This projection is a modified azimuthal equidistant projection, balancing
shape and scale distortion. There are no standard lines and only the
central point is free of distortion.
"""
_handles_ellipses = False
def __init__(self, central_longitude=0, false_easting=None,
false_northing=None):
"""
Parameters
----------
central_longitude: float, optional
The central longitude. Defaults to 0.
false_easting: float, optional
X offset from planar origin in metres. Defaults to 0.
false_northing: float, optional
Y offset from planar origin in metres. Defaults to 0.
.. note::
This projection does not handle elliptical globes.
"""
proj4_params = ['+proj=' + 'aitoff',
'+lon_0=' + str(central_longitude)]
if false_easting is not None:
proj4_params.append('+x_0=' + str(false_easting))
if false_northing is not None:
proj4_params.append('+y_0=' + str(false_northing))
crs = crs_factory.createFromParameters('custom', proj4_params)
JAitoff.__init__(self, crs)
class August(JAugust):
"""
An August projection.
"""
_handles_ellipses = False
def __init__(self, central_longitude=0, false_easting=None,
false_northing=None):
"""
Parameters
----------
central_longitude: float, optional
The central longitude. Defaults to 0.
false_easting: float, optional
X offset from planar origin in metres. Defaults to 0.
false_northing: float, optional
Y offset from planar origin in metres. Defaults to 0.
.. note::
This projection does not handle elliptical globes.
"""
proj4_params = ['+proj=' + 'august',
'+lon_0=' + str(central_longitude)]
if false_easting is not None:
proj4_params.append('+x_0=' + str(false_easting))
if false_northing is not None:
proj4_params.append('+y_0=' + str(false_northing))
crs = crs_factory.createFromParameters('custom', proj4_params)
JAugust.__init__(self, crs)

View File

@ -2316,10 +2316,6 @@ class Axes(object):
:returns: (*contour graphics*) Contour graphics created from array data.
"""
n = len(args)
ls = kwargs.pop('symbolspec', None)
cmap = plotutil.getcolormap(**kwargs)
fill_value = kwargs.pop('fill_value', -9999.0)
xaxistype = None
if n <= 2:
a = args[0]
if isinstance(a, DimArray):
@ -2337,20 +2333,9 @@ class Axes(object):
vmin = kwargs.pop('vmin', a.min())
vmax = kwargs.pop('vmax', a.max())
if ls is None:
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createLegendScheme(vmin, vmax, cn, cmap)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createLegendScheme(vmin, vmax, level_arg, cmap)
else:
ls = LegendManage.createLegendScheme(vmin, vmax, cmap)
ls = ls.convertTo(ShapeTypes.POLYLINE)
plotutil.setlegendscheme(ls, **kwargs)
ls = plotutil.getlegendscheme(args, vmin, vmax, **kwargs)
ls = ls.convertTo(ShapeTypes.POLYLINE)
plotutil.setlegendscheme(ls, **kwargs)
# norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
# ls.setNormalize(norm._norm)
@ -2361,10 +2346,6 @@ class Axes(object):
a, x, y = np.griddata((x, y), a, **griddata_props)
graphics = GraphicFactory.createContourLines(x.asarray(), y.asarray(), a.asarray(), ls, smooth)
if not xaxistype is None:
self.set_xaxis_type(xaxistype)
self._axes.updateDrawExtent()
antialias = kwargs.pop('antialias', None)
if antialias is not None:
graphics.setAntiAlias(antialias)
@ -2483,31 +2464,13 @@ class Axes(object):
vmin = kwargs.pop('vmin', a.min())
vmax = kwargs.pop('vmax', a.max())
extend = ExtendType.valueOf(kwargs.pop('extend', 'neither').upper())
if ls is None:
if len(args) > 0:
level_arg = args[0]
if isinstance(level_arg, int):
cn = level_arg
ls = LegendManage.createLegendScheme(vmin, vmax, cn, cmap, extend)
else:
if isinstance(level_arg, NDArray):
level_arg = level_arg.aslist()
ls = LegendManage.createLegendScheme(level_arg, cmap, extend)
else:
ls = LegendManage.createLegendScheme(vmin, vmax, cmap, extend)
if not kwargs.has_key('extend'):
kwargs['extend'] = 'neither'
ls = plotutil.getlegendscheme(args, vmin, vmax, **kwargs)
ls = ls.convertTo(ShapeTypes.POLYGON)
if 'edgecolor' not in kwargs.keys():
if not kwargs.has_key('edgecolor'):
kwargs['edgecolor'] = None
plotutil.setlegendscheme(ls, **kwargs)
extendfrac = kwargs.pop('extendfrac', None)
if extendfrac is not None:
if extendfrac == 'auto':
efrac = ExtendFraction.AUTO
else:
efrac = ExtendFraction.LENGTH
efrac.fraction = extendfrac
ls.setExtendFraction(efrac)
# norm = kwargs.pop('norm', colors.Normalize(vmin, vmax))
# ls.setNormalize(norm._norm)
# ls.setColorMap(cmap)

View File

@ -961,9 +961,10 @@ class Axes3DGL(Axes3D):
visible = kwargs.pop('visible', True)
if visible:
data_proj = kwargs.pop('transform', layer.getProjInfo())
transform = GeoTransform(data_proj, self.projection)
graphics.transform = transform
if hasattr(self, 'projection'):
data_proj = kwargs.pop('transform', layer.getProjInfo())
transform = GeoTransform(data_proj, self.projection)
graphics.transform = transform
self.add_graphic(graphics)
return graphics

View File

@ -625,9 +625,7 @@ class MapAxes(Axes):
:returns: (*VectorLayer*) Line VectorLayer.
"""
fill_value = kwargs.pop('fill_value', -9999.0)
transform = kwargs.pop('transform', None)
is_lonlat = proj.isLonLat()
n = len(args)
xdatalist = []
ydatalist = []
@ -904,7 +902,7 @@ class MapAxes(Axes):
:param x: (*array_like*) Optional. X coordinate array.
:param y: (*array_like*) Optional. Y coordinate array.
:param z: (*array_like*) 2-D z value array.
:param levs: (*array_like*) Optional. A list of floating point numbers indicating the level curves
:param levels: (*array_like*) Optional. A list of floating point numbers indicating the level curves
to draw, in increasing order.
:param cmap: (*string*) Color map string.
:param colors: (*list*) If None (default), the colormap specified by cmap will be used. If a
@ -930,7 +928,10 @@ class MapAxes(Axes):
y = args[1]
a = args[2]
args = args[3:]
ls = plotutil.getlegendscheme(args, a.min(), a.max(), **kwargs)
vmin = kwargs.pop('vmin', a.min())
vmax = kwargs.pop('vmax', a.max())
ls = plotutil.getlegendscheme(args, vmin, vmax, **kwargs)
ls = ls.convertTo(ShapeTypes.POLYLINE)
plotutil.setlegendscheme(ls, **kwargs)
smooth = kwargs.pop('smooth', True)
@ -991,9 +992,11 @@ class MapAxes(Axes):
a = args[2]
args = args[3:]
vmin = kwargs.pop('vmin', a.min())
vmax = kwargs.pop('vmax', a.max())
if not kwargs.has_key('extend'):
kwargs['extend'] = 'neither'
ls = plotutil.getlegendscheme(args, a.min(), a.max(), **kwargs)
ls = plotutil.getlegendscheme(args, vmin, vmax, **kwargs)
ls = ls.convertTo(ShapeTypes.POLYGON)
if not kwargs.has_key('edgecolor'):
kwargs['edgecolor'] = None
@ -1022,7 +1025,7 @@ class MapAxes(Axes):
return graphics
@_add_transform
#@_add_transform
def imshow(self, *args, **kwargs):
"""
Display an image on the map.
@ -1210,7 +1213,7 @@ class MapAxes(Axes):
plotutil.setlegendscheme(ls, **kwargs)
transform = kwargs.pop('transform', None)
if transform is None or transform.isLonLat():
if transform is None or transform.getSourceProj().isLonLat():
lonlim = 90
else:
lonlim = 0

View File

@ -1781,7 +1781,7 @@ public class ArrayUtil {
sbuff.append(", ");
}
n += 1;
if (n > 200) {
if (n > 200 && ii.hasNext()) {
sbuff.append("...]");
break;
}

View File

@ -46,6 +46,34 @@ package org.meteoinfo.projection;
protected float cutoff = Float.NaN; //Latitude cutoff - valiad for some speciafic projections
// </editor-fold>
// <editor-fold desc="Constructor">
/**
* Constructor
*/
public ProjectionInfo() {
}
/**
* Constructor
* @param crs The coordinate reference system
*/
public ProjectionInfo(CoordinateReferenceSystem crs) {
this.crs = crs;
updateBoundary();
}
/**
* Constructor
* @param crs The coordinate reference system
* @param cutoff The cutoff latitude
*/
public ProjectionInfo(CoordinateReferenceSystem crs, float cutoff) {
this.crs = crs;
this.cutoff = cutoff;
updateBoundary();
}
/**
* Create new ProjectionInfo with crs
* @param crs Coordinate reference system
@ -61,6 +89,22 @@ package org.meteoinfo.projection;
case "Albers Equal Area":
projInfo = new Albers(crs);
break;
case "Airy":
projInfo = new Airy(crs);
break;
case "Aitoff":
case "Winkel Tripel":
projInfo = new Aitoff(crs);
break;
case "August Epicycloidal":
projInfo = new August(crs);
break;
case "Equidistant Azimuthal":
projInfo = new AzimuthEquidistant(crs);
break;
case "Equidistant Conic":
projInfo = new EquidistantConic(crs);
break;
case "Lambert Conformal Conic":
projInfo = new LambertConformalConic(crs);
break;
@ -80,7 +124,7 @@ package org.meteoinfo.projection;
projInfo = new Robinson(crs);
break;
case "Molleweide":
projInfo = new Molleweide(crs);
projInfo = new Mollweide(crs);
break;
case "Geostationary Satellite":
projInfo = new GeostationarySatellite(crs);
@ -106,7 +150,7 @@ package org.meteoinfo.projection;
break;
}
projInfo.updateBoundary();
//projInfo.updateBoundary();
return projInfo;
}

View File

@ -23,6 +23,11 @@ public enum ProjectionNames {
Lambert_Equal_Area_Conic("leac"),
Lambert_Azimuthal_Equal_Area("laea"),
Albers_Equal_Area("aea"),
Airy("airy"),
Aitoff("aitoff"),
August("august"),
Azimuthal_Equidistant("aeqd"),
Equidistant_Conic("eqdc"),
Stereographic_Azimuthal("stere"),
North_Polar_Stereographic_Azimuthal("stere"),
South_Polar_Stereographic_Azimuthal("stere"),

View File

@ -195,6 +195,12 @@ public class ProjectionUtil {
}
}
}
if (minY < -90) {
minY = -90;
}
if (maxY > 90) {
maxY = 90;
}
Extent aExtent = new Extent();
aExtent.minX = minX;

View File

@ -0,0 +1,61 @@
/* Copyright 2012 - Yaqiang Wang,
* yaqiang.wang@gmail.com
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*/
package org.meteoinfo.projection.info;
import org.locationtech.proj4j.CoordinateReferenceSystem;
import org.meteoinfo.common.PointD;
import org.meteoinfo.geometry.shape.PolygonShape;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.ProjectionInfo;
import org.meteoinfo.projection.ProjectionNames;
import org.meteoinfo.projection.ProjectionUtil;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Yaqiang Wang
*/
public class Airy extends ProjectionInfo {
// <editor-fold desc="Variables">
// </editor-fold>
// <editor-fold desc="Constructor">
/**
* Construction
*
* @param crs Coordinate reference system
*/
public Airy(CoordinateReferenceSystem crs) {
super(crs);
}
// </editor-fold>
// <editor-fold desc="Get Set Methods">
/**
* Get projection name
*
* @return Projection name
*/
@Override
public ProjectionNames getProjectionName() {
return ProjectionNames.Airy;
}
// </editor-fold>
// <editor-fold desc="Methods">
// </editor-fold>
}

View File

@ -0,0 +1,145 @@
/* Copyright 2012 - Yaqiang Wang,
* yaqiang.wang@gmail.com
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*/
package org.meteoinfo.projection.info;
import org.locationtech.proj4j.CoordinateReferenceSystem;
import org.meteoinfo.common.*;
import org.meteoinfo.geometry.shape.PolygonShape;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.ProjectionInfo;
import org.meteoinfo.projection.ProjectionNames;
import org.meteoinfo.projection.ProjectionUtil;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Yaqiang Wang
*/
public class Aitoff extends ProjectionInfo {
// <editor-fold desc="Variables">
// </editor-fold>
// <editor-fold desc="Constructor">
/**
* Construction
*
* @param crs Coordinate reference system
*/
public Aitoff(CoordinateReferenceSystem crs) {
super(crs);
}
// </editor-fold>
// <editor-fold desc="Get Set Methods">
/**
* Get projection name
*
* @return Projection name
*/
@Override
public ProjectionNames getProjectionName() {
return ProjectionNames.Aitoff;
}
// </editor-fold>
// <editor-fold desc="Methods">
@Override
public void updateBoundary() {
double epsilon = 1e-10;
double cenLon = this.getCenterLon();
double minLon = cenLon - 180 + epsilon;
double maxLon = cenLon + 180 - epsilon;
double minLat = -90;
double maxLat = 90;
List<PointD> points = new ArrayList<>();
double lon = minLon;
double lat = minLat;
lon = maxLon;
while (lat < maxLat) {
points.add(new PointD(lon, lat));
lat += 1;
}
lat = maxLat;
lon = minLon;
while (lat > minLat) {
points.add(new PointD(lon, lat));
lat -= 1;
}
lat = minLat;
points.add(new PointD(lon, lat));
PolygonShape ps = new PolygonShape();
ps.setPoints(points);
this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this);
}
@Override
public Object[] checkGridLabel(GridLabel gl, float shift) {
float angle = gl.getAngle();
double v = gl.getValue();
float xShift = 0.f;
float yShift = 0.f;
XAlign xAlign = XAlign.CENTER;
YAlign yAlign = YAlign.CENTER;
if (v == 0) {
if (angle == 90) {
xShift = shift;
xAlign = XAlign.LEFT;
} else if (angle == 270) {
xShift = -shift;
xAlign = XAlign.RIGHT;
} else if (angle < 90) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.BOTTOM;
} else if (angle > 90 && angle <= 180) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.TOP;
} else if (angle > 180 && angle < 270) {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.TOP;
} else if (angle > 270 && angle <= 360) {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.BOTTOM;
}
} else if (v > 0) {
if (gl.getLabDirection() == Direction.East) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.BOTTOM;
} else {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.BOTTOM;
}
} else {
if (gl.getLabDirection() == Direction.East) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.TOP;
} else {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.TOP;
}
}
return new Object[]{xShift, yShift, xAlign, yAlign};
}
// </editor-fold>
}

View File

@ -36,10 +36,10 @@ public class Albers extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public Albers(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -0,0 +1,145 @@
/* Copyright 2012 - Yaqiang Wang,
* yaqiang.wang@gmail.com
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*/
package org.meteoinfo.projection.info;
import org.locationtech.proj4j.CoordinateReferenceSystem;
import org.meteoinfo.common.*;
import org.meteoinfo.geometry.shape.PolygonShape;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.ProjectionInfo;
import org.meteoinfo.projection.ProjectionNames;
import org.meteoinfo.projection.ProjectionUtil;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Yaqiang Wang
*/
public class August extends ProjectionInfo {
// <editor-fold desc="Variables">
// </editor-fold>
// <editor-fold desc="Constructor">
/**
* Construction
*
* @param crs Coordinate reference system
*/
public August(CoordinateReferenceSystem crs) {
super(crs);
}
// </editor-fold>
// <editor-fold desc="Get Set Methods">
/**
* Get projection name
*
* @return Projection name
*/
@Override
public ProjectionNames getProjectionName() {
return ProjectionNames.August;
}
// </editor-fold>
// <editor-fold desc="Methods">
@Override
public void updateBoundary() {
double epsilon = 1e-10;
double cenLon = this.getCenterLon();
double minLon = cenLon - 180 + epsilon;
double maxLon = cenLon + 180 - epsilon;
double minLat = -90;
double maxLat = 90;
List<PointD> points = new ArrayList<>();
double lon = minLon;
double lat = minLat;
lon = maxLon;
while (lat < maxLat) {
points.add(new PointD(lon, lat));
lat += 1;
}
lat = maxLat;
lon = minLon;
while (lat > minLat) {
points.add(new PointD(lon, lat));
lat -= 1;
}
lat = minLat;
points.add(new PointD(lon, lat));
PolygonShape ps = new PolygonShape();
ps.setPoints(points);
this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this);
}
@Override
public Object[] checkGridLabel(GridLabel gl, float shift) {
float angle = gl.getAngle();
double v = gl.getValue();
float xShift = 0.f;
float yShift = 0.f;
XAlign xAlign = XAlign.CENTER;
YAlign yAlign = YAlign.CENTER;
if (v == 0) {
if (angle == 90) {
xShift = shift;
xAlign = XAlign.LEFT;
} else if (angle == 270) {
xShift = -shift;
xAlign = XAlign.RIGHT;
} else if (angle < 90) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.BOTTOM;
} else if (angle > 90 && angle <= 180) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.TOP;
} else if (angle > 180 && angle < 270) {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.TOP;
} else if (angle > 270 && angle <= 360) {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.BOTTOM;
}
} else if (v > 0) {
if (gl.getLabDirection() == Direction.East) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.BOTTOM;
} else {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.BOTTOM;
}
} else {
if (gl.getLabDirection() == Direction.East) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.TOP;
} else {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.TOP;
}
}
return new Object[]{xShift, yShift, xAlign, yAlign};
}
// </editor-fold>
}

View File

@ -0,0 +1,96 @@
/* Copyright 2012 - Yaqiang Wang,
* yaqiang.wang@gmail.com
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*/
package org.meteoinfo.projection.info;
import org.locationtech.proj4j.CoordinateReferenceSystem;
import org.meteoinfo.common.PointD;
import org.meteoinfo.geometry.shape.PolygonShape;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.ProjectionInfo;
import org.meteoinfo.projection.ProjectionNames;
import org.meteoinfo.projection.ProjectionUtil;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Yaqiang Wang
*/
public class AzimuthEquidistant extends ProjectionInfo {
// <editor-fold desc="Variables">
// </editor-fold>
// <editor-fold desc="Constructor">
/**
* Construction
*
* @param crs Coordinate reference system
*/
public AzimuthEquidistant(CoordinateReferenceSystem crs) {
super(crs);
}
// </editor-fold>
// <editor-fold desc="Get Set Methods">
/**
* Get projection name
*
* @return Projection name
*/
@Override
public ProjectionNames getProjectionName() {
return ProjectionNames.Azimuthal_Equidistant;
}
// </editor-fold>
// <editor-fold desc="Methods">
@Override
public void updateBoundary() {
double epsilon = 1e-10;
double cenLon = this.getCenterLon();
double minLon = cenLon - 180 + epsilon;
double maxLon = cenLon + 180 - epsilon;
double minLat = -90;
double maxLat = 90;
List<PointD> points = new ArrayList<>();
double lon = minLon;
double lat = minLat;
while (lon < maxLon) {
points.add(new PointD(lon, lat));
lon += 1;
}
lon = maxLon;
while (lat < maxLat) {
points.add(new PointD(lon, lat));
lat += 1;
}
lat = maxLat;
while (lon > minLon) {
points.add(new PointD(lon, lat));
lon -= 1;
}
lon = minLon;
while (lat > minLat) {
points.add(new PointD(lon, lat));
lat -= 1;
}
lat = minLat;
points.add(new PointD(lon, lat));
PolygonShape ps = new PolygonShape();
ps.setPoints(points);
this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this);
}
// </editor-fold>
}

View File

@ -29,10 +29,10 @@ public class Common extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public Common(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -0,0 +1,96 @@
/* Copyright 2012 - Yaqiang Wang,
* yaqiang.wang@gmail.com
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*/
package org.meteoinfo.projection.info;
import org.locationtech.proj4j.CoordinateReferenceSystem;
import org.meteoinfo.common.PointD;
import org.meteoinfo.geometry.shape.PolygonShape;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.ProjectionInfo;
import org.meteoinfo.projection.ProjectionNames;
import org.meteoinfo.projection.ProjectionUtil;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Yaqiang Wang
*/
public class EquidistantConic extends ProjectionInfo {
// <editor-fold desc="Variables">
// </editor-fold>
// <editor-fold desc="Constructor">
/**
* Construction
*
* @param crs Coordinate reference system
*/
public EquidistantConic(CoordinateReferenceSystem crs) {
super(crs);
}
// </editor-fold>
// <editor-fold desc="Get Set Methods">
/**
* Get projection name
*
* @return Projection name
*/
@Override
public ProjectionNames getProjectionName() {
return ProjectionNames.Equidistant_Conic;
}
// </editor-fold>
// <editor-fold desc="Methods">
@Override
public void updateBoundary() {
double epsilon = 1e-10;
double cenLon = this.getCenterLon();
double minLon = cenLon - 180 + epsilon;
double maxLon = cenLon + 180 - epsilon;
double minLat = -90;
double maxLat = 90;
List<PointD> points = new ArrayList<>();
double lon = minLon;
double lat = minLat;
while (lon < maxLon) {
points.add(new PointD(lon, lat));
lon += 1;
}
lon = maxLon;
while (lat < maxLat) {
points.add(new PointD(lon, lat));
lat += 1;
}
lat = maxLat;
while (lon > minLon) {
points.add(new PointD(lon, lat));
lon -= 1;
}
lon = minLon;
while (lat > minLat) {
points.add(new PointD(lon, lat));
lat -= 1;
}
lat = minLat;
points.add(new PointD(lon, lat));
PolygonShape ps = new PolygonShape();
ps.setPoints(points);
this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this);
}
// </editor-fold>
}

View File

@ -40,7 +40,7 @@ public class GeostationarySatellite extends ProjectionInfo {
* @param crs Coordinate reference system
*/
public GeostationarySatellite(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -36,10 +36,10 @@ public class Hammer extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public Hammer(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -35,10 +35,10 @@ public class LambertAzimuthalEqualArea extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public LambertAzimuthalEqualArea(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -41,6 +41,19 @@ public class LambertConformalConic extends ProjectionInfo {
public LambertConformalConic(CoordinateReferenceSystem crs) {
this.crs = crs;
this.cutoff = -80.f;
updateBoundary();
}
/**
* Construction
*
* @param crs Coordinate reference system
* @param cutoff Cutoff latitude
*/
public LambertConformalConic(CoordinateReferenceSystem crs, float cutoff) {
this.crs = crs;
this.cutoff = cutoff;
updateBoundary();
}
// </editor-fold>

View File

@ -36,10 +36,10 @@ public class LambertEqualAreaConic extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public LambertEqualAreaConic(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -36,11 +36,12 @@ public class Mercator extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public Mercator(CoordinateReferenceSystem crs) {
this.crs = crs;
this.cutoff = 85.0511f;
updateBoundary();
}
// </editor-fold>

View File

@ -32,7 +32,7 @@ import java.util.List;
*
* @author Yaqiang Wang
*/
public class Molleweide extends ProjectionInfo {
public class Mollweide extends ProjectionInfo {
// <editor-fold desc="Variables">
// </editor-fold>
@ -40,10 +40,10 @@ public class Molleweide extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public Molleweide(CoordinateReferenceSystem crs) {
this.crs = crs;
public Mollweide(CoordinateReferenceSystem crs) {
super(crs);
}
// </editor-fold>

View File

@ -37,10 +37,10 @@ public class OrthographicAzimuthal extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public OrthographicAzimuthal(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -40,10 +40,10 @@ public class Robinson extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public Robinson(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -36,10 +36,10 @@ public class Sinusoidal extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public Sinusoidal(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>

View File

@ -36,11 +36,24 @@ public class StereographicAzimuthal extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public StereographicAzimuthal(CoordinateReferenceSystem crs) {
this.crs = crs;
this.cutoff = 0.f;
updateBoundary();
}
/**
* Construction
*
* @param crs Coordinate reference system
* @param cutoff Cutoff latitude
*/
public StereographicAzimuthal(CoordinateReferenceSystem crs, float cutoff) {
this.crs = crs;
this.cutoff = cutoff;
updateBoundary();
}
// </editor-fold>

View File

@ -34,11 +34,12 @@ public class TransverseMercator extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public TransverseMercator(CoordinateReferenceSystem crs) {
this.crs = crs;
this.cutoff = 85.0511f;
updateBoundary();
}
// </editor-fold>

View File

@ -14,7 +14,7 @@
package org.meteoinfo.projection.info;
import org.locationtech.proj4j.CoordinateReferenceSystem;
import org.meteoinfo.common.PointD;
import org.meteoinfo.common.*;
import org.meteoinfo.geometry.shape.PolygonShape;
import org.meteoinfo.projection.KnownCoordinateSystems;
import org.meteoinfo.projection.ProjectionInfo;
@ -36,10 +36,10 @@ public class Wagner3 extends ProjectionInfo {
/**
* Construction
*
* @param crs Coorinate reference system
* @param crs Coordinate reference system
*/
public Wagner3(CoordinateReferenceSystem crs) {
this.crs = crs;
super(crs);
}
// </editor-fold>
@ -92,5 +92,72 @@ public class Wagner3 extends ProjectionInfo {
ps.setPoints(points);
this.boundary = ProjectionUtil.projectPolygonShape(ps, KnownCoordinateSystems.geographic.world.WGS1984, this);
}
@Override
public Object[] checkGridLabel(GridLabel gl, float shift) {
float angle = gl.getAngle();
double v = gl.getValue();
float xShift = 0.f;
float yShift = 0.f;
XAlign xAlign = XAlign.CENTER;
YAlign yAlign = YAlign.CENTER;
if (gl.isLongitude()) {
if (gl.getLabDirection() == Direction.South) {
yShift = shift;
yAlign = YAlign.TOP;
} else {
yShift = -shift;
yAlign = YAlign.BOTTOM;
}
} else {
if (v == 0) {
if (angle == 90) {
xShift = shift;
xAlign = XAlign.LEFT;
} else if (angle == 270) {
xShift = -shift;
xAlign = XAlign.RIGHT;
} else if (angle < 90) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.BOTTOM;
} else if (angle > 90 && angle <= 180) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.TOP;
} else if (angle > 180 && angle < 270) {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.TOP;
} else if (angle > 270 && angle <= 360) {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.BOTTOM;
}
} else if (v > 0) {
if (gl.getLabDirection() == Direction.East) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.BOTTOM;
} else {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.BOTTOM;
}
} else {
if (gl.getLabDirection() == Direction.East) {
xShift = shift;
xAlign = XAlign.LEFT;
yAlign = YAlign.TOP;
} else {
xShift = -shift;
xAlign = XAlign.RIGHT;
yAlign = YAlign.TOP;
}
}
}
return new Object[]{xShift, yShift, xAlign, yAlign};
}
// </editor-fold>
}