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); } }