Class AMapMultiPointItem

All Implemented Interfaces:
IFeedbackProvider, IDrawable, EventListener
Direct Known Subclasses:
MapPolygonItem, MapPolylineItem

public abstract class AMapMultiPointItem extends AMapItem
Abstract base for map-native items whose geometry is an ordered array of geographic vertices (longitude/latitude in radians).

Shared behaviour

Provides vertex storage, modification lifecycle (drag / vertex resize), hit-testing, bounds, selection handles, projection caching, and feedback. Subclasses (MapPolylineItem, MapPolygonItem) supply only AItem.drawItem(java.awt.Graphics2D, edu.cnu.mdi.container.IContainer) and the buildShape(edu.cnu.mdi.mapping.container.MapContainer) factory method.

Vertex indexing

Vertices are in _latLons in construction order. For a closed polygon the path is implicitly closed — no duplicate of vertex 0 is stored.

Drag

Raw lon/lat delta from drag-start to current cursor is applied to all vertices from their snapshot positions (no incremental accumulation). Same high-latitude caveat as MapLineItem: at high latitudes a purely northward drag may introduce a small longitudinal error.

Resize

Moves the vertex at ItemModification.getSelectIndex() to the current geographic cursor location.

Rotation

Rotation is silently ignored for arbitrary multi-vertex geographic shapes because there is no single unambiguous spherical rotation centre or "bearing change" for non-line shapes. Subclasses with a well-defined centre (e.g. a geodesic circle) may override modify() to add it.

  • Field Details

  • Constructor Details

    • AMapMultiPointItem

      protected AMapMultiPointItem(Layer layer, Point2D.Double[] latLons, Object... keyVals)
      Parameters:
      layer - the layer; must not be null
      latLons - geographic vertices in radians; must not be null, length ≥ 2
      keyVals - optional PropertyUtils key/value pairs
      Throws:
      IllegalArgumentException - if latLons has fewer than 2 points
  • Method Details

    • getLatLons

      public Point2D.Double[] getLatLons()
      Returns:
      a defensive copy of the vertex array; never null
    • setLatLons

      public void setLatLons(Point2D.Double[] latLons)
      Replace all vertices and mark dirty.
      Parameters:
      latLons - new vertices; must not be null, length ≥ 2
    • getVertexCount

      public int getVertexCount()
      Returns:
      number of vertices (≥ 2)
    • buildShape

      protected abstract MapGraphics.ProjectedMapShape buildShape(MapContainer mc)
      Parameters:
      mc - the owning map container
      Returns:
      projected shape; never null
    • shouldDraw

      public boolean shouldDraw(Graphics2D g2, IContainer container)
      Description copied from class: AItem
      Return true if this item should be drawn on the current frame.

      This is a secondary visibility check beyond the simple AItem._visible flag. A typical implementation checks whether the item's screen bounds intersect the current clip rectangle.

      Specified by:
      shouldDraw in class AItem
      Parameters:
      g2 - the graphics context (may be used to read clip bounds)
      container - the container being rendered
      Returns:
      true if AItem.drawItem(java.awt.Graphics2D, edu.cnu.mdi.container.IContainer) should be called
    • getBounds

      public Rectangle getBounds(IContainer container)
      Description copied from class: AItem
      Return the screen-coordinate bounding rectangle of this item.

      The default implementation returns null. Subclasses should override to return a meaningful bounding box used for hit-testing and rubber-band selection.

      Overrides:
      getBounds in class AItem
      Parameters:
      container - the container rendering this item
      Returns:
      the pixel bounding rectangle, or null if unavailable
    • contains

      public boolean contains(IContainer container, Point screenPoint)
      Description copied from class: AItem
      Test whether this item, as rendered, contains the given screen point.

      Priority order:

      1. AItem._lastDrawnPolygon — exact hit test.
      2. AItem.getBounds(IContainer) — axis-aligned bounding rectangle.
      3. AItem.inASelectRect(edu.cnu.mdi.container.IContainer, java.awt.Point) — selection/rotation handle rectangles.
      Overrides:
      contains in class AItem
      Parameters:
      container - the container rendering this item
      screenPoint - the pixel point to test
      Returns:
      true if the item contains screenPoint
    • containsPoint

      protected boolean containsPoint(MapGraphics.ProjectedMapShape shape, Point screenPoint)
      Tests whether a screen point hits the projected shape.

      Default: 6-pixel proximity (correct for open polylines). MapPolygonItem overrides to also test interior containment.

      Parameters:
      shape - projected shape (may be null)
      screenPoint - device-space test point
      Returns:
      true if the point hits the shape
    • getSelectionPoints

      public Point[] getSelectionPoints(IContainer container)
      Returns all vertices projected to device-space handles, omitting any that are off-map (non-finite projection result).
      Overrides:
      getSelectionPoints in class AItem
      Parameters:
      container - the container rendering this item
      Returns:
      handle positions, or null if none are visible
    • startModification

      public void startModification()
      Classify and begin a drag, resize, or rotate modification.

      Priority: rotate (if start point is in rotation handle) → resize (if start point is in a selection handle) → drag (otherwise).

      This method is a no-op if AItem._modification is null.

      Stores a AMapMultiPointItem.MultiPointStartState snapshot of all vertex positions in the modification's user-object slot.

      Overrides:
      startModification in class AItem
    • modify

      public void modify()
      Update this item's geometry in response to a mouse movement during an active modification.

      Called repeatedly while the user is dragging, resizing, or rotating. The current mouse position is available through AItem._modification.

      DRAG: shifts all vertices by the lon/lat delta from the start snapshot. RESIZE: moves the selected vertex to the cursor. ROTATE: silently ignored.

      Specified by:
      modify in class AItem
    • getWorldBounds

      public Rectangle2D.Double getWorldBounds()
      Return the world-coordinate bounding rectangle of this item.

      Returns the axis-aligned lon/lat bounding box of the vertex set. May under-estimate arcs that bulge beyond the chord; use getBounds(IContainer) for exact pixel bounds.

      Specified by:
      getWorldBounds in class AItem
      Returns:
      the world-coordinate bounding rectangle
    • translateWorld

      public void translateWorld(double dx, double dy)
      Translate this item by (dx, dy) in world coordinates.

      Applies raw lon/lat offsets to all vertices. See MapLineItem for the high-latitude caveat.

      Specified by:
      translateWorld in class AItem
      Parameters:
      dx - the world-coordinate offset along the X axis
      dy - the world-coordinate offset along the Y axis
    • getFeedbackStrings

      public void getFeedbackStrings(IContainer container, Point pp, Point2D.Double wp, List<String> feedbackStrings)
      Populate the feedback string list with information about this item. The default implementation is a no-op.

      Adds vertex count and total great-circle perimeter when the cursor is over the item.

      Specified by:
      getFeedbackStrings in interface IFeedbackProvider
      Overrides:
      getFeedbackStrings in class AItem
      Parameters:
      container - the container rendering this item
      pp - the current mouse position in screen coordinates
      wp - the corresponding world-coordinate position
      feedbackStrings - the list to add strings to
    • updateFocus

      protected void updateFocus()
      Recomputes the focus as the geographic mean of all vertices.
      Overrides:
      updateFocus in class AMapItem
    • setDirty

      public void setDirty(boolean dirty)
      Description copied from class: AItem
      Set the dirty flag. Setting to true also clears AItem._lastDrawnPolygon.
      Specified by:
      setDirty in interface IDrawable
      Overrides:
      setDirty in class AItem
      Parameters:
      dirty - new dirty state
    • prepareForRemoval

      public void prepareForRemoval()
      Description copied from class: AItem
      Prepare this item for removal from its layer.

      Performs two operations:

      1. Feedback de-registration. The item unregisters itself from the container's FeedbackControl so that it is no longer polled after removal. The container reference is captured before AItem._layer is nulled.
      2. Reference nulling. Heavyweight references are set to null to assist garbage collection and to cause fast, obvious NullPointerExceptions if the item is used after removal.

      Subclasses holding additional heavyweight references should override this method, null those fields, and call super.prepareForRemoval() either first or last.

      Specified by:
      prepareForRemoval in interface IDrawable
      Overrides:
      prepareForRemoval in class AItem
    • ensureProjectedShape

      protected void ensureProjectedShape(IContainer container)
      Rebuilds _projectedShape if null.
    • projectLatLon

      protected Point projectLatLon(MapContainer mc, Point2D.Double latLon)
      Projects a geographic point to device pixels.
      Returns:
      device-space point, or null if off-map
    • localToLatLon

      protected Point2D.Double localToLatLon(MapContainer mc, Point p)
      Converts a device-space point to geographic lon/lat in radians.
      Returns:
      geographic point, or null if either argument is null
    • copyVertices

      protected static Point2D.Double[] copyVertices(Point2D.Double[] src)
      Deep defensive copy of a vertex array.