Inheritance: ICloneable
Exemple #1
0
 private void addTitleStyleElement(TitleStyle TitleStyle, XmlDocument doc, XmlElement layerElement)
 {
     XmlElement titleStyleElement = doc.CreateElement("title_style");
     layerElement.AppendChild(titleStyleElement);
     addAttribute(doc, titleStyleElement, "visible", TitleStyle.TitlesVisible ? "1" : "0");
     addAttribute(doc, titleStyleElement, "visible_scale", TitleStyle.VisibleScale.ToString(CultureInfo.InvariantCulture));
     addAttribute(doc, titleStyleElement, "color", ColorTranslator.ToHtml(TitleStyle.Color));
     addAttribute(doc, titleStyleElement, "font_name", TitleStyle.FontFamily);
     addAttribute(doc, titleStyleElement, "font_size", TitleStyle.FontSize.ToString(CultureInfo.InvariantCulture));
     addAttribute(doc, titleStyleElement, "font_style", ((int)TitleStyle.FontStyle).ToString(CultureInfo.InvariantCulture));
     addAttribute(doc, titleStyleElement, "render_priority", ((int)TitleStyle.RenderPriority).ToString(CultureInfo.InvariantCulture));
     addAttribute(doc, titleStyleElement, "use_outline", TitleStyle.UseOutline ? "1" : "0");
     addAttribute(doc, titleStyleElement, "outline_size", TitleStyle.OutlineSize.ToString(CultureInfo.InvariantCulture));
     addAttribute(doc, titleStyleElement, "lead_along", TitleStyle.LeadAlong ? "1" : "0");
 }
        /// <summary>
        /// Draw a polygon.
        /// </summary>
        protected virtual void DrawPolygon(Feature feature, Graphics g, PolygonStyle style, TitleStyle titleStyle,
                                           BoundingRectangle viewBox, bool titleVisible, double scaleFactor)
        {
            if (feature.Polygon.Contours.Count == 0)
                return;

            //if (feature.Layer != null && feature.Layer.Title == "adp.TAB")
            //{
            //    drawPrismPolygon(feature, g, viewBox, scaleFactor);
            //    // inscription
            //    if (!string.IsNullOrEmpty(feature.Title) && titleVisible)
            //        addTitleBufferElement(g, feature, titleStyle, viewBox, scaleFactor);
            //    return;
            //}

            if (!_isSelectionRendering && feature.Selected)
            {
                PolygonBufferElement element = new PolygonBufferElement(feature, style, titleStyle, titleVisible);
                _selectedPolygons.Add(element);
                return;
            }

            double pixelsize = 1/scaleFactor;

            if (_reduceSubpixelDetails)
            {
                if (feature.BoundingRectangle.Width < pixelsize && feature.BoundingRectangle.Height < pixelsize)
                    return;

                Polygon tempPolygon = (Polygon) feature.Polygon.Clone();
                tempPolygon.Weed(pixelsize);
                Feature tempFeature = new Feature(FeatureType.Polygon);
                tempFeature.Title = feature.Title;
                tempFeature.Selected = feature.Selected;
                tempFeature.Polygon = tempPolygon;
                feature = tempFeature;

                if (feature.Polygon.Contours.Count == 0)
                    return;
            }

            using (Pen pen = style.GetPen())
            {
                using (GraphicsPath path = new GraphicsPath(FillMode.Alternate))
                {
                    path.StartFigure();

                    float x = (float) ((feature.Polygon.Contours[0].Vertices[0].X - viewBox.MinX)*scaleFactor);
                    float y = (float) ((viewBox.MaxY - feature.Polygon.Contours[0].Vertices[0].Y)*scaleFactor);

                    g.RenderingOrigin = new Point((int) Math.Round(x), (int) Math.Round(y));

                    foreach (Contour c in feature.Polygon.Contours)
                    {
                        // there is no point in trying to draw the contours of the degenerate
                        if (c.Vertices.Count <= 2)
                            continue;

                        PointF[] points = new PointF[c.Vertices.Count];

                        for (int j = 0; j < c.Vertices.Count; j++)
                        {
                            points[j].X = (float) ((c.Vertices[j].X - viewBox.MinX)*scaleFactor);
                            points[j].Y = (float) ((viewBox.MaxY - c.Vertices[j].Y)*scaleFactor);
                        }

                        if (points.Length > 2)
                            path.AddPolygon(points);
                    }

                    path.CloseFigure();

                    // Fill polygon
                    using (Brush b = style.GetBrush())
                    {
                        if (style.FillPatternInternal != null)
                        {
                            int w = style.FillPatternInternal.Width;
                            int h = style.FillPatternInternal.Height;
                            ((TextureBrush) b).TranslateTransform(g.RenderingOrigin.X%w, g.RenderingOrigin.Y%h);
                        }
                        g.FillPath(b, path);
                    }

                    if (feature.Selected)
                    {
                        //Fills the selected polygon

                        //Color color = Color.FromArgb(50, _selectionColor);
                        //using (Brush b = new HatchBrush(HatchStyle.Percent70, color, Color.Transparent))

                        if (_selectionColorChanged || _selectionTexture == null)
                            createSelectionTexture();

                        using (Brush b = new TextureBrush(_selectionTexture))
                        {
                            ((TextureBrush) b).TranslateTransform(g.RenderingOrigin.X%8, g.RenderingOrigin.Y%8);
                            g.FillPath(b, path);
                        }

                        // boundary of the selected polygons
                        using (Pen p = new Pen(_selectionColor, style.BorderWidth + 3))
                        {
                            p.LineJoin = LineJoin.Bevel;
                            g.DrawPath(p, path);
                        }
                    }

                    //boundary of the landfill
                    if (style.BorderVisible)
                        g.DrawPath(pen, path);
                }

                // inscription
                if (!string.IsNullOrEmpty(feature.Title) && titleVisible)
                    addTitleBufferElement(g, feature, titleStyle, viewBox, scaleFactor);
            }
        }
        /// <summary>
        /// Drawing the line.
        /// </summary>
        protected virtual void DrawPolyline(Feature feature, Graphics g, PolylineStyle style, TitleStyle titleStyle,
                                            BoundingRectangle viewBox, bool titleVisible, double scaleFactor)
        {
            if (!_isSelectionRendering && feature.Selected)
            {
                PolylineBufferElement element = new PolylineBufferElement(feature, style, titleStyle, titleVisible);
                _selectedPolylines.Add(element);
                return;
            }

            double pixelsize = 1/scaleFactor;

            if (_reduceSubpixelDetails)
            {
                if (feature.BoundingRectangle.Width < pixelsize && feature.BoundingRectangle.Height < pixelsize)
                    return;

                Polyline p1 = (Polyline) feature.Polyline.Clone();
                p1.Weed(pixelsize);
                Feature tempFeature = new Feature(FeatureType.Polyline);
                tempFeature.Title = feature.Title;
                tempFeature.Selected = feature.Selected;
                tempFeature.Polyline = p1;
                feature = tempFeature;

                if (feature.Polyline.Paths.Count == 0)
                    return;
            }

            using (Pen pen = style.GetPen())
            {
                if (Math.Min(viewBox.Width/(feature.BoundingRectangle.Width),
                             viewBox.Height/(feature.BoundingRectangle.Height)) < 2)
                    drawPolylineWithIntersectCalculation(g, feature, style, viewBox, scaleFactor);
                else
                    drawPolylineSimple(g, feature, style, viewBox, scaleFactor);

                // inscription
                if (!string.IsNullOrEmpty(feature.Title) && titleVisible)
                    addTitleBufferElement(g, feature, titleStyle, viewBox, scaleFactor);
            }
        }
        /// <summary>
        /// Draw a point.
        /// </summary>        
        protected virtual void DrawPoint(Feature feature, Graphics g, PointStyle style, TitleStyle titleStyle,
                                         BoundingRectangle viewBox, bool titleVisible, double scaleFactor)
        {
            if (!_isSelectionRendering && feature.Selected)
            {
                PointBufferElement element = new PointBufferElement(feature, style, titleStyle, titleVisible);
                _selectedPoints.Add(element);
                return;
            }

            string _fontName = string.IsNullOrEmpty(style.FontName) ? _symbolsDefaultFontName : style.FontName;
            using (Font f = new Font(_fontName, style.Size, FontStyle.Regular, GraphicsUnit.Pixel))
            {
                using (SolidBrush fontBrush = new SolidBrush(style.Color))
                {
                    SizeF size;
                    SizeF offset;
                    if (style.DisplayKind == PointDisplayKind.Symbol)
                        // character size
                        size = g.MeasureString(style.Symbol.ToString(), f, new PointF(0, 0), _symbolStringFormat);
                    else
                    {
                        // image size
                        if (style.Image != null)
                            size = new SizeF(style.Image.Width, style.Image.Height);
                        else
                            size = new SizeF(1, 1);
                    }
                    //Offset relative to the center point
                    offset = new SizeF(size.Width/2,size.Height/2);

                    switch (style.ContentAlignment)
                    {
                        case ContentAlignment.TopLeft: offset = new SizeF(0, 0); break;
                        case ContentAlignment.TopCenter: offset = new SizeF(size.Width / 2,0); break;
                        case ContentAlignment.TopRight: offset = new SizeF(size.Width, 0); break;



                        case ContentAlignment.BottomLeft: offset = new SizeF(0, size.Height ); break;
                        case ContentAlignment.BottomCenter: offset = new SizeF(size.Width / 2, size.Height); break;
                        case ContentAlignment.BottomRight: offset = new SizeF(size.Width, size.Height); break;



                        case ContentAlignment.MiddleLeft: offset = new SizeF(0, size.Height / 2); break;
                        case ContentAlignment.MiddleCenter: offset = new SizeF(size.Width / 2, size.Height / 2); break;
                        case ContentAlignment.MiddleRight: offset = new SizeF(size.Width, size.Height / 2); break;
    
                        default:
                            throw new NotSupportedException();

                    }
                    IEnumerable<ICoordinate> targetPoints = null;
                    if (feature.FeatureType == FeatureType.Point)
                        targetPoints = new ICoordinate[] {feature.Point.Coordinate};
                    else
                        targetPoints = feature.MultiPoint.Points;

                    foreach (ICoordinate targetPoint in targetPoints)
                    {
                        if (style.DisplayKind == PointDisplayKind.Symbol)
                        {
                            // symbol
                            using (GraphicsPath path = new GraphicsPath())
                            {
                                path.AddString(style.Symbol.ToString(),
                                               f.FontFamily,
                                               (int) f.Style,
                                               f.Size,
                                               new PointF((float) ((targetPoint.X - viewBox.MinX)*scaleFactor-offset.Width),
                                                          (float)
                                                          ((viewBox.MaxY - targetPoint.Y)*scaleFactor -offset.Height)),
                                               _symbolStringFormat);

                                g.FillPath(fontBrush, path);
                            }
                        }
                        else
                        {
                            // image
                            if (style.Image != null)
                                g.DrawImageUnscaled(style.Image,
                                                    new Point(
                                                        (int)
                                                        Math.Round(((targetPoint.X - viewBox.MinX)*scaleFactor -
                                                                    offset.Width)),
                                                        (int)
                                                        Math.Round(((viewBox.MaxY - targetPoint.Y)*scaleFactor -
                                                                    offset.Height))));
                        }

                        if (feature.Selected)
                        {
                            // Frame selected object
                            using (Pen p = new Pen(_selectionColor, 2))
                                g.DrawRectangle(p,
                                                (float)((targetPoint.X - viewBox.MinX) * scaleFactor - offset.Width + 1),
                                                (float)((viewBox.MaxY - targetPoint.Y) * scaleFactor - offset.Height + 1),
                                                size.Width - 2, size.Height - 2);

                            using (Brush b = new SolidBrush(Color.FromArgb(50, _selectionColor)))
                                g.FillRectangle(b, (float)((targetPoint.X - viewBox.MinX) * scaleFactor - offset.Width),
                                                (float)((viewBox.MaxY - targetPoint.Y) * scaleFactor - offset.Height),
                                                size.Width, size.Height);
                        }
                    }

                    // inscription
                    if (!string.IsNullOrEmpty(feature.Title) && titleVisible)
                    {
                        if (feature.FeatureType == FeatureType.Point)
                        {
                            //Location signs point object can not be determined only by coordinates,
                            //without knowing the size of the image of a point object. 
                            //Therefore, the ordinate of a point object is displaced by half the size of the symbol.
                            Feature shp = new Feature(FeatureType.Point);
                            shp.Point = new PointD(feature.Point.X, feature.Point.Y + size.Height/2/scaleFactor);
                            shp.Title = feature.Title;
                            addTitleBufferElement(g, shp, titleStyle, viewBox, scaleFactor);
                        }
                        if (feature.FeatureType == FeatureType.MultiPoint)
                            addTitleBufferElement(g, feature, titleStyle, viewBox, scaleFactor);
                    }
                }
            }
        }
 void IFeatureRenderer.DrawPolygon(Feature feature, Graphics g, PolygonStyle style, TitleStyle titleStyle, BoundingRectangle viewBox, bool titleVisible, double scaleFactor)
 {
     DrawPolygon(feature, g, style, titleStyle, viewBox, titleVisible, scaleFactor);
 }
 public PointBufferElement(Feature point, PointStyle style, TitleStyle titleStyle, bool titleVisible)
 {
     _style = style;
     _titleStyle = titleStyle;
     _point = point;
     _titleVisible = titleVisible;
 }
 public PolylineBufferElement(Feature polyline, PolylineStyle style, TitleStyle titleStyle, bool titleVisible)
 {
     _style = style;
     _titleStyle = titleStyle;
     _polyline = polyline;
     _titleVisible = titleVisible;
 }
 public PolygonBufferElement(Feature polygon, PolygonStyle style, TitleStyle titleStyle, bool titleVisible)
 {
     _style = style;
     _titleStyle = titleStyle;
     _polygon = polygon;
     _titleVisible = titleVisible;
 }
 /// <summary>
 /// Creates a copy of an inscription TitleBufferElement located along the object.
 /// </summary>
 public TitleBufferElement(FollowingTitle followingTitle, TitleStyle style, int number)
 {
     _isSimple = false;
     _style = style;
     _box = new Segment(followingTitle.GetBoundingBox().Min, followingTitle.GetBoundingBox().Max);
     _followingTitle = followingTitle;
     _titleCount = number;
 }
 /// <summary>
 /// Creates an instance of the appropriate TitleBufferElement simple inscription.
 /// </summary>
 public TitleBufferElement(TitleStyle style, Segment box, string title, int number)
 {
     _style = style;
     _title = title;
     _box = box;
     _titleCount = number;
 }
        private FollowingTitle getFollowingTitle(Graphics g, LinePath part, double length, string label, TitleStyle titleStyle, BoundingRectangle viewBox, double scaleFactor)
        {
            StringFormat format = StringFormat.GenericTypographic;
            SizeF sizeF;
            PointF zeroPoint = new PointF(0, 0);

            using (Font f = titleStyle.GetFont())
            {
                sizeF = g.MeasureString(label, f, zeroPoint, format);

                // label length must be less than the length of the line
                if (sizeF.Width / scaleFactor < length)
                {
                    LinePath tempPart = new LinePath();
                    foreach (ICoordinate p in part.Vertices)
                        tempPart.Vertices.Add(p);

                    int vertexNumber = 0;
                    ICoordinate centerPoint = getDistantPoint(tempPart.Vertices, length / 2, out vertexNumber);

                    // if the point of the proposed mid-label misses the display area of ​​the map, the inscription does not appear
                    if (!viewBox.ContainsPoint(centerPoint))
                        return null;

                    // simplify the line
                    tempPart.Weed(sizeF.Height / scaleFactor / 2);

                    //get the center point of the simplified line
                    centerPoint = getDistantPoint(tempPart.Vertices, length / 2, out vertexNumber);

                    List<double> leftPointsRotationDeltas = new List<double>();
                    List<double> rightPointsRotationDeltas = new List<double>();

                    // coordinates of points on the left of the middle of the inscription
                    IList<ICoordinate> leftPoints =
                        getLeftPoints(tempPart.Vertices,
                                      centerPoint,
                                      sizeF.Width / 2 / scaleFactor,
                                      vertexNumber,
                                      sizeF.Height / 2 / scaleFactor,
                                      leftPointsRotationDeltas);

                    // coordinates of the points to the right of the middle of the inscription
                    IList<ICoordinate> rightPoints =
                        getRightPoints(tempPart.Vertices,
                                       centerPoint,
                                       sizeF.Width / 2 / scaleFactor,
                                       vertexNumber,
                                       sizeF.Height / 2 / scaleFactor,
                                       rightPointsRotationDeltas);

                    //coordinates of the vertices of the broken line, which will be located along the inscription
                    List<ICoordinate> points = leftPoints.ToList();
                    points.AddRange(rightPoints);

                    // shifts of the inscriptions associated with break lines
                    List<double> rotationDeltas = leftPointsRotationDeltas;
                    rotationDeltas.AddRange(rightPointsRotationDeltas);

                    for (int i = 0; i < points.Count; i++)
                        points[i] = PlanimetryEnvironment.NewCoordinate((points[i].X - viewBox.MinX) * scaleFactor,
                                               (viewBox.MaxY - points[i].Y) * scaleFactor);

                    for (int i = 0; i < rotationDeltas.Count; i++)
                        rotationDeltas[i] = rotationDeltas[i] * scaleFactor;

                    //determine the direction of following labels (direct or reverse)
                    double forwardWeight = 0;
                    double backwardWeight = 0;

                    for (int i = 1; i < points.Count; i++)
                    {
                        Segment s = new Segment(PlanimetryEnvironment.NewCoordinate(points[i].X, points[i].Y),
                                                PlanimetryEnvironment.NewCoordinate(points[i - 1].X, points[i - 1].Y));
                        int quadNumber = pointQuadrantNumber(PlanimetryEnvironment.NewCoordinate(s.V1.X - s.V2.X, s.V1.Y - s.V2.Y));
                        if (quadNumber == 1 || quadNumber == 4)
                            forwardWeight += s.Length();
                        else
                            backwardWeight += s.Length();
                    }

                    if (backwardWeight > forwardWeight)
                    {
                        points.Reverse();
                        rotationDeltas.Reverse();
                    }

                    // inscriptions along the route should not be a large number of points
                    if (label.Length > points.Count - 2)
                    {
                        List<int> subStringLengths = new List<int>();
                        List<double> deltas = new List<double>();

                        LinePath p1 = new LinePath(points.ToArray());
                        double l = p1.Length();

                        // partition of the inscription on the straight parts, the calculation of displacement
                        int startIndex = 0;
                        for (int i = 1; i < points.Count; i++)
                        {
                            double currentDistance = PlanimetryAlgorithms.Distance(points[i - 1], points[i]);

                            if (deltas.Count > 0)
                                if (deltas[deltas.Count - 1] < currentDistance)
                                    currentDistance -= deltas[deltas.Count - 1];

                            //subtract the offset associated with line breaks
                            currentDistance -= rotationDeltas[i - 1];
                            if (i < rotationDeltas.Count)
                                currentDistance -= rotationDeltas[i];

                            int currentLength = (int)(currentDistance / l * label.Length);

                            if (startIndex + currentLength > label.Length)
                                currentLength = label.Length - startIndex;

                            subStringLengths.Add(currentLength > 0 ? currentLength : 0);

                            string subString;
                            if (subStringLengths[i - 1] > 0)
                                subString = label.Substring(startIndex, subStringLengths[i - 1]);
                            else
                                subString = string.Empty;

                            float width1, width2, width3;
                            width1 = width2 = width3 = g.MeasureString(subString, f, zeroPoint, format).Width;

                            if (!string.IsNullOrEmpty(subString))
                            {
                                if (subStringLengths[i - 1] > 1)
                                {
                                    width2 = g.MeasureString(label.Substring(startIndex, subStringLengths[i - 1] - 1), f, zeroPoint, format).Width;
                                    if (Math.Abs(width2 - currentDistance) < Math.Abs(width1 - currentDistance))
                                    {
                                        subStringLengths[i - 1] = subStringLengths[i - 1] - 1;
                                        width1 = width2;
                                    }
                                }

                                if (label.Length > subStringLengths[i - 1] + startIndex)
                                {
                                    width3 = g.MeasureString(label.Substring(startIndex, subStringLengths[i - 1] + 1), f, zeroPoint, format).Width;
                                    if (Math.Abs(width3 - currentDistance) < Math.Abs(width1 - currentDistance) &&
                                        Math.Abs(width3 - currentDistance) < sizeF.Width / label.Length / 6)
                                    {
                                        subStringLengths[i - 1] = subStringLengths[i - 1] + 1;
                                        width1 = width3;
                                    }
                                }
                            }

                            deltas.Add(0.5 * (width1 - currentDistance));
                            if (currentLength > 0)
                                startIndex += currentLength;
                        }

                        int sum = 0;
                        int maxZeroLengths = 0;
                        int zeroLengthsCount = 0;
                        foreach (int k in subStringLengths)
                        {
                            if (k <= 0)
                            {
                                zeroLengthsCount++;
                                if (maxZeroLengths < zeroLengthsCount)
                                    maxZeroLengths = zeroLengthsCount;
                            }
                            else
                                zeroLengthsCount = 0;
                            sum += k;
                        }

                        if (maxZeroLengths > 1)
                            return null;

                        int lastIndex = subStringLengths.Count() - 1;
                        if (lastIndex >= 0)
                        {
                            subStringLengths[lastIndex] += label.Length - sum;
                            if (subStringLengths[lastIndex] < 0)
                            {
                                subStringLengths[lastIndex - 1] -= subStringLengths[lastIndex];
                                subStringLengths[lastIndex] = 0;
                            }
                        }

                        FollowingTitle followingTitle = new FollowingTitle();

                        startIndex = 0;
                        double? previousAngle = null;
                        for (int i = 0; i < subStringLengths.Count(); i++)
                        {
                            if (subStringLengths[i] <= 0)
                                continue;

                            if (startIndex + subStringLengths[i] > label.Length)
                                return null;

                            SizeF size;
                            size = g.MeasureString(label.Substring(startIndex, subStringLengths[i]), f, zeroPoint, format);

                            int x0 = (i == 0 ? 0 : (int)Math.Round(deltas[i - 1] + rotationDeltas[i - 1]));

                            PointF[] v = new PointF[4];
                            v[0].X = x0;
                            v[0].Y = -size.Height / 2;

                            v[1].X = size.Width + x0;
                            v[1].Y = -size.Height / 2;

                            v[2].X = size.Width + x0;
                            v[2].Y = size.Height / 2;

                            v[3].X = x0;
                            v[3].Y = size.Height / 2;

                            float angle = (float)(180 / Math.PI * getAngle(PlanimetryEnvironment.NewCoordinate(Math.Abs(points[i].X * 2), points[i].Y),
                                                                           points[i],
                                                                           points[i + 1],
                                                  false));

                            if (previousAngle != null)
                            {
                                double angleDelta = Math.Abs(angle - previousAngle.Value);
                                if (angleDelta > 45 && 360 - angleDelta > 45)
                                    return null;
                            }

                            previousAngle = angle;

                            g.TranslateTransform((float)points[i].X, (float)points[i].Y);
                            g.RotateTransform(-(angle % 360));

                            g.Transform.TransformPoints(v);
                            for (int j = 0; j < 4; j++)
                            {
                                v[j].X = (float)(v[j].X / scaleFactor + viewBox.MinX);
                                v[j].Y = (float)(viewBox.MaxY - v[j].Y / scaleFactor);
                            }

                            FollowingTitleElement element =
                                new FollowingTitleElement(new PointF((float)points[i].X, (float)points[i].Y),
                                                          -(angle % 360),
                                                          new PointF(x0, -size.Height / 2),
                                                          label.Substring(startIndex, subStringLengths[i]),
                                                          v[0], v[1], v[2], v[3]);

                            startIndex += subStringLengths[i];

                            followingTitle.AddElement(element);

                            g.ResetTransform();
                        }
                        return followingTitle.EnvelopePolygon == null ? null : followingTitle;
                    }
                }
            }
            return null;
        }
 private void addTitleBufferElement(TitleStyle titleStyle, ICoordinate targetPoint, SizeF size, double scaleFactor, Feature feature)
 {
     _titleBuffer.Add(new TitleBufferElement(titleStyle,
                                 new Segment(targetPoint.X - size.Width / scaleFactor / 2,
                                             targetPoint.Y - size.Height / scaleFactor / 2,
                                             targetPoint.X + size.Width / scaleFactor / 2,
                                             targetPoint.Y + size.Height / scaleFactor / 2),
                                 feature.Title,
                                 _titleCount++));
 }
        private void addTitleBufferElement(Graphics g, Feature feature, TitleStyle titleStyle, BoundingRectangle viewBox, double scaleFactor)
        {
            ICoordinate targetCoordinate = PlanimetryEnvironment.NewCoordinate(0, 0);
            Segment s;

            SizeF size;
            using (Font f = titleStyle.GetFont())
                size = g.MeasureString(feature.Title, f, new PointF(0, 0), _titleStringFormat);

            switch (feature.FeatureType)
            {
                case FeatureType.Polyline:
                    if (!titleStyle.LeadAlong)
                    {
                        foreach (LinePath path in feature.Polyline.Paths)
                        {
                            if (path.Vertices.Count > 2)
                                targetCoordinate = path.Vertices[path.Vertices.Count / 2 - 1];
                            else
                            {
                                s = new Segment(path.Vertices[0].X, path.Vertices[0].Y,
                                                path.Vertices[1].X, path.Vertices[1].Y);

                                targetCoordinate = s.Center();
                            }
                            addTitleBufferElement(titleStyle, targetCoordinate, size, scaleFactor, feature);
                        }
                    }
                    else
                    {
                        int i = 0;
                        foreach (LinePath path in feature.Polyline.Paths)
                        {
                            FollowingTitle followingTitle = 
                                getFollowingTitle(g, path, feature.PolylinePartLengths[i], feature.Title, titleStyle, viewBox, scaleFactor);
                            if (followingTitle != null)
                                _titleBuffer.Add(new TitleBufferElement(followingTitle, titleStyle, _titleCount++));
                            i++;
                        }
                    }
                    return;
                case FeatureType.Polygon:
                    //if (feature.Polygon.Contours.Count > 0)
                    //    targetPoint = feature.Polygon.Contours[0].RibsCentroid();
                    //else
                    //    return;
                    //break;

                    if (feature.Polygon.Contours.Count > 0)
                        try
                        {
                            targetCoordinate = feature.Polygon.PointOnSurface();
                        }
                        catch(InvalidOperationException)
                        {
                            //interior point of the polygon for some reason (usually singular) can not be found
                            return;
                        }
                    else
                        return;
                    break;
                    
                case FeatureType.Point:
                    targetCoordinate = feature.Point.Coordinate;
                    //targetPoint.Y += size.Height / scaleFactor / 2;
                    break;
                case FeatureType.MultiPoint:
                    if (titleStyle.LeadAlong)
                    {
                        foreach (ICoordinate p in feature.MultiPoint.Points)
                        {
                            targetCoordinate = p;
                            targetCoordinate.Y += size.Height / scaleFactor / 2;
                            addTitleBufferElement(titleStyle, targetCoordinate, size, scaleFactor, feature);
                        }
                        return;
                    }
                    else
                        targetCoordinate = PlanimetryAlgorithms.GetCentroid(feature.MultiPoint.Points);
                    break;
            }

            addTitleBufferElement(titleStyle, targetCoordinate, size, scaleFactor, feature);
        }
 /// <summary/>
 protected void processTitleStyle(XmlNode layerNode, TitleStyle TitleStyle)
 {
     XmlNode titleStyle = tryGetNodeByName(layerNode.ChildNodes, "title_style");
     if (titleStyle != null)
     {
         TitleStyle.TitlesVisible = titleStyle.Attributes["visible"].Value == "1";
         if (titleStyle.Attributes["visible_scale"] != null)
             TitleStyle.VisibleScale = double.Parse(titleStyle.Attributes["visible_scale"].Value, CultureInfo.InvariantCulture);
         TitleStyle.Color = ColorTranslator.FromHtml(titleStyle.Attributes["color"].Value);
         TitleStyle.FontFamily = titleStyle.Attributes["font_name"].Value;
         TitleStyle.FontSize = float.Parse(titleStyle.Attributes["font_size"].Value, CultureInfo.InvariantCulture);
         TitleStyle.FontStyle = (FontStyle)int.Parse(titleStyle.Attributes["font_style"].Value, CultureInfo.InvariantCulture);
         if (titleStyle.Attributes["render_priority"] != null)
             TitleStyle.RenderPriority = int.Parse(titleStyle.Attributes["render_priority"].Value, CultureInfo.InvariantCulture);
         if (titleStyle.Attributes["use_outline"] != null)
             TitleStyle.UseOutline = titleStyle.Attributes["use_outline"].Value == "1";
         if (titleStyle.Attributes["outline_size"] != null)
             TitleStyle.OutlineSize = int.Parse(titleStyle.Attributes["outline_size"].Value, CultureInfo.InvariantCulture);
         if (titleStyle.Attributes["lead_along"] != null)
             TitleStyle.LeadAlong = titleStyle.Attributes["lead_along"].Value == "1";
     }
 }