Files
cs-map-project/Logica/PolygonManipulatie.cs

342 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Datalaag;
using Globals;
namespace Logica
{
public class PolygonManipulatie
{
public JsonReader JsonReader;
public PolygonManipulatie(JsonReader jsonReader)
{
JsonReader = jsonReader; //haal datalaag binnen
}
public List<PolygonPunten> GetPolygons()
{
return JsonReader._polygons;
}
public List<MultiPolygonPunten> GetMultiPolygons()
{
return JsonReader._multiPolygons;
}
public PolygonPunten GetPolygonByName(string naam)
{
return JsonReader._polygons.Find(punten => punten.Naam == naam);
}
//oude schaalmethodes
public PolygonPunten ScalePolygon(PolygonPunten polygon, double scaleX, double scaleY, double offsetX = 180, double offsetY = 180)
{
double maxX = polygon.MaximumX - polygon.MinimumX;
double maxY = polygon.MaximumY - polygon.MinimumY;
double minX = polygon.MinimumX;
double minY = polygon.MinimumY;
List<Punt> returnWaarde = new List<Punt>();
foreach (Punt punt in polygon.Punten)
{
//Punt x = ScalePoint(scaleX, scaleY, punt, maxX, maxY, offsetX, offsetY);
double x = punt.X - minX;
x /= maxX;
x *= scaleX;
x += offsetX;
double y = punt.Y - minY;
y /= maxY;
y *= scaleY;
y += offsetY;
returnWaarde.Add(new Punt(x, y, punt.Naam));
//x.Naam = punt.Naam;
//returnWaarde.Add(x);
}
return new PolygonPunten(returnWaarde, polygon.Naam);
}
//lat en long = graden, graden => coords (/360 * scale?
private static Punt ScalePoint(double scaleX, double scaleY, Punt punt, double maxX = 360, double maxY = 360, double offsetX = 180, double
offsetY = 180)
{
double x = punt.X;
x /= maxX;
x *= scaleX;
x += offsetX;
double y = punt.Y;
y /= maxY;
y *= scaleY;
y += offsetY;
return new Punt(x, y);
}
public MultiPolygonPunten ScaleMultiPolygon(MultiPolygonPunten multiPolygon, double scaleX, double scaleY, double offsetX = 0, double offsetY = 0)
{
double maxX = multiPolygon.MaximumX;
double maxY = multiPolygon.MaximumY;
double minX = multiPolygon.MinimumX;
double minY = multiPolygon.MinimumY;
maxX -= minX;
maxY -= minY;
List<PolygonPunten> pp = new List<PolygonPunten>();
foreach (PolygonPunten polygon in multiPolygon.PolygonPunten)
{
List<Punt> returnWaarde = new List<Punt>();
foreach (Punt punt in polygon.Punten)
{
/*
double x = punt.X - minX;
x /= maxX;
x *= scaleX;
x += offsetX;
double y = punt.Y - minY;
y /= maxY;
y *= scaleY;
y += offsetY;
returnWaarde.Add(new Punt(x, y, punt.Naam));*/
Punt x = ScalePoint(scaleX, scaleY,punt, maxX, maxY, offsetX, offsetY);
x.Naam = punt.Naam;
returnWaarde.Add(x);
}
pp.Add(new PolygonPunten(returnWaarde, polygon.Naam));
}
return new MultiPolygonPunten(pp, multiPolygon.Naam);
}
//todo (offset var voor center op canvas, vree ambetant)
public List<MultiPolygonPunten> ScaleMultiPolygons(List<MultiPolygonPunten> multiPolygons, double scaleX, double scaleY, double offsetX = 0, double offsetY = 0)
{
double maxX = multiPolygons.Max(m => m.MaximumX);
double maxY = multiPolygons.Max(m => m.MaximumY);
double minX = multiPolygons.Min(m => m.MinimumX);
double minY = multiPolygons.Min(m => m.MinimumY);
List<MultiPolygonPunten> mpps = new List<MultiPolygonPunten>();
foreach (MultiPolygonPunten mp in multiPolygons)
{
List<PolygonPunten> pp = new List<PolygonPunten>();
foreach (PolygonPunten poly in mp.PolygonPunten)
{
List<Punt> punten = new List<Punt>();
foreach (Punt punt in poly.Punten)
{
Punt x = ScalePoint(scaleX, scaleY,punt, maxX, maxY, offsetX, offsetY);
x.Naam = punt.Naam;
punten.Add(x);
/*double x = punt.X - minX;
x /= maxX;
x *= scaleX;
x += offsetX;
double y = punt.Y - minY;
y /= maxY;
y *= scaleY;
y += offsetY;
punten.Add(new Punt(x, y, punt.Naam));*/
}
pp.Add(new PolygonPunten(punten, poly.Naam));
}
mpps.Add(new MultiPolygonPunten(pp, mp.Naam));
}
return mpps;
}
public List<PolygonPunten> GetAllPolygons()
{
List<PolygonPunten> lijst = new List<PolygonPunten>();
lijst.AddRange(GetPolygons());
foreach (MultiPolygonPunten multiPolygonPunten in GetMultiPolygons())
{
lijst.AddRange(multiPolygonPunten.PolygonPunten);
}
return lijst;
}
public List<PolygonPunten> TriangulatePolygon(List<Punt> punten)
{
List<PolygonPunten> returnWaarde = new List<PolygonPunten>();
int i = 0;
int BACKUP = 0;
int BACKBACKUP = punten.Count;
while (true)
{
if (i >= punten.Count)
{
i = 0;
if (punten.Count == BACKBACKUP)
{
BACKUP++;
}
BACKBACKUP = punten.Count;
}
int punt1Index = i;
int punt2Index = i + 1;
if (punt2Index >= punten.Count) punt2Index -= punten.Count;
int punt3Index = i + 2;
if (punt3Index >= punten.Count) punt3Index -= punten.Count;
if (punten.Count < 3)
{
break;
}
double hoek = VindHoek(punten[punt2Index], punten[punt1Index], punten[punt3Index]);
if (hoek < 180)
{
returnWaarde.Add(MaakNieuweDriehoek(punten[punt2Index], punten[punt3Index],
punten[punt1Index], punten[punt1Index].Naam));
punten.RemoveAt(punt2Index);
Debug.WriteLine("added a triangle, polygonLijst count " + punten.Count);
i = punt1Index;
BACKUP = 0;
continue;
}
Debug.WriteLine(hoek);
i++;
if (BACKUP >= punten.Count)
{
Debug.WriteLine("FUCK, couldnt parse " + punten.Count + " points");
break;
}
}
return returnWaarde;
}
public List<PolygonPunten> TriangulatePolygon(PolygonPunten polygon)
{
List<Punt> punten = polygon.Punten;
List<PolygonPunten> returnWaarde = new List<PolygonPunten>();
int i = 0;
int BACKUP = 0;
int BACKBACKUP = punten.Count;
while (true)
{
if (i >= punten.Count)
{
i = 0;
if (punten.Count == BACKBACKUP)
{
BACKUP++;
}
BACKBACKUP = punten.Count;
}
int punt1Index = i;
int punt2Index = i + 1;
if (punt2Index >= punten.Count) punt2Index -= punten.Count;
int punt3Index = i + 2;
if (punt3Index >= punten.Count) punt3Index -= punten.Count;
if (punten.Count < 3)
{
break;
}
double hoek = VindHoek(punten[punt2Index], punten[punt1Index], punten[punt3Index]);
if (hoek < 180)
{
returnWaarde.Add(MaakNieuweDriehoek(punten[punt2Index], punten[punt3Index],
punten[punt1Index], punten[punt1Index].Naam));
punten.RemoveAt(punt2Index);
Debug.WriteLine("added a triangle, polygonLijst count " + punten.Count);
i = punt1Index;
BACKUP = 0;
continue;
}
Debug.WriteLine(hoek);
i++;
if (BACKUP >= punten.Count)
{
Debug.WriteLine("FUCK, couldnt parse " + punten.Count + " points");
break;
}
}
return returnWaarde;
}
private PolygonPunten MaakNieuweDriehoek(Punt punt, Punt punt1, Punt punt2, string naam = "")
{
return new PolygonPunten(new List<Punt>() { punt, punt1, punt2 }, naam);
}
private double VindHoek(Punt p1, Punt p2, Punt p3)
{
double hoek = (Math.Atan2(p3.Y - p1.Y, p3.X - p1.X) - Math.Atan2(p2.Y - p1.Y, p2.X - p1.X)) * (180 / Math.PI);
if (hoek < 0)
{
hoek += 360;
}
return hoek;
}
public PolygonPunten Peuker(PolygonPunten polygon, double epsilon)
{
double nX = Math.Abs(Math.Abs(polygon.MaximumX) - Math.Abs(polygon.MinimumX));
double nY = Math.Abs(Math.Abs(polygon.MaximumY) - Math.Abs(polygon.MinimumY));
epsilon = ((nX + nY) / 2) * epsilon;
polygon.Punten = Peuker(polygon.Punten, epsilon);
return polygon;
}
public MultiPolygonPunten Peuker(MultiPolygonPunten polygons, double epsilon)
{
double nX = Math.Abs(Math.Abs(polygons.MaximumX) - Math.Abs(polygons.MinimumX));
double nY = Math.Abs(Math.Abs(polygons.MaximumY) - Math.Abs(polygons.MinimumY));
epsilon = ((nX + nY) / 2) * epsilon;
foreach (PolygonPunten polygon in polygons.PolygonPunten)
{
polygon.Punten = Peuker(polygon.Punten, epsilon);
}
return polygons;
}
private List<Punt> Peuker(List<Punt> punten, double epsilon)
{
double dmax = -1;
int index = 0;
int end = punten.Count;
for (int i = 1; i < end - 1; i++)
{
double distance = PerpendicularDistance2(punten[i], punten[0], punten[end - 1]);
if (distance > dmax)
{
index = i;
dmax = distance;
}
}
List<Punt> returnWaarde = new List<Punt>();
if (dmax > epsilon)
{
List<Punt> recResults1 = Peuker(punten.GetRange(0, index), epsilon);
List<Punt> recResults2 = Peuker(punten.GetRange(index, end - 1 - index), epsilon);
returnWaarde.AddRange(recResults1);
returnWaarde.AddRange(recResults2);
}
else
{
returnWaarde = new List<Punt>() { punten[0], punten[punten.Count - 1] };
}
return returnWaarde;
}
private double PerpendicularDistance2(Punt point, Punt l1, Punt l2)
{
return Math.Abs((l2.X - l1.X) * (l1.Y - point.Y) - (l1.X - point.X) * (l2.Y - l1.Y)) /
Math.Sqrt(Math.Pow(l2.X - l1.X, 2) + Math.Pow(l2.Y - l1.Y, 2));
}
}
}