Exemplo n.º 1
0
        /// <summary>
        /// Calculate basePoints along a circle defined by a center on the z axis, and going through the point (0,0,1).
        /// .5 is horosphere, 1 is geodesic
        /// Result is in UHS model
        /// </summary>
        private static Vector3D[] BasePointsCircle(double centerUHS)
        {
            if (centerUHS > 1)
            {
                centerUHS = 1;
            }
            if (centerUHS < 0)
            {
                centerUHS = 0;
            }

            if (centerUHS == 0)
            {
                return new Vector3D[] { new Vector3D() }
            }
            ;

            bool hyperbolicOffsets = true;

            if (hyperbolicOffsets)
            {
                // h-distance between each point.
                double d = 0.1;

                // We need to work in 2D first, then we'll switch to xz plane.
                Circle circle = new Circle(new Vector3D(0, 1), new Vector3D(0, 1 - 2 * centerUHS), new Vector3D(centerUHS, 1 - centerUHS));

                // XXX - check to make sure total distance won't wrap around the circle.

                List <Vector3D> points = new List <Vector3D>();
                int             count  = 75;
                for (int i = -count; i <= count; i++)
                {
                    double currentD = d * i;

                    // Angle t around a circle with center c and radius r to get an h-distance.
                    // https://en.wikipedia.org/wiki/Poincar%C3%A9_half-plane_model
                    // http://www.wolframalpha.com/input/?i=d+%3D+arcosh%281%2B%28%28r*sin%28t%29%29%5E2%2B%28r*cos%28t%29-r%29%5E2%29%2F%282*%28c%2Br%29*%28c%2Br*cos%28t%29%29%29%29%2C+solve+for+t
                    double c           = circle.Center.Y;
                    double r           = circle.Radius;
                    double coshd       = DonHatch.cosh(currentD);
                    double numerator   = c * c - c * (c + r) * coshd + c * r + r * r;
                    double denominator = r * ((c + r) * coshd - c);
                    double angle       = Math.Acos(numerator / denominator);
                    if (i < 0)
                    {
                        angle *= -1;
                    }
                    points.Add(new Vector3D(r * Math.Sin(angle), 0, c + r * Math.Cos(angle)));

                    /*
                     * // XXX - This was my first attempt, but this code only works for geodesics, not general arcs!
                     * // Equidistant lines in UHS will all be lines through the origin.
                     * // In the following formula, x is the angle to use to get h-spaced equidistant line a distance d away.
                     * // http://www.wolframalpha.com/input/?i=d+%3D+arccosh%28sec%28x%29%29%2C+solve+for+x
                     * double angle = Math.Acos( 1.0 / DonHatch.cosh( currentD ) );
                     * angle = Math.PI/2 - angle;
                     * if( i < 0 )
                     *      angle *= -1;
                     *
                     * Vector3D p1, p2;
                     * Euclidean2D.IntersectionLineCircle( new Vector3D(), new Vector3D( Math.Cos(angle), Math.Sin(angle) ), circle, out p1, out p2 );
                     * Vector3D highest = p1.Y > p2.Y ? p1 : p2;
                     * points.Add( new Vector3D( highest.X, 0, highest.Y ) );
                     */
                }
                return(points.ToArray());
            }
            else
            {
                // equal euclidean spacing.
                Circle3D c = new Circle3D(new Vector3D(0, 0, 1), new Vector3D(0, 0, 1 - 2 * centerUHS), new Vector3D(centerUHS, 0, 1 - centerUHS));
                return(c.Subdivide(125));
            }
        }