<?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 — Rasterization drawing elements]]></title>
		<link>https://forum.infinity-code.com/viewtopic.php?id=1478</link>
		<atom:link href="https://forum.infinity-code.com/extern.php?action=feed&amp;tid=1478&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[The most recent posts in Rasterization drawing elements.]]></description>
		<lastBuildDate>Wed, 25 Mar 2020 20:00:12 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Rasterization drawing elements]]></title>
			<link>https://forum.infinity-code.com/viewtopic.php?pid=6108#p6108</link>
			<description><![CDATA[<p><span class="postimg"><img src="https://infinity-code.com/sites/default/files/styles/full_post/public/images/news/2020.03.25%20-%20Online%20Maps%20-%20Rasterization%20drawing%20elements.jpg?itok=ASJ0hbQ6" alt="https://infinity-code.com/sites/default/files/styles/full_post/public/images/news/2020.03.25%20-%20Online%20Maps%20-%20Rasterization%20drawing%20elements.jpg?itok=ASJ0hbQ6" /></span></p><p>When you need to display very complex drawing elements, such as country or state borders, the best way is to rasterize it into tiles and use it as overlay.</p><p>Example of how to rasterize drawing elements:<br /></p><div class="codebox"><pre><code>using System.Collections;
using System.IO;
using UnityEngine;

public class RasterizeDrawingForOverlay : MonoBehaviour
{
    public int zoomFrom = 1;
    public int zoomTo = 10;

    private bool started = false;
    private IEnumerator routine;
    private Texture2D texture;
    private Color32[] colors;
    private OnlineMaps map;

    private void Finish()
    {
        Destroy(texture);
        texture = null;
        colors = null;
        map = null;

#if UNITY_EDITOR
        UnityEditor.AssetDatabase.Refresh();
#endif
    }

    private void GetBounds(out double lx, out double ty, out double rx, out double by)
    {
        lx = double.MaxValue;
        ty = double.MinValue;
        rx = double.MinValue;
        by = double.MaxValue;

        foreach (var el in OnlineMapsDrawingElementManager.instance)
        {
            if (el is OnlineMapsDrawingRect)
            {
                OnlineMapsDrawingRect rect = el as OnlineMapsDrawingRect;
                UpdateBounds(ref lx, ref ty, ref rx, ref by, rect.x, rect.y);
                UpdateBounds(ref lx, ref ty, ref rx, ref by, rect.x + rect.width, rect.y + rect.height);
                continue;
            }

            IEnumerable points;
            if (el is OnlineMapsDrawingLine) points = (el as OnlineMapsDrawingLine).points;
            else if (el is OnlineMapsDrawingPoly) points = (el as OnlineMapsDrawingPoly).points;
            else continue;

            int valueType = -1; // 0 - Vector2, 1 - float, 2 - double, 3 - OnlineMapsVector2d
            object v1 = null;
            int i = -1;
            double ppx = 0;

            foreach (object p in points)
            {
                i++;

                if (valueType == -1)
                {
                    if (p is Vector2) valueType = 0;
                    else if (p is float) valueType = 1;
                    else if (p is double) valueType = 2;
                    else if (p is OnlineMapsVector2d) valueType = 3;
                }

                object v2 = v1;
                v1 = p;

                double px = 0;
                double py = 0;

                if (valueType == 0)
                {
                    if (i == 0)
                    {
                        Vector2 p1 = (Vector2)v1;
                        ppx = p1.x;
                        UpdateBounds(ref lx, ref ty, ref rx, ref by, p1.x, p1.y);
                        continue;
                    }

                    Vector2 v = (Vector2) v1;
                    px = v.x;
                    py = v.y;
                }
                else if (valueType == 3)
                {
                    if (i == 0)
                    {
                        OnlineMapsVector2d p1 = (OnlineMapsVector2d)v1;
                        ppx = p1.x;
                        UpdateBounds(ref lx, ref ty, ref rx, ref by, p1.x, p1.y);
                        continue;
                    }

                    Vector2 v = (OnlineMapsVector2d)v1;
                    px = v.x;
                    py = v.y;
                }
                else if (i % 2 == 1)
                {
                    if (i == 1)
                    {
                        if (valueType == 1)
                        {
                            ppx = (float)v2;
                            UpdateBounds(ref lx, ref ty, ref rx, ref by, ppx, (float)v1);
                        }
                        else
                        {
                            ppx = (double)v2;
                            UpdateBounds(ref lx, ref ty, ref rx, ref by, ppx, (double)v1);
                        }
                        continue;
                    }

                    if (valueType == 1)
                    {
                        px = (float) v2;
                        py = (float) v1;
                    }
                    else
                    {
                        px = (double) v2;
                        py = (double) v1;
                    }
                }

                while (true)
                {
                    double ox = px - ppx;

                    if (ox &gt; 180) px -= 360;
                    else if (ox &lt; -180) px += 360;
                    else break;
                }

                UpdateBounds(ref lx, ref ty, ref rx, ref by, px, py);

                ppx = px;
            }
        }
    }

    private void OnGUI()
    {
        if (!started)
        {
            if (GUILayout.Button(&quot;Rasterize&quot;))
            {
                routine = Rasterize();
                StartCoroutine(routine);
            }
        }
        else
        {
            if (GUILayout.Button(&quot;Cancel&quot;))
            {
                StopCoroutine(routine);
                Finish();
            }
        }
    }

    public IEnumerator Rasterize()
    {
        if (OnlineMapsDrawingElementManager.CountItems == 0) yield break;

        double lx, ty, rx, by;
        GetBounds(out lx, out ty, out rx, out by);

        map = OnlineMaps.instance;
        texture = new Texture2D(256, 256, TextureFormat.ARGB32, false);
        colors = new Color32[256 * 256];

        for (int z = zoomFrom; z &lt;= zoomTo; z++)
        {
            int max = 1 &lt;&lt; z;

            double tlx, tty, trx, tby;
            map.projection.CoordinatesToTile(lx, ty, z, out tlx, out tty);
            map.projection.CoordinatesToTile(rx, by, z, out trx, out tby);

            int ilx = (int) tlx;
            int ity = (int) tty;
            int irx = (int) trx;
            int iby = (int) tby;

            if (ilx &gt; irx) irx += max;

            for (int x = ilx; x &lt;= irx; x++)
            {
                int cx = x;
                if (cx &gt;= max) cx -= max;

                for (int y = ity; y &lt;= iby; y++)
                {
                    yield return RasterizeTile(z, cx, y);
                }
            }
        }

        Finish();
    }

    private IEnumerator RasterizeTile(int zoom, int x, int y)
    {
        yield return null;

        Color32 empty = new Color32(255, 255, 255, 0);
        for (int i = 0; i &lt; 256 * 256; i++) colors[i] = empty;

        Vector2 bufferPos = map.buffer.topLeftPosition;
        double sx, sy;
        map.projection.TileToCoordinates(bufferPos.x, bufferPos.y, map.buffer.lastState.zoom, out sx, out sy);

        Vector2 bufferPosition = new Vector2(x, y);

        foreach (OnlineMapsDrawingElement el in map.control.drawingElementManager)
        {
            el.Draw(colors, bufferPosition, 256, 256, zoom);
        }

        bool hasColor = false;
        for (int i = 0; i &lt; 256 * 256; i++)
        {
            if (colors[i].a != 0)
            {
                hasColor = true;
                break;
            }
        }

        if (!hasColor)
        {
            Debug.Log(&quot;Ignore &quot; + zoom + &quot;/&quot; + x + &quot;/&quot; + y);
            yield break;
        }

        texture.SetPixels32(colors);
        texture.Apply(false);

        byte[] bytes = texture.EncodeToPNG();

        string path = Application.dataPath + &quot;/Resources/DrawingTiles/&quot; + zoom + &quot;/&quot; + x + &quot;/&quot; + y + &quot;.png&quot;;
        Debug.Log(path);
        FileInfo info = new FileInfo(path);
        if (!info.Directory.Exists) info.Directory.Create();

        File.WriteAllBytes(path, bytes);
    }

    private static void UpdateBounds(ref double lx, ref double ty, ref double rx, ref double by, double px, double py)
    {
        if (px &lt; lx) lx = px;
        if (px &gt; rx) rx = px;

        if (py &gt; ty) ty = py;
        if (py &lt; by) by = py;
    }
}</code></pre></div><p>P.S. Online Maps v3.6 and below contains a bug due to which this will not work for Tileset.<br />To fix it, update Online Maps to version 3.7 or higher (if present), or modify OnlineMapsDrawingElement.DrawLineToBuffer (line 454):<br /></p><div class="codebox"><pre><code>manager.map.projection.CoordinatesToTile(tlx, tly, izoom, out sx, out sy);</code></pre></div><p>to<br /></p><div class="codebox"><pre><code>manager.map.projection.CoordinatesToTile(0, 0, izoom, out sx, out sy);</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Alex Vertax)]]></author>
			<pubDate>Wed, 25 Mar 2020 20:00:12 +0000</pubDate>
			<guid>https://forum.infinity-code.com/viewtopic.php?pid=6108#p6108</guid>
		</item>
	</channel>
</rss>
