Class MollweideProjection
- All Implemented Interfaces:
IMapProjection
Forward equations (Snyder)
Solve for the auxiliary angle θ using Newton-Raphson iteration:
2θ + sin(2θ) = π sin φ x = (2√2 / π) · (λ - λ₀) · cos θ y = √2 · sin θ
Inverse equations
θ = arcsin(y / √2) φ = arcsin((2θ + sin 2θ) / π) λ = λ₀ + π · x / (2√2 · cos θ)
Domain
The entire globe maps to an ellipse with semi-axes A = 2√2 (x) and B = √2 (y). Latitude is clamped to ±89.999° for numerical safety.
Seam handling
Like Mercator, the Mollweide projection has a seam at λ₀ ± π.
crossesSeam(double, double) is overridden to detect polygon edges that straddle
the seam so they can be split before rendering.
Default central meridian
The central longitude λ₀ defaults to -70° (western Atlantic). This
choice is intentional: it positions the Americas near the centre for an
aesthetically balanced view when the control panel occupies the right side
of the window. It can be changed via setCentralLongitude(double).
-
Constructor Summary
ConstructorsConstructorDescriptionMollweideProjection(MapTheme theme) Creates a Mollweide projection with the supplied theme and the default central meridian of -70°. -
Method Summary
Modifier and TypeMethodDescriptioncreateClipShape(IContainer container) Creates a clipShapein device coordinates that matches the projection's valid domain.booleancrossesSeam(double lon1, double lon2) Tests whether the segment between two longitudes crosses the projection seam (the anti-meridian relative to the central longitude).voiddrawLatitudeLine(Graphics2D g2, IContainer container, double latitude) Draws a line of constant latitude (a parallel) at the given latitude.voiddrawLongitudeLine(Graphics2D g2, IContainer container, double longitude) Draws a line of constant longitude (a meridian) at the given longitude.voiddrawMapOutline(Graphics2D g2, IContainer container) Draws the outer boundary of the projection domain.doubleReturns the central meridian λ₀ in radians.Returns theEProjectionenum constant that identifies this implementation, if this projection is one of MDI's built-in projections.getTheme()Returns theMapThemecurrently used by this projection for drawing outlines and graticule lines.Returns the bounding rectangle of the projection-space domain in world coordinates.booleanReports whether the projection's horizontal domain represents a complete, periodically wrapped 360-degree longitude range.booleanTests whether a projection-space point lies within the valid domain of this projection.booleanisPointVisible(Point2D.Double latLon) Tests whether a geographic location is visible in this projection.voidlatLonFromXY(Point2D.Double latLon, Point2D.Double xy) Inverse projection: projection-space (x, y) → geographic (λ, φ).voidlatLonToXY(Point2D.Double latLon, Point2D.Double xy) Forward projection: geographic (λ, φ) → projection-space (x, y).voidsetCentralLongitude(double centralLongitude) Sets the central meridian λ₀.voidSets theMapThemeused by this projection for all subsequent drawing operations.Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface edu.cnu.mdi.mapping.projection.IMapProjection
fillOcean, name, recenterOn, supportsRecenter, wrapLatitude, wrapLongitude
-
Constructor Details
-
MollweideProjection
Creates a Mollweide projection with the supplied theme and the default central meridian of -70°.- Parameters:
theme- the map theme; must not benull
-
-
Method Details
-
getCentralLongitude
public double getCentralLongitude()Returns the central meridian λ₀ in radians.- Returns:
- central longitude in radians
-
setCentralLongitude
public void setCentralLongitude(double centralLongitude) Sets the central meridian λ₀.The value is normalized to (-π, π] before storage.
- Parameters:
centralLongitude- desired central longitude in radians
-
crossesSeam
public boolean crossesSeam(double lon1, double lon2) Tests whether the segment between two longitudes crosses the projection seam (the anti-meridian relative to the central longitude).Global cylindrical projections such as
MercatorProjectionandMollweideProjectionoverride this method to detect wrap-around so that polygon edges that cross the seam can be split rather than drawn as a horizontal streak across the map.The default implementation returns
false, which is correct for hemispherical projections (OrthographicProjection,LambertEqualAreaProjection) where no seam split is needed.Returns
truewhen the two longitudes — each wrapped relative to λ₀ — differ by more than π radians, indicating an antimeridian crossing.- Specified by:
crossesSeamin interfaceIMapProjection- Parameters:
lon1- first longitude in radianslon2- second longitude in radians- Returns:
trueif the segment crosses the seam;falseotherwise
-
isLongitudePeriodic
public boolean isLongitudePeriodic()Reports whether the projection's horizontal domain represents a complete, periodically wrapped 360-degree longitude range.Adaptive graticule rendering uses this distinction when the entire projected width is visible. Sampling the two horizontal edges of such a projection produces the same seam longitude and can otherwise make half the world appear to be outside the visible longitude extent.
- Specified by:
isLongitudePeriodicin interfaceIMapProjection- Returns:
truefor full-width periodic projections such as Mercator and Mollweide; otherwisefalse
-
latLonToXY
Forward projection: geographic (λ, φ) → projection-space (x, y).Implementations should clamp the latitude to their valid range before computing to avoid
NaNorInfinityresults at the poles.For hemispherical projections (e.g. orthographic) a point on the far side of the globe should set
xyto(Double.NaN, Double.NaN)rather than throwing, because callers testisPointVisibleseparately.Latitude is clamped to [
MIN_LAT,MAX_LAT] before solving for θ. The relative longitude (λ - λ₀) is wrapped to [-π, π) to handle inputs that span the seam.- Specified by:
latLonToXYin interfaceIMapProjection- Parameters:
latLon- input geographic point in radians (x=λ, y=φ); must not benullxy- output projection-space point; must not benull
-
latLonFromXY
Inverse projection: projection-space (x, y) → geographic (λ, φ).If the input point lies outside the valid projection domain, implementations should set
latLonto(Double.NaN, Double.NaN)rather than throwing.- Specified by:
latLonFromXYin interfaceIMapProjection- Parameters:
latLon- output geographic point in radians (x=λ, y=φ); must not benullxy- input projection-space point; must not benull
-
isPointVisible
Tests whether a geographic location is visible in this projection.Global projections (Mercator, Mollweide, Lambert) generally return
truefor any point within their latitude range. Hemispherical projections (Orthographic) returntrueonly for points on the visible hemisphere.The entire globe maps to the Mollweide ellipse, so every point within the latitude range is visible.
- Specified by:
isPointVisiblein interfaceIMapProjection- Parameters:
latLon- geographic point in radians (x=λ, y=φ)- Returns:
trueif the point is visible;falseotherwise
-
isPointOnMap
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 Mollweide ellipse: x²/A² + y²/B² ≤ 1.
- Specified by:
isPointOnMapin interfaceIMapProjection- Parameters:
xy- projection-space point- Returns:
trueif the point is on (or inside) the map;falseotherwise
-
drawMapOutline
Draws the outer boundary of the projection domain.Typical implementations build a
Path2Din world coordinates, transform each vertex to screen space viacontainer.worldToLocal, then stroke the path using colors and widths from the currentMapTheme.Draws the Mollweide ellipse boundary (x²/A² + y²/B² = 1) using the theme's outline color and stroke width.
- Specified by:
drawMapOutlinein interfaceIMapProjection- Parameters:
g2- graphics context to draw intocontainer- container providing the world-to-local transform
-
drawLatitudeLine
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
Draws a horizontal line across the map at the given latitude. The line is clipped to the Mollweide ellipse boundary, so it may be shorter than the full width of the map if the latitude is near the poles. UsesMapTheme.getGraticuleColor()so that theme switching takes full effect.MapTheme.getGraticuleColor()so the color respects theme switching.- Specified by:
drawLatitudeLinein interfaceIMapProjection- Parameters:
g2- graphics contextcontainer- container providing the world-to-local transformlatitude- latitude φ in radians, typically in [-π/2, π/2]
-
drawLongitudeLine
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 360 evenly spaced latitudes at the given longitude and connects the projected screen points. Uses
MapTheme.getGraticuleColor()so the color respects theme switching.- Specified by:
drawLongitudeLinein interfaceIMapProjection- Parameters:
g2- graphics contextcontainer- container providing the world-to-local transformlongitude- longitude λ in radians, typically in [-π, π]
-
getProjection
Returns theEProjectionenum 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 modifyingEProjection,ProjectionFactory, or other MDI built-in projection registries.- Specified by:
getProjectionin interfaceIMapProjection- Returns:
- the built-in projection type, or
nullfor a custom application-supplied projection
-
getXYBounds
Returns the bounding rectangle of the projection-space domain in world coordinates.This rectangle is used by
IContainerimplementations 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 rectangle of the Mollweide ellipse: [-A, -B] to [A, B], i.e.
[-2√2, -√2] to [2√2, √2].- Specified by:
getXYBoundsin interfaceIMapProjection- Returns:
- bounding rectangle in projection space; never
null
-
getTheme
Returns theMapThemecurrently used by this projection for drawing outlines and graticule lines.Implementations must never return
nullonce the theme has been set.- Specified by:
getThemein interfaceIMapProjection- Returns:
- the active map theme
-
setTheme
Sets theMapThemeused by this projection for all subsequent drawing operations.- Specified by:
setThemein interfaceIMapProjection- Parameters:
theme- the new theme; must not benull- Throws:
IllegalArgumentException- ifthemeisnull
-
createClipShape
Creates a clipShapein device coordinates that matches the projection's valid domain.This shape is used to:
- Clip land/ocean rendering to the map region.
- Fill the ocean background via
IMapProjection.fillOcean(java.awt.Graphics2D, edu.cnu.mdi.container.IContainer).
Returns an elliptical path in device coordinates that matches the Mollweide boundary, used as a clip region for ocean fill and land rendering.
- Specified by:
createClipShapein interfaceIMapProjection- Parameters:
container- container providing the world-to-local transform- Returns:
- a device-space
Shape, ornullif no clip is defined for this projection
-