private Poly ReflectPoly(Poly current, Edge inversionEdge) { var geodesic = GetGeodesicLine(inversionEdge); List <int> indices = new List <int>(); foreach (var edge in current.edges) { if (edge.v0 == inversionEdge.v0 || edge.v0 == inversionEdge.v1) { indices.Add(edge.v0); } else { indices.Add(ReflectPoint(geodesic, edge.v0)); } } Poly poly = new Poly(); for (int i = 0; i < indices.Count; ++i) { poly.edges.Add(new Edge(indices[i], indices[(i + 1) % indices.Count])); } poly.level = current.level + 1; poly.center = ReflectPoint(geodesic, current.center); foreach (var edge in poly.edges) { edge.Neighbors.Add(poly.center); } return(poly); }
Poly CreateCenterPolygon(int p, int q) { double s = Math.Sin(Math.PI / p); double c = Math.Cos(Math.PI / q); // Computo OC y AO segun el articulo de Coexeter double OC = 1.0 / Math.Sqrt(((c * c) / (s * s)) - 1.0); double AO = 1.0 / Math.Sqrt(1.0 - ((s * s) / (c * c))); // Creo el circulo con centro = (AO,0) y radio = OC var circle = new Circle(center: new Point(AO, 0), radius: OC); // Computo el punto B hallando la interseccion del circulo con // la linea que parte desde A en direccion = ( cos(pi/p), sin(pi/p) ) var lineAB = new Line(o: new Point(0, 0), dir: new Vector(Math.Cos(Math.PI / p), Math.Sin(Math.PI / p))); Point B = Geometry.LineCircleIntersection(lineAB, circle); // Computo las posiciones de los vertices del polígono central // en la circunferencia de la región fundamental añadiendo un // vertice en la circunferencia cada 2*pi/p radianes double dist = (B - lineAB.O).Length; for (int i = 0; i < p; ++i) { double alpha = (double)i / p * 2.0 * Math.PI; Point X = Complex2Vector(dist * new Complex(Math.Cos(alpha), Math.Sin(alpha))); Points.Add(X); } // Añado el punto A a los vertices Points.Add(Complex2Vector(new Complex(0, 0))); //centro A // Defino el poligono central Poly poly = new Poly(); for (int i = 0; i < p; ++i) { poly.edges.Add(new Edge(i, (i + 1) % p)); } poly.level = 1; poly.center = p; // para computar la teselacion dual cada lado guarda sus // poligonos adyacentes foreach (var e in poly.edges) { e.Neighbors.Add(poly.center); } //retorna el poligono return(poly); }
void ApplyIsometries(Poly centralPoly, int maxLevel) { //Este metodo es de fuerza bruta. //TODO: Implementar K-d-tree (BSP-tree, Quad-tree o UniformGrid son buenas alternativas) para buscar vertices. HashSet <Edge> edges = new HashSet <Edge>(); Queue <Poly> Q = new Queue <Poly>(); Q.Enqueue(centralPoly); Polygons.Add(centralPoly); while (!(Q.Count == 0)) { Poly current = Q.Dequeue(); if (current.level >= maxLevel) { continue; } foreach (var edge in current.edges) { if (!edges.Contains(edge)) { // procesa el lado solo una vez edges.Add(edge); int oldPointSize = Points.Count; // Refleja el poligono en el lado Poly poly = ReflectPoly(current, edge); if (oldPointSize != Points.Count || !Polygons.Contains(poly)) { // si el poligono no existe lo añado a la lista Polygons.Add(poly); Q.Enqueue(poly); } // para computar la teselacion dual cada lado guarda sus // poligonos adyacentes edge.Neighbors.Add(poly.center); } } } }