Implementing Geofence - C# - c#

I need to implement Geofence in C#. Geofence area can be round, rectangle, polygon etc. Does anyone have Geofence implementation in C#?
I found Geo Fencing - point inside/outside polygon. But, it supports polygon only.

I have tested various implementations and this example worked properly for me:
Example
public static bool PolyContainsPoint(List<Point> points, Point p) {
bool inside = false;
// An imaginary closing segment is implied,
// so begin testing with that.
Point v1 = points[points.Count - 1];
foreach (Point v0 in points)
{
double d1 = (p.Y - v0.Y) * (v1.X - v0.X);
double d2 = (p.X - v0.X) * (v1.Y - v0.Y);
if (p.Y < v1.Y)
{
// V1 below ray
if (v0.Y <= p.Y)
{
// V0 on or above ray
// Perform intersection test
if (d1 > d2)
{
inside = !inside; // Toggle state
}
}
}
else if (p.Y < v0.Y)
{
// V1 is on or above ray, V0 is below ray
// Perform intersection test
if (d1 < d2)
{
inside = !inside; // Toggle state
}
}
v1 = v0; //Store previous endpoint as next startpoint
}
return inside;
}

Refer to my Implementation:
Polygon
Circle

Adding both C# implementation here
It worked for me!
//Location will hold the latitude and longitude.
public class Location
{
public double lat { get; set; }
public double lng { get; set; }
public Location(double lat, double lng)
{
this.lat = lat;
this.lng = lng;
}
}
//Implementation for the Polygon.
bool IsPointInPolygon(List<Location> poly, Location point)
{
int i, j;
bool c = false;
for (i = 0, j = poly.Count - 1; i < poly.Count; j = i++)
{
if ((((poly[i].lat <= point.lat) && (point.lat < poly[j].lat))
|| ((poly[j].lat <= point.lat) && (point.lat < poly[i].lat)))
&& (point.lng < (poly[j].lng - poly[i].lng) * (point.lat - poly[i].lat)
/ (poly[j].lat - poly[i].lat) + poly[i].lng))
{
c = !c;
}
}
return c;
}
//Geofencing for the Circle.
//GetDistance will return total Kilometers
//p1 is the Center lat,long and p2 is the current location lat,long
//radius in meters
public bool IsPointInCircle(Location p1,Location p2,double radius)
{
return GetDistance(p1,p2)>radius*0.001?false:true;
}
public double GetDistance(Location pos1, Location pos2)
{
double e = pos1.lat * (Math.PI / 180);
double f = pos1.lng * (Math.PI / 180);
double g = pos2.lat * (Math.PI / 180);
double h = pos2.lng * (Math.PI / 180);
double i =
(Math.Cos(e) * Math.Cos(g) * Math.Cos(f) * Math.Cos(h)
+ Math.Cos(e) * Math.Sin(f) * Math.Cos(g) * Math.Sin(h)
+ Math.Sin(e) * Math.Sin(g));
double j = Math.Acos(i);
return (6371 * j);
}

Related

Optimization of Loop of Large Points in Large Point Cloud

All I have the following implementation of a line detecting Hough transform for point clouds (collection of points in 3-space)
internal sealed class LineHoughTransform : ILineHoughTransform
{
private readonly double _dX;
private readonly double _maxX;
private readonly long _countX;
private readonly long _countB;
private readonly IDiscreetSphere _sphere;
public LineHoughTransform(Vector3 minParameterVector, Vector3 maxParameterVector, double dX, int sphereGranularity)
{
_dX = dX;
_sphere = new Icosahedron();
_sphere.Create(sphereGranularity);
_countB = _sphere.Points.Count;
_maxX = Math.Max(maxParameterVector.Norm(), minParameterVector.Norm());
var rangeX = 2 * _maxX;
if (_dX == 0.0)
_dX = rangeX / 64.0;
_countX = (long)(rangeX / _dX).RoundToNearest();
VotingSpace = new Dictionary<long, int>();
}
public int GetLine(ref Vector3 a, ref Vector3 b)
{
int votes = 0;
long index = 0;
foreach (var storedVote in VotingSpace)
{
if (storedVote.Value > votes)
{
votes = storedVote.Value;
index = storedVote.Key;
}
}
// Retrieve x' coordinate from VotingSpace[_countX * _countX * _countB].
double x = index / (_countX * _countB);
index -= (long)(x * _countX * _countB);
x = x * _dX - _maxX;
// Retrieve y' coordinate from VotingSpace[_countX * _countX * _countB].
double y = index / _countB;
index -= (long)y * _countB;
y = y * _dX - _maxX;
// Retrieve directional vector and Compute anchor point according to Eq. (3).
b = _sphere.Points[(int)index];
a.X = (float)(x * (1 - ((b.X * b.X) / (1 + b.Z))) - y * ((b.X * b.Y) / (1 + b.Z)));
a.Y = (float)(x * (-((b.X * b.Y) / (1 + b.Z))) + y * (1 - ((b.Y * b.Y) / (1 + b.Z))));
a.Z = (float)(-x * b.X - y * b.Y);
return votes;
}
public void Add(IPointCloud pointCloud)
{
CastVote(pointCloud, true);
}
public void Subtract(IPointCloud pointCloud)
{
CastVote(pointCloud, false);
}
private void CastVote(IPointCloud pointCloud, bool add)
{
if (pointCloud == null || pointCloud.Vertices == null)
return;
foreach (var vertex in pointCloud.Vertices)
PointVote(vertex.Point, add);
}
private void PointVote(Vector3 point, bool add)
{
// Loop over directions B.
for (int j = 0; j < _sphere.Points.Count; ++j)
{
// Denominator in Eq. (2).
Vector3 b = _sphere.Points[j];
double beta = 1 / (1 + b.Z);
// Compute x' and y' according to Eq. (2).
double newX = ((1 - (beta * (b.X * b.X))) * point.X) - (beta * (b.X * b.Y) * point.Y) - (b.X * point.Z);
double newY = (-beta * (b.X * b.Y) * point.X) + ((1 - (beta * (b.Y * b.Y))) * point.Y) - (b.Y * point.Z);
long x_i = (long)((newX + _maxX) / _dX).RoundToNearest();
long y_i = (long)((newY + _maxX) / _dX).RoundToNearest();
// Compute one-dimensional index from three indices.
// x_i * <number of planes> * <number of direction vectors> + y_i * <number of direction vectors> + <loop index>
long index = (x_i * _countX * _countB) + (y_i * _countB) + j;
if (!VotingSpace.ContainsKey(index))
VotingSpace.Add(index, 0);
if (add)
VotingSpace[index]++;
else
VotingSpace[index]--;
}
}
public Dictionary<long, int> VotingSpace { get; private set; }
}
I would like to improve the speed of this code, so I attempted to use
public ConcurrentDictionary<long, int> VotingSpace { get; private set; }
with
private void CastVote(IPointCloud pointCloud, bool add)
{
if (pointCloud == null || pointCloud.Vertices == null)
return;
Parallel.ForEach(pointCloud.Vertices, vertex => PointVote(vertex.Point, add));
}
Note, pointCloud in CastVote can contain vast numbers of points, and the VotingSpace incrementation becoming
if (!VotingSpace.ContainsKey(index))
VotingSpace.TryAdd(index, 0);
if (add)
VotingSpace[index]++;
else
VotingSpace[index]--;
However, sometimes the TryAdd is failing, causing my calling algorithm to fail. I have attempted to put a retry on the TryAdd but this does not seem to help the problem of dropped indexes. How can I make this class optimally multi-threaded, as simply as possible and working in exactly the same way as the original?
When working with concurrent collections, you normally use the special atomic APIs they offer. In this case you should probably use the ConcurrentDictionary.AddOrUpdate method:
VotingSpace.AddOrUpdate(index,
addValueFactory: (key) => add ? 1 : -1,
updateValueFactory: (key, existingValue) => existingValue + (add ? 1 : -1));

Display GPS coordinates in a canvas

I'm trying to display GPS coordinates in a canvas.
I have 400 towns in France + USA. I just want to display them in a canvas.
For each town I have its latitude and longitude (taken with google api : https://developers.google.com/maps/documentation/geocoding/ ).
I've managed to have a first result using this thread : Converting from longitude\latitude to Cartesian coordinates
Here is my result :
My code is the following (assuming "_liste" contains a list of Towns) :
private void Button_visualise_Click(object sender, RoutedEventArgs e)
{
System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
watch.Start();
List<Town> _list = LibDAO.Towns_DAO.GetAllTown().Where(u=>u.IdPays == 2 || u.IdPays == 1).ToList<Town>();
this.my_canvas.Children.Clear();
double min_x = 0;
double max_x = 0;
double min_y = 0;
double max_y = 0;
for (int i = 0; i < _list .Count; i++)
{
Ellipse ell = new Ellipse() { Width = 30, Height = 30, Fill = Brushes.Blue };
Point p = ToCanvas(_list [i].Latitude, _list [i].Longitude);
Canvas.SetLeft(ell, p.X);
Canvas.SetTop(ell, p.Y);
if (p.X < min_x) min_x = p.X;
if (p.X > max_x) max_x = p.X;
if (p.Y < min_y) min_y = p.Y;
if (p.Y > max_y) max_y = p.Y;
this.my_canvas.Children.Add(ell);
}
SetCoordinateSystem(this.my_canvas, min_x, max_x, min_y, max_y);
watch.Stop();
}
public static Canvas SetCoordinateSystem(Canvas canvas, Double xMin, Double xMax, Double yMin, Double yMax)
{
var width = xMax - xMin;
var height = yMax - yMin;
var translateX = -xMin;
var translateY = height + yMin;
var group = new TransformGroup();
group.Children.Add(new TranslateTransform(translateX, -translateY));
group.Children.Add(new ScaleTransform(canvas.ActualWidth / width, canvas.ActualHeight / -height));
canvas.RenderTransform = group;
return canvas;
}
private const int earthRadius = 6367;
private Point ToCanvas(double lat, double lon)
{
lon = ConvertToRadians(lon);
lat = ConvertToRadians(lat);
double x = earthRadius * Math.Cos(lat) * Math.Cos(lon); //((lon * my_canvas.ActualWidth) / 360.0) - 180.0; ;// //
double y = earthRadius * Math.Cos(lat) * Math.Sin(lon);// ((lat * my_canvas.ActualHeight) / 180.0) - 90.0;
return new Point(x, y);
}
public double ConvertToRadians(double angle)
{
return (Math.PI / 180) * angle;
}
As you can see in my result it's almost perfect, we can recognize the 2 countries but why are they in the wrong place ? (I would like to have them like this : http://geology.com/world/world-map.gif
Am I missing something ?
Based on this link, my result may be displayed with "Azimuthal (projections onto a plane)" while I would prefer this : http://en.wikipedia.org/wiki/Equirectangular_projection
So I'm thinking of changing my function "ToCanvas" but I don't know the component "the standard parallels (north and south of the equator) where the scale of the projection is true;"
Bonus question : What's the best way to get the border from a country in GPS coordinates ? I would like to draw the border of USA for example, so I guessed I could just get coordinates of borders to draw the country.
I've tried several websites, managed to get a .shp file from there : http://www.naturalearthdata.com/downloads/110m-cultural-vectors/, but I didn't manage to retrieve borders coordinates from there.
Thank you
EDIT Seems better with this code :
private Point ToCanvas(double lat, double lon)
{
// Equirectangular projection
double x1 = lon * Math.Cos(ConvertToRadians(lat));
double y1 = lat;
//lon = ConvertToRadians(lon);
//lat = ConvertToRadians(lat);
//double x = earthRadius * Math.Cos(lat) * Math.Cos(lon); //((lon * my_canvas.ActualWidth) / 360.0) - 180.0; ;// //
//double y = earthRadius * Math.Cos(lat) * Math.Sin(lon);// ((lat * my_canvas.ActualHeight) / 180.0) - 90.0;
return new Point(x1 * 10, y1 * 10);
}

Best method to check if a point lies on an arc in c#

What I want to do should be simple but it has been a while since I studied math.
Let's say I have Point and Arc classes as below. How can I check if the Point p lies on Arc a.
public class Point
{
public double X;
public double Y;
}
public class Arc
{
public double Radius;
public double StartAngle;
public double EndAngle;
// center of the arc
public double Xc;
public double Yc;
}
Point p = new Point() { X = 5, Y = 5 };
Arc a = new Arc()
{
Radius = 5,
StartAngle = 0,
EndAngle = Math.PI/2,
Xc = 0,
Yc = 0
};
I came up with this answer which is posted here for future reference. I know it is not the most efficient method but it does the job.
// first check if the point is on a circle with the radius of the arc.
// Next check if it is between the start and end angles of the arc.
public static bool IsPointOnArc(Point p, Arc a)
{
if (p.Y * p.Y == a.Radius * a.Radius - p.X * p.X)
{
double t = Math.Acos(p.X / a.Radius);
if (t >= a.StartAngle && t <= a.EndAngle)
{
return true;
}
}
return false;
}

Translating concave hull algorithm to c#

So I am trying to translate the algorith found here for concave hulls: http://repositorium.sdum.uminho.pt/bitstream/1822/6429/1/ConcaveHull_ACM_MYS.pdf
(Page 65)
Ive read through the entire thing but I cant figure out how to implement sortByAngle and angle, im not to sure what method I should do inside of them. This is what I have so far:
//Main method
public static Vertex[] ConcaveHull(Vertex[] points, int k = 3)
{
if (k < 3)
throw new ArgumentException("K is required to be 3 or more", "k");
List<Vertex> hull = new List<Vertex>();
//Clean first, may have lots of duplicates
Vertex[] clean = RemoveDuplicates(points);
if (clean.Length < 3)
throw new ArgumentException("At least 3 dissimilar points reqired", "points");
if (clean.Length == 3)//This is the hull, its already as small as it can be.
return clean;
if (clean.Length < k)
throw new ArgumentException("K must be equal to or smaller then the amount of dissimilar points", "points");
Vertex firstPoint = clean[0]; //TODO find mid point
hull.Add(firstPoint);
Vertex currentPoint = firstPoint;
Vertex[] dataset = RemoveIndex(clean, 0);
double previousAngle = 0;
int step = 2;
int i;
while (((currentPoint != firstPoint) || (step == 2)) && (dataset.Length > 0))
{
if (step == 5)
dataset = Add(dataset, firstPoint);
Vertex[] kNearestPoints = nearestPoints(dataset, currentPoint, k);
Vertex[] cPoints = sortByAngle(kNearestPoints, currentPoint, previousAngle);
bool its = true;
i = 0;
while ((its) && (i < cPoints.Length))
{
i++;
int lastPoint = 0;
if (cPoints[0] == firstPoint)
lastPoint = 1;
int j = 2;
its = false;
while ((!its) && (j < hull.Count - lastPoint))
{
its = intersectsQ(hull[step - 1 - 1], cPoints[0], hull[step - i - j - 1], hull[step - j - 1]);
j++;
}
}
if (its)
{
return ConcaveHull(points, k + 1);
}
currentPoint = cPoints[0];
hull.Add(currentPoint);
previousAngle = angle(hull[step - 1], hull[step - 2]);
dataset = RemoveIndex(dataset, 0);
step++;
}
bool allInside = true;
i = dataset.Length;
while (allInside && i > 0)
{
allInside = new Polygon(dataset).Contains(currentPoint); //TODO havent finished ray casting yet.
i--;
}
if (!allInside)
return ConcaveHull(points, k + 1);
return hull.ToArray();
}
private static Vertex[] Add(Vertex[] vs, Vertex v)
{
List<Vertex> n = new List<Vertex>(vs);
n.Add(v);
return n.ToArray();
}
private static Vertex[] RemoveIndex(Vertex[] vs, int index)
{
List<Vertex> removed = new List<Vertex>();
for (int i = 0; i < vs.Length; i++)
if (i != index)
removed.Add(vs[i]);
return removed.ToArray();
}
private static Vertex[] RemoveDuplicates(Vertex[] vs)
{
List<Vertex> clean = new List<Vertex>();
VertexComparer vc = new VertexComparer();
foreach (Vertex v in vs)
{
if (!clean.Contains(v, vc))
clean.Add(v);
}
return clean.ToArray();
}
private static Vertex[] nearestPoints(Vertex[] vs, Vertex v, int k)
{
Dictionary<double, Vertex> lengths = new Dictionary<double, Vertex>();
List<Vertex> n = new List<Vertex>();
double[] sorted = lengths.Keys.OrderBy(d => d).ToArray();
for (int i = 0; i < k; i++)
{
n.Add(lengths[sorted[i]]);
}
return n.ToArray();
}
private static Vertex[] sortByAngle(Vertex[] vs, Vertex v, double angle)
{
//TODO
return new Vertex[]{};
}
private static bool intersectsQ(Vertex v1, Vertex v2, Vertex v3, Vertex v4)
{
return intersectsQ(new Edge(v1, v2), new Edge(v3, v4));
}
private static bool intersectsQ(Edge e1, Edge e2)
{
double x1 = e1.A.X;
double x2 = e1.B.X;
double x3 = e2.A.X;
double x4 = e2.B.X;
double y1 = e1.A.Y;
double y2 = e1.B.Y;
double y3 = e2.A.Y;
double y4 = e2.B.Y;
var x = ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
var y = ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / ((x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4));
if (double.IsNaN(x) || double.IsNaN(y))
{
return false;
}
else
{
if (x1 >= x2)
{
if (!(x2 <= x && x <= x1)) { return false; }
}
else
{
if (!(x1 <= x && x <= x2)) { return false; }
}
if (y1 >= y2)
{
if (!(y2 <= y && y <= y1)) { return false; }
}
else
{
if (!(y1 <= y && y <= y2)) { return false; }
}
if (x3 >= x4)
{
if (!(x4 <= x && x <= x3)) { return false; }
}
else
{
if (!(x3 <= x && x <= x4)) { return false; }
}
if (y3 >= y4)
{
if (!(y4 <= y && y <= y3)) { return false; }
}
else
{
if (!(y3 <= y && y <= y4)) { return false; }
}
}
return true;
}
private static double angle(Vertex v1, Vertex v2)
{
// TODO fix
Vertex v3 = new Vertex(v1.X, 0);
if (Orientation(v3, v1, v2) == 0)
return 180;
double b = EuclideanDistance(v3, v1);
double a = EuclideanDistance(v1, v2);
double c = EuclideanDistance(v3, v2);
double angle = Math.Acos((Math.Pow(a, 2) + Math.Pow(b, 2) - Math.Pow(c, 2)) / (2 * a * b));
if (Orientation(v3, v1, v2) < 0)
angle = 360 - angle;
return angle;
}
private static double EuclideanDistance(Vertex v1, Vertex v2)
{
return Math.Sqrt(Math.Pow((v1.X - v2.X), 2) + Math.Pow((v1.Y - v2.Y), 2));
}
public static double Orientation(Vertex p1, Vertex p2, Vertex p)
{
double Orin = (p2.X - p1.X) * (p.Y - p1.Y) - (p.X - p1.X) * (p2.Y - p1.Y);
if (Orin > 0)
return -1;//Left
if (Orin < 0)
return 1;//Right
return 0;//Colinier
}
I know that there is a load of code here. But im not sure if I can show the context and what I have without it.
Other classes:
public class Polygon
{
private Vertex[] vs;
public Polygon(Vertex[] Vertexes)
{
vs = Vertexes;
}
public Polygon(Bounds bounds)
{
vs = bounds.ToArray();
}
public Vertex[] ToArray()
{
return vs;
}
public IEnumerable<Edge> Edges()
{
if (vs.Length > 1)
{
Vertex P = vs[0];
for (int i = 1; i < vs.Length; i++)
{
yield return new Edge(P, vs[i]);
P = vs[i];
}
yield return new Edge(P, vs[0]);
}
}
public bool Contains(Vertex v)
{
return RayCasting.RayCast(this, v);
}
}
public class Edge
{
public Vertex A = new Vertex(0, 0);
public Vertex B = new Vertex(0, 0);
public Edge() { }
public Edge(Vertex a, Vertex b)
{
A = a;
B = b;
}
public Edge(double ax, double ay, double bx, double by)
{
A = new Vertex(ax, ay);
B = new Vertex(bx, by);
}
}
public class Bounds
{
public Vertex TopLeft;
public Vertex TopRight;
public Vertex BottomLeft;
public Vertex BottomRight;
public Bounds() { }
public Bounds(Vertex TL, Vertex TR, Vertex BL, Vertex BR)
{
TopLeft = TL;
TopRight = TR;
BottomLeft = BL;
BottomRight = BR;
}
public Vertex[] ToArray()
{
return new Vertex[] { TopLeft, TopRight, BottomRight, BottomLeft };
}
}
public class Vertex
{
public double X = 0;
public double Y = 0;
public Vertex() { }
public Vertex(double x, double y)
{
X = x;
Y = y;
}
public static Vertex[] Convert(string vs)
{
vs = vs.Replace("[", "");
vs = vs.Replace("]", "");
string[] spl = vs.Split(';');
List<Vertex> nvs = new List<Vertex>();
foreach (string s in spl)
{
try
{
nvs.Add(new Vertex(s));
}
catch
{
}
}
return nvs.ToArray();
}
public static string Stringify(Vertex[] vs)
{
string res = "[";
foreach (Vertex v in vs)
{
res += v.ToString();
res += ";";
}
res = res.RemoveLastCharacter();
res += "]";
return res;
}
public static string ToString(Vertex[] array)
{
string res = "[";
foreach (Vertex v in array)
res += v.ToString() + ",";
return res.RemoveLastCharacter() + "]";
}
/*
//When x < y return -1
//When x == y return 0
//When x > y return 1
public static int Compare(Vertex x, Vertex y)
{
//To find lowest
if (x.X < y.X)
{
return -1;
}
else if (x.X == y.X)
{
if (x.Y < y.Y)
{
return -1;
}
else if (x.Y == y.Y)
{
return 0;
}
else
{
return 1;
}
}
else
{
return 1;
}
}
*/
public static int CompareY(Vertex a, Vertex b)
{
if (a.Y < b.Y)
return -1;
if (a.Y == b.Y)
return 0;
return 1;
}
public static int CompareX(Vertex a, Vertex b)
{
if (a.X < b.X)
return -1;
if (a.X == b.X)
return 0;
return 1;
}
public double distance (Vertex b){
double dX = b.X - this.X;
double dY = b.Y - this.Y;
return Math.Sqrt((dX*dX) + (dY*dY));
}
public double slope (Vertex b){
double dX = b.X - this.X;
double dY = b.Y - this.Y;
return dY / dX;
}
public static int Compare(Vertex u, Vertex a, Vertex b)
{
if (a.X == b.X && a.Y == b.Y) return 0;
Vertex upper = new Vertex();
Vertex p1 = new Vertex();
Vertex p2 = new Vertex();
upper.X = (u.X + 180) * 360;
upper.Y = (u.Y + 90) * 180;
p1.X = (a.X + 180) * 360;
p1.Y = (a.Y + 90) * 180;
p2.X = (b.X + 180) * 360;
p2.Y = (b.Y + 90) * 180;
if(p1 == upper) return -1;
if(p2 == upper) return 1;
double m1 = upper.slope(p1);
double m2 = upper.slope(p2);
if (m1 == m2)
{
return p1.distance(upper) < p2.distance(upper) ? -1 : 1;
}
if (m1 <= 0 && m2 > 0) return -1;
if (m1 > 0 && m2 <= 0) return -1;
return m1 > m2 ? -1 : 1;
}
public static Vertex UpperLeft(Vertex[] vs)
{
Vertex top = vs[0];
for (int i = 1; i < vs.Length; i++)
{
Vertex temp = vs[i];
if (temp.Y > top.Y || (temp.Y == top.Y && temp.X < top.X))
{
top = temp;
}
}
return top;
}
}
Just a note on convention: you should start function names with upper case, and variables with lower case. In the function sortByAngle, you have a reference to the parameter angle and the function angle simultaneously.
Assuming Angle(...) is simply meant to calculate the angle between two points:
private static double Angle(Vertex v1, Vertex v2)
{
return Math.Atan2(v2.Y - v1.Y, v2.X - v1.X);
}
will give you the angle from v1 to v2, in radians between -pi and +pi. Do not mix degrees and radians. My suggestion is to always use radians, and only convert to degrees if necessary for human-readable output.
private static Vertex[] SortByAngle(Vertex[] vs, Vertex v, double angle)
{
List<Vertex> vertList = new List<Vertex>(vs);
vertList.Sort((v1, v2) => AngleDifference(angle, Angle(v, v1)).CompareTo(AngleDifference(angle, Angle(v, v2))));
return vertList.ToArray();
}
uses List.Sort to sort the vertices from greatest to least angle difference between the vertices point and itself, and angle. The order of v1 and v2 are swapped in the input tuple to sort descending, that is, greatest difference first. The difference between angles is calculated like so:
private static double AngleDifference(double a, double b)
{
while (a < b - Math.PI) a += Math.PI * 2;
while (b < a - Math.PI) b += Math.PI * 2;
return Math.Abs(a - b);
}
The first two lines ensure that the angles are not more than 180 degrees apart.
You have error in
private static Vertex[] nearestPoints(Vertex[] vs, Vertex v, int k)
{
Dictionary<double, Vertex> lengths = new Dictionary<double, Vertex>();
List<Vertex> n = new List<Vertex>();
double[] sorted = lengths.Keys.OrderBy(d => d).ToArray();
for (int i = 0; i < k; i++)
{
n.Add(lengths[sorted[i]]);
}
return n.ToArray();
}
according to code if you have several vertexes at the same distance, function returns only one. Since Dictionary uses unique keys.
BTW, did anyone finish this?
I don't have the time right now to read the paper, but I assume from my knowledge of conVEX hull algorithms that you're going around the points in a particular direction looking for the next point to link to.
If that's the case, "angle" would be the angle of the most recent line segment of the hull, and you want to sort the points by their angle from that line. Therefore you want to calculate the angles between a line (on the hull) and a set of lines (from the current point to each other point being considered). Whether the angles calculated are positive or negative depends upon whether you're going clockwise or anticlockwise. To calculate the angles, look at something like this:
Calculating the angle between two lines without having to calculate the slope? (Java)
Then just sort by the angles.
What about that?
private List<Vector> sortClockwiseFromCentroid(List<Vector> points, Vector center)
{
points = points.OrderBy(x => Math.Atan2(x.X - center.X, x.Y - center.Y)).ToList();
return points;
}

Code blocks because it is also trying to generate a circle around it when is a space near

I am developing a small program, and to generate the coordenates I am using this code:
public double[] GenerateNewCircle(int maxSize, int numberOfBalls, double centerx, double centery)
{
double[] position = null;
double angle = 360 / 6;
double angleRad = DegreeToRadian(incrementAngle);
position = CalculatePosition(radiusX, radiusY, centerx, centery, angleRad);
return position;
}
public double[] CalculatePosition(double radiusX, double radiusY, double centerX, double centerY, double angle)
{
double[] position = new double[2];
position[0] = Math.Cos(angle) * (radiusX + centerX)*1.5;
position[1] = Math.Sin(angle) * (radiusY + centerY)*1.5;
return position;
}
To check if not overlapping or if is in the area I used this
bool circleIsAllowed(List<Circle> circles, Circle newCircle)
{
if (newCircle.x < 10 || newCircle.x > pictureBox1.Width)
return false;
if (newCircle.y < 9 || newCircle.y > pictureBox1.Height)
return false;
foreach (Circle it in circles)
{
double aX = Math.Pow(it.x - newCircle.x, 2);
double aY = Math.Pow(it.y - newCircle.y, 2);
double Dif = Math.Abs(aX - aY);
double ra1 = it.r / 2;
double ra2 = it.r / 2;
double raDif = Math.Pow(ra1 + ra2, 2);
if ((raDif + 1) > Dif) return false;
}
return true; // no existing circle overlaps
}
I have two problems right now
It blocks because is also trying to generate a circle around it, when is a space near.
How can I increase the distance between the circles? They are too close.
This circles is to draw around a circle (around it)
This is the image:
There is mistake in second code block. Try this:
double aX = Math.Pow(it.x - newCircle.x, 2);
double aY = Math.Pow(it.y - newCircle.y, 2);
double distance = Math.Pow(aX + aY, 0.5); // distance between circles centers
double ra1 = it.r / 2;
double ra2 = it.r / 2;
// is it.r diameter? if so, then ok, else div by 2 is useless
double circlesDistance = 10; // distance between circles (not centers)
if (distance < ra1 + ra2 + circlesDistance)
{
return false;
}
To compute the distance between two circle centers, you should apply the Pythagorean Theorem:
a2 + b2 = c2.
This works perfectly if we have circles (with ellipses you'd have to compute their radius along the connection between their centres which would involve some sinus and cosinus computations).
double aX = Math.Pow(it.x - newCircle.x, 2);
double aY = Math.Pow(it.y - newCircle.y, 2);
if ((aX + aY) <= Math.Pow(it.r + newCircle.r, 2)) {
return false;
}

Categories