Class MapGraphics
Purpose
This class is the geographic analogue of
edu.cnu.mdi.graphics.world.WorldGraphicsUtils. Whereas the world
graphics utilities assume the input vertices are already expressed in the
container's world coordinate system, MapGraphics accepts vertices in
geographic coordinates and handles the additional steps needed for map-aware
rendering:
- Great-circle interpolation between consecutive geographic vertices.
- Forward projection from geographic coordinates (longitude, latitude) to
projection-space (x, y) coordinates via
IMapProjection. - Seam-aware splitting of projected paths so that segments crossing a longitude wrap boundary are not drawn as spurious streaks across the full map.
- Conversion from projection-space coordinates to device pixels through the
owning
MapContainer.
Coordinate conventions
- All geographic coordinates are in radians.
- A geographic point is represented by a
Point2D.Doublewithx = λ(longitude) andy = φ(latitude). - Projected coordinates are ordinary map projection coordinates in the
IMapProjectionXY plane, not device pixels. - Device pixels are produced only at the final rendering stage via
BaseContainer.worldToLocal(java.awt.Point, java.awt.geom.Point2D.Double).
Seam handling
Global projections with longitude wrapping, such as Mercator and Mollweide,
may split a single geographic polyline or polygon into multiple projected
subpaths. The decision is delegated to
IMapProjection.crossesSeam(double, double). When a seam crossing is
detected, the current subpath is terminated and a new subpath is started.
For closed polygons, seam crossings are refined by bisection along the great-circle edge. Each resulting fragment therefore reaches the appropriate map boundary before it is closed. Open polylines are simply split at the sampled crossing because they do not require a filled boundary.
Typical use
Point2D.Double[] latLon = ...; // radians, x=lon, y=lat
MapGraphics.drawMapPolygon(g2, mapContainer, latLon,
new Color(255, 200, 0, 80), Color.ORANGE, 1.5f, LineStyle.SOLID);
Intended scope
This class is designed as the low-level rendering and geometry engine for
future map-native items such as MapPolylineItem and
MapPolygonItem. Those items can store their vertices in geographic
coordinates and delegate projection, seam handling, bounds, and hit testing
to this utility.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classImmutable representation of a projected map shape that may consist of multiple subpaths. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final doubleDefault maximum angular step, in degrees, used when approximating a great-circle segment by sampled intermediate points.static final floatMinimum allowed line width in device pixels. -
Method Summary
Modifier and TypeMethodDescriptionbuildProjectedPolygon(MapContainer container, Point2D.Double[] latLonPoints) Builds a seam-aware projected polygon from geographic vertices using the default great-circle sampling step.buildProjectedPolygon(MapContainer container, Point2D.Double[] latLonPoints, double maxStepDeg) Builds a seam-aware projected polygon from geographic vertices.buildProjectedPolyline(MapContainer container, Point2D.Double[] latLonPoints) Builds a seam-aware projected polyline from geographic vertices using the default great-circle sampling step.buildProjectedPolyline(MapContainer container, Point2D.Double[] latLonPoints, double maxStepDeg) Builds a seam-aware projected polyline from geographic vertices.static booleancontains(MapGraphics.ProjectedMapShape shape, Point p) Tests whether a device-space point lies inside any closed projected subpath of a map shape.static voiddrawHorizontalLatitudeLine(Graphics2D g2, IContainer container, IMapProjection projection, double latitude, double centralLon, MapTheme theme) Draws a horizontal latitude line across the map at a specified latitude.static voiddrawMapLine(Graphics2D g2, MapContainer container, Point2D.Double ll0, Point2D.Double ll1, Color lineColor, float lineWidth, LineStyle lineStyle) Draws a single great-circle map segment between two geographic endpoints.static voiddrawMapPolygon(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, IStyled style) Draws a great-circle map polygon using style parameters from anIStyledsource.static voiddrawMapPolygon(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, Color fillColor, Color lineColor, float lineWidth, LineStyle lineStyle) Draws a great-circle map polygon from a geographic vertex array.static voiddrawMapPolyline(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, IStyled style) Draws a great-circle map polyline using style parameters from anIStyledsource.static voiddrawMapPolyline(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, Color lineColor, float lineWidth, LineStyle lineStyle) Draws a great-circle map polyline from a geographic vertex array.static voiddrawVerticalLongitudeLine(Graphics2D g2, IContainer container, IMapProjection projection, double longitude, MapTheme theme) Draws a vertical longitude line across the map at a specified longitude.static RectangleReturns the pixel bounds of a projected map shape.static doublegreatCircleAzimuth(Point2D.Double startLatLon, Point2D.Double endLatLon) Computes the initial great-circle azimuth (bearing) from a start geographic point to an end geographic point on the unit sphere.static Point2D.DoublegreatCircleEndPoint(Point2D.Double startPoint, double azimuth, double normalizedLength) Computes the endpoint of a great-circle path on the unit sphere from a start geographic point, an initial azimuth, and a normalized arc length.static doublegreatCircleLength(Point2D.Double startLatLon, Point2D.Double endLatLon) Computes the central-angle length of the shorter great-circle arc between two geographic points on the unit sphere.static booleanisPointNear(MapGraphics.ProjectedMapShape shape, Point p, double tolPix) Tests whether a device-space point lies within a specified tolerance of any projected path segment.static Point2D.DoublenormalizeLatLon(IMapProjection projection, Point2D.Double latLon) Normalizes a geographic point by wrapping its longitude to the projection's canonical range and clamping latitude to [-π/2, π/2].
-
Field Details
-
DEFAULT_MAX_GREAT_CIRCLE_STEP_DEG
public static final double DEFAULT_MAX_GREAT_CIRCLE_STEP_DEGDefault maximum angular step, in degrees, used when approximating a great-circle segment by sampled intermediate points.Smaller values produce smoother curves and more accurate seam placement at the cost of more projected vertices.
- See Also:
-
MIN_LINE_WIDTH
public static final float MIN_LINE_WIDTHMinimum allowed line width in device pixels.This prevents zero-width lines from disappearing completely.
- See Also:
-
-
Method Details
-
drawMapLine
public static void drawMapLine(Graphics2D g2, MapContainer container, Point2D.Double ll0, Point2D.Double ll1, Color lineColor, float lineWidth, LineStyle lineStyle) Draws a single great-circle map segment between two geographic endpoints.- Parameters:
g2- the graphics contextcontainer- the map container that owns the projection and supplies the world-to-device transformll0- first endpoint in radians (x=λ, y=φ)ll1- second endpoint in radians (x=λ, y=φ)lineColor- the line color;nullsuppresses drawinglineWidth- the line width in pixelslineStyle- the line dash style; ifnull,LineStyle.SOLIDis used
-
drawMapPolyline
public static void drawMapPolyline(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, Color lineColor, float lineWidth, LineStyle lineStyle) Draws a great-circle map polyline from a geographic vertex array.- Parameters:
g2- the graphics contextcontainer- the owning map containerlatLonPoints- geographic vertices in radians; at least two points are requiredlineColor- the line color;nullsuppresses drawinglineWidth- the line width in pixelslineStyle- the line dash style; ifnull,LineStyle.SOLIDis used
-
drawMapPolygon
public static void drawMapPolygon(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, Color fillColor, Color lineColor, float lineWidth, LineStyle lineStyle) Draws a great-circle map polygon from a geographic vertex array.The polygon is automatically closed by connecting the last vertex back to the first using a great-circle segment.
- Parameters:
g2- the graphics contextcontainer- the owning map containerlatLonPoints- geographic polygon vertices in radians; at least three points are requiredfillColor- the fill color;nullsuppresses filllineColor- the outline color;nullsuppresses outlinelineWidth- the outline width in pixelslineStyle- the outline dash style; ifnull,LineStyle.SOLIDis used
-
drawMapPolyline
public static void drawMapPolyline(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, IStyled style) Draws a great-circle map polyline using style parameters from anIStyledsource.- Parameters:
g2- the graphics contextcontainer- the owning map containerlatLonPoints- geographic vertices in radiansstyle- the style source; must not benull
-
drawMapPolygon
public static void drawMapPolygon(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, IStyled style) Draws a great-circle map polygon using style parameters from anIStyledsource.- Parameters:
g2- the graphics contextcontainer- the owning map containerlatLonPoints- geographic polygon vertices in radiansstyle- the style source; must not benull
-
buildProjectedPolyline
public static MapGraphics.ProjectedMapShape buildProjectedPolyline(MapContainer container, Point2D.Double[] latLonPoints) Builds a seam-aware projected polyline from geographic vertices using the default great-circle sampling step.- Parameters:
container- the owning map containerlatLonPoints- geographic vertices in radians- Returns:
- a seam-split projected shape; never
null
-
buildProjectedPolygon
public static MapGraphics.ProjectedMapShape buildProjectedPolygon(MapContainer container, Point2D.Double[] latLonPoints) Builds a seam-aware projected polygon from geographic vertices using the default great-circle sampling step.- Parameters:
container- the owning map containerlatLonPoints- geographic polygon vertices in radians- Returns:
- a seam-split projected shape; never
null
-
buildProjectedPolyline
public static MapGraphics.ProjectedMapShape buildProjectedPolyline(MapContainer container, Point2D.Double[] latLonPoints, double maxStepDeg) Builds a seam-aware projected polyline from geographic vertices.- Parameters:
container- the owning map containerlatLonPoints- geographic vertices in radiansmaxStepDeg- maximum angular sampling step in degrees along each great-circle segment; values less than or equal to zero are replaced byDEFAULT_MAX_GREAT_CIRCLE_STEP_DEG- Returns:
- a seam-split projected shape; never
null
-
buildProjectedPolygon
public static MapGraphics.ProjectedMapShape buildProjectedPolygon(MapContainer container, Point2D.Double[] latLonPoints, double maxStepDeg) Builds a seam-aware projected polygon from geographic vertices.- Parameters:
container- the owning map containerlatLonPoints- geographic polygon vertices in radiansmaxStepDeg- maximum angular sampling step in degrees along each great-circle segment; values less than or equal to zero are replaced byDEFAULT_MAX_GREAT_CIRCLE_STEP_DEG- Returns:
- a seam-split projected shape; never
null
-
getBounds
Returns the pixel bounds of a projected map shape.- Parameters:
shape- the projected map shape; may benull- Returns:
- the union of all path bounds, or an empty rectangle if the shape is
nullor empty
-
contains
Tests whether a device-space point lies inside any closed projected subpath of a map shape.This method is intended for filled polygons, not open polylines.
- Parameters:
shape- the projected map shapep- the test point in device coordinates- Returns:
trueif any closed subpath contains the point;falseotherwise
-
isPointNear
Tests whether a device-space point lies within a specified tolerance of any projected path segment.This method is useful for hit testing open polylines and polygon outlines.
- Parameters:
shape- the projected map shapep- the test point in device coordinatestolPix- the tolerance in pixels; values less than zero are treated as zero- Returns:
trueif the point is withintolPixof any segment;falseotherwise
-
normalizeLatLon
Normalizes a geographic point by wrapping its longitude to the projection's canonical range and clamping latitude to [-π/2, π/2].- Parameters:
projection- the active map projection; must not benulllatLon- the geographic point in radians; must not benullThe x coordinate is interpreted as longitude and the y coordinate as latitude.- Returns:
- a normalized copy of the input point
-
greatCircleLength
Computes the central-angle length of the shorter great-circle arc between two geographic points on the unit sphere.The input points use the standard MDI geographic convention:
x = longitudeandy = latitude, both in radians. The returned value is also in radians. On a sphere of radiusR, the physical arc length is thereforeR * greatCircleLength(...).The computation uses the spherical law of cosines in a numerically safe form by clamping the cosine argument to
[-1, 1]before callingMath.acos(double).- Parameters:
startLatLon- the start geographic point in radians (x = longitude, y = latitude); must not benullendLatLon- the end geographic point in radians (x = longitude, y = latitude); must not benull- Returns:
- the shorter great-circle arc length in radians on the unit sphere, in
the range
[0, π] - Throws:
IllegalArgumentException- if either argument isnull
-
greatCircleAzimuth
Computes the initial great-circle azimuth (bearing) from a start geographic point to an end geographic point on the unit sphere.The input points use the standard MDI geographic convention:
x = longitudeandy = latitude, both in radians. The returned azimuth is also in radians and uses the navigation convention:0= northπ/2= eastπ= south3π/2= west
The value is normalized to the half-open range
[0, 2π). This is the initial azimuth at the start point. Along a great-circle path the local heading generally changes continuously, so the azimuth at the end point will usually be different.If the two points are coincident, the azimuth is undefined. In that degenerate case this method returns
Double.NaN.- Parameters:
startLatLon- the start geographic point in radians (x = longitude, y = latitude); must not benullendLatLon- the end geographic point in radians (x = longitude, y = latitude); must not benull- Returns:
- the initial great-circle azimuth in radians, normalized to
[0, 2π), orDouble.NaNif the two points are coincident - Throws:
IllegalArgumentException- if either argument isnull
-
greatCircleEndPoint
public static Point2D.Double greatCircleEndPoint(Point2D.Double startPoint, double azimuth, double normalizedLength) Computes the endpoint of a great-circle path on the unit sphere from a start geographic point, an initial azimuth, and a normalized arc length.The input start point uses the standard MDI geographic convention:
x = longitudeandy = latitude, both in radians. The azimuth is also in radians and uses the navigation convention:0= northπ/2= eastπ= south3π/2= west
The
normalizedLengthparameter is the angular arc length on the unit sphere, in radians. Thus:0returns the start pointπ/2is a quarter great circleπreaches the antipode
The returned longitude is wrapped to
(-π, π]using the same canonical convention used elsewhere in the mapping subsystem. The returned latitude is naturally in[-π/2, π/2].- Parameters:
startPoint- the start geographic point in radians (x = longitude, y = latitude); must not benullazimuth- the initial azimuth in radians, using the navigation conventionnormalizedLength- the angular arc length on the unit sphere in radians- Returns:
- the endpoint geographic point in radians
(
x = longitude, y = latitude) - Throws:
IllegalArgumentException- ifstartPointisnull
-
drawHorizontalLatitudeLine
public static void drawHorizontalLatitudeLine(Graphics2D g2, IContainer container, IMapProjection projection, double latitude, double centralLon, MapTheme theme) Draws a horizontal latitude line across the map at a specified latitude.The line is drawn as a single straight segment between the left and right edges of the map, which is appropriate for projections with parallels are straight horizontal lines (e.g., cylindrical projections).
- Parameters:
g2- the graphics contextcontainer- the owning map containerlatitude- the latitude in radians at which to draw the linecentralLon- the central longitude in radians used to determine the left and right edges of the map; typically this is the current projection center longitudetheme- the map theme providing styling information; must not benull
-
drawVerticalLongitudeLine
public static void drawVerticalLongitudeLine(Graphics2D g2, IContainer container, IMapProjection projection, double longitude, MapTheme theme) Draws a vertical longitude line across the map at a specified longitude.The line is drawn as a single straight segment between the top and bottom edges of the map, which is appropriate for projections with meridians are straight vertical lines (e.g., cylindrical projections).
- Parameters:
g2- the graphics contextcontainer- the owning map containerlongitude- the longitude in radians at which to draw the linetheme- the map theme providing styling information; must not benull
-