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 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); } }
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!"); }
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(); } } }
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); } } }
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); } } }