static bool IsPointInPolygon(Geo x, Geo center, IList<Geo> poly)
        {
            // do this only once and pass it in for the math.
            // Geo c = Limits.center(poly);

            // bail out if the point is more than 90 degrees off the
            // centroid
            var d = x.DistanceRadians(center);
            if (d >= (Math.PI / 2))
            {
                return false;
            }
            // ray is normal to the great circle from c to x. reusing c to hold ray
            // info
            var ray = center.CrossNormalize(x);
            /*
       * side is a point on the great circle between c and x. It is used to
       * choose a direction.
       */
            var side = x.CrossNormalize(ray);
            var isIn = false;
            // Why do we need to allocate new Geos?
            // Geo p1 = new Geo(poly[0]);
            // Geo p2 = new Geo(poly[0]);
            var p1 = new Geo(poly[0]);
            Geo p2;
            var polySize = poly.Count;
            for (var i = 1; i < polySize; i++)
            {
                p2 = new Geo(poly[i]);
                /*
          * p1 and p2 are on different sides of the ray, and the great acircle
          * between p1 and p2 is on the side that counts;
          */
                if ((p1.Dot(ray) < 0.0) != (p2.Dot(ray) < 0.0) && new GeoSegment(p1, p2).GreatCircleIntersection(ray).Dot(side) > 0.0)
                {
                    isIn = !isIn;
                }

                p1 = new Geo(p2);
            }

            // Check for unclosed polygons, if the polygon isn't closed,
            // do the calculation for the last point to the starting
            // point.
            if (!poly[0].Equals(p1))
            {
                p2 = new Geo(poly[0]);
                if ((p1.Dot(ray) < 0.0) != (p2.Dot(ray) < 0.0) && new GeoSegment(p1, p2).GreatCircleIntersection(ray).Dot(side) > 0.0)
                {
                    isIn = !isIn;
                }
            }

            return isIn;
        }
 /// <summary>
 /// Treating the passed in GeoSegments as planar vectors, return the dot product
 /// </summary>
 /// <param name="segment1"></param>
 /// <param name="segment2"></param>
 /// <returns></returns>
 public static double Dot(this GeoSegment segment1, GeoSegment segment2)
 {
     // Using Geo only for convenience, these are NOT Geos, really!
     // X is delta longitude, Y is delta latitude, Z is always zero.
     var vec1 = new Geo(segment1[1].Longitude - segment1[0].Longitude, segment1[1].Latitude - segment1[0].Latitude, 0).Normalized;
     var vec2 = new Geo(segment2[1].Longitude - segment2[0].Longitude, segment2[1].Latitude - segment2[0].Latitude, 0).Normalized;
     return vec1.Dot(vec2);
 }