O2O地图应用之判断用户订单地址是否在服务范围内
O2O地图应用之判断用户订单地址是否在服务范围内
需求分析
在o2o项目中,经常要用到在用户下单时判断用户所填地址的坐标点是否在服务范围内的情况,这里参考网上的实现方式,用C#来实现,经测试后有效,特此记录。
代码
public class MapHelper
{
/// <summary>
/// 判断一个坐标点在多边形坐标点的内部还是外部
/// </summary>
/// <param name="point">要判断的坐标点</param>
/// <param name="pts">多边形坐标点集合</param>
/// <returns></returns>
public static bool IsPointInPolygon(Point point, List<Point> pts)
{
int N = pts.Count;
//如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
bool boundOrVertex = true;
//经过点的次数
int intersectCount = 0;
double precision = 2e-10;
Point p1, p2;
Point p = point;//当前点
p1 = pts[0];
for (int i = 1; i <= N; i++)
{
//如果点在多边形上
if (p.Equals(p1))
{
return boundOrVertex;
}
p2 = pts[(i % N)];
if (p.Lng<Math.Min(p1.Lng,p2.Lng)||p.Lng>Math.Max(p1.Lng,p2.Lng))
{
p1 = p2;
continue;
}
if (p.Lng>Math.Min(p1.Lng,p2.Lng)&&p.Lng<Math.Max(p1.Lng,p2.Lng))
{
if (p.Lat<=Math.Max(p1.Lat,p2.Lat))
{
if (p1.Lng==p2.Lng&&p.Lat>=Math.Min(p1.Lat,p2.Lat))
{
return boundOrVertex;
}
if (p1.Lat==p2.Lat)
{
if (p1.Lat==p.Lat)
{
return boundOrVertex;
}
else
{
intersectCount++;
}
}
else
{
double xinters = (p.Lng - p1.Lng) * (p2.Lat - p1.Lat) / (p2.Lng - p1.Lng) + p1.Lat;
if (Math.Abs(p.Lat-xinters)<precision)
{
return boundOrVertex;
}
if (p.Lat<xinters)
{
intersectCount++;
}
}
}
}
else
{
if (p.Lng==p2.Lng&&p.Lat<=p2.Lat)
{
Point p3 = pts[(i+1)%N];
if (p.Lng>=Math.Min(p1.Lng,p3.Lng)&&p.Lng<=Math.Max(p1.Lng,p3.Lng))
{
intersectCount++;
}
else
{
intersectCount += 2;
}
}
}
p1 = p2;
}
if (intersectCount%2==0)
{
//偶数在多边形外
return false;
}
else
{
//奇数在多边形内
return true;
}
}
}
public class Point
{
/// <summary>
/// 经度
/// </summary>
public double Lng { get; set; }
/// <summary>
/// 纬度
/// </summary>
public double Lat { get; set; }
}
测试
这里我用高德地图标出了北京五环范围的坐标点集合,然后随意选择一个坐标点来进行判断:
坐标点可以用这个工具来获取:高德地图API
五环范围:
- 香泉桥 116.222208,39.992436
- 箭亭桥 116.327147,40.02046
- 上清桥 116.353948,40.02299
- 顾家庄桥 116.44128,40.020526
- 东北五环 116.48441,40.013624
- 平房桥 116.541101,39.942393
- 东南五环 116.549202,39.851595
- 旧宫新桥 116.43082,39.785968
- 狼垈东桥 116.296044,39.777442
- 宛平桥 116.225062,39.845517
- 衙门口桥 116.211308,39.894396
- 西五环 116.212595,39.944705
随机坐标:
- 林萃桥地铁站 116.37297,40.021857
- 望京西园四区 116.47086,39.99648
- 观音禅寺 116.533811,39.880533
- 俏狐国际 116.299713,39.772619
- 芳园里小区 116.416336,39.78394
- 润枫锦尚小区 116.429039,39.790535
class Program
{
static void Main(string[] args)
{
var Plist = new List<Point> {
new Point {Lng=116.222208,Lat= 39.992436},
new Point {Lng=116.327147,Lat= 40.02046},
new Point {Lng=116.353948,Lat= 40.02299},
new Point {Lng=116.44128,Lat= 40.020526},
new Point {Lng=116.48441,Lat=40.013624 },
new Point {Lng=116.541101,Lat= 39.942393},
new Point {Lng=116.549202,Lat= 39.851595},
new Point {Lng=116.43082,Lat=39.785968},
new Point {Lng=116.296044,Lat=39.777442 },
new Point {Lng=116.225062,Lat=39.845517 },
new Point {Lng=116.211308,Lat= 39.894396},
new Point {Lng=116.212595,Lat=39.944705}
};
//var p = new Point { Lng = 116.37297, Lat = 40.021857 };
//林萃桥地铁站 内
//var p = new Point { Lng = 116.47086, Lat = 39.99648 };
//望京西园四区 内
//var p = new Point { Lng = 116.533811, Lat = 39.880533 };
//观音禅寺 内
//var p = new Point { Lng = 116.299713, Lat = 39.772619 };
//俏狐国际 外
//var p = new Point { Lng = 116.416336, Lat = 39.78394 };
//芳园里小区 外
var p = new Point { Lng = 116.429039, Lat = 39.790535 };
//润枫锦尚小区 内
bool isin = MapHelper.IsPointInPolygon(p, Plist);
if (isin)
{
Console.WriteLine("随机点在五环范围内,可以派单");
}
else
{
Console.WriteLine("随机点不在五环范围内");
}
Console.ReadKey();
}
}
总结
- 北京的五环范围毕竟不是一个规则的多边形,可以尽量选择有标志性的坐标点来规范多边形
- 参考自:百度地图——判断用户是否在配送范围内解决方案 - aheizi - 博客园
O2O地图应用之判断用户订单地址是否在服务范围内的更多相关文章
- 判断一个IP地址是否是本局域网内地址
// /// <summary> /// 判断一个IP地址是否是本局域网内地址,是返回true 否则返回false, /// </summa ...
- 百度地图WEB端判断用户是否在网格范围内
在pc端设置商家的配送范围,用户在下单时,根据用户设置的配送地点判断是否在可配送范围内,并给用户相应的提示. 下面说下我的实现思路: 1.用百度地图在PC端设置配送范围,可拖拽选择 2.根据用户设置的 ...
- 判断IP地址是否在指定范围内的方法
比如给定一个ip段:127.0.0.1 ~ 127.0.0.255,我们想判断一个给定的ip地址是否在此段内,可以先将ip地址转换成整数,然后整数比较大小就很容易了. 例如: 127.0.0.1 = ...
- PHP中获取内网用户MAC地址(WINDOWS/linux)的实现代码
做一个内网根据MAC地址自动登录的应用,在WINDOW 2003可以正常使用,函数如下 复制代码 代码如下: function ce_getmac() { if(PHP_OS == 'WINNT' ...
- Android 判断用户2G/3G/4G移动数据网络
Android 判断用户2G/3G/4G移动数据网络 在做 Android App 的时候,为了给用户省流量,为了不激起用户的愤怒,为了更好的用户体验,是需要根据用户当前网络情况来做一些调整的,也可以 ...
- C#判断用户是否使用微信浏览器,并据此来显示真实内容或二维码
平时我们看一些网页的时候会发现这样的功能:有的页面只能在微信里访问,如果在电脑上访问就只显示当前地址的二维码.这个用C#怎么实现呢?我们结合代码来看看. 首先,我们需要先判断用户使用的是什么浏览器,这 ...
- JavaScript 判断用户输入的邮箱及手机格式是否正确
JavaScript判断用户输入的邮箱格式是否正确.判断用户输入的手机号格式是否正确,下面有个不错的示例,感兴趣的朋友可以参考下. 复制代码代码如下: /* * 功能:判断用户输入的邮箱格式是否正确 ...
- c语言判断用户是否输入-非阻塞函数kbhit
一.基础研究 要从地址读取数据,肯定是要定义一个指针变量p,用它来实现变换地址和取值的功能.另外程序是当两个条件中的某一个出现时才停止,所以应该用while~do循环语句循环输出n和d,并用while ...
- 【百度地图API】让用户选择起点和终点的驾车导航
原文:[百度地图API]让用户选择起点和终点的驾车导航 摘要: 如果用户搜索“从机场到火车站”,使用驾车导航DrivingRoute会默认显示一条结果.但同一个城市可能有多个机场和火车站,那么,如何用 ...
随机推荐
- nodejs: C++扩展
Nodejs的C++扩展首先保证nodejs和v8都正确安装 下载NodeJS源码,我的放在D盘. NodeJS的C++扩展要用VS2010开发,新建一个空的Win32控制台项目,右键——属性,在常规 ...
- iOS开发零基础--Swift基础篇--常量&变量的定义
什么是常量和变量 在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量 使用let来定义常量,定义之后不可以修改 使用var来定义变量,定义之后可以修改 常量和变量的使用注意: ...
- FIM相关报错汇总
1.错误1:FIM在修改MA名字的时候报错: The management agent cannot be deleted or renamed because the working directo ...
- 对象池与.net—从一个内存池实现说起
本来想写篇关于System.Collections.Immutable中提供的ImmutableList里一些实现细节来着,结果一时想不起来源码在哪里--为什么会变成这样呢--第一次有了想写分析的源码 ...
- [Hyper-V]在Windows 8.1 操作系统中启用Hyper-V功能
描述: 如何在Windows 8.1 操作中启用Hyper-V功能 实现步骤: 1,安装Hyper-V 1 打开Control Panel,点击Progress 2 点击Turn Windows fe ...
- [WinAPI] API 1 [桌面上画一个简单彩色图形]
#include<Windows.h> void GdiOut(HDC hdc); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hP ...
- Web API 简单示例
一.RESTful和Web API Representational State Transfer (REST) is a software architecture style consisting ...
- freshcodecolor纯正则实现的在线代码着色(高亮)
小菜最新完成的一款在线代码着色工具-freshcodecolor,该工具采用Javascript编写,着色识别策略完全采用正则表达式,无奈正则表达式在Javascript中有很大局限性,导致某些场合识 ...
- Express 4 更新改变文档
概览 从 Express 3 到Express 4 是一个巨大的变化,这意味着现存的 Express 3 应用在不更新依赖的情况下将不能工作. 这篇文章涵盖一下内容: Express 4 中的变化 一 ...
- 使用jsdoc-toolkit实现JS API文档自动化
在前面的博文中探讨自动化工程问题时,写过基于NodeJS的,使用gulp.grunt的jsdoc插件实现文档自动化.本文探讨基于java环境的自动化实现. 一.Java安装与环境配置 关于Java的安 ...