public static string CreateFromMap(Map map)
        {
            if (map == null)
            {
                throw new ArgumentNullException("map");
            }

            Rectangle extents = map.Extents.Clone();

            // reproject map extents to wgs 84 for Google Earth
            if (!string.IsNullOrEmpty(map.Projection))
            {
                using (ProjFourWrapper src = new ProjFourWrapper(map.Projection))
                {
                    using (ProjFourWrapper dst = new ProjFourWrapper(ProjFourWrapper.WGS84))
                    {
                        extents = new Rectangle(src.Transform(dst, extents.Min),
                                                    src.Transform(dst, extents.Max));
                    }
                }
            }

            MemoryStream ms = new MemoryStream();
            XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);

            xtw.WriteStartDocument();
            xtw.WriteStartElement("kml", "http://www.opengis.net/kml/2.2");
            xtw.WriteStartElement("Document");

            foreach (Layer l in map.Layers)
            {
                if (l.Data ==  null) continue;

                foreach (Style s in l.Styles)
                {
                    CreateFromStyle(xtw, s, l.Data.SourceFeatureType);
                }
            }

            foreach (Layer l in map.Layers)
            {
                if (l.Data == null) continue;

                CreateFromLayer(xtw, l, extents);
            }

            xtw.WriteEndElement(); // Document
            xtw.WriteEndElement(); // kml
            xtw.WriteEndDocument();
            xtw.Flush();

            // Now read back
            ms.Seek(0, SeekOrigin.Begin);
            TextReader tr = new StreamReader(ms);
            return tr.ReadToEnd();
        }
        public void TestProject()
        {
            using (ProjFourWrapper proj = new ProjFourWrapper("+init=epsg:2236"))
            {
                Point pt = proj.Project(new Point(-81, 26));

                // used proj command line to acquire this
                CompareAlbersPoints(new Point(656166.67, 605690.54), pt);
            }
        }
        public void TestTransformPointFromCSToCS()
        {
            using (ProjFourWrapper src = new ProjFourWrapper("+init=epsg:2236"))
            {
                using (ProjFourWrapper dst = new ProjFourWrapper("+proj=aea +lat_1=24 +lat_2=31.5 +lat_0=24 +lon_0=-84 +x_0=400000 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs"))
                {
                    Point pt = src.Transform(dst,  new Point(656166.67, 605690.54));

                    // used cs2cs command line to acquire this
                    CompareAlbersPoints(new Point(699831.04, 225395.97), pt);
                }
            }
        }
        static void CreateFromLayer(XmlTextWriter xtw, Layer layer, Rectangle extents)
        {
            ProjFourWrapper src = null;
            ProjFourWrapper dst = null;
            Rectangle queryExtents = extents.Clone();

            try
            {

                if (!string.IsNullOrEmpty(layer.Projection) &&
                    layer.Projection != ProjFourWrapper.WGS84)
                {
                    src = new ProjFourWrapper(layer.Projection);
                    dst = new ProjFourWrapper(ProjFourWrapper.WGS84);

                    queryExtents = new Rectangle(dst.Transform(src, queryExtents.Min),
                                                    dst.Transform(src, queryExtents.Max));
                }

                xtw.WriteStartElement("Folder");
                xtw.WriteElementString("name", layer.Id);
                xtw.WriteElementString("visibility", layer.Visible ? "1" : "0");

                foreach (Feature f in layer.Data.GetFeatures(queryExtents, layer.ThemeField, layer.LabelField))
                {
                    CreateFromFeature(xtw, layer, f, src, dst);
                }

                xtw.WriteEndElement(); // Folder
            }
            finally
            {
                if (src != null)
                {
                    src.Dispose();
                    dst.Dispose();
                }
            }
        }
        static void CreateFromFeature(XmlTextWriter xtw,
            Layer layer,
            Feature feature,
            ProjFourWrapper source,
            ProjFourWrapper destination)
        {
            Style style = layer.GetStyleForFeature(feature.ThemeFieldValue);

            if (style == null) return;

            string name = !string.IsNullOrEmpty(feature.LabelFieldValue) ?
                feature.LabelFieldValue :
                    !string.IsNullOrEmpty(feature.ThemeFieldValue) ?
                    feature.ThemeFieldValue : null;

            bool transform = destination != null;

            if (layer.Data.SourceFeatureType == FeatureType.Point)
            {
                Point pt = feature as Point;

                if (transform)
                {
                    pt = source.Transform(destination, pt);
                }

                xtw.WriteStartElement("Placemark");

                if (style != null && !string.IsNullOrEmpty(style.Id))
                {
                    xtw.WriteElementString("styleUrl", "#" + style.Id);
                }

                if (name != null)
                {
                    xtw.WriteElementString("name", name);
                }

                xtw.WriteStartElement("Point");
                xtw.WriteElementString("coordinates", string.Format("{0},{1}",
                                                                    pt.X.ToString(CultureInfo.InvariantCulture),
                                                                    pt.Y.ToString(CultureInfo.InvariantCulture)));
                xtw.WriteEndElement(); // Point

                xtw.WriteEndElement(); // Placemark
            }
            else if (layer.Data.SourceFeatureType == FeatureType.Polyline)
            {
                PolyLine pl = feature as PolyLine;

              	foreach (Line l in pl.Lines)
                {
                    xtw.WriteStartElement("Placemark");

                    if (style != null && !string.IsNullOrEmpty(style.Id))
                    {
                        xtw.WriteElementString("styleUrl", "#" + style.Id);
                    }

                    if (name != null)
                    {
                        xtw.WriteElementString("name", name);
                    }

                    xtw.WriteStartElement("LineString");
                    xtw.WriteElementString("tessellate", "1");

                    StringBuilder sb = new StringBuilder();

                    foreach (Point pt in l.Points)
                    {
                        Point tpt = pt;
                        if (transform)
                        {
                            tpt = source.Transform(destination, pt);
                        }

                        sb.AppendFormat("{0},{1} ",
                                        tpt.X.ToString(CultureInfo.InvariantCulture),
                                        tpt.Y.ToString(CultureInfo.InvariantCulture));
                    }

                    xtw.WriteElementString("coordinates", sb.ToString());
                    xtw.WriteEndElement(); // LineString
                    xtw.WriteEndElement(); // Placemark
                }
            }
            else if (layer.Data.SourceFeatureType == FeatureType.Polygon)
            {
                Polygon pg = feature as Polygon;

                bool inRing = false;
                bool clockwiseIsExterior = true;

                foreach (Ring r in pg.Rings)
                {
                    // Assumptions:
                    // - The first ring in an polygon is an exterior ring
                    // - Interior rings will come consecutively after exterior rings
                    // - Exterior/interior rings are determined by their ring orientation (clockwise/counter)

                    // Therefore, we check the first ring's orientation and use that
                    // to decide which orientation is exterior

                    bool isClockwise = r.IsClockwise;

                    if (!inRing)
                    {
                        clockwiseIsExterior = isClockwise;
                    }

                    if (clockwiseIsExterior == isClockwise)
                    {
                        // exterior ring

                        if (inRing)
                        {
                            xtw.WriteEndElement(); // Polygon
                            xtw.WriteEndElement(); // Placemark
                        }

                        inRing = true;

                        xtw.WriteStartElement("Placemark");

                        if (style != null && !string.IsNullOrEmpty(style.Id))
                        {
                            xtw.WriteElementString("styleUrl", "#" + style.Id);
                        }

                        if (name != null)
                        {
                            xtw.WriteElementString("name", name);
                        }

                        xtw.WriteStartElement("Polygon");
                        xtw.WriteStartElement("outerBoundaryIs");
                        xtw.WriteStartElement("LinearRing");

                        xtw.WriteElementString("tessellate", "1");

                        StringBuilder sb = new StringBuilder();
                        foreach (Point pt in r.Points)
                        {
                            Point tpt = pt;
                            if (transform)
                            {
                                tpt = source.Transform(destination, pt);
                            }

                            sb.AppendFormat("{0},{1} ",
                                            tpt.X.ToString(CultureInfo.InvariantCulture),
                                            tpt.Y.ToString(CultureInfo.InvariantCulture));
                        }

                        xtw.WriteElementString("coordinates", sb.ToString());

                        xtw.WriteEndElement(); // LinearRing
                        xtw.WriteEndElement(); // outerBoundaryIs
                                            }
                    else
                    {
                        xtw.WriteStartElement("innerBoundaryIs");
                        xtw.WriteStartElement("LinearRing");

                        xtw.WriteElementString("tessellate", "1");

                        StringBuilder sb = new StringBuilder();
                        foreach (Point pt in r.Points)
                        {
                            Point tpt = pt;
                            if (transform)
                            {
                                tpt = source.Transform(destination, pt);
                            }

                            sb.AppendFormat("{0},{1} ",
                                            tpt.X.ToString(CultureInfo.InvariantCulture),
                                            tpt.Y.ToString(CultureInfo.InvariantCulture));
                        }

                        xtw.WriteElementString("coordinates", sb.ToString());

                        xtw.WriteEndElement(); // LinearRing
                        xtw.WriteEndElement(); // innerBoundaryIs
                    }
                }

                xtw.WriteEndElement(); // Polygon
                xtw.WriteEndElement(); // Placemark
                //xe.Add(node);
            }
        }
Example #6
0
        public static void Main(string[] args)
        {
            #region check arguments

            Rectangle worldExtents = null;
            Rectangle extents = new Rectangle();
            string path = ".";
            bool showHelp = false;
            int maxZoomLevel = 19;
            int minZoomLevel = 0;
            bool onlyCount = false;
            TileConsumer consumer = TileConsumer.GoogleMaps;
            bool mxzlChanged = false;
            bool mnzlChanged = false;
            int bleedInPixels = 0;
            bool showVersion = false;

            OptionSet options = new OptionSet();
            options.Add("e|extents=",
                        "comma-delimited extents for clipping tile generation (e.g. -180,-90,180,90).  Overrides the map file.  (Must be in map's coordinate system)",
                        delegate (string v) { extents = ParseExtents(v); });
            options.Add("h|help",  "show this message and exit",
                        delegate (string v) { showHelp = v!= null; });
            options.Add("o|output=",
                        "the path of the where to create.  Defaults to current directory",
                        delegate (string v) { path = v; });
            options.Add("x|maxzoom=",
                        "the maximum zoom level",
                        delegate (string v) { maxZoomLevel = int.Parse(v, CultureInfo.InvariantCulture); mxzlChanged = true; });
            options.Add("n|minzoom=",
                        "the minimum zoom level",
                        delegate (string v) { minZoomLevel = int.Parse(v, CultureInfo.InvariantCulture); mnzlChanged = true; });
            options.Add("t|test",
                        "Test - only calculate the total and return",
                        delegate (string v) { onlyCount = v != null; });
            options.Add("c|consumer=",
                        "The consumer.  Valid values are 'googlemaps', 'tms', and 've'.",
                        delegate (string v)
                        {
                if (v == "googlemaps")
                {
                    consumer = TileConsumer.GoogleMaps;
                }
                else if (v == "tms")
                {
                    consumer = TileConsumer.TileMapService;
                }
                else if (v == "ve")
                {
                    consumer = TileConsumer.VirtualEarth;
                }
                else
                {
                    System.Console.WriteLine("Error: Unknown consumer.");
                    ShowHelp(options);
                    return;
                }
            });
            options.Add("w|worldextents=",
                        "comma-delimited extents for defining world (e.g. -180,-90,180,90). Valid only for TMS",
                        delegate (string v) { worldExtents = ParseExtents(v); } );
            options.Add("b|bleed=",
                        "the bleed in pixels for tiles (useful for catching overrunning symbols/labels from other tiles",
                        delegate (string v) { bleedInPixels = int.Parse(v, CultureInfo.InvariantCulture); });
            options.Add("v|version",
                        "shows the version and exits",
                        delegate (string v) { showVersion = v != null; });

            List<string> rest = options.Parse(args);

            if (showVersion)
            {
                System.Console.WriteLine("Version " +
                                         System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
                return;
            }

            if (showHelp)
            {
                ShowHelp(options);
                return;
            }

            if (rest.Count == 0)
            {
                System.Console.WriteLine("No map provided");
                ShowHelp(options);
                return;
            }

            if (!File.Exists(rest[0]))
            {
                System.Console.WriteLine("Map xml file not found");
                ShowHelp(options);
                return;
            }

            if ((consumer == TileConsumer.GoogleMaps || consumer == TileConsumer.VirtualEarth) &&
                worldExtents != null)
            {
                System.Console.WriteLine("Error: cannot set world extents for this consumer");
                ShowHelp(options);
                return;
            }

            #endregion

            #region get map

            // search in the local directory for espg files
            // so Windows ppl don't have to have it installed
            ProjFourWrapper.CustomSearchPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            MapSerializer ms = new MapSerializer();
            ms.AddDatabaseFeatureSourceType<Cumberland.Data.PostGIS.PostGISFeatureSource>();
            ms.AddDatabaseFeatureSourceType<Cumberland.Data.SqlServer.SqlServerFeatureSource>();

            Map map = ms.Deserialize(rest[0]);

            // use map extents as clipping range if not provided
            if (extents.IsEmpty && !map.Extents.IsEmpty)
            {
                extents = map.Extents;
            }

            // if map has a projection, reproject clipping area
            if ((consumer == TileConsumer.GoogleMaps || consumer == TileConsumer.VirtualEarth) &&
                !extents.IsEmpty)
            {
                if (!string.IsNullOrEmpty(map.Projection))
                {
                    using (ProjFourWrapper src = new ProjFourWrapper(map.Projection))
                    {
                        using (ProjFourWrapper dst = new ProjFourWrapper(ProjFourWrapper.SphericalMercatorProjection))
                        {
                            extents = new Rectangle(src.Transform(dst, extents.Min),
                                                    src.Transform(dst, extents.Max));
                        }
                    }
                }
                else
                {
                    System.Console.WriteLine(@"Warning: Your map doesn't have a projection.
                                            Unless your data is in spherical mercator,
                                            you will not get correct tiles");
                }
            }

            if (consumer == TileConsumer.VirtualEarth)
            {
                if (!mnzlChanged) minZoomLevel = 1;
                if (!mxzlChanged) maxZoomLevel = 23;
            }

            #endregion

            #region calculate total # of tiles

            TileProvider tp;
            if (worldExtents == null)
            {
                tp = new TileProvider(consumer);
            }
            else
            {
                tp = new TileProvider(consumer, worldExtents);
            }
            tp.DrawExceptionsOnTile = false;
            tp.BleedInPixels = bleedInPixels;

            // calculate total number of tiles
            long totalCount = 0;
            for (int ii = minZoomLevel; ii <= maxZoomLevel; ii++)
            {
                //System.Console.WriteLine(tp.ClipRectangleAtZoomLevel(extents, ii).ToString());
                if (extents.IsEmpty)
                {
                    int across = tp.CalculateNumberOfTilesAcross(ii);
                    totalCount += (Convert.ToInt64(across)*Convert.ToInt64(across));
                }
                else
                {
                    System.Drawing.Rectangle r = tp.ClipRectangleAtZoomLevel(extents, ii);
                    totalCount += Convert.ToInt64(r.Width+1) * Convert.ToInt64(r.Height+1);
                }
            }

            string info = string.Format("0{0} of {1}", new string(' ', totalCount.ToString().Length-1),totalCount);
            System.Console.Write(info);

            if (onlyCount)
            {
                return;
            }

            #endregion

            #region render tiles

            Directory.CreateDirectory(path);

            #region Handle TMS xml file

            XmlWriter writer = null;

            if (consumer == TileConsumer.TileMapService)
            {
                writer = new XmlTextWriter(Path.Combine(path, "tilemapresource.xml"),
                                                 Encoding.UTF8);
                writer.WriteStartDocument();

                writer.WriteStartElement("TileMap");
                writer.WriteAttributeString("version", "1.0.0");
                writer.WriteAttributeString("tilemapservice", "http://tms.osgeo.org/1.0.0");

                writer.WriteElementString("Title", string.Empty);
                writer.WriteElementString("Abstract", string.Empty);

                int epsg;
                if (ProjFourWrapper.TryParseEpsg(map.Projection, out epsg))
                {
                    writer.WriteElementString("SRS", "EPSG:" + epsg.ToString());
                }
                else
                {
                    writer.WriteElementString("SRS", string.Empty);

                    System.Console.WriteLine("Warning: could not parse epsg code from map projection.  SRS element not set");
                }

                writer.WriteStartElement("BoundingBox");
                writer.WriteAttributeString("minx", extents.Min.X.ToString());
                writer.WriteAttributeString("miny", extents.Min.Y.ToString());
                writer.WriteAttributeString("maxx", extents.Max.X.ToString());
                writer.WriteAttributeString("maxy", extents.Max.Y.ToString());
                writer.WriteEndElement(); // BoundingBox

                writer.WriteStartElement("Origin");
                writer.WriteAttributeString("x", extents.Center.X.ToString());
                writer.WriteAttributeString("y", extents.Center.Y.ToString());
                writer.WriteEndElement(); // Origin

                writer.WriteStartElement("TileFormat");
                writer.WriteAttributeString("width", "256");
                writer.WriteAttributeString("height", "256");
                writer.WriteAttributeString("mime-type", "image/png");
                writer.WriteAttributeString("extension", "png");
                writer.WriteEndElement(); // TileFormat

                writer.WriteStartElement("TileSets");
                writer.WriteAttributeString("profile", "local");
            }

            #endregion

            long current = 0;
            for (int ii = minZoomLevel; ii <= maxZoomLevel; ii++)
            {
                string tilepath = Path.Combine(path, ii.ToString());

                if (consumer == TileConsumer.VirtualEarth)
                {
                    tilepath = path;
                }

                Directory.CreateDirectory(tilepath);

                System.Drawing.Rectangle r;
                if (extents.IsEmpty)
                {
                    int across = tp.CalculateNumberOfTilesAcross(ii);
                    r = new System.Drawing.Rectangle(0, 0, across, across);
                }
                else
                {
                    r = tp.ClipRectangleAtZoomLevel(extents, ii);
                }

                if (consumer == TileConsumer.TileMapService)
                {
                    writer.WriteStartElement("TileSet");
                    writer.WriteAttributeString("href", tilepath);
                    writer.WriteAttributeString("units-per-pixel", tp.CalculateMapUnitsPerPixel(ii).ToString());
                    writer.WriteAttributeString("order", ii.ToString());
                    writer.WriteEndElement(); // TileSet
                }

                for (int x = r.Left; x <= (r.Left+r.Width); x++)
                {
                    string xtilepath = Path.Combine(tilepath, x.ToString());

                    if (consumer == TileConsumer.VirtualEarth)
                    {
                        xtilepath = path;
                    }

                    Directory.CreateDirectory(xtilepath);

                    for (int y = r.Top; y <= (r.Top+r.Height); y++)
                    {
                        current++;

                        // render tile and save to file
                        Bitmap b = tp.DrawTile(map, x, y, ii);
                        string tileFile = string.Format("{0}{1}{2}.png",
                                      xtilepath,
                                      Path.DirectorySeparatorChar,
                                      (consumer == TileConsumer.VirtualEarth ? tp.ConvertTileToQuadKey(x,y,ii) : y.ToString()));
                        b.Save(tileFile ,ImageFormat.Png);

                        // update count in console
                        Console.SetCursorPosition(0, Console.CursorTop);
                        Console.Write(current.ToString());
                        Console.SetCursorPosition(info.Length+1, Console.CursorTop);
                    }
                }
            }

            if (consumer == TileConsumer.TileMapService)
            {
                writer.WriteEndElement(); // TileSets
                writer.WriteEndElement(); // TileMap
                writer.Close();
            }

            #endregion

            System.Console.WriteLine("Finished!");
        }
Example #7
0
        public Bitmap Draw(Map map, Cumberland.Rectangle extents, string projection, int width, int height)
        {
            ProjFourWrapper dst = null;
            Graphics g = null;
            List<string> label_names = new List<string>();
            List<LabelRequest> labels = new List<LabelRequest>();

            try
            {
                #region setup drawing

                Bitmap b = new Bitmap(width, height);
                g = Graphics.FromImage(b);

                if (map.BackgroundColor.A > 0)
                {
                    g.Clear(map.BackgroundColor);
                }

                // set antialiasing mode
                g.SmoothingMode = Smoothing;
                g.TextRenderingHint = textRenderingHint;

                // we need to convert map points to pixel points
                // so let's do as much of this at once:
                // calculate map rectangle based on image width/height
                Rectangle envelope = extents.Clone();

                // set aspect ratio to image
                envelope.AspectRatioOfWidth = Convert.ToDouble(width) /
                    Convert.ToDouble(height);

                // get the scale
                double scale = Convert.ToDouble(envelope.Width) /
                                         Convert.ToDouble(width);
                double displayScale = scale;

                // instantiate output projection
                if (!string.IsNullOrEmpty(projection))
                {
                    dst = new ProjFourWrapper(projection);

                    if (!string.IsNullOrEmpty(map.Projection) &&
                        projection != map.Projection)
                    {
                        // we want to use the map projection for min/max scale on layers/styles/etc.
                        using (ProjFourWrapper orig = new ProjFourWrapper(map.Projection))
                        {
                            Point p1 = dst.Transform(orig, extents.Min);
                            Point p2 = dst.Transform(orig, extents.Max);

                            displayScale = Math.Abs(p1.X-p2.X) / width;
                        }
                    }
                }
                else if (!string.IsNullOrEmpty(map.Projection))
                {
                    dst = new ProjFourWrapper(map.Projection);
                }

                #endregion

                foreach (Layer layer in map.Layers)
                {
                    if (!layer.Visible ||
                        layer.Data == null ||
                        displayScale > layer.MaxScale ||
                        displayScale < layer.MinScale)
                    {
                        continue;
                    }

                    ProjFourWrapper src = null;

                    try
                    {
                        #region set up layer drawing

                        Rectangle layerEnvelope = envelope.Clone();

                        // instantiate layer projection
                        bool reproject = false;
                        if (dst != null && !string.IsNullOrEmpty(layer.Projection))
                        {
                            src = new ProjFourWrapper(layer.Projection);
                            reproject = true;

                            // reproject extents to our source for querying
                            layerEnvelope = new Rectangle(dst.Transform(src, layerEnvelope.Min),
                                                    dst.Transform(src, layerEnvelope.Max));
                        }

                        string themeField = null;

                        // query our data
                        List<Feature> features = null;
                        if (layer.Theme == ThemeType.None)
                        {
                            features = layer.Data.GetFeatures(layerEnvelope, null, layer.LabelField);
                        }
                        else
                        {
                            // check for valid field
                            themeField = layer.ThemeField;
                            if (string.IsNullOrEmpty(themeField))
                            {
                                throw new MapConfigurationException("Layer has been set for theming, but no ThemeField was provided");
                            }

                            features = layer.Data.GetFeatures(layerEnvelope, themeField, layer.LabelField);
                        }

                        if (features.Count == 0)
                        {
                            continue;
                        }

                        if (layer.Styles.Count == 0)
                        {
                            throw new MapConfigurationException("Layer lacks a Style");
                        }

                        List<string> names = new List<string>();

                        // set up a delegate for getting style based on theme type
                        StyleForFeatureFinder getStyle = GetBasicStyleForFeature;

                        if (layer.Theme == ThemeType.Unique)
                        {
                            getStyle = GetUniqueStyleForFeature;
                        }
                        else if (layer.Theme == ThemeType.NumericRange)
                        {
                            getStyle = GetRangeStyleForFeature;
                        }

                        #endregion

                        if (layer.Data.SourceFeatureType == FeatureType.Point)
                        {
                            #region handle point rendering

                            for (int ii=0; ii < features.Count; ii++)
                            {
                                Point p = features[ii] as Point;

                                Style style = getStyle(layer, p.ThemeFieldValue, displayScale);

                                if (style == null)
                                {
                                    continue;
                                }

                                PointDrawer drawPoint = GetPointDrawer(style);

                                if (reproject)
                                {
                                    // convert our data point to the map projection
                                    p = src.Transform(dst, p);
                                }

                                // convert our map projected point to a pixel point
                                System.Drawing.Point pp = ConvertMapToPixel(envelope, scale, p);

                                drawPoint(style, g, pp);

                                if (style.ShowLabels &&
                                    displayScale <= style.LabelMaxScale &&
                                    displayScale >= style.LabelMinScale)
                                {
                                    labels.Add(new LabelRequest(style,
                                        p.LabelFieldValue,
                                        pp,
                                        layer.AllowDuplicateLabels,
                                        names));
                                }
                            }

                            #endregion
                        }
                        else if (layer.Data.SourceFeatureType == FeatureType.Polyline)
                        {
                            #region Handle line rendering

                            for (int ii=0; ii < features.Count; ii++)
                            {
                                PolyLine pol = (PolyLine) features[ii];

                                Style style = getStyle(layer, pol.ThemeFieldValue, displayScale);

                                if (style == null ||
                                    style.LineStyle == LineStyle.None)
                                {
                                    continue;
                                }

                                for (int jj=0; jj < pol.Lines.Count; jj++)
                                {
                                    Line r = pol.Lines[jj];

                                    if (style.Simplify)
                                    {
                                        r = r.Simplify(style.SimplifyTolerance);
                                    }

                                    System.Drawing.Point[] ppts = new System.Drawing.Point[r.Points.Count];

                                    int segmentIdx = 1;
                                    double maxSegment = 0;

                                    for (int kk = 0; kk < r.Points.Count; kk++)
                                    {
                                        Point p = r.Points[kk];

                                        if (reproject)
                                        {
                                            p = src.Transform(dst, p);
                                        }

                                        ppts[kk] = ConvertMapToPixel(envelope, scale, p);

                                        if ((style.DrawPointSymbolOnPolyLine ||
                                            (style.ShowLabels &&
                                            scale <= style.LabelMaxScale &&
                                            scale >= style.LabelMinScale)) &&
                                            kk > 0)
                                        {
                                            // find the segment with the longest length to pin a label to

                                            double seg = r.Points[kk-1].Distance(r.Points[kk]);

                                            if (seg > maxSegment)
                                            {
                                                maxSegment = seg;
                                                segmentIdx = kk;
                                            }
                                        }
                                    }

                                    g.DrawLines(ConvertLayerToPen(style), ppts);

                                    if (style.DrawPointSymbolOnPolyLine ||
                                        (style.ShowLabels &&
                                        pol.LabelFieldValue != null &&
                                        displayScale <= style.LabelMaxScale &&
                                        displayScale >= style.LabelMinScale))
                                    {
                                        Point start = r.Points[segmentIdx-1];
                                        Point end = r.Points[segmentIdx];

                                        // pin our label to the center point of the line
                                        Point polyCenter = new Point((start.X+end.X)/2, (start.Y+end.Y)/2);
                                        //Point polyCenter = r.CalculateBounds().Center;

                                        // transform (if neccessary) the convert to pixel point
                                        System.Drawing.Point plpt = ConvertMapToPixel(envelope,
                                                                                      scale,
                                                                                      (reproject ? src.Transform(dst, polyCenter) : polyCenter));

                                        if (style.ShowLabels)
                                        {

                                            float angle = style.LabelAngle;

                                            if (style.CalculateLabelAngleForPolyLine)
                                            {
                                                // calculate the slope of this line and use as our label angle
                                                angle = CalculateSegmentAngle(start, end);
                                            }

                                            labels.Add(new LabelRequest(style,
                                                                        pol.LabelFieldValue,
                                                                        plpt,
                                                                        layer.AllowDuplicateLabels,
                                                                        names,
                                                                        angle));
                                        }
                                    }
                                }
                            }

                            #endregion
                        }
                        else if (layer.Data.SourceFeatureType == FeatureType.Polygon)
                        {
                            #region polygon rendering

                            for (int ii=0; ii < features.Count; ii++)
                            {
                                Polygon po = features[ii] as Polygon;

                                Style style = getStyle(layer, po.ThemeFieldValue, displayScale);

                                if (style == null)
                                {
                                    continue;
                                }

                                GraphicsPath gp = new GraphicsPath(FillMode.Alternate);

                                for (int jj = 0; jj < po.Rings.Count; jj++)
                                {
                                    Ring r = po.Rings[jj];

                                    if (style.Simplify)
                                    {
                                        r = r.Simplify(style.SimplifyTolerance);
                                    }

                                    System.Drawing.Point[] ppts = new System.Drawing.Point[r.Points.Count];

                                    for (int kk = 0; kk < r.Points.Count; kk++)
                                    {
                                        Point p = r.Points[kk];

                                        if (reproject)
                                        {
                                            p = src.Transform(dst, p);
                                        }

                                        ppts[kk] = ConvertMapToPixel(envelope, scale, p);

                                    }

                                    gp.AddPolygon(ppts);
                                }

                                if (style.FillStyle != FillStyle.None)
                                {
                                    Brush fillBrush;

                                    if (style.FillStyle == FillStyle.Texture)
                                    {
                                        if (string.IsNullOrEmpty(style.FillTexturePath))
                                        {
                                            throw new MapConfigurationException("A style with FillStyle.Texture must have a FillTexturePath");
                                        }

                                        fillBrush = new TextureBrush(new Bitmap(style.FillTexturePath));
                                    }
                                    else
                                    {
                                        fillBrush = new SolidBrush(style.FillColor);
                                    }

                                    g.FillPath(fillBrush, gp);
                                }

                                if (style.LineStyle != LineStyle.None)
                                {
                                    g.DrawPath(ConvertLayerToPen(style), gp);
                                }

                                if (style.ShowLabels &&
                                    po.LabelFieldValue != null &&
                                    displayScale <= style.LabelMaxScale &&
                                    displayScale >= style.LabelMinScale)
                                {
                                    Point polyCenter = po.CalculateBounds().Center;

                                    labels.Add(new LabelRequest(style,
                                                                po.LabelFieldValue,
                                                                ConvertMapToPixel(envelope,
                                                                                  scale,
                                                                                  (reproject ? src.Transform(dst, polyCenter): polyCenter)),
                                                                layer.AllowDuplicateLabels,
                                                                names));
                                }
                            }

                            #endregion
                        }
                    }
                    finally
                    {
                        // dispose of proj4
                        if (src != null)
                        {
                            src.Dispose();
                        }
                    }

                }

                foreach (LabelRequest lr in labels)
                {
                    if (!lr.AllowDuplicates)
                    {
                        if (label_names.Contains(lr.Label)) continue;

                        label_names.Add(lr.Label);
                    }

                    if (lr.Style.DrawPointSymbolOnPolyLine)
                    {
                        GetPointDrawer(lr.Style)(lr.Style, g, lr.Coord);
                    }

                    DrawLabel(g, lr.Style, lr.Coord, lr.Label, lr.ForcedLabelAngle);
                }

                return b;
            }
            finally
            {
                // dispose of proj4
                if (dst != null)
                {
                    dst.Dispose();
                }

                if (g != null)
                {
                    g.Dispose();
                }
            }
        }
Example #8
0
        public Point Transform(ProjFourWrapper destinationProj, Point point)
        {
            double[] x = new double[] { point.X };
            double[] y = new double[] { point.Y };

            if (this.IsLatLong)
            {
                x[0] = x[0] * DegreesToRadians;
                y[0] = y[0] * DegreesToRadians;
            }

            int errno = pj_transform(this.projPJ, destinationProj.projPJ, 1, 0, x, y, new double[] {0}) ;
            if (errno != 0)
            {
                throw new ProjFourException(errno, GetError() + " " + point.ToString());
            }

            if (destinationProj.IsLatLong)
            {
                x[0] = x[0] / DegreesToRadians;
                y[0] = y[0] / DegreesToRadians;
            }

            Point p = new Point(x[0], y[0]);
            p.LabelFieldValue = point.LabelFieldValue;
            p.ThemeFieldValue = point.ThemeFieldValue;

            return p;
        }
        public void TestTransformPointFromCSToLL()
        {
            using (ProjFourWrapper src = new ProjFourWrapper("+init=epsg:2236"))
            {
                using (ProjFourWrapper dst = new ProjFourWrapper("+init=epsg:4326"))
                {
                    Point pt = src.Transform(dst, new Point(656166.67, 605690.54));

                    // used proj command line to acquire this
                    CompareLLPoints(new Point(-81, 26), pt);
                }
            }
        }
Example #10
0
        public void TestTransformPointFromLLToLL()
        {
            using (ProjFourWrapper src = new ProjFourWrapper("+init=epsg:4326"))
            {
                using (ProjFourWrapper dst = new ProjFourWrapper("+init=epsg:4269"))
                {
                    Point pt1 = new Point(-81, 26);
                    Point pt2 = src.Transform(dst, pt1);

                    // NAD83 and WGS84 should be essentially same
                    Assert.AreEqual(pt1, pt2);
                }
            }
        }