Class LambertEqualAreaProjection

java.lang.Object
edu.cnu.mdi.mapping.projection.LambertEqualAreaProjection
All Implemented Interfaces:
IMapProjection

public class LambertEqualAreaProjection extends Object implements IMapProjection
Lambert azimuthal equal-area projection (spherical Earth, R = 1).

Forward equations (Snyder, spherical form)

   k = √(2 / (1 + sin φ₀ sin φ + cos φ₀ cos φ cos(λ - λ₀)))

   x = k · cos φ · sin(λ - λ₀)
   y = k · (cos φ₀ · sin φ − sin φ₀ · cos φ · cos(λ - λ₀))
 

Inverse equations

   ρ = √(x² + y²),   c = 2 arcsin(ρ / 2)

   φ = arcsin(cos c · sin φ₀ + (y · sin c · cos φ₀) / ρ)
   λ = λ₀ + atan2(x · sin c, ρ · cos φ₀ · cos c − y · sin φ₀ · sin c)
 

Domain

The entire sphere maps to a disk of radius 2 (for R = 1). The antipode of the center point maps to the outer boundary circle. The bounding box is [-2, -2] to [2, 2].

Antipode singularity

When the denominator 1 + cos γ approaches zero, the input point is at or extremely close to the antipode of the projection center. The antipode is not represented by one unique point in the projected disk; the limiting point on the boundary depends on the direction of approach. This implementation therefore returns NaN for the exact singular point, and drawing routines break the polyline at that location.

No seam

The Lambert projection has no antimeridian seam because the mapping from globe to disk is continuous. The default IMapProjection.crossesSeam(double, double) returning false is correct for this class.

  • Constructor Details

    • LambertEqualAreaProjection

      public LambertEqualAreaProjection(double centerLon, double centerLat)
      Creates a Lambert equal-area projection centered at the given geographic point. The MapTheme must be set via setTheme(MapTheme) before any drawing methods are called, or use the three-argument constructor to set it atomically.
      Parameters:
      centerLon - central longitude λ₀ in radians
      centerLat - central latitude φ₀ in radians
    • LambertEqualAreaProjection

      public LambertEqualAreaProjection()
      Convenience constructor centered at (0°, 0°). The theme must still be set before drawing.
    • LambertEqualAreaProjection

      public LambertEqualAreaProjection(double centerLon, double centerLat, MapTheme theme)
      Convenience constructor that sets both the center and the theme atomically, preventing the NullPointerException that arises when drawing methods are called before the theme is set.
      Parameters:
      centerLon - central longitude λ₀ in radians
      centerLat - central latitude φ₀ in radians
      theme - map theme; must not be null
    • LambertEqualAreaProjection

      public LambertEqualAreaProjection(MapTheme theme)
      Convenience constructor centered at (0°, 0°) with the given theme.
      Parameters:
      theme - map theme; must not be null
  • Method Details

    • setCenter

      public void setCenter(double centerLon, double centerLat)
      Changes the center of the projection. The next repaint will show the globe centred on the new point.
      Parameters:
      centerLon - central longitude λ₀ in radians
      centerLat - central latitude φ₀ in radians
    • latLonToXY

      public void latLonToXY(Point2D.Double latLon, Point2D.Double xy)
      Forward projection: geographic (λ, φ) → projection-space (x, y).

      Implementations should clamp the latitude to their valid range before computing to avoid NaN or Infinity results at the poles.

      For hemispherical projections (e.g. orthographic) a point on the far side of the globe should set xy to (Double.NaN, Double.NaN) rather than throwing, because callers test isPointVisible separately.

      Latitude is clamped to [MIN_LAT, MAX_LAT] before projection. When the input point is the antipode of the center (the denominator 1 + cos γ ≈ 0, tested as denom <= 1e-15), both output coordinates are set to Double.NaN rather than a boundary point, since the true projected location is undefined at that singularity.

      Specified by:
      latLonToXY in interface IMapProjection
      Parameters:
      latLon - input geographic point in radians (x=λ, y=φ); must not be null
      xy - output projection-space point; must not be null
    • latLonFromXY

      public void latLonFromXY(Point2D.Double latLon, Point2D.Double xy)
      Inverse projection: projection-space (x, y) → geographic (λ, φ).

      If the input point lies outside the valid projection domain, implementations should set latLon to (Double.NaN, Double.NaN) rather than throwing.

      Specified by:
      latLonFromXY in interface IMapProjection
      Parameters:
      latLon - output geographic point in radians (x=λ, y=φ); must not be null
      xy - input projection-space point; must not be null
    • isPointVisible

      public boolean isPointVisible(Point2D.Double latLon)
      Tests whether a geographic location is visible in this projection.

      Global projections (Mercator, Mollweide, Lambert) generally return true for any point within their latitude range. Hemispherical projections (Orthographic) return true only for points on the visible hemisphere.

      The Lambert projection maps the entire globe, so every point in the valid latitude range is visible.

      Specified by:
      isPointVisible in interface IMapProjection
      Parameters:
      latLon - geographic point in radians (x=λ, y=φ)
      Returns:
      true if the point is visible; false otherwise
    • isPointOnMap

      public boolean isPointOnMap(Point2D.Double xy)
      Tests whether a projection-space point lies within the valid domain of this projection.

      This is used after IMapProjection.latLonToXY(java.awt.geom.Point2D.Double, java.awt.geom.Point2D.Double) to guard against rendering points that fall slightly outside the projection boundary due to floating-point rounding.

      A point is on the map when it lies within or on the boundary of the disk: x² + y² ≤ RHO_MAX².

      Specified by:
      isPointOnMap in interface IMapProjection
      Parameters:
      xy - projection-space point
      Returns:
      true if the point is on (or inside) the map; false otherwise
    • drawMapOutline

      public void drawMapOutline(Graphics2D g2, IContainer container)
      Draws the outer boundary of the projection domain.

      Typical implementations build a Path2D in world coordinates, transform each vertex to screen space via container.worldToLocal, then stroke the path using colors and widths from the current MapTheme.

      Draws the circular boundary of the projection disk (radius RHO_MAX = 2) using the theme's outline color and stroke width.

      Specified by:
      drawMapOutline in interface IMapProjection
      Parameters:
      g2 - graphics context to draw into
      container - container providing the world-to-local transform
    • drawLatitudeLine

      public void drawLatitudeLine(Graphics2D g2, IContainer container, double latitude)
      Draws a line of constant latitude (a parallel) at the given latitude.

      Implementations should approximate the curve by sampling at a sufficient number of longitude values, projecting each sample, and connecting the resulting screen points with a polyline. The line color must be MapTheme.getGraticuleColor() so that theme switching takes full effect.

      Samples 360 evenly-spaced longitudes at the given latitude and connects the projected screen points. NaN results (e.g. near the antipode boundary) are skipped. Uses MapTheme.getGraticuleColor() so the line color reflects the active theme.

      Specified by:
      drawLatitudeLine in interface IMapProjection
      Parameters:
      g2 - graphics context
      container - container providing the world-to-local transform
      latitude - latitude φ in radians, typically in [-π/2, π/2]
    • drawLongitudeLine

      public void drawLongitudeLine(Graphics2D g2, IContainer container, double longitude)
      Draws a line of constant longitude (a meridian) at the given longitude.

      Implementations should approximate the curve by sampling at a sufficient number of latitude values, projecting each sample, and connecting the resulting screen points with a polyline. The line color must be MapTheme.getGraticuleColor() so that theme switching takes full effect.

      Samples 180 evenly-spaced latitudes at the given longitude and connects the projected screen points. Uses MapTheme.getGraticuleColor() for the line color.

      Specified by:
      drawLongitudeLine in interface IMapProjection
      Parameters:
      g2 - graphics context
      container - container providing the world-to-local transform
      longitude - longitude λ in radians, typically in [-π, π]
    • getProjection

      public EProjection getProjection()
      Returns the EProjection enum constant that identifies this implementation, if this projection is one of MDI's built-in projections.

      Application-supplied projections are allowed to return null. This permits an application to provide a projection without modifying EProjection, ProjectionFactory, or other MDI built-in projection registries.

      Specified by:
      getProjection in interface IMapProjection
      Returns:
      the built-in projection type, or null for a custom application-supplied projection
    • getXYBounds

      public Rectangle2D.Double getXYBounds()
      Returns the bounding rectangle of the projection-space domain in world coordinates.

      This rectangle is used by IContainer implementations to build the initial world-to-screen transform. The returned rectangle should tightly enclose the entire valid projected domain (e.g. [-π, π] × [MIN_Y, MAX_Y] for Mercator).

      Returns the bounding square of the disk: [-RHO_MAX, -RHO_MAX] to [RHO_MAX, RHO_MAX], i.e. [-2, -2] to [2, 2] for a unit sphere.

      Specified by:
      getXYBounds in interface IMapProjection
      Returns:
      bounding rectangle in projection space; never null
    • getTheme

      public MapTheme getTheme()
      Returns the MapTheme currently used by this projection for drawing outlines and graticule lines.

      Implementations must never return null once the theme has been set.

      Specified by:
      getTheme in interface IMapProjection
      Returns:
      the active map theme
    • setTheme

      public void setTheme(MapTheme theme)
      Sets the MapTheme used by this projection for all subsequent drawing operations.
      Specified by:
      setTheme in interface IMapProjection
      Parameters:
      theme - the new theme; must not be null
      Throws:
      IllegalArgumentException - if theme is null
    • createClipShape

      public Shape createClipShape(IContainer container)
      Creates a clip Shape in device coordinates that matches the projection's valid domain.

      This shape is used to:

      Returns a circular path in device coordinates matching the disk boundary (radius RHO_MAX), used as a clip region for ocean fill and land rendering.

      Specified by:
      createClipShape in interface IMapProjection
      Parameters:
      container - container providing the world-to-local transform
      Returns:
      a device-space Shape, or null if no clip is defined for this projection