// Convert an input geometry instance to a valid geography instance.
        // This function requires that the WKT coordinate values are longitude/latitude values,
        // in that order and that a valid geography SRID value is supplied.
        //
        public static SqlGeography MakeValidGeographyFromGeometry(SqlGeometry geometry)
        {
            if (geometry.IsNull)
            {
                return(SqlGeography.Null);
            }
            if (geometry.STIsEmpty().Value)
            {
                return(CreateEmptyGeography(geometry.STSrid.Value));
            }

            // Extract vertices from our input to be able to compute geography EnvelopeCenter
            SqlGeographyBuilder pointSetBuilder = new SqlGeographyBuilder();

            geometry.Populate(new GeometryToPointGeographySink(pointSetBuilder));
            SqlGeography center;

            try
            {
                center = pointSetBuilder.ConstructedGeography.EnvelopeCenter();
            }
            catch (ArgumentException)
            {
                // Input is larger than a hemisphere.
                return(SqlGeography.Null);
            }

            // Construct Gnomonic projection centered on input geography
            SqlProjection gnomonicProjection = SqlProjection.Gnomonic(center.Long.Value, center.Lat.Value);

            // Project, run geometry MakeValid and unproject
            SqlGeometryBuilder geometryBuilder = new SqlGeometryBuilder();

            geometry.Populate(new VacuousGeometryToGeographySink(geometry.STSrid.Value, new Projector(gnomonicProjection, geometryBuilder)));
            SqlGeometry outGeometry = MakeValidForGeography(geometryBuilder.ConstructedGeometry);

            try
            {
                return(gnomonicProjection.Unproject(outGeometry));
            }
            catch (ArgumentException)
            {
                // Try iteratively to reduce the object to remove very close vertices.
                for (double tollerance = 1e-4; tollerance <= 1e6; tollerance *= 2)
                {
                    try
                    {
                        return(gnomonicProjection.Unproject(outGeometry.Reduce(tollerance)));
                    }
                    catch (ArgumentException)
                    {
                        // keep trying
                    }
                }
                return(SqlGeography.Null);
            }
        }
        // Computes ConvexHull of input geography and returns a polygon (unless all input points are colinear).
        //
        public static SqlGeography ConvexHullGeography(SqlGeography geography)
        {
            if (geography.IsNull || geography.STIsEmpty().Value)
            {
                return(geography);
            }

            SqlGeography  center             = geography.EnvelopeCenter();
            SqlProjection gnomonicProjection = SqlProjection.Gnomonic(center.Long.Value, center.Lat.Value);
            SqlGeometry   geometry           = gnomonicProjection.Project(geography);

            return(gnomonicProjection.Unproject(geometry.MakeValid().STConvexHull()));
        }
示例#3
0
 public Projector(SqlProjection projection, IGeometrySink sink)
 {
     _projection = projection;
     _sink       = sink;
 }
 public Unprojector(SqlProjection projection, IGeographySink sink, int newSrid)
 {
     _projection = projection;
     _sink       = sink;
     _sink.SetSrid(newSrid);
 }