Topic: How to add Polygons programmatically?

Hi, I am using the CalcAreaExample script which I have slightly altered so that I can grab geolocations from a database and display them on the map as a polygon. I have no problem populating the map with markers, but no polygon gets created.

I have added my own public function AddMarker() which is pretty much exactly the same as the OnMouseUp()  function in the original script. The only difference is that I pass geocoordinates directly to it instead of cursor coordinates.

        public void AddMarker( float lat, float lon  )
        {
               
                // Get the geographical coordinates
                Vector2 cursorCoords = new Vector2 (lon,lat)  ; // 2d
               
                // Create a new marker at the specified coordinates.
                OnlineMapsMarker marker = map.AddMarker (cursorCoords, markerTexture, "Marker " + (map.markers.Length + 1));

                // Save marker and coordinates.
                markerPositions.Add(cursorCoords);
                markers.Add(marker);

                // Mark that markers changed.
                changed = true;
               
        }

I call this function from inside a coroutine that grabs the locations from the database.
Like so:

            GameObject MapO = GameObject.Find("Map");
        CalcArea calcarea = MapO.GetComponent <CalcArea>();
        OnlineMaps map = calcarea.map;
                ....
                [Code that gets the locations from the db]
                ....
                map.AddMarker (lon, lat);

Any idea why doing this does not draw a polygon while shift-clicking  (and this using  OnMouseUp() does? )

Thanks!

Re: How to add Polygons programmatically?

Hello.

I'm very confused by two lines:

public void AddMarker (float lat, float lon)
....
map.AddMarker (lon, lat);

Perhaps you've mixed the latitude and longitude?!

If the problem is somewhat different, please show the full script.

Kind Regards,
Infinity Code Team.

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

Re: How to add Polygons programmatically?

Oh, thanks- didn't catch that. But it made no difference when I fixed it.

I've put the full scripts below with a few security details starred out.

Basically, what happens is, when the user enters the scene, there is a map object with the CalcArea script attached.
The start function calls StartCoroutine (mysqlcontroller.getMarkers()  so that right away, it searches the db for geolocations. For reasons I won't get into here, the locations are stored in the db as radians instead of degrees, so there is some conversion happening, but basically that script gets the locations from db in a loop and one by one turns around and calls AddMarker() on the map object of the CalcArea script. It works - in that it adds the markers. But I was expecting that because the AddMarker() function I added was basically the same as the OnMouseUP() function, that Update() would create the polygon automatically, just as if I had hit left shift and added the markers by hand.  But it doesn't.

Thanks so much for your help by the way. You guys are AWESOME and I have already left a 5 star review.

Anyway, Here is the full AreaCalc Script:

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using LonelySharp;
using System.Collections;

namespace InfinityCode.OnlineMapsExamples

{
    /// <summary>
    /// Example of calculating the size of area.
    /// </summary>
    [AddComponentMenu("Infinity Code/Online Maps/Examples (API Usage)/CalcArea")]
    public class CalcArea : MonoBehaviour
    {
        /// <summary>
        /// Texture of marker
        /// </summary>
        public Texture2D markerTexture;

        /// <summary>
        /// Line width.
        /// </summary>
        public float borderWidth = 1;

        public OnlineMaps map;
    //    private OnlineMapsControlBase3D map;  // 3d? 
        private bool changed = false;
        private List<OnlineMapsMarker> markers = new List<OnlineMapsMarker>();
        private List<Vector2> markerPositions = new List<Vector2>();
        private OnlineMapsDrawingPoly polygon;
        public string locationsInDB;
        public GeoLocation geolocation ; 
        public MySQLController mysqlcontroller; 


        private float _borderWidth;

        private void CheckMarkerPositions()
        {
            // Check the position of each marker.
            for (int i = 0; i < markers.Count; i++)
            {
                if (markerPositions[i] != markers[i].position)
                {
                    // If the position marker changed, then change the value in markerPositions. 
                    // In the polygon value changes automatically.
                    markerPositions[i] = markers[i].position;
                    changed = true;
                }
            }
        }

        private void OnMouseUp()
        {
            if (Input.GetKey(KeyCode.LeftShift))
            {
                // Get the geographical coordinates of the cursor.
                     Vector2 cursorCoords = map.control.GetCoords();  // 2d
                //   Vector2 cursorCoords = map.UpdateControl.GetCoords();  //3d

                // Create a new marker at the specified coordinates.
            //    OnlineMapsMarker marker = map.AddMarker(cursorCoords, markerTexture, "Marker " + (map.markers.Length + 1));
                OnlineMapsMarker marker = map.AddMarker (cursorCoords, markerTexture, "Marker " + (map.markers.Length + 1));

                Debug.Log ("CalcArea: cursorCoords: "+ cursorCoords.ToString("R")  );

                // Save marker and coordinates.
                markerPositions.Add(cursorCoords);
                markers.Add(marker);

                // Mark that markers changed.
                changed = true;
            }
        }


        public void AddMarker( float lon , float lat)
        {
                
                // Get the geographical coordinates of the cursor.
            Vector2 cursorCoords = new Vector2 (lon, lat)  ; // 2d
                //   Vector2 cursorCoords = map.UpdateControl.GetCoords();  //3d

                // Create a new marker at the specified coordinates.
                //    OnlineMapsMarker marker = map.AddMarker(cursorCoords, markerTexture, "Marker " + (map.markers.Length + 1));
                OnlineMapsMarker marker = map.AddMarker (cursorCoords, markerTexture, "Marker " + (map.markers.Length + 1));

                // Save marker and coordinates.
                markerPositions.Add(cursorCoords);
                markers.Add(marker);

                // Mark that markers changed.
                changed = true;
                
        }

        



        private void Start()
        {
            // Get a reference to an instance of the map.
            map = OnlineMaps.instance;

            _borderWidth = borderWidth;

            // Get the scripts we need to talk to the db and interpret the results
            geolocation = GetComponent <GeoLocation> ();   
            mysqlcontroller = GetComponent <MySQLController> (); 

            // Run the DB Query (Must be run in a Coroutine as it is an IENumerator)
            StartCoroutine (mysqlcontroller.getMarkers() );
             
        }


    

        private void Update()
        {
            if (Math.Abs(_borderWidth - borderWidth) > float.Epsilon)
            {
                _borderWidth = borderWidth;
                if (polygon != null)
                {
                    polygon.borderWidth = borderWidth;
                    map.Redraw();
                }
            }

            // Check the position of the markers.
            CheckMarkerPositions();

            // If nothing happens, then return.
            if (!changed) return;
            changed = false;

            // If the number of points is less than 3, then return.
            if (markers.Count < 3)
            {
                map.Redraw();
                return;
            }

            // If the polygon is not created, then create.
            if (polygon == null)
            {
                // For points, reference to markerPositions. 
                // If you change the values in markerPositions, value in the polygon will be adjusted automatically.
                polygon = new OnlineMapsDrawingPoly(markerPositions, Color.green, borderWidth, new Color(0, 128, 0, 0.3f));
            
                // Add an element to the map.
                map.AddDrawingElement(polygon);
                polygon.checkMapBoundaries = false;
            }

            // Calculates area of the polygon.
            // Important: this algorithm works correctly only if the lines do not intersect.
            float area = 0;

            // Triangulate points.
            int[] indexes = OnlineMapsUtils.Triangulate(markerPositions).ToArray();

            // Calculate the area of each triangle.
            for (int i = 0; i < indexes.Length / 3; i++)
            {
                // Get the points of the triangle.
                Vector2 p1 = markerPositions[indexes[i * 3]];
                Vector2 p2 = markerPositions[indexes[i * 3 + 1]];
                Vector2 p3 = markerPositions[indexes[i * 3 + 2]];

                // Calculate the distance between points.
                float d1 = OnlineMapsUtils.DistanceBetweenPoints(p1, p2).magnitude;
                float d2 = OnlineMapsUtils.DistanceBetweenPoints(p2, p3).magnitude;
                float d3 = OnlineMapsUtils.DistanceBetweenPoints(p3, p1).magnitude;

                // Calculate the area.
                float p = (d1 + d2 + d3) / 2;
                area += Mathf.Sqrt(p * (p - d1) * (p - d2) * (p - d2));
            }

            Debug.Log("Area: " + area + " km^2");

            map.Redraw();
        }
    }
}


And here is the script for talking to the database:  (The relevant function is getMarkers () ) :


using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System;
using InfinityCode.OnlineMapsExamples;
using LonelySharp.Utilities;
using LonelySharp ;

public class MySQLController : MonoBehaviour
{
    private string secretKey = "**************"; // Edit this value and make sure it's the same as the one stored on the server
    public string postMessageURL = "************************";  
    public string updateMessageURL =""************************";
    public string getMessageURL = "************************";
    public string getMarkersURL = "************************";
    public string message ; 
    public double RadLatInDB;
    public double RadLonInDB;
    public string locationsInDb; 


    InputField debug;

    void Awake ()
    {
        //StartCoroutine(GetMessage());
    
    }
        

    void Start()
    {


    }

    // remember to use StartCoroutine when calling this function!
    public IEnumerator postMessage(string message, double radlat, double radlon, double lat, double lon)
    {
        //This connects to a server side php script that will add the name and score to a MySQL DB.
        // Supply it with a string representing the players name and the players score.
        //string hash = MD5Test.Md5Sum(name + score + secretKey);
        //string hash = Crypto.ComputeMD5Hash( name + score + secretKey);
        string post_url = ""; 

        if ( this.message == null) {

         // TO DO - Need to Escape URLS since getting BAD REQUEST ERROR
            post_url = postMessageURL + "Message=" + [url=://WWW.EscapeURL]WWW.EscapeURL[/url] (message) + "&RadLat=" + radlat + "&RadLon=" + radlon + "&MapURL=://maps.google.com/maps?q=" +lat + ","+ lon ;   //"' target='_blank'\>"+ lat + "," + lon + "\<\/ a \>";  //+ "&hash=" + hash;

        } else {

            post_url = updateMessageURL + "Message=" + [url=://WWW.EscapeURL]WWW.EscapeURL[/url] (message) + "&RadLat=" + radlat + "&RadLon=" + radlon + "&MapURL=://maps.google.com/maps?q=" +lat + ","+ lon ;  ; //"&MapURL=\< a href='://maps.google.com/maps?q=" +lat + ","+ lon +"' target='_blank'\>"+ lat + "," + lon + "\<\/ a \>";  //+ "&hash=" + hash;

        }
            

        // Post the URL to the site and create a download object to get the result.
        WWW hs_post = new WWW(post_url);
        yield return hs_post; // Wait until the download is done

        if (hs_post.error != null) {
            Debug.Log ("There was an error posting the message to MySQL: " + hs_post.error);
            debug.text = ("There was an error posting the message to MySQL: " + hs_post.error);

        } else if ( hs_post.text == "No message saved at location.")
        {
            Debug.Log (hs_post.text);
            debug.text = hs_post.text;
        }
        else
        {
            Debug.Log ("posted the message to MySQL: " + hs_post.text);
            debug.text = ("posted the message to MySQL: " + hs_post.text);
        }    

    }


        
    public IEnumerator getMarkers ()
    {

        string getmarkersurl = getMarkersURL;

//        GameObject debugInfoGO = GameObject.Find ("debugInfo");
        //InputField debugInfoCO = debugInfoGO.GetComponent<InputField> ();
        //debug = debugInfoCO; 


        GameObject MapO = GameObject.Find("Map");
        CalcArea calcarea = MapO.GetComponent <CalcArea>();
        OnlineMaps map = calcarea.map;

//        GeoLocation geolocation = GetComponent<GeoLocation>();

        WWW hs_get = new WWW(getmarkersurl); 
        yield return hs_get;

        if (hs_get.error != null) {
            Debug.Log ("There was an error getting the markers from the MySQL DB " + hs_get.error);
        //    debug.text = "There was an error getting the markers from the MySQL DB " + hs_get.error;
         

            yield return hs_get.error;

        } else if (hs_get.text == null || hs_get.text == "") {
            Debug.Log ("MySQLController: locations are null- probably nothing in DB yet.");
        //    debug.text = "MySQLController: locations are null- probably nothing in DB yet.";
         
            yield return hs_get.text;

        } else {

            Debug.Log ("MySQLController Got string back from DB: " + hs_get.text );
            //debug.text = "MySQLController: " + hs_get.text ;
            locationsInDb = hs_get.text; 




            string[] stringSeparators = new string[] {" ||| "};
            string[] markers = locationsInDb.Split (stringSeparators, StringSplitOptions.None); 


            //Debug.Log ("MySQLController: Converted string to array: " + string.Join( "," , markers ) );

             
//            string message; 
            double radlat;
            double radlon;
            float lat = 0f;
            float lon = 0f;

            for  ( int i = 0; i < markers.Length - 3; i+=3) 
            {
            //    message = markers[i]; 
                //Debug.Log ("MySQLController:  Message= "+ message);

                radlat = Convert.ToDouble  (markers[i+1]) ;
                lat = Convert.ToSingle (Helpers.ConvertRadiansToDegrees (radlat)); 
                //Debug.Log ("MySQLController:  lat= " + lat);
                     
                radlon = Convert.ToDouble (markers[i+2]);
                lon = Convert.ToSingle (Helpers.ConvertRadiansToDegrees (radlon)); 
                //Debug.Log ("MySQLController:  lon= " + lon);

                map.AddMarker (lon, lat);
                Debug.Log ("MySQLController: Added Marker to Map at lon= " + lon + " lat = " + lat);

            }
              
            yield break ; 
            //yield return locationsInDb;
                 
        }

            

    }




    // Get the message from the MySQL DB to display in a GUIText.
    // remember to use StartCoroutine when calling this function!
    public IEnumerator getMessage(double radLat, double radLon, double LatLower, double LongLower, double LatUpper, double LongUpper, double SearchRadius)
    {

        //Get The TextMesh where the inputField's text will be displayed
        GameObject word = GameObject.Find ("Word");
        TextMesh textMeshCo = word.GetComponentInChildren<TextMesh> ();


        GameObject debugInfoGO = GameObject.Find ("debugInfo");
        InputField debugInfoCO = debugInfoGO.GetComponent<InputField> ();
        debug = debugInfoCO; 

        string getURL = getMessageURL + "&RadLat=" + radLat + "&RadLon=" + radLon + "&LatLower=" + LatLower + "&LongLower=" + LongLower + "&LatUpper=" + LatUpper + "&LongUpper=" + LongUpper + "&SearchRadius=" + SearchRadius;  //+ "&hash=" + hash;

        //gameObject.guiText.text = "Loading Scores";
        //gameObject.GetComponent<GUIText>().text= "Loading Scores";
        WWW hs_get = new WWW(getURL);
        yield return hs_get;

        if (hs_get.error != null) 
        {
            Debug.Log ("There was an error getting the message from the MySQL DB " + hs_get.error);
            debug.text = "There was an error getting the message from the MySQL DB " + hs_get.error;
            message = null;
            // Make sure old message is not displayed 
            textMeshCo.text = "";

            yield return hs_get.error;
        } else if (hs_get.text == null || hs_get.text == "No message saved at location.") 
        {
            Debug.Log ("MySQLController: Message is null- probably nothing in DB yet.");
            debug.text = "MySQLController: Message is null- probably nothing in DB yet.";
            message = null; 
            // Make sure old message is not displayed 
            textMeshCo.text = "";
            yield return message; 

        } else 
        {
            // The getLocation.php script returned a www onject with the message from the db with the lat and lon 
            // So now we have to pull apart the message, lat and lon so that we can display the message 
            // and use the lat and lon if the user wants to replace the message 

            Debug.Log("Got message from MySQL DB: " + hs_get.text);
            debug.text ="Got message from MySQL DB: " + hs_get.text ;

            int separatorIndex1 = hs_get.text.LastIndexOf ('|') ; // "|" separates the message from the lat

            Debug.Log ("separatorIndex1: " + separatorIndex1);

            int separatorIndex2 = hs_get.text.LastIndexOf (',') ; //  "," separates the lat from the lon 
            
            Debug.Log ("separatorIndex2: " + separatorIndex2);

            message = hs_get.text.Substring(0, separatorIndex1 );

            Debug.Log ("message: " + message);

            RadLatInDB = Convert.ToDouble(hs_get.text.Substring(separatorIndex1 + 1  , separatorIndex2 - separatorIndex1 -1 ));

            Debug.Log ("Lat: " + RadLatInDB );

            RadLonInDB = Convert.ToDouble(hs_get.text.Substring(separatorIndex2 + 1));

            Debug.Log ("Lon: " + RadLonInDB);

            //Display the message in the db in text component of the Word Object. 
            // Doing this here so that it shows up right away. Otherwise, it doesn't display the first time
            textMeshCo.text = message;
            // Keep text centered on stop sign (more or less) 
            ConstrainText ct =  textMeshCo.GetComponentInChildren<ConstrainText> ();
            ct.DoConstrainText ();    



            yield return message;
            //gameObject.GetComponent<GUIText>().text = hs_get.text; // this is a GUIText that will display the scores in game.
            //gameObject.guiText.text = hs_get.text; // this is a GUIText that will display the scores in game.
        }
    }

}

Re: How to add Polygons programmatically?

I checked your code.
Please show me where you invoke CalcArea.AddMarker.
I do not see a single invoke of this method.
You invoke only OnlineMaps.AddMarker.

Kind Regards,
Infinity Code Team.

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

Re: How to add Polygons programmatically?

That was it!

THANK YOU!

Re: How to add Polygons programmatically?

Update:  Ok so that worked. But now, I'd like to add new polygons that aren't connected to the first one. How would I do that? I tried creating a new calcanea object but that didn't work. I also tried creating a new markers object but that just removed the polygon entirely.  Thanks !

Re: How to add Polygons programmatically?

If you want to create a new polygon, you need to create a new list of markers, marker positions, and drawing element.
Important: you need to create new elements instead of clear existing ones.

Kind Regards,
Infinity Code Team.

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

Re: How to add Polygons programmatically?

Thanks! I can now create polygons from the database of different colors. Brilliant. So pleased I got this asset.