【问题标题】:C# Code to list locations within certain locationC# 代码列出特定位置内的位置
【发布时间】:2013-05-08 11:20:54
【问题描述】:

我有一个位置列表,我希望能够输入一个位置,并将我指定位置 X 英里半径内的位置填充到数据网格中。有没有人有为 C# 编写代码以实现此目的的经验?

我确实有我的数据的纬度和经度。

任何帮助将不胜感激!谢谢!

我想通了!这似乎有效。我输入一个位置,然后将该纬度/经度与剩余的 1300 个字段进行比较,以显示表格中的数据。如果有人对压缩代码有任何建议,那就太棒了!

private void btnSubmit_Click(object sender, EventArgs e)
    {


        if (comboBox1.SelectedIndex != 0)
        {
            lblMsg.Text = "Please select Location no From DropDown for Radius search";
            return;
        }
        else
        {
            if (txtRadius.Text == "")
            {
                lblMsg.Text = "Please enter radius value";
                return;
            }

            double radius = Convert.ToDouble(txtRadius.Text);
            searchData = txtLocNo.Text;
            str = "Select latitude,longitude from details where locno='" + searchData + "'";
            con.Open();
            cmd = new OleDbCommand(str, con);
            dr = cmd.ExecuteReader();

            if (!dr.HasRows)
            {
                lblMsg.Text = "No Records Found";
                dataGridView1.Visible = false;
                con.Close();
                return;
            }
            else
            {
                dr.Read();
                double lat1 = dr.GetDouble(0);
                double lng1 = dr.GetDouble(1);
                double lat2, lng2,dist;
                String loc="";

                lblMsg.Text = lat1 + "  " + lng1;
                dr.Dispose();
                str = "Select locno,latitude,longitude from details";
                cmd = new OleDbCommand(str, con);
                dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    loc=dr.GetString(0);
                    lat2 = dr.GetDouble(1);
                    lng2 = dr.GetDouble(2);
                    dist=calculateDistance(lat1,lng1,lat2,lng2);

                    str = "Update details set distance=" + dist + " where locno='"+loc+"'";
                    cmd = new OleDbCommand(str, con);
                    cmd.ExecuteNonQuery();

                }

                str = "select * from details where distance<=" + radius;
                con.Close();
                lblResult.Text = "Radius Search Results";
                fillGrid();
            }


        }
    }

    private double calculateDistance(double lat1,double lng1,double lat2,double lng2)
    {
        double x= 69.1 * (lat2 - lat1); 
        double y = 69.1 * (lng2 - lng1) * Math.Cos(lat1 / 57.3);

        double dist = Math.Sqrt(x * x + y * y);
        dist = Math.Round(dist, 2);
        return dist;

    }

    private double calculateDistance1(double lat1, double lng1, double lat2, double lng2)
    {
        double theta = lng1 - lng2;
        double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) +
            Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) *
            Math.Cos(deg2rad(theta));
        dist = Math.Acos(dist);
        dist = rad2deg(dist);
        dist = dist * 60 * 1.1515;
        dist = Math.Round(dist, 2);
        return dist;
    }

    private double deg2rad(double deg)
    {
        return (deg * Math.PI / 180.0);
    }

    private double rad2deg(double rad)
    {
        return (rad / Math.PI * 180.0);
    }

    private void txtRadius_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar != '0' && e.KeyChar != '1' && e.KeyChar != '2' && e.KeyChar != '3' &&
            e.KeyChar != '4' && e.KeyChar != '5' && e.KeyChar != '6' && e.KeyChar != '7' &&
            e.KeyChar != '8' && e.KeyChar != '9' && e.KeyChar != '.' && e.KeyChar!= Convert.ToChar(8))
        {
            e.Handled = true;
        }

【问题讨论】:

  • 计算两个坐标的距离,你应该看看haversine公式:en.wikipedia.org/wiki/Haversine_formula
  • SQL 函数有用吗? 2008 年以上的 SQL 提供 Geography 类型,在一个小查询中您可以获取您的位置
  • 我会尝试一个sql函数,我对sql不太熟悉,但会放在一起。
  • 你可以查看我的答案

标签: c# visual-studio latitude-longitude


【解决方案1】:

你可以使用System.Device.Location.GeoCoordinate

var loc = new GeoCoordinate(0, 0);
var dist = loc.GetDistanceTo(new GeoCoordinate(1, 1));

编辑

数据集有1300行

1300 行数据集太小。您可以使用任何方法,无需优化(您甚至不需要数据库。您可以将所有数据加载到内存中)

double radius = ....
List<GeoCoordinate> locations = .....;
var result = locations.Where(l=>l.GetDistanceTo(loc)<radius);

【讨论】:

    【解决方案2】:

    这完全取决于您的算法必须有多快以及您拥有多少位置。

    您可以通过遍历所有位置并仅保留半径范围内的位置来实现,但如果您有很多位置,这会很慢。

    另一种方法是将您的位置放入链表中,并且在每个节点上都有一个到下一个节点的距离列表,这可以加快搜索速度。您还可以将这些节点放在区域中,以便您可以快速找到从哪个节点开始搜索。

    那么如果您的问题只是关于计算两个位置之间的距离,请参阅@I4V 的回答

    【讨论】:

    • 不是这个问题的确切答案,但提及这种实现目标的方式+1仍然是一件好事
    • 谢谢:)!由于问题非常大,我想我会回答在我看来是困难的部分
    • 感谢您的完整解释!数据集有 1300 行,所以我认为 sql 查询可能会更好?我会尝试你的第一个解决方案,看看我得到了什么。谢谢!
    • 不客气 :)!是的,如果您只有 1300 行并且只搜索到 1 个位置的距离,那么数据库解决方案(或我谈到的第一个解决方案)应该就足够了。无论如何尝试从那开始,如果你有性能问题,你可以尝试优化
    【解决方案3】:

    我之前有过这样的任务,但我使用 SQL 函数解决了它,这可能不是你的场景,但对于任何感兴趣的人来说:

    -- =============================================
    -- Description: Return list of myTable within provided radius and location
    -- =============================================
    ALTER PROCEDURE [dbo].[proc_] 
        @lattitude DECIMAL(9, 6) = 0 ,
        @longitude DECIMAL(9, 6) = 0 ,
        @radius DECIMAL(18, 3) = 0
    AS 
        BEGIN
    
            DECLARE @point GEOGRAPHY = GEOGRAPHY::Point(@lattitude, @longitude, 4326)
    
            SELECT  *
            FROM    myTable a
            WHERE   @point.STDistance(GEOGRAPHY::Point(a.Lattitude, a.Longitude, 4326)) <= @radius *2
    
        END
    

    myTable 列包含:

    Lattitude   decimal
    Longitude   decimal
    

    注意:SQL 版本为 2008 或更高版本。

    A helpful link

    希望有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-01
      • 2011-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多