Ejemplo n.º 1
0
        public void epsg3140_to_wgs()
        {
            var crs = EpsgMicroDatabase.Default.GetCrs(3140);
            var wgs = EpsgMicroDatabase.Default.GetCrs(4326);

            // source for coordinates is http://epsg.io/3140/map
            var ptWgs  = new GeographicCoordinate(-17.785, 177.97);
            var pt3140 = new Point2(530138.52663372, 821498.68898981); // units in links

            var gen      = new EpsgCrsCoordinateOperationPathGenerator();
            var paths    = gen.Generate(wgs, crs);
            var compiler = new StaticCoordinateOperationCompiler();
            var txs      = paths
                           .Select(p => compiler.Compile(p))
                           .Where(p => p != null);

            var forward       = txs.Single();
            var actualForward = (Point2)forward.TransformValue(ptWgs);

            Assert.AreEqual(pt3140.X, actualForward.X, 30);
            Assert.AreEqual(pt3140.Y, actualForward.Y, 30);

            var reverse       = forward.GetInverse();
            var actualReverse = (GeographicCoordinate)reverse.TransformValue(pt3140);

            Assert.AreEqual(ptWgs.Longitude, actualReverse.Longitude, 0.01);
            Assert.AreEqual(ptWgs.Latitude, actualReverse.Latitude, 0.01);
        }
        public void epsg3140_to_wgs()
        {
            var crs = EpsgMicroDatabase.Default.GetCrs(3140);
            var wgs = EpsgMicroDatabase.Default.GetCrs(4326);

            // source for coordinates is http://epsg.io/3140/map
            var ptWgs = new GeographicCoordinate(-17.785, 177.97);
            var pt3140 = new Point2(530138.52663372, 821498.68898981); // units in links

            var gen = new EpsgCrsCoordinateOperationPathGenerator();
            var paths = gen.Generate(wgs, crs);
            var compiler = new StaticCoordinateOperationCompiler();
            var txs = paths
                .Select(p => compiler.Compile(p))
                .Where(p => p != null);

            var forward = txs.Single();
            var actualForward = (Point2)forward.TransformValue(ptWgs);
            Assert.AreEqual(pt3140.X, actualForward.X, 30);
            Assert.AreEqual(pt3140.Y, actualForward.Y, 30);

            var reverse = forward.GetInverse();
            var actualReverse = (GeographicCoordinate)reverse.TransformValue(pt3140);
            Assert.AreEqual(ptWgs.Longitude, actualReverse.Longitude, 0.01);
            Assert.AreEqual(ptWgs.Latitude, actualReverse.Latitude, 0.01);
        }
Ejemplo n.º 3
0
        public void old_web_mercator_to_new_web_mercator()
        {
            var oldCrs = EpsgMicroDatabase.Default.GetCrs(3785);
            var newCrs = EpsgMicroDatabase.Default.GetCrs(3857);

            var generator = new EpsgCrsCoordinateOperationPathGenerator();
            var forwardPaths = generator.Generate(oldCrs, newCrs);
            Assert.IsNotEmpty(forwardPaths);
        }
Ejemplo n.º 4
0
        public void epsg3079_to_epsg3575()
        {
            var from = EpsgMicroDatabase.Default.GetCrs(3079);
            var to   = EpsgMicroDatabase.Default.GetCrs(3575);
            var wgs  = EpsgMicroDatabase.Default.GetCrs(4326);

            var somePlaceInMichigan = new GeographicCoordinate(40.4, -91.8);
            var expected3079        = new Point2(6992.885640195105, -644.956855237484);
            var expected3575        = new Point2(-5244224.354585549, 1095575.5476152631);

            var gen      = new EpsgCrsCoordinateOperationPathGenerator();
            var fromPath = gen.Generate(from, wgs).First();
            var toPath   = gen.Generate(to, wgs).First();

            var compiler = new StaticCoordinateOperationCompiler();

            var fromTx = compiler.Compile(fromPath);
            var toTx   = compiler.Compile(toPath);

            var a = (GeographicCoordinate)fromTx.TransformValue(expected3079);

            Assert.AreEqual(somePlaceInMichigan.Latitude, a.Latitude, 0.01);
            Assert.AreEqual(somePlaceInMichigan.Longitude, a.Longitude, 0.01);
            var b = (Point2)fromTx.GetInverse().TransformValue(somePlaceInMichigan);

            Assert.AreEqual(expected3079.X, b.X, 0.01);
            Assert.AreEqual(expected3079.Y, b.Y, 0.01);
            var d = (Point2)toTx.GetInverse().TransformValue(somePlaceInMichigan);

            Assert.AreEqual(expected3575.X, d.X, 0.01);
            Assert.AreEqual(expected3575.Y, d.Y, 0.01);
            var c = (GeographicCoordinate)toTx.TransformValue(expected3575);

            Assert.AreEqual(somePlaceInMichigan.Latitude, c.Latitude, 0.01);
            Assert.AreEqual(somePlaceInMichigan.Longitude, c.Longitude, 0.01);

            var allTotalPaths = gen.Generate(from, to).ToList();
            var totalPath     = allTotalPaths.First();
            var totalTx       = compiler.Compile(totalPath);
            var actual3575    = (Point2)totalTx.TransformValue(expected3079);

            Assert.AreEqual(expected3575.X, actual3575.X, 1);
            Assert.AreEqual(expected3575.Y, actual3575.Y, 1);
        }
Ejemplo n.º 5
0
        public void old_web_mercator_to_nad83()
        {
            var oldCrs = EpsgMicroDatabase.Default.GetCrs(3785);
            var newCrs = EpsgMicroDatabase.Default.GetCrs(4269);

            var generator    = new EpsgCrsCoordinateOperationPathGenerator();
            var forwardPaths = generator.Generate(oldCrs, newCrs);

            Assert.IsNotEmpty(forwardPaths);
        }
Ejemplo n.º 6
0
 public void epsg2039_to_epsg28191()
 {
     var from = EpsgMicroDatabase.Default.GetCrs(2039);
     var to = EpsgMicroDatabase.Default.GetCrs(28191);
     var pathGenerator = new EpsgCrsCoordinateOperationPathGenerator();
     var epsgPath = pathGenerator.Generate(from, to);
     Assert.IsNotEmpty(epsgPath);
     var proj4Transform = new Proj4Transform(from, to);
     Assert.IsNotNull(proj4Transform);
 }
Ejemplo n.º 7
0
        public void epsg3031_to_epsg3293()
        {
            var from          = EpsgMicroDatabase.Default.GetCrs(3031);
            var to            = EpsgMicroDatabase.Default.GetCrs(3293);
            var pathGenerator = new EpsgCrsCoordinateOperationPathGenerator();
            var epsgPath      = pathGenerator.Generate(from, to);

            Assert.IsNotEmpty(epsgPath);
            var proj4Transform = new Proj4Transform(from, to);

            Assert.IsNotNull(proj4Transform);
        }
        public void epsg3079_to_epsg3575()
        {
            var from = EpsgMicroDatabase.Default.GetCrs(3079);
            var to = EpsgMicroDatabase.Default.GetCrs(3575);
            var wgs = EpsgMicroDatabase.Default.GetCrs(4326);

            var somePlaceInMichigan = new GeographicCoordinate(40.4, -91.8);
            var expected3079 = new Point2(6992.885640195105, -644.956855237484);
            var expected3575 = new Point2(-5244224.354585549, 1095575.5476152631);

            var gen = new EpsgCrsCoordinateOperationPathGenerator();
            var fromPath = gen.Generate(from, wgs).First();
            var toPath = gen.Generate(to, wgs).First();

            var compiler = new StaticCoordinateOperationCompiler();

            var fromTx = compiler.Compile(fromPath);
            var toTx = compiler.Compile(toPath);

            var a = (GeographicCoordinate)fromTx.TransformValue(expected3079);
            Assert.AreEqual(somePlaceInMichigan.Latitude, a.Latitude, 0.01);
            Assert.AreEqual(somePlaceInMichigan.Longitude, a.Longitude, 0.01);
            var b = (Point2)fromTx.GetInverse().TransformValue(somePlaceInMichigan);
            Assert.AreEqual(expected3079.X, b.X, 0.01);
            Assert.AreEqual(expected3079.Y, b.Y, 0.01);
            var d = (Point2)toTx.GetInverse().TransformValue(somePlaceInMichigan);
            Assert.AreEqual(expected3575.X, d.X, 0.01);
            Assert.AreEqual(expected3575.Y, d.Y, 0.01);
            var c = (GeographicCoordinate)toTx.TransformValue(expected3575);
            Assert.AreEqual(somePlaceInMichigan.Latitude, c.Latitude, 0.01);
            Assert.AreEqual(somePlaceInMichigan.Longitude, c.Longitude, 0.01);

            var allTotalPaths = gen.Generate(from, to).ToList();
            var totalPath = allTotalPaths.First();
            var totalTx = compiler.Compile(totalPath);
            var actual3575 = (Point2)totalTx.TransformValue(expected3079);

            Assert.AreEqual(expected3575.X, actual3575.X, 1);
            Assert.AreEqual(expected3575.Y, actual3575.Y, 1);
        }
Ejemplo n.º 9
0
        public void has_cat_paths_4267_and_4326()
        {
            var crs4267 = EpsgMicroDatabase.Default.GetCrs(4267);
            var crs4326 = EpsgMicroDatabase.Default.GetCrs(4326);

            var generator = new EpsgCrsCoordinateOperationPathGenerator();
            var forwardPaths = generator.Generate(crs4267, crs4326);
            var forwardWithCatOps = forwardPaths
                .Select(x => x.CoordinateOperations)
                .Where(x => x.OfType<EpsgConcatenatedCoordinateOperationInfo>().Any());
            Assert.IsNotEmpty(forwardWithCatOps);

            var inversePaths = generator.Generate(crs4326, crs4267);
            var inverseWithCatOps = inversePaths
                .Select(x => x.CoordinateOperations)
                .Where(x => x
                    .OfType<EpsgCoordinateOperationInverse>()
                    .Select(y => y.Core)
                    .OfType<EpsgConcatenatedCoordinateOperationInfo>()
                    .Any());
            Assert.IsNotEmpty(inverseWithCatOps);
        }
Ejemplo n.º 10
0
        public void has_cat_paths_4267_and_4326()
        {
            var crs4267 = EpsgMicroDatabase.Default.GetCrs(4267);
            var crs4326 = EpsgMicroDatabase.Default.GetCrs(4326);

            var generator         = new EpsgCrsCoordinateOperationPathGenerator();
            var forwardPaths      = generator.Generate(crs4267, crs4326);
            var forwardWithCatOps = forwardPaths
                                    .Select(x => x.CoordinateOperations)
                                    .Where(x => x.OfType <EpsgConcatenatedCoordinateOperationInfo>().Any());

            Assert.IsNotEmpty(forwardWithCatOps);

            var inversePaths      = generator.Generate(crs4326, crs4267);
            var inverseWithCatOps = inversePaths
                                    .Select(x => x.CoordinateOperations)
                                    .Where(x => x
                                           .OfType <EpsgCoordinateOperationInverse>()
                                           .Select(y => y.Core)
                                           .OfType <EpsgConcatenatedCoordinateOperationInfo>()
                                           .Any());

            Assert.IsNotEmpty(inverseWithCatOps);
        }
Ejemplo n.º 11
0
        public void epsg4326_to_5072()
        {
            var wgs         = EpsgMicroDatabase.Default.GetCrs(4326);
            var nad83Albers = EpsgMicroDatabase.Default.GetCrs(5072);
            var gen         = new EpsgCrsCoordinateOperationPathGenerator();
            var paths       = gen.Generate(wgs, nad83Albers);
            var compiler    = new StaticCoordinateOperationCompiler();
            var txs         = paths.Select(p => compiler.Compile(p)).Where(p => p != null);
            var forward     = txs.Single();

            var transformed = (Point2)forward.TransformValue(new GeographicCoordinate(39, -105));

            Assert.AreEqual(-771063, transformed.X, 1);
            Assert.AreEqual(1811448, transformed.Y, 1);
        }
Ejemplo n.º 12
0
        public void epsg4087_to_wgs()
        {
            var crs = EpsgMicroDatabase.Default.GetCrs(4087);
            var wgs = EpsgMicroDatabase.Default.GetCrs(4326);

            var ptWgs  = new GeographicCoordinate(39, -104);
            var pt4087 = new Point2(-11577227, 4341460);

            var gen      = new EpsgCrsCoordinateOperationPathGenerator();
            var paths    = gen.Generate(wgs, crs);
            var compiler = new StaticCoordinateOperationCompiler();
            var txs      = paths.Select(p => compiler.Compile(p)).Where(p => p != null);

            var forward = txs.Single();

            var actualZeroMeters = (Point2)forward.TransformValue(GeographicCoordinate.Zero);

            Assert.AreEqual(0, actualZeroMeters.X);
            Assert.AreEqual(0, actualZeroMeters.Y);

            var actualForward = (Point2)forward.TransformValue(ptWgs);

            Assert.AreEqual(pt4087.X, actualForward.X, 30);
            Assert.AreEqual(pt4087.Y, actualForward.Y, 30);

            var reverse = forward.GetInverse();

            var actualZeroDegrees = (GeographicCoordinate)reverse.TransformValue(Point2.Zero);

            Assert.AreEqual(0, actualZeroDegrees.Longitude);
            Assert.AreEqual(0, actualZeroDegrees.Latitude);

            var actualReverse = (GeographicCoordinate)reverse.TransformValue(pt4087);

            Assert.AreEqual(ptWgs.Longitude, actualReverse.Longitude, 0.01);
            Assert.AreEqual(ptWgs.Latitude, actualReverse.Latitude, 0.01);
        }
Ejemplo n.º 13
0
        public IEnumerable <TestCase> CreateTestCases()
        {
            var crs4326 = Crs4326;

            if (crs4326 == null)
            {
                throw new InvalidOperationException("No implementation of EPSG:4326 has been found.");
            }

            var testableCrsList = new List <TestableCrs>();

            foreach (var crs in GetAllCrs().Where(x => x.Kind == EpsgCrsKind.Projected))
            {
                if (crs.Area == null)
                {
                    continue;
                }
                if (crs.Area.LongitudeRange.Start > crs.Area.LongitudeRange.End)
                {
                    continue; // ignore the dateline wrapped ones for now
                }
                var paths = _epsgPathGenerator.Generate(crs4326, crs)
                            .OrderBy(x => GetEpsgAccuracy(x) ?? 999);
                var transform = paths
                                .Select(p => _coordinateOperationCompiler.Compile(p))
                                .Where(x => x != null)
                                .FirstOrDefault();
                if (transform == null)
                {
                    continue;
                }

                Console.WriteLine("Preparing {1}: {0} ", crs, testableCrsList.Count);

                testableCrsList.Add(new TestableCrs {
                    Crs = crs,
                    From4325Transform = transform,
                    Area = crs.Area
                });
            }

            Console.WriteLine("Prepared tests for {0} CRSs.", testableCrsList.Count);

            for (var fromTestableIndex = 0; fromTestableIndex < testableCrsList.Count; ++fromTestableIndex)
            {
                var fromTestable = testableCrsList[fromTestableIndex];
                var fromCrs      = fromTestable.Crs;
                var fromArea     = fromTestable.Area;

                Console.WriteLine("{0:P} complete...", (fromTestableIndex / (double)testableCrsList.Count));

                foreach (var toTestable in testableCrsList)
                {
                    if (fromTestable == toTestable)
                    {
                        continue;
                    }

                    var toCrs  = toTestable.Crs;
                    var toArea = toTestable.Area;

                    var areaIntersection = fromArea.Intersection(toArea);
                    if (areaIntersection == null)
                    {
                        continue;
                    }

                    if (areaIntersection.LongitudeRange.Start > areaIntersection.LongitudeRange.End)
                    {
                        continue; // ignore the dateline wrapped ones for now
                    }
                    var inputCoordsWgs84       = CreateTestPoints(areaIntersection);
                    var transformedInputCoords = inputCoordsWgs84.ConvertAll(c => fromTestable.From4325Transform.TransformValue(c));

                    yield return(new TestCase {
                        Source = fromCrs,
                        Target = toCrs,
                        Area = areaIntersection,
                        InputWgs84Coordinates = inputCoordsWgs84,
                        InputCoordinates = transformedInputCoords
                    });
                }
            }
        }
Ejemplo n.º 14
0
        public HttpResponseMessage Draw(double? minLon, double? maxLon, double? minLat, double? maxLat, int? maxImgWidth, int? maxImgHeight)
        {
            var shapefilePath = HostingEnvironment.MapPath("~/App_Data/builtupp_usa/builtupp_usa.shp");

            ITransformation<GeographicCoordinate, Point2> transformation = null;
            var targetCrs = EpsgMicroDatabase.Default.GetCrs(3005);
            LongitudeDegreeRange dataLongitudeRange;
            Range dataLatitudeRange;
            using (var shapeFile = Shapefile.Open(shapefilePath)) {
                dataLongitudeRange = new LongitudeDegreeRange(shapeFile.Extent.MinX, shapeFile.Extent.MaxX);
                dataLatitudeRange = new Range(shapeFile.Extent.MinY, shapeFile.Extent.MaxY);

                var dataCrs = EpsgMicroDatabase.Default.GetCrs(4326);
                var pathGenerator = new EpsgCrsCoordinateOperationPathGenerator();
                var paths = pathGenerator.Generate(dataCrs, targetCrs);
                var compiler = new StaticCoordinateOperationCompiler();
                var firstTransfom = paths.Select(p => {
                    return compiler.Compile(p);
                }).First(x => x != null);

                transformation = firstTransfom as ITransformation<GeographicCoordinate, Point2>;
                if (transformation == null && firstTransfom is IEnumerable<ITransformation>)
                    transformation = new CompiledConcatenatedTransformation<GeographicCoordinate, Point2>((IEnumerable<ITransformation>)firstTransfom);

            }

            var geoMbrMin = new GeographicCoordinate(minLat ?? dataLatitudeRange.Low, minLon ?? dataLongitudeRange.Start);
            var geoMbrMax = new GeographicCoordinate(maxLat ?? dataLatitudeRange.High, maxLon ?? dataLongitudeRange.End);
            var geoMbrTL = new GeographicCoordinate(geoMbrMax.Latitude, geoMbrMin.Longitude);
            var geoMbrTR = new GeographicCoordinate(geoMbrMin.Latitude, geoMbrMax.Longitude);

            var projectedMbrPoints = new[] {
                    geoMbrMin,
                    geoMbrMax,
                    geoMbrTL,
                    geoMbrTR,
                    new GeographicCoordinate(geoMbrMin.Latitude, Math.Abs(geoMbrMin.Longitude + geoMbrMax.Longitude) / 2.0)
                }
                .Select(transformation.TransformValue)
                .ToArray();

            var projectedExtent = new Mbr(
                new Point2(projectedMbrPoints.Min(x => x.X), projectedMbrPoints.Min(x => x.Y)),
                new Point2(projectedMbrPoints.Max(x => x.X), projectedMbrPoints.Max(x => x.Y))
            );

            var geogMapOrigin = new GeographicCoordinate(dataLatitudeRange.Mid, dataLongitudeRange.Mid);
            var mapOrigin = transformation.TransformValue(geogMapOrigin);

            var mapOffset = new Vector2(0/*-(mapOrigin.X - projectedExtent.X.Mid)*/, projectedExtent.Height / 2.0);

            var imageSizeLimits = new Vector2(maxImgWidth ?? 300, maxImgHeight ?? 300);
            if (imageSizeLimits.X > 4096 || imageSizeLimits.Y > 4096)
                throw new ArgumentException("Image size too large");

            var dataRatio = new Vector2(projectedExtent.Width / imageSizeLimits.X, projectedExtent.Height / imageSizeLimits.Y);
            var lowCorner = projectedExtent.Min;
            Vector2 desiredImageSize;
            double imageScaleFactor;
            if (dataRatio.Y < dataRatio.X) {
                imageScaleFactor = imageSizeLimits.X / projectedExtent.Width;
                desiredImageSize = new Vector2(imageSizeLimits.X, (int)(projectedExtent.Height * imageScaleFactor));
            }
            else {
                imageScaleFactor = imageSizeLimits.Y / projectedExtent.Height;
                desiredImageSize = new Vector2((int)(projectedExtent.Width * imageScaleFactor), imageSizeLimits.Y);
            }

            using (var image = new System.Drawing.Bitmap((int)desiredImageSize.X, (int)desiredImageSize.Y))
            using (var graphics = Graphics.FromImage(image)) {
                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                var shapeSource = new PointShapefileShapeSource(shapefilePath);
                var shapeReader = new ShapeReader(shapeSource);
                using (var shapeEnumerator = shapeReader.GetEnumerator()) {
                    var sourceCoordinates = ReadPagesToGeographicCoordinate(shapeEnumerator).SelectMany(x => x);
                    var pointColor = Color.Black;
                    var circleFillBrush = new SolidBrush(Color.FromArgb(64,16,64,128));
                    var featureRadius = 3.0;
                    var featureDiameter = featureRadius * 2;
                    var featureDiameterFloat = (float)featureDiameter;
                    var topLeftOffset = new Vector2(-featureRadius,-featureRadius);

                    foreach (var transformedPoint in transformation.TransformValues(sourceCoordinates)) {
                        var offsetPoint = transformedPoint.Difference(lowCorner).Add(mapOffset);

                        var scaledPoint = offsetPoint.GetScaled(imageScaleFactor);
                        var screenPoint = new Point2(scaledPoint.X, image.Height - scaledPoint.Y);
                        var drawTopLeft = screenPoint.Add(topLeftOffset);

                        graphics.FillEllipse(circleFillBrush, (float)drawTopLeft.X, (float)drawTopLeft.Y, featureDiameterFloat, featureDiameterFloat);
                    }
                }
                var result = new HttpResponseMessage(HttpStatusCode.OK);
                byte[] imageBytes;
                using (var memoryStream = new MemoryStream()) {
                    image.Save(memoryStream, ImageFormat.Png);
                    imageBytes = memoryStream.ToArray();
                }
                result.Content = new ByteArrayContent(imageBytes);
                result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png");
                return result;
            }
        }
        public void epsg4326_to_5072()
        {
            var wgs = EpsgMicroDatabase.Default.GetCrs(4326);
            var nad83Albers = EpsgMicroDatabase.Default.GetCrs(5072);
            var gen = new EpsgCrsCoordinateOperationPathGenerator();
            var paths = gen.Generate(wgs, nad83Albers);
            var compiler = new StaticCoordinateOperationCompiler();
            var txs = paths.Select(p => compiler.Compile(p)).Where(p => p != null);
            var forward = txs.Single();

            var transformed = (Point2)forward.TransformValue(new GeographicCoordinate(39, -105));
            Assert.AreEqual(-771063, transformed.X, 1);
            Assert.AreEqual(1811448, transformed.Y, 1);
        }
Ejemplo n.º 16
0
        public HttpResponseMessage Draw(double?minLon, double?maxLon, double?minLat, double?maxLat, int?maxImgWidth, int?maxImgHeight)
        {
            var shapefilePath = HostingEnvironment.MapPath("~/App_Data/builtupp_usa/builtupp_usa.shp");

            ITransformation <GeographicCoordinate, Point2> transformation = null;
            var targetCrs = EpsgMicroDatabase.Default.GetCrs(3005);
            LongitudeDegreeRange dataLongitudeRange;
            Range dataLatitudeRange;

            using (var shapeFile = Shapefile.Open(shapefilePath)) {
                dataLongitudeRange = new LongitudeDegreeRange(shapeFile.Extent.MinX, shapeFile.Extent.MaxX);
                dataLatitudeRange  = new Range(shapeFile.Extent.MinY, shapeFile.Extent.MaxY);

                var dataCrs       = EpsgMicroDatabase.Default.GetCrs(4326);
                var pathGenerator = new EpsgCrsCoordinateOperationPathGenerator();
                var paths         = pathGenerator.Generate(dataCrs, targetCrs);
                var compiler      = new StaticCoordinateOperationCompiler();
                var firstTransfom = paths.Select(p => {
                    return(compiler.Compile(p));
                }).First(x => x != null);

                transformation = firstTransfom as ITransformation <GeographicCoordinate, Point2>;
                if (transformation == null && firstTransfom is IEnumerable <ITransformation> )
                {
                    transformation = new CompiledConcatenatedTransformation <GeographicCoordinate, Point2>((IEnumerable <ITransformation>)firstTransfom);
                }
            }

            var geoMbrMin = new GeographicCoordinate(minLat ?? dataLatitudeRange.Low, minLon ?? dataLongitudeRange.Start);
            var geoMbrMax = new GeographicCoordinate(maxLat ?? dataLatitudeRange.High, maxLon ?? dataLongitudeRange.End);
            var geoMbrTL  = new GeographicCoordinate(geoMbrMax.Latitude, geoMbrMin.Longitude);
            var geoMbrTR  = new GeographicCoordinate(geoMbrMin.Latitude, geoMbrMax.Longitude);

            var projectedMbrPoints = new[] {
                geoMbrMin,
                geoMbrMax,
                geoMbrTL,
                geoMbrTR,
                new GeographicCoordinate(geoMbrMin.Latitude, Math.Abs(geoMbrMin.Longitude + geoMbrMax.Longitude) / 2.0)
            }
            .Select(transformation.TransformValue)
            .ToArray();


            var projectedExtent = new Mbr(
                new Point2(projectedMbrPoints.Min(x => x.X), projectedMbrPoints.Min(x => x.Y)),
                new Point2(projectedMbrPoints.Max(x => x.X), projectedMbrPoints.Max(x => x.Y))
                );

            var geogMapOrigin = new GeographicCoordinate(dataLatitudeRange.Mid, dataLongitudeRange.Mid);
            var mapOrigin     = transformation.TransformValue(geogMapOrigin);

            var mapOffset = new Vector2(0 /*-(mapOrigin.X - projectedExtent.X.Mid)*/, projectedExtent.Height / 2.0);

            var imageSizeLimits = new Vector2(maxImgWidth ?? 300, maxImgHeight ?? 300);

            if (imageSizeLimits.X > 4096 || imageSizeLimits.Y > 4096)
            {
                throw new ArgumentException("Image size too large");
            }

            var     dataRatio = new Vector2(projectedExtent.Width / imageSizeLimits.X, projectedExtent.Height / imageSizeLimits.Y);
            var     lowCorner = projectedExtent.Min;
            Vector2 desiredImageSize;
            double  imageScaleFactor;

            if (dataRatio.Y < dataRatio.X)
            {
                imageScaleFactor = imageSizeLimits.X / projectedExtent.Width;
                desiredImageSize = new Vector2(imageSizeLimits.X, (int)(projectedExtent.Height * imageScaleFactor));
            }
            else
            {
                imageScaleFactor = imageSizeLimits.Y / projectedExtent.Height;
                desiredImageSize = new Vector2((int)(projectedExtent.Width * imageScaleFactor), imageSizeLimits.Y);
            }

            using (var image = new System.Drawing.Bitmap((int)desiredImageSize.X, (int)desiredImageSize.Y))
                using (var graphics = Graphics.FromImage(image)) {
                    graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    var shapeSource = new PointShapefileShapeSource(shapefilePath);
                    var shapeReader = new ShapeReader(shapeSource);
                    using (var shapeEnumerator = shapeReader.GetEnumerator()) {
                        var sourceCoordinates    = ReadPagesToGeographicCoordinate(shapeEnumerator).SelectMany(x => x);
                        var pointColor           = Color.Black;
                        var circleFillBrush      = new SolidBrush(Color.FromArgb(64, 16, 64, 128));
                        var featureRadius        = 3.0;
                        var featureDiameter      = featureRadius * 2;
                        var featureDiameterFloat = (float)featureDiameter;
                        var topLeftOffset        = new Vector2(-featureRadius, -featureRadius);

                        foreach (var transformedPoint in transformation.TransformValues(sourceCoordinates))
                        {
                            var offsetPoint = transformedPoint.Difference(lowCorner).Add(mapOffset);



                            var scaledPoint = offsetPoint.GetScaled(imageScaleFactor);
                            var screenPoint = new Point2(scaledPoint.X, image.Height - scaledPoint.Y);
                            var drawTopLeft = screenPoint.Add(topLeftOffset);

                            graphics.FillEllipse(circleFillBrush, (float)drawTopLeft.X, (float)drawTopLeft.Y, featureDiameterFloat, featureDiameterFloat);
                        }
                    }
                    var    result = new HttpResponseMessage(HttpStatusCode.OK);
                    byte[] imageBytes;
                    using (var memoryStream = new MemoryStream()) {
                        image.Save(memoryStream, ImageFormat.Png);
                        imageBytes = memoryStream.ToArray();
                    }
                    result.Content = new ByteArrayContent(imageBytes);
                    result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/png");
                    return(result);
                }
        }
        public void epsg3857_to_wgs()
        {
            var crs = EpsgMicroDatabase.Default.GetCrs(3857);
            var wgs = EpsgMicroDatabase.Default.GetCrs(4326);

            var ptWgs = new GeographicCoordinate(45,10);
            var pt3857 = new Point2(1113194, 5621521);

            var gen = new EpsgCrsCoordinateOperationPathGenerator();
            var paths = gen.Generate(wgs, crs);
            var compiler = new StaticCoordinateOperationCompiler();
            var txs = paths.Select(p => compiler.Compile(p)).Where(p => p != null);

            var forward = txs.Single();

            var actualZeroMeters = (Point2)forward.TransformValue(GeographicCoordinate.Zero);
            Assert.AreEqual(0, actualZeroMeters.X);
            Assert.AreEqual(0, actualZeroMeters.Y, 0.0000001);

            var actualForward = (Point2)forward.TransformValue(ptWgs);
            Assert.AreEqual(pt3857.X, actualForward.X, 30);
            Assert.AreEqual(pt3857.Y, actualForward.Y, 30);

            var reverse = forward.GetInverse();

            var actualZeroDegrees = (GeographicCoordinate)reverse.TransformValue(Point2.Zero);
            Assert.AreEqual(0, actualZeroDegrees.Longitude);
            Assert.AreEqual(0, actualZeroDegrees.Latitude);

            var actualReverse = (GeographicCoordinate)reverse.TransformValue(pt3857);
            Assert.AreEqual(ptWgs.Longitude, actualReverse.Longitude, 0.0001);
            Assert.AreEqual(ptWgs.Latitude, actualReverse.Latitude, 0.0001);
        }