World Wind Forums

Go Back   World Wind Forums > WorldWind JAVA forums > Development Help

Development Help Help for building applications or diagnosing problems with WWJ

Reply
 
Thread Tools Display Modes
Old 02-11-2010, 06:51 AM   #1
gk_fabs
Junior Member
 
Join Date: Jan 2010
Posts: 13
gk_fabs is on a distinguished road
Default Openstreetmap Layer

Hello,

I have done a Openstreetmap layer. This one takes the information directly from the openstreetmap website, using their api instead of displaying the information from an another server. You will have more actualize data then.

You will need the following jars to make it work:
libosm-2.5.2-RC1.jar
osmnavigation-2.5.2-RC1.jar

You can get them from http://sourceforge.net/projects/travelingsales/

Could you give me your comments?

I have a couple of bug / improvement in mind but it is already usable:
- Keep data downloaded in a cache
- Check if the data downloaded is already displayed
- Display more information like water, land, names of cities, ...
- At the beginning there is a bug and you have to move the view so it begins to download

Code:
package org.layers;

import gov.nasa.worldwind.layers.SurfaceShapeLayer;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Sector;
import gov.nasa.worldwind.render.BasicShapeAttributes;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.ShapeAttributes;
import gov.nasa.worldwind.render.SurfaceCircle;
import gov.nasa.worldwind.render.SurfacePolyline;
import gov.nasa.worldwind.util.Logging;

import org.openstreetmap.osm.Tags;
import org.openstreetmap.osm.data.IDataSet;
import org.openstreetmap.osm.data.MemoryDataSet;
import org.openstreetmap.osm.data.WayHelper;
import org.openstreetmap.osm.data.coordinates.Bounds;
import org.openstreetmap.osm.io.BoundingBoxDownloader;
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
import org.openstreetmap.osmosis.core.domain.v0_6.Relation;
import org.openstreetmap.osmosis.core.domain.v0_6.Way;
import org.openstreetmap.osmosis.core.domain.v0_6.WayNode;
import org.openstreetmap.travelingsalesman.routing.selectors.Motorcar;
import org.openstreetmap.travelingsalesman.routing.selectors.UsedTags;

import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

public class OpenStreetMapLayer extends SurfaceShapeLayer
{
    private Sector lastVisible = null;
    private IDataSet displayData = new MemoryDataSet();

    public static final HashMap<String, ShapeAttributes> WAYSTYLEBYHIGHWAY = new HashMap<String, ShapeAttributes>();
    public static final ShapeAttributes DEFAULTWAYCOLOR;
    public static final int DEFAULTWAYWIDTH = 3;
    public static final int MOTORWAYROADWIDTH = 6;
    public static final int TRUNKROADWIDTH = 5;
    public static final int SECONDARYROADWIDTH = 4;
    public static final int MOTORWAYLINKROADWIDTH = 6;
    public static final int PRIMARYLINKROADWIDTH = 4;
    public static final int PRIMARYROADWIDTH = 4;
    public static final int RESIDENTIALROADWIDTH = 3;

    static {
        DEFAULTWAYCOLOR = new BasicShapeAttributes();
        Material material = new Material(Color.white);
        DEFAULTWAYCOLOR.setInteriorMaterial(material);
        DEFAULTWAYCOLOR.setOutlineMaterial(material);
        DEFAULTWAYCOLOR.setOutlineWidth(DEFAULTWAYWIDTH);

        ShapeAttributes attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(MOTORWAYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("motorway", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(MOTORWAYLINKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("motorway_link", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter().brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(TRUNKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("trunk", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.RED.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(PRIMARYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("primary", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.RED.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(PRIMARYLINKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("primary_link", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.orange.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(SECONDARYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("secondary", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.white);
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(RESIDENTIALROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("residential", attributes);

        Color forbiddenRoad = new Color(1f, 1f, 1f, 1f / 2);

        attributes = new BasicShapeAttributes();
        material = new Material(forbiddenRoad);
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(2);
        WAYSTYLEBYHIGHWAY.put("footway", attributes);
        WAYSTYLEBYHIGHWAY.put("cycleway", attributes);
        WAYSTYLEBYHIGHWAY.put("steps", attributes);
    }

    public OpenStreetMapLayer()
    {
        this.setName("OpenStreetMapLayer");
    }

    protected void doPreRender(DrawContext dc)
    {
        super.doPreRender(dc);
        Sector visible = dc.getVisibleSector();

        if (lastVisible == null) {
            lastVisible = visible;
        } else if (lastVisible.equals(visible)) {
            lastVisible = visible;
            return;
        } else if (lastVisible.contains(visible)) {
            lastVisible = visible;
            return;
        }

        lastVisible = visible;
        if (visible.getDeltaLatDegrees() > 0.25 || visible.getDeltaLonDegrees() > 0.25) {
            return;
        }

        OsmDownload o = new OsmDownload(this, displayData, visible);
        o.start();
    }

    private class OsmDownload extends Thread {
        private OpenStreetMapLayer osmL;
        private IDataSet displayData;
        private Sector visible;

        public OsmDownload(OpenStreetMapLayer osmL, IDataSet displayData, Sector visible) {
            super("OsmDownload-Thread");
            this.setPriority(MIN_PRIORITY);
            this.osmL = osmL;
            this.displayData = displayData;
            this.visible = visible;
        }

        @Override
        public void run() {
            Logging.logger().info("Downloading");
            BoundingBoxDownloader downloader = new BoundingBoxDownloader(visible.getMinLatitude().degrees,
                                                                         visible.getMinLongitude().degrees,
                                                                         visible.getMaxLatitude().degrees,
                                                                         visible.getMaxLongitude().degrees);
            IDataSet data = downloader.parseOsm();
            int waycount = 0;

            Bounds visibleBounds = new Bounds(visible.getMinLatitude().degrees,
                                              visible.getMinLongitude().degrees,
                                              visible.getMaxLatitude().degrees,
                                              visible.getMaxLongitude().degrees);
            for (Iterator<Way> ways = data.getWays(visibleBounds); ways.hasNext();) {
                Way way = ways.next();
                if (visit(data, way))
                    waycount++;
            }

            Logging.logger().info("Displayed " + waycount);
        }

        public boolean visit(IDataSet data, final Way w) {
            String highway = WayHelper.getTag(w, Tags.TAG_HIGHWAY);
            if (highway == null) {
                return false;
            }

            //-------

            ShapeAttributes attributes = WAYSTYLEBYHIGHWAY.get(highway);
            if (attributes == null)
                attributes = DEFAULTWAYCOLOR;
            ArrayList<LatLon> nodes = new ArrayList<LatLon>();
            for (WayNode waynode : w.getWayNodes()) {
                Node n = data.getNodeByID(waynode.getNodeId());
                LatLon node = LatLon.fromDegrees(n.getLatitude(), n.getLongitude());
                nodes.add(node);
            }
            SurfacePolyline l = new SurfacePolyline(attributes, nodes);
            osmL.addRenderable(l);
            return true;
        }
    }
}
gk_fabs is offline   Reply With Quote
Old 02-11-2010, 03:46 PM   #2
mac123
Junior (har har...) Member
 
Join Date: Nov 2009
Location: Europe, Germany/Austria
Posts: 12
mac123 is on a distinguished road
Default

Works & looks good - but puts quite some strain on my machine, the GUI gets really sloooow.
(Maybe the disable picking trick will help (?))
Nice idea taking the data from the openStreetMap Servers directly.
mac123 is offline   Reply With Quote
Old 02-11-2010, 03:56 PM   #3
gk_fabs
Junior Member
 
Join Date: Jan 2010
Posts: 13
gk_fabs is on a distinguished road
Default

What is the disable picking trick ?

I got implemented this:
- Check if the data downloaded is already displayed
- At the beginning there is a bug and you have to move the view so it begins to download

That should be quicker, could you try ?

Code:
package org.layers;

import gov.nasa.worldwind.layers.SurfaceShapeLayer;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Sector;
import gov.nasa.worldwind.render.BasicShapeAttributes;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.ShapeAttributes;
import gov.nasa.worldwind.render.SurfaceCircle;
import gov.nasa.worldwind.render.SurfacePolyline;
import gov.nasa.worldwind.util.Logging;

import org.openstreetmap.osm.Tags;
import org.openstreetmap.osm.data.IDataSet;
import org.openstreetmap.osm.data.FileTileDataSet;
import org.openstreetmap.osm.data.MemoryDataSet;
import org.openstreetmap.osm.data.WayHelper;
import org.openstreetmap.osm.data.coordinates.Bounds;
import org.openstreetmap.osm.io.BoundingBoxDownloader;
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
import org.openstreetmap.osmosis.core.domain.v0_6.Relation;
import org.openstreetmap.osmosis.core.domain.v0_6.Way;
import org.openstreetmap.osmosis.core.domain.v0_6.WayNode;
import org.openstreetmap.travelingsalesman.routing.selectors.Motorcar;
import org.openstreetmap.travelingsalesman.routing.selectors.UsedTags;

import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

public class OpenStreetMapLayer extends SurfaceShapeLayer
{
    private Sector lastVisible = null;
    private IDataSet displayData = new MemoryDataSet();

    public static final HashMap<String, ShapeAttributes> WAYSTYLEBYHIGHWAY = new HashMap<String, ShapeAttributes>();
    public static final ShapeAttributes DEFAULTWAYCOLOR;
    public static final int DEFAULTWAYWIDTH = 3;
    public static final int MOTORWAYROADWIDTH = 6;
    public static final int TRUNKROADWIDTH = 5;
    public static final int SECONDARYROADWIDTH = 4;
    public static final int MOTORWAYLINKROADWIDTH = 6;
    public static final int PRIMARYLINKROADWIDTH = 4;
    public static final int PRIMARYROADWIDTH = 4;
    public static final int RESIDENTIALROADWIDTH = 3;

    static {
        DEFAULTWAYCOLOR = new BasicShapeAttributes();
        Material material = new Material(Color.white);
        DEFAULTWAYCOLOR.setInteriorMaterial(material);
        DEFAULTWAYCOLOR.setOutlineMaterial(material);
        DEFAULTWAYCOLOR.setOutlineWidth(DEFAULTWAYWIDTH);

        ShapeAttributes attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(MOTORWAYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("motorway", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(MOTORWAYLINKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("motorway_link", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter().brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(TRUNKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("trunk", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.RED.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(PRIMARYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("primary", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.RED.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(PRIMARYLINKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("primary_link", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.orange.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(SECONDARYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("secondary", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.white);
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(RESIDENTIALROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("residential", attributes);

        Color forbiddenRoad = new Color(1f, 1f, 1f, 1f / 2);

        attributes = new BasicShapeAttributes();
        material = new Material(forbiddenRoad);
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(2);
        WAYSTYLEBYHIGHWAY.put("footway", attributes);
        WAYSTYLEBYHIGHWAY.put("cycleway", attributes);
        WAYSTYLEBYHIGHWAY.put("steps", attributes);
    }

    public OpenStreetMapLayer()
    {
        this.setName("OpenStreetMapLayer");
    }

    protected void doPreRender(DrawContext dc)
    {
        super.doPreRender(dc);
        Sector visible = dc.getVisibleSector();

        if (lastVisible == null) {
            lastVisible = visible;
        } else if (lastVisible.equals(visible)) {
            lastVisible = visible;
            return;
        } else if (lastVisible.contains(visible) &&
                   lastVisible.getDeltaLatDegrees() <= 0.25 &&
                   lastVisible.getDeltaLonDegrees() <= 0.25) {
            lastVisible = visible;
            return;
        }

        lastVisible = visible;
        if (visible.getDeltaLatDegrees() > 0.25 || visible.getDeltaLonDegrees() > 0.25) {
            return;
        }

        OsmDownload o = new OsmDownload(this, displayData, visible);
        o.start();
    }

    private class OsmDownload extends Thread {
        private OpenStreetMapLayer osmL;
        private IDataSet displayData;
        private Sector visible;

        public OsmDownload(OpenStreetMapLayer osmL, IDataSet displayData, Sector visible) {
            super("OsmDownload-Thread");
            this.setPriority(MIN_PRIORITY);
            this.osmL = osmL;
            this.displayData = displayData;
            this.visible = visible;
        }

        @Override
        public void run() {
            Logging.logger().info("Downloading");
            long start = System.currentTimeMillis();
            BoundingBoxDownloader downloader = new BoundingBoxDownloader(visible.getMinLatitude().degrees,
                                                                         visible.getMinLongitude().degrees,
                                                                         visible.getMaxLatitude().degrees,
                                                                         visible.getMaxLongitude().degrees);
            IDataSet data = downloader.parseOsm();
            int waycount = 0;

            Bounds visibleBounds = new Bounds(visible.getMinLatitude().degrees,
                                              visible.getMinLongitude().degrees,
                                              visible.getMaxLatitude().degrees,
                                              visible.getMaxLongitude().degrees);
            for (Iterator<Way> ways = data.getWays(visibleBounds); ways.hasNext();) {
                Way way = ways.next();
                if (!displayData.containsWay(way)) {
                    if (visit(data, way))
                        waycount++;
                    displayData.addWay(way);
                }
            }

            long end = System.currentTimeMillis();
            Logging.logger().info("Displayed " + waycount + " in " + (end - start) + " ms");
        }

        public boolean visit(IDataSet data, final Way w) {
            String highway = WayHelper.getTag(w, Tags.TAG_HIGHWAY);
            if (highway == null) {
                return false;
            }

            //-------

            ShapeAttributes attributes = WAYSTYLEBYHIGHWAY.get(highway);
            if (attributes == null)
                attributes = DEFAULTWAYCOLOR;
            ArrayList<LatLon> nodes = new ArrayList<LatLon>();
            for (WayNode waynode : w.getWayNodes()) {
                Node n = data.getNodeByID(waynode.getNodeId());
                LatLon node = LatLon.fromDegrees(n.getLatitude(), n.getLongitude());
                nodes.add(node);
            }
            SurfacePolyline l = new SurfacePolyline(attributes, nodes);
            osmL.addRenderable(l);
            return true;
        }
    }
}
gk_fabs is offline   Reply With Quote
Old 02-11-2010, 04:03 PM   #4
gk_fabs
Junior Member
 
Join Date: Jan 2010
Posts: 13
gk_fabs is on a distinguished road
Default

If I understood, the picking trick could be done just by adding this.setPickEnabled(false); in the constructor, and that's soooooooo quick

Thanks!
gk_fabs is offline   Reply With Quote
Old 02-11-2010, 04:17 PM   #5
mac123
Junior (har har...) Member
 
Join Date: Nov 2009
Location: Europe, Germany/Austria
Posts: 12
mac123 is on a distinguished road
Default

public OpenStreetMapLayer()
{
this.setName("OpenStreetMapLayer");
this.setPickEnabled(false);
}

That's what i just wanted to say :-)
As i understand it, picking can be disabled if you do not want to interact with your layer and use it "for display only".
mac123 is offline   Reply With Quote
Old 02-12-2010, 03:07 AM   #6
gk_fabs
Junior Member
 
Join Date: Jan 2010
Posts: 13
gk_fabs is on a distinguished road
Default

Hi,

Should I implement the Retriever interface, and run the download through WorldWind.getRetrievalService().runRetri ever(myDownloadTask) ?

Thanks
gk_fabs is offline   Reply With Quote
Old 02-12-2010, 11:17 AM   #7
patmurris
WWJ Consultant
 
patmurris's Avatar
 
Join Date: Jun 2005
Location: Saint-Paul de Vence, Alpes Maritimes, France
Posts: 3,412
patmurris is an unknown quantity at this point
Default

Using one SurfacePolyline for each road will not scale well for a lot of roads...

You may want to have a look at experimental...render.SurfacePolylines (with an 's') which will render a lot many polyline segments in bulk. It uses a CompoundVecBuffer that contains all the locations along with two index buffers for the different polylines parts. You can see example code to deal with these buffers in experimental...examples.ShapefileLoader.
__________________
My World Wind Java Blog & WW.net Plugins page
patmurris is offline   Reply With Quote
Old 02-12-2010, 07:18 PM   #8
gk_fabs
Junior Member
 
Join Date: Jan 2010
Posts: 13
gk_fabs is on a distinguished road
Default

Hi,

I have been looking on SurfacePolylines.

I need to have one SurfacePolylines per ShapeAttributes (I need to change the width and the color depending on the road type)

I am not sure to have fully understood the way to use SurfacePolylines, but I want to use it this way:

public static final ShapeAttributes DEFAULTWAYCOLOR;
public static SurfacePolylines defaultway;

In the constructor

DEFAULTWAYCOLOR = new BasicShapeAttributes();
Material material = new Material(Color.white);
DEFAULTWAYCOLOR.setInteriorMaterial(mate rial);
DEFAULTWAYCOLOR.setOutlineMaterial(mater ial);
DEFAULTWAYCOLOR.setOutlineWidth(DEFAULTW AYWIDTH);
CompoundVecBuffer buf = new CompoundVecBuffer(2, new BufferFactory.DoubleBufferFactory(), 10, 10);
buf.appendEmptyBuffer();
buf.appendSubBuffer(new VecBuffer(2, 10, new BufferFactory.DoubleBufferFactory()));
defaultway = new SurfacePolylines(buf);
defaultway.setAttributes(DEFAULTWAYCOLOR );

this.addRenderable(defaultway);


I thought it was going to create me an empty polylines, but I always get t his error message:

SEVERE gov.nasa.worldwin Argument out of range position < 0 or position >= size
in gov.nasa.worldwind.util.VecBuffer:getLoc ation-gov.nasa.worldwind

What am I doing wrong ?

Thanks
gk_fabs is offline   Reply With Quote
Old 02-12-2010, 07:56 PM   #9
nlneilson
Super Moderator
 
Join Date: Nov 2006
Location: Mojave & Oxnard California
Posts: 2,617
nlneilson is on a distinguished road
Default

Quote:
Originally Posted by gk_fabs View Post
I thought it was going to create me an empty polylines, ...
Empty polyline?? new concept maybe?

A polyline needs points that are not the same. You need to make sure the points are seen as different or you will get errors.

Do a search in this forum for "fudge".
Post #9
http://forum.worldwindcentral.com/sh...ighlight=fudge
nlneilson is offline   Reply With Quote
Old 02-12-2010, 10:42 PM   #10
gk_fabs
Junior Member
 
Join Date: Jan 2010
Posts: 13
gk_fabs is on a distinguished road
Default

Ok I am using Polylines and Retriever in the layer.

That works great. I am not sure if it is quicker than the second version thought... Let me know your comments or just let me know if it worked for you.

Saddly I will not be able to keep data downloaded in a cache, because the File implementation of the openstreetmap library has a small bug. That's not a requisition for my project, so I leave that.

Code:
package org.layers;

import gov.nasa.worldwind.Configuration;
import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.WWObjectImpl;
import gov.nasa.worldwind.avlist.AVKey;
import gov.nasa.worldwind.layers.SurfaceShapeLayer;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Sector;
import gov.nasa.worldwind.render.BasicShapeAttributes;
import gov.nasa.worldwind.render.DrawContext;
import gov.nasa.worldwind.render.Material;
import gov.nasa.worldwind.render.ShapeAttributes;
import gov.nasa.worldwind.render.SurfacePolylines;
import gov.nasa.worldwind.retrieve.Retriever;
import gov.nasa.worldwind.util.BufferFactory;
import gov.nasa.worldwind.util.CompoundVecBuffer;
import gov.nasa.worldwind.util.Logging;
import gov.nasa.worldwind.util.VecBuffer;

import org.openstreetmap.osm.Tags;
import org.openstreetmap.osm.data.IDataSet;
import org.openstreetmap.osm.data.FileTileDataSet;
import org.openstreetmap.osm.data.MemoryDataSet;
import org.openstreetmap.osm.data.WayHelper;
import org.openstreetmap.osm.data.coordinates.Bounds;
import org.openstreetmap.osm.io.BoundingBoxDownloader;
import org.openstreetmap.osmosis.core.domain.v0_6.Node;
import org.openstreetmap.osmosis.core.domain.v0_6.Relation;
import org.openstreetmap.osmosis.core.domain.v0_6.Way;
import org.openstreetmap.osmosis.core.domain.v0_6.WayNode;
import org.openstreetmap.travelingsalesman.routing.selectors.Motorcar;
import org.openstreetmap.travelingsalesman.routing.selectors.UsedTags;

import java.awt.Color;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicInteger;

public class OpenStreetMapLayer extends SurfaceShapeLayer
{
    private Sector lastVisible = null;
    private IDataSet displayData = new MemoryDataSet();

    public static final HashMap<String, ShapeAttributes> WAYSTYLEBYHIGHWAY = new HashMap<String, ShapeAttributes>();
    public static final ShapeAttributes DEFAULTWAYCOLOR;
    public static final int DEFAULTWAYWIDTH = 3;
    public static final int MOTORWAYROADWIDTH = 6;
    public static final int TRUNKROADWIDTH = 5;
    public static final int SECONDARYROADWIDTH = 4;
    public static final int MOTORWAYLINKROADWIDTH = 6;
    public static final int PRIMARYLINKROADWIDTH = 4;
    public static final int PRIMARYROADWIDTH = 4;
    public static final int RESIDENTIALROADWIDTH = 3;

    public static SurfacePolylines defaultway;
    public static SurfacePolylines motorwayroad;
    public static SurfacePolylines trunkroad;
    public static SurfacePolylines secondaryroad;
    public static SurfacePolylines motorwaylinkroad;
    public static SurfacePolylines primarylinkroad;
    public static SurfacePolylines primaryroad;
    public static SurfacePolylines residentialroad;
    public static SurfacePolylines forbiddenroad;
    
    static {
        DEFAULTWAYCOLOR = new BasicShapeAttributes();
        Material material = new Material(Color.white);
        DEFAULTWAYCOLOR.setInteriorMaterial(material);
        DEFAULTWAYCOLOR.setOutlineMaterial(material);
        DEFAULTWAYCOLOR.setOutlineWidth(DEFAULTWAYWIDTH);

        ShapeAttributes attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(MOTORWAYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("motorway", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(MOTORWAYLINKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("motorway_link", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.blue.brighter().brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(TRUNKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("trunk", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.RED.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(PRIMARYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("primary", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.RED.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(PRIMARYLINKROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("primary_link", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.orange.brighter());
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(SECONDARYROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("secondary", attributes);

        attributes = new BasicShapeAttributes();
        material = new Material(Color.white);
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(RESIDENTIALROADWIDTH);
        WAYSTYLEBYHIGHWAY.put("residential", attributes);

        Color forbiddenRoad = new Color(1f, 1f, 1f, 1f / 2);

        attributes = new BasicShapeAttributes();
        material = new Material(forbiddenRoad);
        attributes.setInteriorMaterial(material);
        attributes.setOutlineMaterial(material);
        attributes.setOutlineWidth(2);
        WAYSTYLEBYHIGHWAY.put("footway", attributes);
        WAYSTYLEBYHIGHWAY.put("cycleway", attributes);
        WAYSTYLEBYHIGHWAY.put("steps", attributes);
    }

    public OpenStreetMapLayer()
    {
        this.setName("OpenStreetMapLayer");
        this.setPickEnabled(false);
    }

    protected void doPreRender(DrawContext dc)
    {
        super.doPreRender(dc);
        Sector visible = dc.getVisibleSector();

        if (lastVisible == null) {
            lastVisible = visible;
        } else if (lastVisible.equals(visible)) {
            lastVisible = visible;
            return;
        } else if (lastVisible.contains(visible) &&
                   lastVisible.getDeltaLatDegrees() <= 0.25 &&
                   lastVisible.getDeltaLonDegrees() <= 0.25) {
            lastVisible = visible;
            return;
        }

        lastVisible = visible;
        if (visible.getDeltaLatDegrees() > 0.25 || visible.getDeltaLonDegrees() > 0.25) {
            return;
        }

        OsmDownload o = new OsmDownload(this, displayData, visible);

        WorldWind.getRetrievalService().runRetriever(o);
    }

    private class OsmDownload extends WWObjectImpl implements Retriever {
        private OpenStreetMapLayer osmL;
        private IDataSet displayData;
        private Sector visible;

        private volatile String state = RETRIEVER_STATE_NOT_STARTED;
        private volatile int contentLength = 0;
        private AtomicInteger contentLengthRead = new AtomicInteger(0);
        private volatile String contentType;
        private volatile ByteBuffer byteBuffer;
        private int connectTimeout = Configuration.getIntegerValue(AVKey.URL_CONNECT_TIMEOUT, 8000);
        private int readTimeout = Configuration.getIntegerValue(AVKey.URL_READ_TIMEOUT, 5000);
        private int staleRequestLimit = -1;
        private long submitTime;
        private long beginTime;
        private long endTime;

        public OsmDownload(OpenStreetMapLayer osmL, IDataSet displayData, Sector visible) {
            this.osmL = osmL;
            this.displayData = displayData;
            this.visible = visible;
        }

        public final int getContentLength()
        {
            return this.contentLength;
        }

        public final int getContentLengthRead()
        {
            return this.contentLengthRead.get();
        }

        public final String getContentType()
        {
            return this.contentType;
        }

        public final ByteBuffer getBuffer()
        {
            return this.byteBuffer;
        }

        public final String getName()
        {
            return "OsmDownload-Thread";
        }

        public final String getState()
        {
            return this.state;
        }

        public final int getConnectTimeout()
        {
            return connectTimeout;
        }

        public int getReadTimeout()
        {
            return readTimeout;
        }

        public void setReadTimeout(int readTimeout)
        {
            this.readTimeout = readTimeout;
        }

        public int getStaleRequestLimit()
        {
            return staleRequestLimit;
        }

        public void setStaleRequestLimit(int staleRequestLimit)
        {
            this.staleRequestLimit = staleRequestLimit;
        }

        public final void setConnectTimeout(int connectTimeout)
        {
            this.connectTimeout = connectTimeout;
        }

        public long getSubmitTime()
        {
            return submitTime;
        }

        public void setSubmitTime(long submitTime)
        {
            this.submitTime = submitTime;
        }

        public long getBeginTime()
        {
            return beginTime;
        }

        public void setBeginTime(long beginTime)
        {
            this.beginTime = beginTime;
        }

        public long getEndTime()
        {
            return endTime;
        }

        public void setEndTime(long endTime)
        {
            this.endTime = endTime;
        }

        public final Retriever call() throws Exception
        {
            if (this.interrupted())
                return this;

            this.setState(RETRIEVER_STATE_STARTED);
            contentType = "OpenStreetMapLayer";

            Logging.logger().info("Downloading");
            long start = System.currentTimeMillis();

            if (this.interrupted())
                return this;

            this.setState(RETRIEVER_STATE_CONNECTING);
            BoundingBoxDownloader downloader = new BoundingBoxDownloader(visible.getMinLatitude().degrees,
                                                                         visible.getMinLongitude().degrees,
                                                                         visible.getMaxLatitude().degrees,
                                                                         visible.getMaxLongitude().degrees);

            if (this.interrupted()) {
                return this;
            }

            this.setState(RETRIEVER_STATE_READING);
            IDataSet data = downloader.parseOsm();

            Bounds visibleBounds = new Bounds(visible.getMinLatitude().degrees,
                                              visible.getMinLongitude().degrees,
                                              visible.getMaxLatitude().degrees,
                                              visible.getMaxLongitude().degrees);
            for (Iterator<Way> ways = data.getWays(visibleBounds); ways.hasNext();) {
                Way way = ways.next();
                if (!displayData.containsWay(way)) {
                    if (visit(data, way))
                        contentLength++;
                    displayData.addWay(way);
                }
            }

            if (!this.interrupted())
                this.setState(RETRIEVER_STATE_SUCCESSFUL);

            long end = System.currentTimeMillis();
            Logging.logger().info("Displayed " + contentLength + " in " + (end - start) + " ms");

            return this;
        }

        public boolean visit(IDataSet data, final Way w) {
            String highway = WayHelper.getTag(w, Tags.TAG_HIGHWAY);
            if (highway == null) {
                return false;
            }

            //-------

            ShapeAttributes attributes = WAYSTYLEBYHIGHWAY.get(highway);
            if (attributes == null)
                attributes = DEFAULTWAYCOLOR;
            int i = 0;
            List<WayNode> waynodes = w.getWayNodes();
            VecBuffer vecbuffer = new VecBuffer(2, waynodes.size(), new BufferFactory.DoubleBufferFactory());
            for (WayNode waynode : waynodes) {
                Node n = data.getNodeByID(waynode.getNodeId());
                LatLon node = LatLon.fromDegrees(n.getLatitude(), n.getLongitude());
                vecbuffer.putLocation(i, node);
                i++;
            }
            SurfacePolylines pl = getSurfacePolylines(highway);
            CompoundVecBuffer buf;
            if (pl == null) {
                buf = new CompoundVecBuffer(2, new BufferFactory.DoubleBufferFactory(), 10, 10);
            } else {
                buf = pl.getBuffer();
            }
            buf.appendSubBuffer(vecbuffer);

            if (pl == null) {
                pl = new SurfacePolylines(buf);
                pl.setAttributes(attributes);
                osmL.addRenderable(pl);
            }
            return true;
        }

        private SurfacePolylines getSurfacePolylines(String type) {
            if (type.equals("motorway")) {
                return motorwayroad;
            } else if (type.equals("trunk")) {
                return trunkroad;
            } else if (type.equals("secondary")) {
                return secondaryroad;
            } else if (type.equals("motorway_link")) {
                return motorwaylinkroad;
            } else if (type.equals("primary_link")) {
                return primarylinkroad;
            } else if (type.equals("primary")) {
                return primaryroad;
            } else if (type.equals("residential")) {
                return residentialroad;
            } else if (type.equals("footway")
                       || type.equals("cycleway")
                       || type.equals("steps")) {
                return forbiddenroad;
            }
            return defaultway;
        }

        private void setState(String state)
        {
            String oldState = this.state;
            this.state = state;
            this.firePropertyChange(AVKey.RETRIEVER_STATE, oldState, this.state);
        }

        private boolean interrupted()
        {
            if (Thread.currentThread().isInterrupted())
                {
                    this.setState(RETRIEVER_STATE_INTERRUPTED);
                    String message = Logging.getMessage("URLRetriever.RetrievalInterruptedFor", "OpenStreetMapLayer");
                    Logging.logger().fine(message);
                    return true;
                }
            return false;
        }

    }
}
gk_fabs is offline   Reply With Quote
Reply

Tags
layer, openstreetmap


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may post new threads
You may post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Plugin: My favorite Icons - Add Icons/Favorite canosso Add-ons & Scripts 26 03-02-2010 03:06 AM
WW1.3.2-Plugin: Layer Edit canosso Add-ons & Scripts 21 02-27-2010 04:37 AM
[Solved] How to add OpenStreetMap layer? linnuxxy Development Help 37 02-11-2010 05:36 PM
Layer Priority WWG Add-on & Script Development 3 12-08-2005 01:01 PM
GPX to Track and Layer, Waypoints to Layer canosso Add-ons & Scripts 14 03-05-2005 06:37 PM


All times are GMT +1. The time now is 07:10 AM.


Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.