0

I'm trying to write a function that simply draws a circle on a map. I'm basically following code given here. Here's my actual code:

using attempt2.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Device.Location;
using System.Windows;
using Windows.Foundation;
using Windows.UI.Xaml.Controls.Maps;
using Windows.Devices.Geolocation;
using Windows.Services.Maps;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Shapes;
using System.Device.Location;

namespace attempt2
{
    class MapsClass
{

    //computes a point on the perimeter given an arbitrary point and distance

    public GeoCoordinate getDistanceBearing(this GeoCoordinate point, double distance, double bearing = 180)
    {
        double radius = Convert.ToDouble(this.Set.container.Values["Radius"]);

        const double degreestoRadian = Math.PI / 180;
        const double radiantoDegrees = 180 / Math.PI;
        const double earthRadius = 6378137.0;

        var latA = point.Latitude * degreestoRadian;
        var longA = point.Longitude * degreestoRadian;
        var angularDistance = distance / earthRadius;
        var trueCourse = bearing * degreestoRadian;

        var lat = Math.Asin(Math.Sin(latA) * Math.Cos(angularDistance) + Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));

        var dlon = Math.Atan2(Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
            Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));

        var lon = ((longA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;

        var result = new GeoCoordinate(lat * radiantoDegrees, lon * radiantoDegrees);

        return result;
    }

    //adds up a series of those points to create a circle

    public static IList<GeoCoordinate> GetCirclePoints(this GeoCoordinate center,
                               double radius, int nrOfPoints = 50)
    {
        var angle = 360.0 / nrOfPoints;
        var locations = new List<GeoCoordinate>();
        for (var i = 0; i <= nrOfPoints; i++)
        {
            locations.Add(center.getDistanceBearing(radius, angle * i));
        }
        return locations;
    }

    //draws the circle on the map

    private void MainPageLoaded()
    {
        if (this.Data.CurrentOrNot == false)     //searched location
        {
            var location = this.Data.SearchedLocation;
            Map.Center = location;
            Map.ZoomLevel = 16;

            var fill = Windows.UI.Color.FromArgb(50, 100, 0, 100);
            var stroke = Windows.UI.Color.FromArgb(150, 250, 0, 0);
            fill.A = 80;
            stroke.A = 80;
            var circle = new MapPolygon
            {
                StrokeThickness = 2,
                FillColor = fill,
                StrokeColor = stroke,
                StrokeDashed = false,
            };

            foreach (var p in location.GetCirclePoints(150))
            {
                circle.Path.Add(p);
            }

            Map.MapElements.Add(circle);


        } else
        {
            var location = this.Data.CurrentLocation;
            Map.Center = location;
            Map.ZoomLevel = 16;

            var fill = Windows.UI.Color.FromArgb(50, 100, 0, 100);
            var stroke = Windows.UI.Color.FromArgb(150, 250, 0, 0);
            fill.A = 80;
            stroke.A = 80;
            var circle = new MapPolygon
            {
                StrokeThickness = 2,
                FillColor = fill,
                StrokeColor = stroke,
                StrokeDashed = false,
            };

            foreach (var p in location.GetCirclePoints(150))
            {
                circle.Path.Add(p);
            }

            Map.MapElements.Add(circle);

        }         

    }

The only errors I'm getting are in the lines when I'm calling one of the methods, so specifically the line locations.Add(center.getDistanceBearing(radius, angle * i));, and both instances of foreach (var p in location.GetCirclePoints(150)). Visual studio is giving me the error

'System.Device.Location.GeoCoordinate' does not contain a definition for 'getDistanceBearing' and no extension method 'getDistanceBearing' accepting a first argument of type 'System.Device.Location.GeoCoordinate' could be found (are you missing a using directive or an assembly reference?)

and an error of the exact same type for when I reference GetCirclePoints. But why is it giving me these errors when I already have the methods defined? And why does basically the same code apparently work in the example I provided?

2 Answers2

0

extension methods should be static methods in static class

MapsClass and getDistanceBearing are not static

you can use your methods as common methods

ASh
  • 34,632
  • 9
  • 60
  • 82
0

You are not following the rules for extension methods. These classes, and the methods must be marked static too. A simple example :

public static class Extension
{
    const string _DefaultBasePath = @"C:\Users\stuyckp\Documents\Visual Studio 2013\Projects\WPF\Interstone";
    private static string _BasePath = null;
    public static string getFullPath(this string relativePath)
    {
        if (relativePath == null) return null;
        string path = BasePath;
        if (!path.EndsWith("\\") && !relativePath.StartsWith("\\")) path += "\\";
        return path + relativePath;
    }

    static private string BasePath
    {
        get
        {
            if (_BasePath != null) return _BasePath;

            try
            {
                Configuration cs = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                ConfigurationSectionGroup g = cs.SectionGroups["applicationSettings"];
                ClientSettingsSection s
                    = (from ConfigurationSection section in g.Sections
                        where section is ClientSettingsSection
                        select section).FirstOrDefault() as ClientSettingsSection;
                _BasePath = s.Settings.Get("BasePath").Value.ValueXml.InnerText;
            }
            catch
            {
                _BasePath = _DefaultBasePath;
            }

            return _BasePath;
        }
    }
}

Don't combine anything, only use these static classes for code that is required for the extension method itself. This effectively makes just about everything in the class as static : private variables, helper methods, ...

so you need something like this :

public static class MapsClass{
//computes a point on the perimeter given an arbitrary point and distance

public static GeoCoordinate getDistanceBearing(this GeoCoordinate point, double distance, double bearing = 180)
{
    double radius = Convert.ToDouble(this.Set.container.Values["Radius"]);

    const double degreestoRadian = Math.PI / 180;
    const double radiantoDegrees = 180 / Math.PI;
    const double earthRadius = 6378137.0;

    var latA = point.Latitude * degreestoRadian;
    var longA = point.Longitude * degreestoRadian;
    var angularDistance = distance / earthRadius;
    var trueCourse = bearing * degreestoRadian;

    var lat = Math.Asin(Math.Sin(latA) * Math.Cos(angularDistance) + Math.Cos(latA) * Math.Sin(angularDistance) * Math.Cos(trueCourse));

    var dlon = Math.Atan2(Math.Sin(trueCourse) * Math.Sin(angularDistance) * Math.Cos(latA),
        Math.Cos(angularDistance) - Math.Sin(latA) * Math.Sin(lat));

    var lon = ((longA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;

    var result = new GeoCoordinate(lat * radiantoDegrees, lon * radiantoDegrees);

    return result;
}

//adds up a series of those points to create a circle

public static IList<GeoCoordinate> GetCirclePoints(this GeoCoordinate center,
                           double radius, int nrOfPoints = 50)
{
    var angle = 360.0 / nrOfPoints;
    var locations = new List<GeoCoordinate>();
    for (var i = 0; i <= nrOfPoints; i++)
    {
        locations.Add(center.getDistanceBearing(radius, angle * i));
    }
    return locations;
}
Philip Stuyck
  • 7,344
  • 3
  • 28
  • 39