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; } public List GetPolygons() { return JsonReader._polygons; } public List GetMultiPolygons() { return JsonReader._multiPolygons; } public PolygonPunten GetPolygonByName(string naam) { return JsonReader._polygons.Find(punten => punten.Naam == naam); } public List GetTrianglesPolygon(PolygonPunten polygon, double scaleX = 1, double scaleY = 1, double epsilonPercet = 0) { double grootsteAfstandX = Math.Abs(polygon.MaximumX - polygon.MinimumX); double grootsteAfstandY = Math.Abs(polygon.MaximumY - polygon.MinimumY); double epsilon = ((grootsteAfstandX + grootsteAfstandY) / 2) * epsilonPercet; polygon.Punten = Peuker(polygon.Punten, epsilon); polygon = ScalePolygon(polygon, scaleX, scaleY); return TriangulatePolygon(polygon); } 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 returnWaarde = new List(); 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 pp = new List(); foreach (PolygonPunten polygon in multiPolygon.PolygonPunten) { List returnWaarde = new List(); 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 ScaleMultiPolygons(List 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 mpps = new List(); foreach (MultiPolygonPunten mp in multiPolygons) { List pp = new List(); foreach (PolygonPunten poly in mp.PolygonPunten) { List punten = new List(); 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 GetAllPolygons() { List lijst = new List(); lijst.AddRange(GetPolygons()); foreach (MultiPolygonPunten multiPolygonPunten in GetMultiPolygons()) { lijst.AddRange(multiPolygonPunten.PolygonPunten); } return lijst; } public List TriangulatePolygon(List punten) { List returnWaarde = new List(); 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 TriangulatePolygon(PolygonPunten polygon) { List punten = polygon.Punten; List returnWaarde = new List(); 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, 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; } private List Peuker(List 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 returnWaarde = new List(); if (dmax > epsilon) { List recResults1 = Peuker(punten.GetRange(0, index), epsilon); List recResults2 = Peuker(punten.GetRange(index, end - 1 - index), epsilon); returnWaarde.AddRange(recResults1); returnWaarde.AddRange(recResults2); } else { returnWaarde = new List() { 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)); } } }