java 地理围栏实现_使用Path2D和凸包算法实现地理围栏服务

本文介绍了如何使用Java的Path2D类和凸包算法来实现地理围栏服务。首先讲解了如何通过Path2D创建多边形,接着展示了判断坐标是否在多边形内的方法,然后利用凸包算法获取覆盖区域,并根据地图窗口查询相交的Path2D。这些技术在物流配送等行业中有广泛应用。
摘要由CSDN通过智能技术生成

前言

地理围栏(Geo-fencing)是LBS的一种新应用,就是用一个虚拟的栅栏围出一个虚拟地理边界。在物流配送行业应用比较广,划分每个配送网点或者商家配送的范围,提高配送员的配送效率和服务的范围。

1.使用Path2D创建一个多边形

Path2D类是java.awt.geom包提供的工具包,可表示任意几何路径的简单而灵活的形状。它可以完全表示PathIterator接口可以迭代的任何路径, 包括其所有段类型和绕组规则,并且它实现了Shape接口的所有基本命中测试方法。

使用Path2D.Float带有可表示且能使用浮点精度的数据的时候。使用Path2D.Double 对于需要双精度的准确性或范围的数据。

先通过高德地图在线编辑一个多边形覆盖图,然后获取到有序的坐标

8eb31ad992ce471a949f732d1ccc5d87.png

代码示例如下:

//传参 有序的坐标范围

public static Path2D.Double create(List polygon) {

//创建path2D对象

Path2D.Double generalPath = new Path2D.Double();

//获取有序坐标范围的第一个坐标

PointDouble first = polygon.get(0);

//通过移动到指定坐标(以双精度指定),将一个点添加到路径中

generalPath.moveTo(first.getX(), first.getY());

//删除有序坐标范围第一个

polygon.remove(0);

//遍历有序坐标范围后面的坐标

for (PointDouble d : polygon) {

// 通过绘制一条从当前坐标到新指定坐标(以双精度指定)的直线,将一个点添加到路径中。

generalPath.lineTo(d.getX(), d.getY());

}

// 将几何多边形封闭

generalPath.lineTo(first.getX(), first.getY());

//关闭路径

generalPath.closePath();

return generalPath;

}

以上用到了的方法详解

moveTo(double x, double y)

通过移动到以double精度指定的指定坐标,向路径添加一个点。

lineTo(double x, double y)

通过从当前坐标绘制直线到以double精度指定的新指定坐标,将路径添加到路径。

closePath()

通过将直线绘制回最后一个坐标来关闭当前子路径moveTo。

2.判断某个坐标是否在Path2D

代码示例

PointDouble point = new PointDouble(116.403322,39.920255);

//生成好的多边形是不是包含某个坐标

path2d.contains(point)

以上用到了的方法详解

contains(double x, double y)

测试指定坐标是否在边界内Shape

3.判断某个矩形区域是否在Path2D

contains(PathIterator pi, double x, double y, double w, double h)

测试指定的矩形区域是否完全位于指定的闭合边界内PathIterator

4.使用凸包算法把指定Path2D转换成一块大的覆盖面

凸包(Convex Hull)是一个计算几何(图形学)中的概念。在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,...Xn)的凸组合来构造.在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

56ee894615ac7a5f77835ffe642f7d53.png

代码示例:

/**

* 凸包算法

*

* @author wangnian

*/

public class ConvexUtil {

/**

* 凸包算法,返回点集合中凸多边形的点集合

*

* @param pointList

* @return

*/

public static List getConvexPoint(List pointList) {

//用于计算最终返回结果中是凸包中点的个数

List resultList = new ArrayList<>();

for (int i = 0; i < pointList.size(); i++) {

for (int j = 0; j < pointList.size(); j++) {

if (j == i) {

//除去选中作为确定直线的第一个点

continue;

}

//存放点到直线距离所使用判断公式的结果

double[] judge = new double[pointList.size()];

for (int k = 0; k < pointList.size(); k++) {

double a = pointList.get(j).getX() - pointList.get(i).getY();

double b = pointList.get(i).getX() - pointList.get(j).getX();

double c = (pointList.get(i).getX()) * (pointList.get(j).getY()) - (pointList.get(i).getY()) * (pointList.get(j).getX());

//根据公式计算具体判断结果

judge[k] = a * (pointList.get(k).getX()) + b * (pointList.get(k).getY()) - c;

}

// 如果点均在直线的一边,则相应的A[i]是凸包中的点

if (JudgeArray(judge)) {

resultList.add(pointList.get(i));

break;

}

}

}

return resultList;

}

/**

* 判断数组中元素是否全部大于等于0或者小于等于0,如果是则返回true,否则返回false

*

* @param Array

* @return

*/

private static boolean JudgeArray(double[] Array) {

boolean judge = false;

int len1 = 0, len2 = 0;

for (int i = 0; i < Array.length; i++) {

if (Array[i] >= 0) {

len1++;

}

}

for (int j = 0; j < Array.length; j++) {

if (Array[j] <= 0) {

len2++;

}

}

if (len1 == Array.length || len2 == Array.length) {

judge = true;

}

return judge;

}

}

5. 根据当前地图窗口查询所有相交Path2D

根据当前地图显示范围获取到northeast东北角和southwest西南角的坐标位置,查询相交的所有Path2D

高德地图示例地址:

20563d6ea6ba1e23a0a71d3a6e6e4691.png

代码示例

//获取西南的纬度 也就是X

double lng = southwest.getLng();

//获取西南的经度 也就是Y

double lat = southwest.getLat();

//东北角的X减去西南角的X ,得到宽

double w = northeast.getLng() - southwest.getLng();

//东北角的Y减去西南角的Y ,得到高

double h = northeast.getLat() - southwest.getLat();

//判断是否相交

Path2D.intersects(lng, lat, w, h)

以上用到了的方法详解

intersects(double x, double y, double w, double h)

测试内部是否与Shape指定矩形区域的内部相交。

提示: 以上只是一些关键的局部代码,在实际应用中,需要将所有的范围对象按照凸包算法或者其他纬度的行政区域进行分类并缓存,方便快速遍历查询。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java语言中实现凸包算法可以使用 Graham 扫描算法。以下是一个简单的示例代码: ```java import java.util.*; public class ConvexHull { public static List<Point> convexHull(List<Point> points) { // 如果点的数量小于等于1,则返回点列表 if (points.size() <= 1) { return points; } // 对点按照x坐标进行排序 Collections.sort(points); // 创建一个栈来保存凸包上的点 Stack<Point> stack = new Stack<>(); // 将前两个点加入栈中 stack.push(points.get(0)); stack.push(points.get(1)); // 从第三个点开始,依次判断是否为凸包上的点 for (int i = 2; i < points.size(); i++) { Point top = stack.pop(); while (!stack.isEmpty() && orientation(stack.peek(), top, points.get(i)) <= 0) { top = stack.pop(); } stack.push(top); stack.push(points.get(i)); } // 将栈中的点转换成列表 List<Point> hull = new ArrayList<>(stack); Collections.reverse(hull); return hull; } // 判断点a、b、c的方向 public static int orientation(Point a, Point b, Point c) { return (b.y - a.y) * (c.x - b.x) - (b.x - a.x) * (c.y - b.y); } public static void main(String[] args) { List<Point> points = new ArrayList<>(); points.add(new Point(0, 0)); points.add(new Point(1, 1)); points.add(new Point(2, 2)); points.add(new Point(3, 3)); points.add(new Point(0, 3)); List<Point> hull = convexHull(points); System.out.println("Convex Hull:"); for (Point p : hull) { System.out.println(p); } } } class Point implements Comparable<Point> { int x, y; public Point(int x, int y) { this.x = x; this.y = y; } @Override public int compareTo(Point other) { if (this.x == other.x) { return Integer.compare(this.y, other.y); } return Integer.compare(this.x, other.x); } @Override public String toString() { return "(" + x + ", " + y + ")"; } } ``` 在上面的代码中,我们定义了一个 `Point` 类来表示一个二维点,然后实现了 `convexHull` 方法来计算给定点集的凸包。最后,我们在 `main` 方法中测试了这个算法,并输出了计算结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值