diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/geo/MapGridLine.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/geo/MapGridLine.java index 1d1a7668..a3df4480 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/geo/MapGridLine.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/geo/MapGridLine.java @@ -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); diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/geo/MapPlot.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/geo/MapPlot.java index f50bb489..4c01acfc 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/geo/MapPlot.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/geo/MapPlot.java @@ -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; diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/MeshGraphic.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/MeshGraphic.java index ecdded23..a1f02265 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/MeshGraphic.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/graphic/MeshGraphic.java @@ -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()); + } + } + } } diff --git a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java index 251ba1ab..7a72144f 100644 --- a/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java +++ b/meteoinfo-chart/src/main/java/org/meteoinfo/chart/jogl/GLPlot.java @@ -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()) { diff --git a/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/graphic/Line2DGraphic.java b/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/graphic/Line2DGraphic.java index d7786177..55845bea 100644 --- a/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/graphic/Line2DGraphic.java +++ b/meteoinfo-geometry/src/main/java/org/meteoinfo/geometry/graphic/Line2DGraphic.java @@ -116,6 +116,33 @@ public class Line2DGraphic extends Graphic { this.legend = cbc; } + protected void updateShapeLegend(List cbs) { + List 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 diff --git a/meteoinfo-lab/milconfig.xml b/meteoinfo-lab/milconfig.xml index 5bed7b25..f273a89f 100644 --- a/meteoinfo-lab/milconfig.xml +++ b/meteoinfo-lab/milconfig.xml @@ -1,30 +1,32 @@ - - - - + - - - - - - + + + + + + + + + - + + - + + @@ -32,5 +34,5 @@
- + diff --git a/meteoinfo-lab/pylib/mipylib/geolib/__init__$py.class b/meteoinfo-lab/pylib/mipylib/geolib/__init__$py.class index 4cf9fd82..32efd12c 100644 Binary files a/meteoinfo-lab/pylib/mipylib/geolib/__init__$py.class and b/meteoinfo-lab/pylib/mipylib/geolib/__init__$py.class differ diff --git a/meteoinfo-lab/pylib/mipylib/geolib/__init__.py b/meteoinfo-lab/pylib/mipylib/geolib/__init__.py index b71fed9d..97ea4ee1 100644 --- a/meteoinfo-lab/pylib/mipylib/geolib/__init__.py +++ b/meteoinfo-lab/pylib/mipylib/geolib/__init__.py @@ -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__ diff --git a/meteoinfo-lab/pylib/mipylib/geolib/crs.py b/meteoinfo-lab/pylib/mipylib/geolib/crs.py new file mode 100644 index 00000000..61be1a25 --- /dev/null +++ b/meteoinfo-lab/pylib/mipylib/geolib/crs.py @@ -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) diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/_axes$py.class index 78f6f845..e0e0c770 100644 Binary files a/meteoinfo-lab/pylib/mipylib/plotlib/_axes$py.class and b/meteoinfo-lab/pylib/mipylib/plotlib/_axes$py.class differ diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes.py b/meteoinfo-lab/pylib/mipylib/plotlib/_axes.py index 2e7a4c91..7d81996c 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/_axes.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/_axes.py @@ -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) diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class index b3b1d641..eb917a4a 100644 Binary files a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class and b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl$py.class differ diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py index 82a9096c..a74c2ec6 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/_axes3dgl.py @@ -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 diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_mapaxes$py.class b/meteoinfo-lab/pylib/mipylib/plotlib/_mapaxes$py.class index 50e1fd80..d8f8f142 100644 Binary files a/meteoinfo-lab/pylib/mipylib/plotlib/_mapaxes$py.class and b/meteoinfo-lab/pylib/mipylib/plotlib/_mapaxes$py.class differ diff --git a/meteoinfo-lab/pylib/mipylib/plotlib/_mapaxes.py b/meteoinfo-lab/pylib/mipylib/plotlib/_mapaxes.py index 82085d98..a2f32045 100644 --- a/meteoinfo-lab/pylib/mipylib/plotlib/_mapaxes.py +++ b/meteoinfo-lab/pylib/mipylib/plotlib/_mapaxes.py @@ -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 diff --git a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayUtil.java b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayUtil.java index 03f5ea7a..c52083c2 100644 --- a/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayUtil.java +++ b/meteoinfo-ndarray/src/main/java/org/meteoinfo/ndarray/math/ArrayUtil.java @@ -1781,7 +1781,7 @@ public class ArrayUtil { sbuff.append(", "); } n += 1; - if (n > 200) { + if (n > 200 && ii.hasNext()) { sbuff.append("...]"); break; } diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionInfo.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionInfo.java index bc3ba80e..52a4ad67 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionInfo.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionInfo.java @@ -46,6 +46,34 @@ package org.meteoinfo.projection; protected float cutoff = Float.NaN; //Latitude cutoff - valiad for some speciafic projections // // + + /** + * 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; } diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionNames.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionNames.java index 93d29038..38f4de4f 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionNames.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionNames.java @@ -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"), diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionUtil.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionUtil.java index 86b162a0..ac46a4d2 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionUtil.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/ProjectionUtil.java @@ -195,6 +195,12 @@ public class ProjectionUtil { } } } + if (minY < -90) { + minY = -90; + } + if (maxY > 90) { + maxY = 90; + } Extent aExtent = new Extent(); aExtent.minX = minX; diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Airy.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Airy.java new file mode 100644 index 00000000..c9996e5a --- /dev/null +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Airy.java @@ -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 { + + // + // + // + /** + * Construction + * + * @param crs Coordinate reference system + */ + public Airy(CoordinateReferenceSystem crs) { + super(crs); + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Airy; + } + + // + // + + // +} diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Aitoff.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Aitoff.java new file mode 100644 index 00000000..78d78d6f --- /dev/null +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Aitoff.java @@ -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 { + + // + // + // + /** + * Construction + * + * @param crs Coordinate reference system + */ + public Aitoff(CoordinateReferenceSystem crs) { + super(crs); + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Aitoff; + } + + // + // + @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 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}; + } + // +} diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Albers.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Albers.java index e5aaadd7..2b8c9e06 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Albers.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Albers.java @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/August.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/August.java new file mode 100644 index 00000000..15edce51 --- /dev/null +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/August.java @@ -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 { + + // + // + // + /** + * Construction + * + * @param crs Coordinate reference system + */ + public August(CoordinateReferenceSystem crs) { + super(crs); + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.August; + } + + // + // + @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 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}; + } + // +} diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/AzimuthEquidistant.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/AzimuthEquidistant.java new file mode 100644 index 00000000..20ea666e --- /dev/null +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/AzimuthEquidistant.java @@ -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 { + + // + // + // + /** + * Construction + * + * @param crs Coordinate reference system + */ + public AzimuthEquidistant(CoordinateReferenceSystem crs) { + super(crs); + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Azimuthal_Equidistant; + } + + // + // + @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 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); + } + // +} diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Common.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Common.java index 6fd51a1c..6b5e0d63 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Common.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Common.java @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/EquidistantConic.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/EquidistantConic.java new file mode 100644 index 00000000..7ee6cf56 --- /dev/null +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/EquidistantConic.java @@ -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 { + + // + // + // + /** + * Construction + * + * @param crs Coordinate reference system + */ + public EquidistantConic(CoordinateReferenceSystem crs) { + super(crs); + } + + // + // + /** + * Get projection name + * + * @return Projection name + */ + @Override + public ProjectionNames getProjectionName() { + return ProjectionNames.Equidistant_Conic; + } + + // + // + @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 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); + } + // +} diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/GeostationarySatellite.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/GeostationarySatellite.java index 0ac6c2e0..8f68853d 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/GeostationarySatellite.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/GeostationarySatellite.java @@ -40,7 +40,7 @@ public class GeostationarySatellite extends ProjectionInfo { * @param crs Coordinate reference system */ public GeostationarySatellite(CoordinateReferenceSystem crs) { - this.crs = crs; + super(crs); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Hammer.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Hammer.java index d5fb8760..a3ed35a5 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Hammer.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Hammer.java @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertAzimuthalEqualArea.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertAzimuthalEqualArea.java index 4ba960e8..6ffe9b9c 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertAzimuthalEqualArea.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertAzimuthalEqualArea.java @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java index 96d36153..05c4ec70 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertConformalConic.java @@ -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(); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertEqualAreaConic.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertEqualAreaConic.java index f11523da..0957d875 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertEqualAreaConic.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/LambertEqualAreaConic.java @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Mercator.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Mercator.java index 841903d4..d25e93e2 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Mercator.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Mercator.java @@ -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(); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Molleweide.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Mollweide.java similarity index 96% rename from meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Molleweide.java rename to meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Mollweide.java index f27efd2c..4b78dba8 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Molleweide.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Mollweide.java @@ -32,7 +32,7 @@ import java.util.List; * * @author Yaqiang Wang */ -public class Molleweide extends ProjectionInfo { +public class Mollweide extends ProjectionInfo { // // @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/OrthographicAzimuthal.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/OrthographicAzimuthal.java index 479a0bdc..ec279f1b 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/OrthographicAzimuthal.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/OrthographicAzimuthal.java @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Robinson.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Robinson.java index 615f1556..b50db7fb 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Robinson.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Robinson.java @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Sinusoidal.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Sinusoidal.java index b6381c38..18b14936 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Sinusoidal.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Sinusoidal.java @@ -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); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/StereographicAzimuthal.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/StereographicAzimuthal.java index b5f5110e..5c92580a 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/StereographicAzimuthal.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/StereographicAzimuthal.java @@ -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(); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/TransverseMercator.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/TransverseMercator.java index a17672a0..67cf96a9 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/TransverseMercator.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/TransverseMercator.java @@ -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(); } // diff --git a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Wagner3.java b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Wagner3.java index 798360c9..8bd543d6 100644 --- a/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Wagner3.java +++ b/meteoinfo-projection/src/main/java/org/meteoinfo/projection/info/Wagner3.java @@ -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); } // @@ -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}; + } // }