1、定义点
public class Point {
private BigDecimal x;
private BigDecimal y;
public Point() {
};
@Override
public String toString() {
DecimalFormat df = new DecimalFormat("#.000000000000000000000000000000");
return "Point [x=" + df.format(x) + ", y=" + df.format(y) + "]";
}
public Point(BigDecimal x, BigDecimal y) {
this.x = x;
this.y = y;
}
public BigDecimal getX() {
return x;
}
public void setX(BigDecimal x) {
this.x = x;
}
public BigDecimal getY() {
return y;
}
public void setY(BigDecimal y) {
this.y = y;
}
}
2、定义线(多边形的边)
public class Line {
private Point apoint;
private Point zpoint;
private BigDecimal k;
private BigDecimal b;
public Line() {
}
public Line(Point a, Point z) {
this.apoint = a;
this.zpoint = z;
}
public Line(BigDecimal x1, BigDecimal y1, BigDecimal x2, BigDecimal y2) {
this.apoint = new Point(x1, y1);
this.zpoint = new Point(x2, y2);
}
/**
* 计算中点
*
* @return
*/
public Point getMidPoint() {
Point midPoint = null;
if (apoint != null && zpoint != null) {
BigDecimal x = (apoint.getX().add(zpoint.getX())).divide(
new BigDecimal(2), PolygonUtil.ACCURACY,
BigDecimal.ROUND_HALF_UP);
BigDecimal y = (apoint.getY().add(zpoint.getY())).divide(
new BigDecimal(2), PolygonUtil.ACCURACY,
BigDecimal.ROUND_HALF_UP);
midPoint = new Point(x, y);
}
return midPoint;
}
/**
* 获取斜率
*
* @return
*/
public BigDecimal getK() {
// k = (y1 - y2) / (x1 - x2)
if (k == null) {
k = BigDecimal.ZERO;
if (apoint != null && zpoint != null) {
if (apoint.getX().compareTo(zpoint.getX()) != 0) {
k = (apoint.getY().subtract(zpoint.getY())).divide(apoint
.getX().subtract(zpoint.getX()),
PolygonUtil.ACCURACY, BigDecimal.ROUND_HALF_UP);
}
}
}
return k;
}
public BigDecimal getB() {
// b = y - kx
if (b == null) {
b = BigDecimal.ZERO;
if (apoint != null && zpoint != null) {
BigDecimal k = getK();
if (k.compareTo(BigDecimal.ZERO) == 0) {
b = apoint.getY();
} else {
b = apoint.getY().subtract(apoint.getX().multiply(k));
}
}
}
return b;
}
@Override
public String toString() {
DecimalFormat df = new DecimalFormat("#.000000000000000000000000000000");
return "Line [apoint=" + apoint + ", zpoint=" + zpoint
+ ", getMidPoint()=" + getMidPoint() + ", getK()="
+ df.format(getK()) + ", getB()=" + df.format(getB())
+ ", getApoint()=" + getApoint() + ", getZpoint()="
+ getZpoint() + ", getClass()=" + getClass() + ", hashCode()="
+ hashCode() + ", toString()=" + super.toString() + "]";
}
public Point getApoint() {
return apoint;
}
public void setApoint(Point apoint) {
this.apoint = apoint;
}
public Point getZpoint() {
return zpoint;
}
public void setZpoint(Point zpoint) {
this.zpoint = zpoint;
}
}
3、判断线是否在多边形内
public class PolygonUtil {
private final static Logger logger = LoggerFactory
.getLogger(GeoService.class);
public static final int ACCURACY = 30;
/**
* 将多边形拆除多条边(此处为超图多边形模型,可根据具体模型修改此方法)
* @param polygon
* @return
*/
public List<Line> getLineList(GeoRegion polygon) {
List<Line> lines = new ArrayList<Line>();
Point2D apt = null;
Point2D zpt = null;
Point2Ds pts = null;
Line line = null;
for (int i = 0; i < polygon.getPartCount(); i++) {
pts = polygon.getPart(i);
for (int j = 0; j < pts.getCount() - 1; j++) {
apt = pts.getItem(j);
zpt = pts.getItem(j + 1);
line = new Line(new BigDecimal(apt.getX()), new BigDecimal(
apt.getY()), new BigDecimal(zpt.getX()),
new BigDecimal(zpt.getY()));
lines.add(line);
}
}
return lines;
}
/**
* 判断点是否在多边形内
*
* @param point
* @param lines
* @return
*/
public boolean withIn(Point point, List<Line> lines) {
// 根据面第一条边中点确认射线
Line ray = new Line(point, lines.get(0).getMidPoint());
Line line = null;
Point meetPoint = null;
// logger.info(ray.toString());
// logger.info(lines.get(0).getMidPoint().toString());
// 因为第一条边必定与射线相交,则从第二条边开始判断
int count = 1;
for (int i = 1; i < lines.size(); i++) {
// logger.info("---------------------");
line = lines.get(i);
meetPoint = getMeetPoint(ray, line);
if (line.getK().compareTo(ray.getK()) != 0) {
if (isInline(meetPoint, line) && isInRay(meetPoint, ray)) {
count++;
}
}
// logger.info(line.toString());
// logger.info(meetPoint.toString());
}
return count % 2 == 0 ? false : true;
}
/**
* 获取交汇点
*
* @param ray
* @param line
* @return
*/
public Point getMeetPoint(Line ray, Line line) {
// x = (b1 - b2) / (k2 - k1)
// y = kx + b
Point point = null;
BigDecimal x = BigDecimal.ZERO;
BigDecimal y = BigDecimal.ZERO;
// logger.info("KK:{}", line.getK().compareTo(ray.getK()));
if (line.getK().compareTo(ray.getK()) != 0) {
if (line.getK().compareTo(BigDecimal.ONE) == 0) {
x = line.getApoint().getX();
} else {
x = (ray.getB().subtract(line.getB())).divide(line.getK()
.subtract(ray.getK()), PolygonUtil.ACCURACY,
BigDecimal.ROUND_HALF_UP);
}
if (line.getK().compareTo(BigDecimal.ZERO) == 0) {
y = line.getApoint().getY();
} else {
y = ray.getK().multiply(x).add(ray.getB());
}
point = new Point(x, y);
}
return point;
}
/**
* 判断交汇点是否在线段上
*
* @param point
* @param line
* @return
*/
public boolean isInline(Point point, Line line) {
boolean result = false;
if (point == null || point.getX() == null || point.getY() == null) {
result = false;
} else if ((line.getApoint().getX().compareTo(point.getX()) == -1 && line
.getZpoint().getX().compareTo(point.getX()) == -1)
|| (line.getApoint().getX().compareTo(point.getX()) == 1 && line
.getZpoint().getX().compareTo(point.getX()) == 1)
|| (line.getApoint().getY().compareTo(point.getY()) == -1 && line
.getZpoint().getY().compareTo(point.getY()) == -1)
|| (line.getApoint().getY().compareTo(point.getY()) == 1 && line
.getZpoint().getY().compareTo(point.getY()) == 1)) {
result = false;
} else {
result = true;
}
// logger.info("AX:{}",
// line.getApoint().getX().compareTo(point.getX()));
// logger.info("ZX:{}",
// line.getZpoint().getX().compareTo(point.getX()));
// logger.info("AY:{}",
// line.getApoint().getY().compareTo(point.getY()));
// logger.info("ZY:{}",
// line.getZpoint().getY().compareTo(point.getY()));
// logger.info("RESULT:{}", result);
return result;
}
/**
* 判断点是否在射线上
*
* @param point
* @param ray
* @return
*/
public boolean isInRay(Point point, Line ray) {
boolean result = false;
if (point == null || point.getX() == null || point.getY() == null) {
result = false;
} else {
BigDecimal x = (ray.getApoint().getX().subtract(ray.getZpoint()
.getX())).multiply(ray.getApoint().getX()
.subtract(point.getX()));
BigDecimal y = (ray.getApoint().getY().subtract(ray.getZpoint()
.getY())).multiply(ray.getApoint().getY()
.subtract(point.getY()));
if (x.compareTo(new BigDecimal(0)) < 0
|| y.compareTo(new BigDecimal(0)) < 0) {
result = false;
} else {
result = true;
}
}
return result;
}
/**
* 测试
* @param args
*/
public static void main(String[] args) {
// 组成多边形的边集合
List<Line> lines = new ArrayList<Line>();
Point a = new Point(new BigDecimal(1D), new BigDecimal(1D));
Point b = new Point(new BigDecimal(2D), new BigDecimal(5D));
Point c = new Point(new BigDecimal(5D), new BigDecimal(6D));
Point d = new Point(new BigDecimal(4D), new BigDecimal(2D));
lines.add(new Line(a, b));
lines.add(new Line(b, c));
lines.add(new Line(c, d));
lines.add(new Line(d, a));
List<Point> pointList = new ArrayList<Point>();
pointList.add(new Point(new BigDecimal(3.1D), new BigDecimal(3.1D)));
pointList.add(new Point(new BigDecimal(7D), new BigDecimal(7D)));
PolygonUtil test = new PolygonUtil();
for (Point point: pointList) {
if (test.withIn(point, lines)) {
System.out.printf("点在多边形内:%s\n", point.toString());
} else {
System.out.printf("点不在多边形内:%s\n", point.toString());
}
}
}
}