Så alt med 3 decimaler.
Jeg er bange for at den matematisk korrekte løsning er mere end jeg kan klare.
Jeg kan klare en næsten korekt løsning.
using System;
using System.Collections.Generic;
using System.Linq;
namespace E
{
public class MapPoint
{
public double Long { get; set; }
public double Lat { get; set; }
}
public class XPoint
{
public int X { get; set; }
public int Y { get; set; }
}
public static class Extensions
{
public static XPoint ToXpoint(this MapPoint mp, int scale)
{
return new XPoint { X = (int)(mp.Long * scale + 0.5), Y = (int)(mp.Lat * scale + 0.5) };
}
public static MapPoint ToMapPoint(this XPoint xp, int scale)
{
return new MapPoint { Long = xp.X * 1.0 / scale, Lat = xp.Y * 1.0 / scale };
}
public static XPoint Minus(this XPoint xp, XPoint zero)
{
return new XPoint { X = xp.X - zero.X, Y = xp.Y - zero.Y };
}
public static XPoint Plus(this XPoint xp, XPoint zero)
{
return new XPoint { X = xp.X + zero.X, Y = xp.Y + zero.Y };
}
}
public enum PointValue { OUTER, CORNER, BORDER, INNER };
public class Analyze
{
private static XPoint FindMin(IEnumerable<XPoint> poly)
{
return new XPoint { X = poly.Select(xp => xp.X).Min(), Y = poly.Select(xp => xp.Y).Min() };
}
private static XPoint FindMax(IEnumerable<XPoint> poly)
{
return new XPoint { X = poly.Select(xp => xp.X).Max(), Y = poly.Select(xp => xp.Y).Max() };
}
public static PointValue[,] CreateMap(int w, int h)
{
PointValue[,] res = new PointValue[w,h];
for(int x = 0; x < w; x++)
for(int y = 0; y < h; y++)
res[x,y] = PointValue.INNER;
return res;
}
private static void Draw(PointValue[,] map, XPoint start, XPoint finish)
{
int minx = Math.Min(start.X, finish.X);
int maxx = Math.Max(start.X, finish.X);
int miny = Math.Min(start.Y, finish.Y);
int maxy = Math.Max(start.Y, finish.Y);
for(int x = minx; x <= maxx; x++)
{
int y2 = (int)((x - minx) * 1.0 / (maxx - minx) * (maxy - miny) + miny + 0.5);
if(map[x,y2] != PointValue.CORNER)
map[x,y2] = PointValue.BORDER;
}
for(int y = maxy; y >= miny; y--)
{
int x2 = (int)((y - miny) * 1.0 / (maxy - miny) * (maxx - minx) + minx + 0.5);
if(map[x2,y] != PointValue.CORNER)
map[x2,y] = PointValue.BORDER;
}
}
public static void Draw(PointValue[,] map, List<XPoint> poly)
{
foreach(XPoint xp in poly)
{
map[xp.X,xp.Y] = PointValue.CORNER;
}
for(int i = 0; i < poly.Count - 1; i++)
{
Draw(map, poly[i], poly[i + 1]);
}
Draw(map, poly[poly.Count - 1], poly[0]);
}
private static char Visual(PointValue pv)
{
switch(pv)
{
case PointValue.OUTER: return ' ';
case PointValue.CORNER: return 'X';
case PointValue.BORDER: return '*';
case PointValue.INNER: return '-';
default: throw new Exception("Ooops");
}
}
public static void Fill(PointValue[,] map)
{
Queue<Tuple<int, int>> todo = new Queue<Tuple<int, int>>();
todo.Enqueue(Tuple.Create(0, 0));
while(todo.Count > 0)
{
Tuple<int, int> temp = todo.Dequeue();
int x = temp.Item1;
int y = temp.Item2;
if(map[x,y] == PointValue.INNER)
{
map[x,y] = PointValue.OUTER;
if(x - 1 >= 0 && map[x - 1,y] == PointValue.INNER) todo.Enqueue(Tuple.Create(x - 1, y));
if(x + 1 < map.GetLength(0) && map[x + 1,y] == PointValue.INNER) todo.Enqueue(Tuple.Create(x + 1, y));
if(y - 1 >= 0 && map[x,y - 1] == PointValue.INNER) todo.Enqueue(Tuple.Create(x, y - 1));
if(y + 1 < map.GetLength(1) && map[x,y + 1] == PointValue.INNER) todo.Enqueue(Tuple.Create(x, y + 1));
}
}
}
public static void Dump(PointValue[,] map)
{
for(int y = map.GetLength(1) - 1; y >= 0; y--)
{
for(int x = 0; x < map.GetLength(0); x++)
{
Console.Write(Visual(map[x,y]));
}
Console.WriteLine();
}
}
private static List<XPoint> Find(PointValue[,] map)
{
List<XPoint> res = new List<XPoint>();
for(int y = map.GetLength(1) - 1; y >= 0; y--)
{
for(int x = 0; x < map.GetLength(0); x++)
{
if(map[x,y] == PointValue.INNER)
{
res.Add(new XPoint { X = x, Y = y });
}
}
}
return res;
}
public static List<MapPoint> Find(List<MapPoint> poly, int scale)
{
IEnumerable<XPoint> temp = poly.Select(mp => mp.ToXpoint(scale));
XPoint zero = FindMin(temp);
zero.X--;
zero.Y--;
List<XPoint> poly2 = temp.Select(xp => xp.Minus(zero)).ToList();
XPoint minp = FindMin(poly2);
XPoint maxp = FindMax(poly2);
PointValue[,] map = CreateMap(maxp.X - minp.X + 3, maxp.Y - minp.Y + 3);
Draw(map, poly2);
Fill(map);
if(scale == 10) Dump(map);
List<XPoint> inner = Find(map);
List<MapPoint> inner2 = inner.Select(xp => xp.Plus(zero).ToMapPoint(scale)).ToList();
return inner2;
}
}
public class Program
{
public static void Main(string[] args)
{
List<MapPoint> poly = new List<MapPoint> { new MapPoint { Long = 2.0, Lat = 2.0 },
new MapPoint { Long = 7.5, Lat = 6.0 },
new MapPoint { Long = 5.5, Lat = 2.5 } };
List<MapPoint> inner = Analyze.Find(poly, 10);
Console.WriteLine("Found: {0}", inner.Count);
Console.WriteLine("Range: ({0},{1}) ... ({2},{3})", inner.First().Long, inner.First().Lat, inner.Last().Long, inner.Last().Lat);
inner = Analyze.Find(poly, 100);
Console.WriteLine("Found: {0}", inner.Count);
inner = Analyze.Find(poly, 1000);
Console.WriteLine("Found: {0}", inner.Count);
Console.ReadKey();
}
}
}