Skip to main content

JXMapViewer questions and observations

16 replies [Last post]
swebb
Offline
Joined: 2010-03-10
Points: 0

Hi,

I've been looking in to using JXMapViewer with Ordnance Survey maps. The coord system used by Ordnance survey is British National Grid which is OSGB36 not WGS84 (lat/long). I notice that the code for JXMapViewer seems to refer to lat longs including attribute and method calls. Shouldn't it actually just refer to locations so GeoPosition for instance should just have say getX() and getY() methods and other classes can look after appropriate conversions as required.

I also not that the maps I have seen used with JXMapViewer appear to be world maps, has anyone had any success with using maps that don't cover the entire world ?

Finally the zoom feature appears to go in or out a map level which is fine if you have a regular pyramid of tiles we an even distribution of scales but if say you have 250K, 50K and 10K tiles as you would with the Ordnance Survey maps there is a big jump when going from one map level to another. Does JXMapViewer offer the facility to scale in and out of tiles being displayed up to a predefined amount before going to the next map layer ? I can't find any classes that provide this behavior but I would be interested in views!

Thanks

Steve

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
beginner_prithvi
Offline
Joined: 2012-06-10
Points: 0

Hello Steve,
I am also trying to integrate JxMapViewer into my swing application. You seems to have expertise on JxMapViewer component. I am facing one issue:
JXMapViewer provides the method calculateZoomFrom(Set positions) which helps me to shift my focus to the center and adjust zoom level such that my waypoints are inside view port bounds, For view port bounds it creates outer rectangle. for waypoint bounds it creates inner rectangle. Now even if waypoints are inside view port bounds (so that outer.contains(inner) condition is satisfied) and zoom is at some maximum level so that my waypoint inner rectangle is not exactly fitting into view port bounds, JxMapViewer does nothing. In this case JxMapViewer assumes that waypoints are inside view port bounds irrespective of zoom level and stops there. I am trying to fix this issue. But no luck. I tried to implement my own calculateFromZoom method. But not able to find any way with which I can make sure that my inner rectangle for waypoints fits exactly into viewPortBounds given by JxMapViewer. Here is my code:
Something is wrong with the code formatting. So putting code without formatting;
int zoom = mainMap.getZoom();
Rectangle2D inner = generateBoundedRectangleForLine(positionSet, mainMap.getZoom());

int count = 0;
Rectangle outer = mainMap.getViewportBounds();
while(!outer.contains(inner) || (outer.contains(inner) && !(inner.getHeight() >= mainMap.getHeight() " 50))) {
Point2D center = new Point2D.Double(
inner.getX() + inner.getWidth()/2,
inner.getY() + inner.getHeight()/2);
GeoPosition px = mainMap.getTileFactory().pixelToGeo(center,zoom);
mainMap.setCenterPosition(px);
count++;
if(count > 30) break;
if(outer.contains(inner)) {
if (!(inner.getHeight() >= mainMap.getHeight() " 50)) {
zoom = zoom " 1;
if(zoom 15) {
break;
}
}

mainMap.setZoom(zoom);
inner = generateBoundedRectangleForLine(positionSet, zoom);
}

Kindly let me know any hint on how to proceed.

beginner_prithvi
Offline
Joined: 2012-06-10
Points: 0

Hello Steve,
I am also trying to integrate JxMapViewer into my swing application. You seems to have expertise on JxMapViewer component. I am facing one issue:
JXMapViewer provides the method calculateZoomFrom(Set positions) which helps me to shift my focus to the center and adjust zoom level such that my waypoints are inside view port bounds, For view port bounds it creates outer rectangle. for waypoint bounds it creates inner rectangle. Now even if waypoints are inside view port bounds (so that outer.contains(inner) condition is satisfied) and zoom is at some maximum level so that my waypoint inner rectangle is not exactly fitting into view port bounds, JxMapViewer does nothing. In this case JxMapViewer assumes that waypoints are inside view port bounds irrespective of zoom level and stops there. I am trying to fix this issue. But no luck. I tried to implement my own calculateFromZoom method. But not able to find any way with which I can make sure that my inner rectangle for waypoints fits exactly into viewPortBounds given by JxMapViewer. Here is my code:

int zoom = mainMap.getZoom();
Rectangle2D inner = generateBoundedRectangleForLine(positionSet, mainMap.getZoom());

int count = 0;
Rectangle outer = mainMap.getViewportBounds();
while(!outer.contains(inner) || (outer.contains(inner) && !(inner.getHeight() >= mainMap.getHeight() " 50))) {
Point2D center = new Point2D.Double(
inner.getX() + inner.getWidth()/2,
inner.getY() + inner.getHeight()/2);
GeoPosition px = mainMap.getTileFactory().pixelToGeo(center,zoom);
mainMap.setCenterPosition(px);
count++;
if(count > 30) break;
if(outer.contains(inner)) {
if (!(inner.getHeight() >= mainMap.getHeight() " 50)) {
zoom = zoom " 1;
if(zoom 15) {
break;
}
}

mainMap.setZoom(zoom);
inner = generateBoundedRectangleForLine(positionSet, zoom);
}

Kindly let me know any hint on how to proceed.

swebb
Offline
Joined: 2010-03-10
Points: 0

Issues found so far now reported

swebb
Offline
Joined: 2010-03-10
Points: 0

AbstractTileFactory has a tileMap attribute (HashMap) which it uses to hold tile objects. No tiles appear to be ever removed from the map. This is fine for small web based tile sets with only a small amount of tiles however for normal GIS applications using many hundreds of thousands of tiles memory eventually overflows. Using WeakHashMap or a caching mechanism similar to TileCache is the way to go.

TileCache would be better names ImageCache as it does not cache tiles, it caches images.

TileCache::NeedsMoreMemory clears imgmap but not imgmapAccessQueue so you get a null pointer exception when the cache is filled again. Also it should set imagesize to 0 when the method is called!

WaypointPainter has several protected methods (good) but it also declares renderer private (bad) and only provides a setter for it (bad). This gives serious problems when you try and extend the class for more specific requirements.

Onwards and upwards.

swebb
Offline
Joined: 2010-03-10
Points: 0

JXMapViewer::calculateZoomFrom is hard coded to allow a maximum of 15 zoom levels !

swebb
Offline
Joined: 2010-03-10
Points: 0

JXMapViewer has a PanListender which when mousemoved event is called grabs the focus for the viewer. This is all defined in private attributes and classes.

If you are displaying a map in an internal frame its not really very user friendly that every time the user moves the mouse over the map by accident that the map grabs focus. I could understand the grab for focus if it was on a mouseclicked event but not the mouse move event.

swebb
Offline
Joined: 2010-03-10
Points: 0

JXMapViewer has an attribute isNegativeYAllowed which is set to true. It is used in various places but it is never set to false and there is no code that is written to change it. Oh and its private as well !

I noticed this because I'm working around the issue with the PanMouseInputListener which is a private class and grabs focus, it also uses isNegativeYAllowed . I'm actually having to loop through the mouse listneers and mouse motion listeners in my derived JXMapViewer class so that all PanMouseInputListeners are removed and I replace them with my own that doesn't grab focus on mousemove.

Message was edited by: swebb

swebb
Offline
Joined: 2010-03-10
Points: 0

Test

swebb
Offline
Joined: 2010-03-10
Points: 0

I'm currently working on viewing OS Maps I'll let you know how I get on with this and post my findings ;)

swebb
Offline
Joined: 2010-03-10
Points: 0

Well so far my biggest issue is that GeoPosition has the methods getLatitude() & getLongitude() and is totally based around WGS84 which just isn't flexible enough for a GIS solution.

A better implementation would be something like a Location object which could be created passing the coordinate system to used, for instance WGS84, OSGB36. The location object could default to using this coordinate so a call to getX() or getY() would return the values in the default coordinate system. However if a call was made for getX(CoordSystem) or getY(CoordSystem) the relevant conversion could take place. If the location object internally held a hashmap keyed with coordsystem and values of x,y then the conversion would only take place once.

Just some thoughts.

swebb
Offline
Joined: 2010-03-10
Points: 0

I've found yet another big issue in the code that basically stops me extending code that is declared as protected. Basically in JXMapViewer the drawMapTiles needs to be overridden because it always calls info.getTileSize(0) which is fine if all files are the same size. However this isn't always the case with all tile engines or tiles supplied from 3rd parties.

I thought thats easy I'll just extend JXMapViewer and override the protected method but shucks if it doesn't use a private methods and attributes (isTileOnMap, tileLoadListener). So that stops me dead.

Whats the situation with correcting the original code and updating whats in the swingx-ws delivery ? Is this something I need to request ?

Thanks

Steve

swebb
Offline
Joined: 2010-03-10
Points: 0

Yet another private/protected issue. This is all because I have different tile sizes at different map levels.

Basically the setZoom should really be getting the centre GeoPosition and then using this to recalculate the new centre position based on the the new zoom level. However it does everything based on pixel which is fine if the tile is the same size on the new level, however its not. So I started to override setZoom but it used zoom attribute which is private :( So I create my own zoom attribute :) This is ok but there are two methods in JXMapViewer (setCenterPositon, getCentrePosition) that access the zoom attribute direct and not view getZoom() like every other method. So now I've had to override these.

How should I progress all these findings. It would be nice if they are put in the code Swingx-ws code at some point so people who want maps with un-even tiles and zoom steps can use it.

Steve

swebb
Offline
Joined: 2010-03-10
Points: 0

Another inheritance issue!

AbstractTileFactory declares CreateTileRunner() as protected so great I will create my own TileRunner which will catch exceptions if a tile isn't found and replace it with an appropriate emptytile (not the normal empty tile). However the class also uses tileQueue which I would like to carry on using in my own TileRunner but its declared private. So This forces me to create my own tileQueue object and then override all the methods that make use of it.

In short I now think that the JXMapViewer classes and all classes it uses need a good look at to sort out the declaration of attributes and methods so it is easier to derive from the classes and extend or tweak the functionality. This shouldn't be a big task and will make the viewer a lot easier to extend for none pyramid based tile layers or anything slightly out of the ordinary.

swebb
Offline
Joined: 2010-03-10
Points: 0

JXMapViewer has its own private keyListener and MouseListener which are private classes. It would be better if a protected methods where used (protected KeyListener getMapKeyListener(), protected MouseListener getMapMouseListener()) which could then be used by derived classes to supply different listeners. For instance it would be nice to move the map via keyboard by GeoPosition based on the current map scale, not just by 10 pixels.

i30817
Offline
Joined: 2006-05-02
Points: 0

guess you should open issues

swebb
Offline
Joined: 2010-03-10
Points: 0

Yes I will do at some point. I'l probably open a detailed issue on all the things I've found.

I was offline for a while because I couldn't post to the site for some reason but now I'm back on the tinternet I will update when I find more issues.