<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Infinity Code Forum — Draw roads and water by OSM Overpass API]]></title>
		<link>https://forum.infinity-code.com/viewtopic.php?id=257</link>
		<atom:link href="https://forum.infinity-code.com/extern.php?action=feed&amp;tid=257&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[The most recent posts in Draw roads and water by OSM Overpass API.]]></description>
		<lastBuildDate>Thu, 08 Sep 2016 01:22:53 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: Draw roads and water by OSM Overpass API]]></title>
			<link>https://forum.infinity-code.com/viewtopic.php?pid=1214#p1214</link>
			<description><![CDATA[<p>Hello.</p><p>Sorry for the long answer.<br />Creation of example takes time.</p><div class="codebox"><pre><code>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&lt;string, OnlineMapsOSMNode&gt; nodes;
    private List&lt;OnlineMapsOSMWay&gt; ways;

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

        if (points.Count &lt; 2) return;

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

        for (int i = 0; i &lt; 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 &amp;&amp; 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 &gt; w2)
                    {
                        is1x = o1x / m1 * w2 + px;
                        is1z = o1z / m1 * w2 + pz;
                    }
                    if (m2 &gt; 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 &gt; 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&lt;Vector3&gt; GetLocalPoints(List&lt;OnlineMapsOSMNode&gt; 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&lt;Vector3&gt; localPoints = new List&lt;Vector3&gt;(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 &lt; 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&lt;OnlineMapsOSMRelation&gt; 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(&quot;node({0},{1},{2},{3});way(bn)[&#039;highway&#039;];(._;&gt;;);out;&quot;, 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(&quot;Roads&quot;);
        MeshFilter meshFilter = roadsGO.AddComponent&lt;MeshFilter&gt;();
        MeshRenderer meshRenderer = roadsGO.AddComponent&lt;MeshRenderer&gt;();
        meshRenderer.material = new Material(Shader.Find(&quot;Transparent/Diffuse&quot;));
        roadsMesh = meshFilter.sharedMesh = new Mesh();
        roadsMesh.name = &quot;Roads&quot;;
        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 &lt; Time.time) SendRequest();

        UpdateRoadsMesh();
    }

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

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

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

        double tlx, tly, brx, bry;

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

        if (brx &lt; tlx) brx += 360;

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

        List&lt;OnlineMapsOSMNode&gt; usedNodes = new List&lt;OnlineMapsOSMNode&gt;(30);
        List&lt;Vector3&gt; vertices = new List&lt;Vector3&gt;(128);
        List&lt;Vector3&gt; normals = new List&lt;Vector3&gt;(128);
        List&lt;Vector2&gt; uv = new List&lt;Vector2&gt;(128);
        List&lt;int&gt; triangles = new List&lt;int&gt;(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);
    }
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Alex Vertax)]]></author>
			<pubDate>Thu, 08 Sep 2016 01:22:53 +0000</pubDate>
			<guid>https://forum.infinity-code.com/viewtopic.php?pid=1214#p1214</guid>
		</item>
		<item>
			<title><![CDATA[Re: Draw roads and water by OSM Overpass API]]></title>
			<link>https://forum.infinity-code.com/viewtopic.php?pid=1203#p1203</link>
			<description><![CDATA[<p>Hello, I tried to follow &lt;Online Map Building BuiltIn.Create&gt; write script generation road, but it seems to be wrong, please give me some tips, thank you</p>]]></description>
			<author><![CDATA[null@example.com (89452876)]]></author>
			<pubDate>Tue, 06 Sep 2016 08:04:30 +0000</pubDate>
			<guid>https://forum.infinity-code.com/viewtopic.php?pid=1203#p1203</guid>
		</item>
		<item>
			<title><![CDATA[Re: Draw roads and water by OSM Overpass API]]></title>
			<link>https://forum.infinity-code.com/viewtopic.php?pid=1140#p1140</link>
			<description><![CDATA[<p>Hello.</p><p>OSM Overpass API is a very powerful technology that can give you these objects.<br />To make a request to use OSM Overpass OnlineMapsOSMAPIQuery.Find:<br /><a href="http://infinity-code.com/doxygen/online-maps/classOnlineMapsOSMAPIQuery.html#a6a0e2ecc8a370fa028631f57b09e3d01">http://infinity-code.com/doxygen/online … 57b09e3d01</a><br />For example, to get the roads use:<br />node ({bry}, {tlx}, {tly}, {brx}); way(bn)[ &#039;highway&#039;]; (._;&gt;;); out;<br />where tlx, tly, brx, bry - coordinates of map corners.</p><p>Full list of tags:<br /><a href="http://wiki.openstreetmap.org/wiki/Map_Features">http://wiki.openstreetmap.org/wiki/Map_Features</a><br />Next you will need to generate meshes based on coordinates of the points.<br />Example of how to do this you can see in «OnlineMapsBuildingBuiltIn.Create» script.</p><p>But I think to use OSM Overpass API, to just draw these objects is a bad idea.<br />It is much better to make a stylized map using snazzymaps or mapbox. <br />In this case, you can have any style of map, and it will work fast.</p>]]></description>
			<author><![CDATA[null@example.com (Alex Vertax)]]></author>
			<pubDate>Sun, 21 Aug 2016 14:11:11 +0000</pubDate>
			<guid>https://forum.infinity-code.com/viewtopic.php?pid=1140#p1140</guid>
		</item>
		<item>
			<title><![CDATA[Draw roads and water by OSM Overpass API]]></title>
			<link>https://forum.infinity-code.com/viewtopic.php?pid=1138#p1138</link>
			<description><![CDATA[<p>I bought the asset from asset store a few days ago.&nbsp; <br />I found that there is a component which can let me draw buildings by the data from Overpass API.<br />However, I can&#039;t found the way to draw the roads, water and parks from the API Data.</p><p>Can you give me some hints on how to achieve it?</p><p>What I want to do with Online Map is something like the below link.&nbsp; Thank you very much.</p><p><a href="http://barankahyaoglu.com/dev/pokemongo-clone-using-mapzen-api-unity3d/">http://barankahyaoglu.com/dev/pokemongo … i-unity3d/</a></p>]]></description>
			<author><![CDATA[null@example.com (Allen Walker)]]></author>
			<pubDate>Sun, 21 Aug 2016 13:27:12 +0000</pubDate>
			<guid>https://forum.infinity-code.com/viewtopic.php?pid=1138#p1138</guid>
		</item>
	</channel>
</rss>
