Class MapGraphics

java.lang.Object
edu.cnu.mdi.mapping.graphics.MapGraphics

public final class MapGraphics extends Object
Static utility methods for drawing and geometry operations on geographic data in the MDI mapping subsystem.

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:

  1. Great-circle interpolation between consecutive geographic vertices.
  2. Forward projection from geographic coordinates (longitude, latitude) to projection-space (x, y) coordinates via IMapProjection.
  3. Seam-aware splitting of projected paths so that segments crossing a longitude wrap boundary are not drawn as spurious streaks across the full map.
  4. Conversion from projection-space coordinates to device pixels through the owning MapContainer.

Coordinate conventions

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.

  • Field Details

    • DEFAULT_MAX_GREAT_CIRCLE_STEP_DEG

      public static final double DEFAULT_MAX_GREAT_CIRCLE_STEP_DEG
      Default 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_WIDTH
      Minimum 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 context
      container - the map container that owns the projection and supplies the world-to-device transform
      ll0 - first endpoint in radians (x=λ, y=φ)
      ll1 - second endpoint in radians (x=λ, y=φ)
      lineColor - the line color; null suppresses drawing
      lineWidth - the line width in pixels
      lineStyle - the line dash style; if null, LineStyle.SOLID is 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 context
      container - the owning map container
      latLonPoints - geographic vertices in radians; at least two points are required
      lineColor - the line color; null suppresses drawing
      lineWidth - the line width in pixels
      lineStyle - the line dash style; if null, LineStyle.SOLID is 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 context
      container - the owning map container
      latLonPoints - geographic polygon vertices in radians; at least three points are required
      fillColor - the fill color; null suppresses fill
      lineColor - the outline color; null suppresses outline
      lineWidth - the outline width in pixels
      lineStyle - the outline dash style; if null, LineStyle.SOLID is 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 an IStyled source.
      Parameters:
      g2 - the graphics context
      container - the owning map container
      latLonPoints - geographic vertices in radians
      style - the style source; must not be null
    • drawMapPolygon

      public static void drawMapPolygon(Graphics2D g2, MapContainer container, Point2D.Double[] latLonPoints, IStyled style)
      Draws a great-circle map polygon using style parameters from an IStyled source.
      Parameters:
      g2 - the graphics context
      container - the owning map container
      latLonPoints - geographic polygon vertices in radians
      style - the style source; must not be null
    • 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 container
      latLonPoints - 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 container
      latLonPoints - 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 container
      latLonPoints - geographic vertices in radians
      maxStepDeg - maximum angular sampling step in degrees along each great-circle segment; values less than or equal to zero are replaced by DEFAULT_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 container
      latLonPoints - geographic polygon vertices in radians
      maxStepDeg - maximum angular sampling step in degrees along each great-circle segment; values less than or equal to zero are replaced by DEFAULT_MAX_GREAT_CIRCLE_STEP_DEG
      Returns:
      a seam-split projected shape; never null
    • getBounds

      public static Rectangle getBounds(MapGraphics.ProjectedMapShape shape)
      Returns the pixel bounds of a projected map shape.
      Parameters:
      shape - the projected map shape; may be null
      Returns:
      the union of all path bounds, or an empty rectangle if the shape is null or empty
    • contains

      public static boolean contains(MapGraphics.ProjectedMapShape shape, Point p)
      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 shape
      p - the test point in device coordinates
      Returns:
      true if any closed subpath contains the point; false otherwise
    • isPointNear

      public static boolean isPointNear(MapGraphics.ProjectedMapShape shape, Point p, double tolPix)
      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 shape
      p - the test point in device coordinates
      tolPix - the tolerance in pixels; values less than zero are treated as zero
      Returns:
      true if the point is within tolPix of any segment; false otherwise
    • normalizeLatLon

      public static Point2D.Double normalizeLatLon(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].
      Parameters:
      projection - the active map projection; must not be null
      latLon - the geographic point in radians; must not be null The x coordinate is interpreted as longitude and the y coordinate as latitude.
      Returns:
      a normalized copy of the input point
    • greatCircleLength

      public static double greatCircleLength(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.

      The input points use the standard MDI geographic convention: x = longitude and y = latitude, both in radians. The returned value is also in radians. On a sphere of radius R, the physical arc length is therefore R * greatCircleLength(...).

      The computation uses the spherical law of cosines in a numerically safe form by clamping the cosine argument to [-1, 1] before calling Math.acos(double).

      Parameters:
      startLatLon - the start geographic point in radians (x = longitude, y = latitude); must not be null
      endLatLon - the end geographic point in radians (x = longitude, y = latitude); must not be null
      Returns:
      the shorter great-circle arc length in radians on the unit sphere, in the range [0, π]
      Throws:
      IllegalArgumentException - if either argument is null
    • greatCircleAzimuth

      public static double greatCircleAzimuth(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.

      The input points use the standard MDI geographic convention: x = longitude and y = latitude, both in radians. The returned azimuth is also in radians and uses the navigation convention:

      • 0 = north
      • π/2 = east
      • π = south
      • 3π/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 be null
      endLatLon - the end geographic point in radians (x = longitude, y = latitude); must not be null
      Returns:
      the initial great-circle azimuth in radians, normalized to [0, 2π), or Double.NaN if the two points are coincident
      Throws:
      IllegalArgumentException - if either argument is null
    • 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 = longitude and y = latitude, both in radians. The azimuth is also in radians and uses the navigation convention:

      • 0 = north
      • π/2 = east
      • π = south
      • 3π/2 = west

      The normalizedLength parameter is the angular arc length on the unit sphere, in radians. Thus:

      • 0 returns the start point
      • π/2 is 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 be null
      azimuth - the initial azimuth in radians, using the navigation convention
      normalizedLength - the angular arc length on the unit sphere in radians
      Returns:
      the endpoint geographic point in radians (x = longitude, y = latitude)
      Throws:
      IllegalArgumentException - if startPoint is null
    • 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 context
      container - the owning map container
      latitude - the latitude in radians at which to draw the line
      centralLon - the central longitude in radians used to determine the left and right edges of the map; typically this is the current projection center longitude
      theme - the map theme providing styling information; must not be null
    • 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 context
      container - the owning map container
      longitude - the longitude in radians at which to draw the line
      theme - the map theme providing styling information; must not be null