Hello.
You can do this using textures.
For example, convert geographic coordinates to the texture coordinates, and find the closest pink point using some algorithm (eg, A-Star).
But I think it will be very slow solution, because it requires a lot of of calculations.
Much better is define the geofence as an array of points.
For example:
using System;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class GeofenceExample : MonoBehaviour
{
public List<Geofence> geofences;
private void InitGeofences()
{
int countGeofences = Random.Range(5, 10);
geofences = new List<Geofence>();
for (int i = 0; i < countGeofences; i++)
{
int countPoints = Random.Range(4, 20);
float radius = Random.Range(1, 10f);
double centerLng = Random.Range(-180, 180f);
double centerLat = Random.Range(-60, 60f);
float radiusOffset = Random.Range(0, radius / 4);
float angleOffset = Random.Range(0, 180f / countPoints);
double[] points = new double[countPoints * 2];
double left = double.PositiveInfinity, right = double.NegativeInfinity, top = double.NegativeInfinity, bottom = double.PositiveInfinity;
List<Vector2> drawingPoints = new List<Vector2>();
for (int j = 0; j < countPoints; j++)
{
float angle = 360f / countPoints * j + Random.Range(-angleOffset, angleOffset);
double lng = centerLng + Random.Range(radius - radiusOffset, radius + radiusOffset) * Mathf.Cos(angle * Mathf.Deg2Rad);
double lat = centerLat + Random.Range(radius - radiusOffset, radius + radiusOffset) * Mathf.Sin(angle * Mathf.Deg2Rad);
drawingPoints.Add(new Vector2((float) lng, (float) lat));
if (left > lng) left = lng;
if (right < lng) right = lng;
if (top < lat) top = lat;
if (bottom > lat) bottom = lat;
points[j * 2] = lng;
points[j * 2 + 1] = lat;
}
geofences.Add(new Geofence
{
id = i.ToString(),
left = left,
right = right,
top = top,
bottom = bottom,
points = points
});
OnlineMaps.instance.AddDrawingElement(new OnlineMapsDrawingPoly(drawingPoints, Color.red, 3));
}
}
private void OnMapClick()
{
double lng, lat;
OnlineMapsControlBase.instance.GetCoords(out lng, out lat);
double closestSqrDistance = double.PositiveInfinity;
foreach (Geofence geofence in geofences)
{
if (geofence.Contains(lng, lat, ref closestSqrDistance))
{
Debug.Log("Hit " + geofence.id);
return;
}
}
Debug.Log("Closest Distance " + Math.Sqrt(closestSqrDistance) + " km");
}
private void Start()
{
InitGeofences();
OnlineMapsControlBase.instance.OnMapClick += OnMapClick;
}
public class Geofence
{
public string id;
// The boundaries of geofence.
public double left, right, top, bottom;
// Points of geofence (0 - lng, 1 - lat, 2 - lng, 3 - lat, ...).
// Or it can be Vector2[].
public double[] points;
public bool Contains(double lng, double lat, ref double closestSqrDistance)
{
double d = left - lng;
if (d > 180) lng += 360;
else if (d < -180) lng -= 360;
if (lng < left || lng > right || lat > top || lat < bottom)
{
double dx, dy;
OnlineMapsUtils.DistanceBetweenPoints(left, top, lng, lat, out dx, out dy);
if (dx * dx + dy * dy < closestSqrDistance)
{
UpdateClosestDistance(lng, lat, ref closestSqrDistance);
return false;
}
OnlineMapsUtils.DistanceBetweenPoints(right, top, lng, lat, out dx, out dy);
if (dx * dx + dy * dy < closestSqrDistance)
{
UpdateClosestDistance(lng, lat, ref closestSqrDistance);
return false;
}
OnlineMapsUtils.DistanceBetweenPoints(left, bottom, lng, lat, out dx, out dy);
if (dx * dx + dy * dy < closestSqrDistance)
{
UpdateClosestDistance(lng, lat, ref closestSqrDistance);
return false;
}
OnlineMapsUtils.DistanceBetweenPoints(right, bottom, lng, lat, out dx, out dy);
if (dx * dx + dy * dy < closestSqrDistance) UpdateClosestDistance(lng, lat, ref closestSqrDistance);
return false;
}
bool isPointInPolygon = OnlineMapsUtils.IsPointInPolygon(points, lng, lat);
if (!isPointInPolygon) UpdateClosestDistance(lng, lat, ref closestSqrDistance);
else closestSqrDistance = 0;
return isPointInPolygon;
}
private void UpdateClosestDistance(double lng, double lat, ref double closestSqrDistance)
{
for (int i = 0; i < points.Length; i += 2)
{
double dx, dy;
OnlineMapsUtils.DistanceBetweenPoints(lng, lat, points[i], points[i + 1], out dx, out dy);
double sqrDistance = dx * dx + dy * dy;
if (sqrDistance < closestSqrDistance) closestSqrDistance = sqrDistance;
}
}
}
}
This will work much faster.
It uses a small cheating - is calculated the distance to the point.
If you want a more accurate result, use OnlineMapsUtils.NearestPointStrict.
Kind Regards,
Infinity Code Team.
Boost your productivity a lot and immediately using
Ultimate Editor Enhancer.
Trial and non-commerce versions available.