Class MapGridPaintable

  • All Implemented Interfaces:
    MapViewPaintable, PreferenceChangedListener, Destroyable

    public class MapGridPaintable
    extends AbstractMapViewPaintable
    implements PreferenceChangedListener, Destroyable
    A grid drawn over the whole map view, on top of all layers.

    The grid is a pure visual aid (there is no snapping to it). It is either aligned to latitude/longitude, with a spacing in degrees, or to the projected coordinates, with a spacing in metres (true distance, measured at the grid origin), an optional rotation and an origin offset. When the grid cells would become smaller than a minimal size on screen, the spacing is multiplied by 10 until the cells are large enough, so the grid stays readable at every zoom level while remaining aligned to the configured one.

    All settings are preferences (prefix draw.grid.), see GridPreference.

    An instance registers itself as a preference listener, so destroy() must be called when it is no longer used (MapFrame does this), otherwise the listener is leaked.

    Since:
    19640
    • Constructor Detail

      • MapGridPaintable

        public MapGridPaintable()
        Constructs a new MapGridPaintable.
    • Method Detail

      • paint

        public void paint​(java.awt.Graphics2D g,
                          MapView mv,
                          Bounds bbox)
        Description copied from interface: MapViewPaintable
        Paint the dataset using the engine set.
        Specified by:
        paint in interface MapViewPaintable
        Parameters:
        g - Graphics
        mv - The object that can translate GeoPoints to screen coordinates.
        bbox - Bounding box
      • getVisibleLatLonBounds

        static Bounds getVisibleLatLonBounds​(MapView mv)
        Computes the latitude/longitude bounds of the part of the world which is visible in the given view.

        Contrary to NavigatableComponent.getRealBounds() this does not simply convert the corners of the view: as soon as the view is larger than the world, those lie outside the world and their longitude wraps around, which yields a range much narrower than what is really visible (and one which jumps around while zooming or panning). The view is therefore first clipped to the world in projected coordinates.

        The clipped area is kept a hair inside the world, because a point exactly on the antimeridian converts to an ambiguous longitude: Projection.eastNorth2latlon(org.openstreetmap.josm.data.coor.EastNorth) normalizes it to -180, which would turn the visible range of a view showing e.g. 60° E to 180° into 180° W to 60° E, i.e. the other half of the world.

        Parameters:
        mv - the map view
        Returns:
        the visible bounds, or null if no part of the world is visible
      • probePixels

        private static double probePixels​(MapView mv,
                                          java.awt.geom.Point2D center,
                                          LatLon at,
                                          double spacing,
                                          boolean lon)
        Measures the distance on screen which corresponds to one grid spacing at the center of the view. The probe is placed on whichever side of the center stays inside the valid coordinate range, and it is shortened if the spacing itself does not fit, so that the result is a usable length at every zoom level.
        Parameters:
        mv - the map view
        center - the center of the view, on screen
        at - the center of the view
        spacing - the grid spacing, in degrees
        lon - true to probe along the longitude, false along the latitude
        Returns:
        the distance in pixels; 0 if it cannot be measured
      • projectionUnitsPerMetre

        public static double projectionUnitsPerMetre​(Projection projection,
                                                     EastNorth at)
        Computes how many projection units correspond to one metre on the ground at the given position. For conformal projections (e.g. Mercator) this is the local scale factor, for a Mercator grid at 60° latitude one metre is two projection units.
        Parameters:
        projection - the projection
        at - the position (projected coordinates)
        Returns:
        projection units per metre; 1 if it cannot be determined (position outside the world)
      • thinningFactor

        static double thinningFactor​(double pixelSpacing)
        Computes the factor (a power of 10) by which the spacing must be multiplied so that the lines are at least MIN_PIXEL_SPACING apart.
        Parameters:
        pixelSpacing - the distance between two lines on screen, in pixels
        Returns:
        the factor (at least 1)
      • getProjectedGridLines

        public static java.util.List<MapGridPaintable.ProjectedGridLine> getProjectedGridLines​(ProjectionBounds area,
                                                                                               double spacingX,
                                                                                               double spacingY,
                                                                                               double rotationDegrees,
                                                                                               double originX,
                                                                                               double originY)
        Computes the lines of a (possibly rotated) grid in projected coordinates which cross the given area.
        Parameters:
        area - the area to cover
        spacingX - distance between the lines running in the "north" direction of the grid (before rotation)
        spacingY - distance between the lines running in the "east" direction of the grid (before rotation)
        rotationDegrees - rotation of the grid, counter clockwise
        originX - east coordinate of the grid origin
        originY - north coordinate of the grid origin
        Returns:
        the lines; empty if the spacing is invalid or there would be too many lines
      • gridToEastNorth

        private static EastNorth gridToEastNorth​(double u,
                                                 double v,
                                                 double c,
                                                 double s,
                                                 double originX,
                                                 double originY)
      • getLatLonGridLines

        public static java.util.List<MapGridPaintable.LatLonGridLine> getLatLonGridLines​(Bounds area,
                                                                                         Bounds world,
                                                                                         double spacingLon,
                                                                                         double spacingLat,
                                                                                         double originLon,
                                                                                         double originLat,
                                                                                         int segments)
        Computes the lines of a latitude/longitude grid which cross the given area. Since these lines are curves in most projections, each line is returned as a polyline.
        Parameters:
        area - the area to cover
        world - the bounds of the world in the current projection, the lines are clamped to it
        spacingLon - distance between the meridians, in degrees
        spacingLat - distance between the parallels, in degrees
        originLon - longitude of a meridian of the grid
        originLat - latitude of a parallel of the grid
        segments - number of segments of each polyline
        Returns:
        the lines; empty if the spacing is invalid or there would be too many lines
      • addParallel

        private static void addParallel​(java.util.List<MapGridPaintable.LatLonGridLine> lines,
                                        double lat,
                                        double minLon,
                                        double maxLon,
                                        int segments)
        Adds a parallel running from one longitude to another. A parallel which crosses the antimeridian is added as two lines, one on each side of it: wrapping the longitudes of a single polyline would instead make it jump right across the view.
        Parameters:
        lines - the list to add to
        lat - the latitude of the parallel
        minLon - the longitude to start at, in [-180, 180]
        maxLon - the longitude to end at, may be larger than 180 if the area crosses the antimeridian
        segments - number of segments of each polyline