예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
                    }
                }
            }
        }