Modify

Opened 3 years ago

Closed 3 years ago

#12889 closed enhancement (fixed)

Rewrite MapView coordinate conversion to be more universal

Reported by: michael2402 Owned by: team
Priority: normal Milestone: 16.08
Component: Core Version:
Keywords: gsoc-core Cc: Don-vip, bastiK, stoecker

Description (last modified by michael2402)

I plan to move all coordinate conversion out of MapView into an extra class. This will be one of the main tasks of this year's GSoC.

MapViewState

That class will then contain the current MapView state (size, position, coordinate system) and has methods to convert between all coordinate systems:

  • Screen coordinates
  • Window coordinates
  • MapView coordinates (used for drawing)
  • EastNorth coordinates
  • LatLon coordinates (using the current coordinate system)


The following conversion methods exist:

  • Convert any Point/EastNorth/LatLon object into a universal position object
  • Fast methods to convert LatLon -> Point, EastNorth -> Point, ... (whatever we need to be fast)
  • Convert LatLon rectangle to Polygon

Whenever the MapView changes, a new MapViewState object is created. That way we can track view changes easilly. With this, we can add layer draw result caching or asynchronous rendering in the future.

It has a getBounds() method that replaces the current bounding box that is passed on to Layer#paint()

The center and other (corner, ...) positions are returned as MapViewPoint to make their use universal.

MapViewPoint

This object can be constructed from a position in any coordinate system.

It is the universal representation of that point on the screen.

You can convert it to any other coordinate system.

This should not be used during drawing because it is slow but it makes much code easier to read and conversion between coordinate systems a lot smoother.

Methods:

  • getOnScreen(): Point2D
  • getInWindow(): Point2D
  • getInMapView(): Point2D
  • getEastNorth(): EastNorth
  • getLatLon(): LatLon or null, but may wrap around at 180° if coordinate system supports it
  • getLatLonUnwrapped(): LatLon or null, prevents wrapping
  • if needed: getLatLonForced(): LatLon. Forces a LatLon conversion, returns something as useful as possible outside the coordinate system.
  • if needed: getLatLonClamped(): LatLon. The closest point inside the coordinate system.

Painting

I plan to add a new Layer#paint mechanism while doing this:

  • paint(Graphics2D, MapViewState) paints the whole layer and should not be overriden. It is split into:
  • beforePaint() sets up Graphics2D (anti-aliasing, opacity filters, ...)
  • paintData() the real paint method
  • paintSubLayers() if/when it is implemented.

180° Problem

The center of the screen is always in the Range -180°...180°.

When 180° wrapping is active and if the coordinate systems tells us that it supports it, LatLon coordinates will be mapped to the respective EastNorth coordinates. We do not paint anything twice, so if the user scrolled out too much we only draw 360°

EastNort <-> LatLon conversion will do everything for simple nodes.

We add a new method isAroundScreenWrap(LatLon, LatLon). It returns true if the horizontal distance between two LatLon objects would be more than 180° on the screen. We do not paint those (to avoid lines through the whole view when having zoomed out).

Imagery is something special, I'll have a look on how to do it there.

Converting Areas is more difficult. We do not need this often, mostly for e.g. computing bounds. The OsmDataLayer needs to handle this in a special way (split the bounds at 180° and search primitives twice). Other layers only get the bigger of the two bounds for backword compatibility if they do not implement the new paint(). They will not support painting over 180° but the user can move the view so that the other side of the world will get painted.

Implementation

(1) Implement MapViewPoint - done
(2) Implement MapViewState and add a temporary getState() to the MapView that uses scale/center to compute a ViewState - done
(3) Change MapView to only use the last MapViewState for view position handling. - done
(4) Change the layer class to use that view state.
(5) Change view undo/redo system to use that state.

Attachments (1)

josm-coord-systems.png (21.8 KB) - added by michael2402 3 years ago.

Download all attachments as: .zip

Change History (7)

Changed 3 years ago by michael2402

Attachment: josm-coord-systems.png added

comment:1 Changed 3 years ago by michael2402

Description: modified (diff)

comment:2 Changed 3 years ago by michael2402

This is the more generic version of my old patch #11637

comment:3 Changed 3 years ago by michael2402

Description: modified (diff)

comment:4 Changed 3 years ago by michael2402

Milestone: 16.0616.07

comment:5 Changed 3 years ago by Don-vip

Milestone: 16.0716.08

comment:6 Changed 3 years ago by michael2402

Resolution: fixed
Status: newclosed

I consider this to be done. The map view is using the state, the rendering code is, too.

Modify Ticket

Change Properties
Set your email in Preferences
Action
as closed The owner will remain team.
as The resolution will be set.
The resolution will be deleted.

Add Comment


E-mail address and name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.