ThinkGeo.com    |     Documentation    |     Premium Support

Creating ellipse around line in a rulertrack overlay

I have a RulerTrackInteractiveOverlay in WinForms that I’m trying to bring over to the WPF version, but I noticed some things are different and I’m unable to get it working properly. In my overlay, I’m creating an ellipse dynamically around the ruler line.

Here’s my WinForms version that works:

public class RulerTrackInteractiveOverlay : TrackInteractiveOverlay
{
    private const string currentFeatureKey = "CurrentFeature";
    private LineShape rulerLineShape;
    private int mouseDown;

    public RulerTrackInteractiveOverlay()
        : base()
    {
        TrackShapeLayer.Open();
        TrackShapeLayer.Columns.Add(new FeatureSourceColumn("length"));
        //Sets the appearance of the ruler
        TrackShapeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.FromArgb(150, GeoColor.StandardColors.DarkRed), 4, false);
        TrackShapeLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = new TextStyle("length", new GeoFont("Arial", 10, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.SimpleColors.Black));
        TrackShapeLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle.TextLineSegmentRatio = 100;
        TrackShapeLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle.YOffsetInPixel = 10;
        TrackShapeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
    }

    protected override InteractiveResult MouseDownCore(InteractionArguments interactionArguments)
    {
        //Sets the first and last point of the line where the user clicks.
        InteractiveResult interactiveResult = new InteractiveResult();
        interactiveResult.DrawThisOverlay = InteractiveOverlayDrawType.Draw;
        interactiveResult.ProcessOtherOverlaysMode = ProcessOtherOverlaysMode.DoNotProcessOtherOverlays;

        rulerLineShape = new LineShape(new Collection<Vertex>() { new Vertex(interactionArguments.WorldX, interactionArguments.WorldY), new Vertex(interactionArguments.WorldX, interactionArguments.WorldY) });

        TrackShapeLayer.InternalFeatures.Add(currentFeatureKey, new Feature(rulerLineShape));

        mouseDown++;
        return interactiveResult;
    }

    protected override InteractiveResult MouseMoveCore(InteractionArguments interactionArguments)
    {
        //Updates the line with the last point to where the mouse pointer is being dragged.
        InteractiveResult interactiveResult = new InteractiveResult();

        if (mouseDown > 0)
        {
            Lock.EnterWriteLock();
            rulerLineShape.Vertices[rulerLineShape.Vertices.Count - 1] = new Vertex(interactionArguments.WorldX, interactionArguments.WorldY);
            Lock.ExitWriteLock();

            interactiveResult.DrawThisOverlay = InteractiveOverlayDrawType.Draw;
            interactiveResult.ProcessOtherOverlaysMode = ProcessOtherOverlaysMode.DoNotProcessOtherOverlays;
        }

        return interactiveResult;
    }

    protected override InteractiveResult MouseUpCore(InteractionArguments interactionArguments)
    {
        //Removes the line of the ruler at finishing dragging (at mouse up event).
        InteractiveResult interactiveResult = new InteractiveResult();

        interactiveResult.DrawThisOverlay = InteractiveOverlayDrawType.Draw;
        interactiveResult.ProcessOtherOverlaysMode = ProcessOtherOverlaysMode.DoNotProcessOtherOverlays;

        if (mouseDown == 1)
        {
            mouseDown = 0;
            Lock.EnterWriteLock();
            try
            {
                TrackShapeLayer.InternalFeatures.Remove("test");
            }
            catch (Exception)
            {

            }
            TrackShapeLayer.InternalFeatures.Remove(currentFeatureKey);
            Lock.ExitWriteLock();
        }
        return interactiveResult;
    }

    protected override void DrawCore(GeoCanvas canvas)
    {
        //Draws the line and update the distance text of the ruler.
        Collection<SimpleCandidate> labelingInAllLayers = new Collection<SimpleCandidate>();

        try
        {
            if (rulerLineShape != null)
            {
                double length;
                Feature feature = new Feature(rulerLineShape);
                length = rulerLineShape.GetLength(GeographyUnit.DecimalDegree, DistanceUnit.Feet);

                feature.ColumnValues.Add("length", ((int)length).ToString() + " feet");
                if (length != 0)
                {
                    BaseShape test = new EllipseShape(new PointShape(rulerLineShape.Vertices[0]), length);
                    Feature feature2 = new Feature(test);
                    if (!TrackShapeLayer.InternalFeatures.Contains("test"))
                    {
                        TrackShapeLayer.InternalFeatures.Add("test", feature2);
                    }
                }

                Lock.EnterWriteLock();
                {
                    if (TrackShapeLayer.InternalFeatures.Contains(currentFeatureKey))
                    {
                        TrackShapeLayer.InternalFeatures[currentFeatureKey] = feature;
                    }
                    else
                    {
                        TrackShapeLayer.InternalFeatures.Add(currentFeatureKey, feature);
                    }                        
                }
                Lock.ExitWriteLock();
            }

            TrackShapeLayer.Open();
            TrackShapeLayer.Draw(canvas, labelingInAllLayers);

            var bitmap = (Bitmap)canvas.NativeImage;
            var rulerFirstPoint = rulerLineShape.Vertices[0];
            var rulerEndPoint = rulerLineShape.Vertices[rulerLineShape.Vertices.Count - 1];

            var distance = ExtentHelper.GetScreenDistanceBetweenTwoWorldPoints(canvas.CurrentWorldExtent, new PointShape(rulerFirstPoint), new PointShape(rulerEndPoint), canvas.Width, canvas.Height);
            var centerPoint = ExtentHelper.ToScreenCoordinate(canvas.CurrentWorldExtent, rulerFirstPoint.X, rulerFirstPoint.Y, canvas.Width, canvas.Height);
            var endPoint = ExtentHelper.ToScreenCoordinate(canvas.CurrentWorldExtent, rulerEndPoint.X, rulerEndPoint.Y, canvas.Width, canvas.Height);

            var graphics = Graphics.FromImage(bitmap);
            graphics.DrawEllipse(Pens.Maroon, centerPoint.X - distance, centerPoint.Y - distance, 2 * distance, 2 * distance);

            canvas.Flush();
        }
        finally
        {
            TrackShapeLayer.Close();
        }
    }
}

Since it’s WPF, I’m not using System.Drawing and I don’t see a GeoCanvas in the DrawCore function.

Below is a gif of what I’m trying to achieve.

Hi Dan,

The old logic is not so good, please try the new sample, it make the logic easier and works well.

9364.zip (102.2 KB)

Regards,

Ethan