Topic: Draw roads and water by OSM Overpass API

I bought the asset from asset store a few days ago. 
I found that there is a component which can let me draw buildings by the data from Overpass API.
However, I can't found the way to draw the roads, water and parks from the API Data.

Can you give me some hints on how to achieve it?

What I want to do with Online Map is something like the below link.  Thank you very much.

http://barankahyaoglu.com/dev/pokemongo … i-unity3d/

Re: Draw roads and water by OSM Overpass API

Hello.

OSM Overpass API is a very powerful technology that can give you these objects.
To make a request to use OSM Overpass OnlineMapsOSMAPIQuery.Find:
http://infinity-code.com/doxygen/online … 57b09e3d01
For example, to get the roads use:
node ({bry}, {tlx}, {tly}, {brx}); way(bn)[ 'highway']; (._;>;); out;
where tlx, tly, brx, bry - coordinates of map corners.

Full list of tags:
http://wiki.openstreetmap.org/wiki/Map_Features
Next you will need to generate meshes based on coordinates of the points.
Example of how to do this you can see in «OnlineMapsBuildingBuiltIn.Create» script.

But I think to use OSM Overpass API, to just draw these objects is a bad idea.
It is much better to make a stylized map using snazzymaps or mapbox.
In this case, you can have any style of map, and it will work fast.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

3 (edited by 89452876 2016-09-06 08:04:54)

Re: Draw roads and water by OSM Overpass API

Hello, I tried to follow <Online Map Building BuiltIn.Create> write script generation road, but it seems to be wrong, please give me some tips, thank you

Re: Draw roads and water by OSM Overpass API

Hello.

Sorry for the long answer.
Creation of example takes time.

using System;
using System.Collections.Generic;
using UnityEngine;

public class GenerateRoadsExample:MonoBehaviour
{
    public OnlineMapsRange zoomRange = new OnlineMapsRange(19, 20);

    private OnlineMaps map;
    private OnlineMapsTileSetControl control;

    private OnlineMapsVector2i topLeft;
    private OnlineMapsVector2i bottomRight;
    private float lastRequestTime;
    private float requestRate = 0.1f;
    private string requestData;
    private OnlineMapsOSMAPIQuery osmRequest;
    private Mesh roadsMesh;
    private Dictionary<string, OnlineMapsOSMNode> nodes;
    private List<OnlineMapsOSMWay> ways;

    private void DrawRoad(OnlineMapsOSMWay way, List<OnlineMapsOSMNode> usedNodes, List<Vector3> vertices, List<Vector3> normals, List<Vector2> uv, List<int> triangles, float width, double tlx, double tly, double brx, double bry, float bestElevationYScale)
    {
        way.GetNodes(nodes, usedNodes);
        List<Vector3> points = GetLocalPoints(usedNodes);

        if (points.Count < 2) return;

        float w2 = width * 2;
        Vector3 prevS1 = Vector3.zero;
        Vector3 prevS2 = Vector3.zero;

        for (int i = 0; i < points.Count; i++)
        {
            float px = points[i].x;
            float pz = points[i].z;

            Vector3 s1 = Vector3.zero;
            Vector3 s2 = Vector3.zero;

            if (i == 0 || i == points.Count - 1)
            {
                float p1x, p1z, p2x, p2z;

                if (i == 0)
                {
                    p1x = px;
                    p1z = pz;
                    Vector3 np = points[i + 1];
                    p2x = np.x;
                    p2z = np.z;
                }
                else
                {
                    Vector3 pp = points[i - 1];
                    p1x = pp.x;
                    p1z = pp.z;
                    p2x = px;
                    p2z = pz;
                }

                float a = OnlineMapsUtils.Angle2DRad(p1x, p1z, p2x, p2z, 90);
                float offX = Mathf.Cos(a) * width;
                float offZ = Mathf.Sin(a) * width;
                float s1x = px + offX;
                float s1z = pz + offZ;
                float s2x = px - offX;
                float s2z = pz - offZ;

                float s1y = control.GetElevationValue(s1x, s1z, bestElevationYScale, tlx, tly, brx, bry);
                float s2y = control.GetElevationValue(s2x, s2z, bestElevationYScale, tlx, tly, brx, bry);

                s1 = new Vector3(s1x, s1y, s1z);
                s2 = new Vector3(s2x, s2y, s2z);
            }
            else
            {
                Vector3 pp = points[i - 1];
                Vector3 np = points[i + 1];

                float p1x = pp.x;
                float p1z = pp.z;
                float p2x = np.x;
                float p2z = np.z;

                float a1 = OnlineMapsUtils.Angle2DRad(p1x, p1z, px, pz, 90);
                float a2 = OnlineMapsUtils.Angle2DRad(px, pz, p2x, p2z, 90);

                float off1x = Mathf.Cos(a1) * width;
                float off1z = Mathf.Sin(a1) * width;
                float off2x = Mathf.Cos(a2) * width;
                float off2z = Mathf.Sin(a2) * width;

                float p21x = px + off1x;
                float p21z = pz + off1z;
                float p22x = px - off1x;
                float p22z = pz - off1z;
                float p31x = px + off2x;
                float p31z = pz + off2z;
                float p32x = px - off2x;
                float p32z = pz - off2z;

                float is1x, is1z, is2x, is2z;

                int state1 = OnlineMapsUtils.GetIntersectionPointOfTwoLines(p1x + off1x, p1z + off1z, p21x, p21z, p31x, p31z, p2x + off2x, p2z + off2z, out is1x, out is1z);
                int state2 = OnlineMapsUtils.GetIntersectionPointOfTwoLines(p1x - off1x, p1z - off1z, p22x, p22z, p32x, p32z, p2x - off2x, p2z - off2z, out is2x, out is2z);

                if (state1 == 1 && state2 == 1)
                {
                    float o1x = is1x - px;
                    float o1z = is1z - pz;
                    float o2x = is2x - px;
                    float o2z = is2z - pz;

                    float m1 = Mathf.Sqrt(o1x * o1x + o1z * o1z);
                    float m2 = Mathf.Sqrt(o2x * o2x + o2z * o2z);

                    if (m1 > w2)
                    {
                        is1x = o1x / m1 * w2 + px;
                        is1z = o1z / m1 * w2 + pz;
                    }
                    if (m2 > w2)
                    {
                        is2x = o2x / m2 * w2 + px;
                        is2z = o2z / m2 * w2 + pz;
                    }

                    s1 = new Vector3(is1x, control.GetElevationValue(is1x, is1z, bestElevationYScale, tlx, tly, brx, bry), is1z);
                    s2 = new Vector3(is2x, control.GetElevationValue(is2x, is2z, bestElevationYScale, tlx, tly, brx, bry), is2z);
                }
                else
                {
                    float po1x = p1x + off1x;
                    float po1z = p1z + off1z;
                    float po2x = p2x - off1x;
                    float po2z = p2z - off1z;

                    s1 = new Vector3(po1x, control.GetElevationValue(po1x, po1z, bestElevationYScale, tlx, tly, brx, bry), po1z);
                    s2 = new Vector3(po2x, control.GetElevationValue(po2x, po2z, bestElevationYScale, tlx, tly, brx, bry), po2z);
                }
            }

            if (i > 0)
            {
                int ti = vertices.Count;

                vertices.Add(prevS1);
                vertices.Add(s1);
                vertices.Add(s2);
                vertices.Add(prevS2);

                normals.Add(Vector3.up);
                normals.Add(Vector3.up);
                normals.Add(Vector3.up);
                normals.Add(Vector3.up);

                uv.Add(new Vector2(0, 0));
                uv.Add(new Vector2(0, 1));
                uv.Add(new Vector2(1, 1));
                uv.Add(new Vector2(1, 0));

                triangles.Add(ti);
                triangles.Add(ti + 1);
                triangles.Add(ti + 2);
                triangles.Add(ti);
                triangles.Add(ti + 2);
                triangles.Add(ti + 3);
            }

            prevS1 = s1;
            prevS2 = s2;
        }
    }

    protected List<Vector3> GetLocalPoints(List<OnlineMapsOSMNode> nodes)
    {
        double tlx, tly;
        map.GetTopLeftPosition(out tlx, out tly);

        double sx, sy;
        map.projection.CoordinatesToTile(tlx, tly, map.buffer.apiZoom, out sx, out sy);

        List<Vector3> localPoints = new List<Vector3>(nodes.Count);

        float sw = OnlineMapsUtils.tileSize * map.tilesetSize.x / map.tilesetWidth;
        float sh = OnlineMapsUtils.tileSize * map.tilesetSize.y / map.tilesetHeight;

        for (int i = 0; i < nodes.Count; i++)
        {
            double px, py;
            map.projection.CoordinatesToTile(nodes[i].lon, nodes[i].lat, map.buffer.apiZoom, out px, out py);

            localPoints.Add(new Vector3((float)(-(px - sx) * sw), 0, (float)((py - sy) * sh)));
        }
        return localPoints;
    }

    private void OnRoadRequestComplete(string response)
    {
        osmRequest = null;
        List<OnlineMapsOSMRelation> relations;
        OnlineMapsOSMAPIQuery.ParseOSMResponse(response, out nodes, out ways, out relations);
    }

    private void PrepareRequest()
    {
        double tlx, tly, brx, bry;
        map.projection.TileToCoordinates(topLeft.x, topLeft.y, map.zoom, out tlx, out tly);
        map.projection.TileToCoordinates(bottomRight.x, bottomRight.y, map.zoom, out brx, out bry);

        requestData = String.Format("node({0},{1},{2},{3});way(bn)['highway'];(._;>;);out;", bry, tlx, tly, brx);
    }

    private void SendRequest()
    {
        if (osmRequest != null || string.IsNullOrEmpty(requestData)) return;

        osmRequest = OnlineMapsOSMAPIQuery.Find(requestData);
        osmRequest.OnComplete += OnRoadRequestComplete;
        lastRequestTime = Time.time;
        requestData = null;
    }

    private void Start()
    {
        map = OnlineMaps.instance;
        control = OnlineMapsTileSetControl.instance;

        GameObject roadsGO = new GameObject("Roads");
        MeshFilter meshFilter = roadsGO.AddComponent<MeshFilter>();
        MeshRenderer meshRenderer = roadsGO.AddComponent<MeshRenderer>();
        meshRenderer.material = new Material(Shader.Find("Transparent/Diffuse"));
        roadsMesh = meshFilter.sharedMesh = new Mesh();
        roadsMesh.name = "Roads";
        roadsMesh.MarkDynamic();
    }

    private void Update()
    {
        if (!zoomRange.InRange(map.zoom))
        {
            roadsMesh.Clear();
            return;
        }

        double tlx, tly, brx, bry;
        map.GetTopLeftPosition(out tlx, out tly);
        map.GetBottomRightPosition(out brx, out bry);
        map.projection.CoordinatesToTile(tlx, tly, map.zoom, out tlx, out tly);
        map.projection.CoordinatesToTile(brx, bry, map.zoom, out brx, out bry);

        OnlineMapsVector2i newTopLeft = new OnlineMapsVector2i((int) Math.Round(tlx - 2), (int) Math.Round(tly - 2));
        OnlineMapsVector2i newBottomRight = new OnlineMapsVector2i((int) Math.Round(brx + 2), (int) Math.Round(bry + 2));

        if (newTopLeft != topLeft || newBottomRight != bottomRight)
        {
            topLeft = newTopLeft;
            bottomRight = newBottomRight;
            PrepareRequest();
        }

        if (lastRequestTime + requestRate < Time.time) SendRequest();

        UpdateRoadsMesh();
    }

    private void UpdateRoadsMesh()
    {
        roadsMesh.Clear();

        if (ways == null || ways.Count == 0) return;

        float width = 12f * (1 << map.zoom) / (1 << 19);

        double tlx, tly, brx, bry;

        map.GetTopLeftPosition(out tlx, out tly);
        map.GetBottomRightPosition(out brx, out bry);

        if (brx < tlx) brx += 360;

        float bestElevationYScale = control.GetBestElevationYScale(tlx, tly, brx, bry);

        List<OnlineMapsOSMNode> usedNodes = new List<OnlineMapsOSMNode>(30);
        List<Vector3> vertices = new List<Vector3>(128);
        List<Vector3> normals = new List<Vector3>(128);
        List<Vector2> uv = new List<Vector2>(128);
        List<int> triangles = new List<int>(128);

        foreach (OnlineMapsOSMWay way in ways) DrawRoad(way, usedNodes, vertices, normals, uv, triangles, width, tlx, tly, brx, bry, bestElevationYScale);

        roadsMesh.vertices = vertices.ToArray();
        roadsMesh.normals = normals.ToArray();
        roadsMesh.uv = uv.ToArray();
        roadsMesh.SetTriangles(triangles.ToArray(), 0);
    }
}
Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.