intersection.java
来自「OpenMap是一个基于JavaBeansTM的开发工具包。利用OpenMap你」· Java 代码 · 共 1,455 行 · 第 1/4 页
JAVA
1,455 行
/** * Returns the center of the polygon poly. */ public static Geo center(Geo[] poly) { return center(poly, new Geo()); } /** * Returns the center of the polygon poly. */ public static Geo center(Geo[] poly, Geo ret) { Geo c = new Geo(poly[0]); for (int i = 1; i < poly.length; i++) { ret.initialize(poly[i]); c = c.add(poly[i], c); } return c.normalize(ret); } /** * Returns the center of the polygon poly. */ public static Geo center(GeoArray poly) { return center(poly, new Geo()); } /** * Returns the center of the polygon poly. * * @param poly the GeoArray of the polygon * @param ret a Geo to use for the return values. * @return ret. */ public static Geo center(GeoArray poly, Geo ret) { Geo c = poly.get(0, new Geo()); int size = poly.getSize(); for (int i = 1; i < size; i++) { poly.get(i, ret); c = c.add(ret, c); } return c.normalize(ret); } /** * Determines whether <code>x</code> is inside <code>poly</code>. * * <p> * <em>N.B.</em><br> * <ul> * <li><code>poly</code> must be a closed polygon. In other words, the * first and last point must be the same. * <li>It is recommended that a bounds check is run before this method. * This method will return true if either <code>x</code> or the antipode * (the point on the opposite side of the planet) of <code>x</code> are * inside <code>poly</code>. * </ul> * * <p> * <code>poly<code> is an array of latitude/longitude points where: * <br> * <pre> * * * poly[0] = latitude 1 * poly[1] = longitude 1 * poly[2] = latitude 2 * poly[3] = longitude 2 * . * . * . * poly[n-1] = latitude 1 * poly[n] = longitude 1 * * </pre> * * @param x a geographic coordinate * @param poly an array of lat/lons describing a closed polygon * @return true iff <code>x</code> or <code>antipode(x)</code> is * inside <code>poly</code> */ public static boolean isPointInPolygon(Geo x, GeoArray poly) { Geo c = center(poly, new Geo()); // bail out if the point is more than 90 degrees off the // centroid double d = x.distance(c); if (d >= (Math.PI / 2)) { return false; } // ray is normal to the great circle from c to x. reusing c to hold ray // info Geo ray = c.crossNormalize(x, c); /* * side is a point on the great circle between c and x. It is used to * choose a direction. */ Geo side = x.crossNormalize(ray, new Geo()); boolean in = false; // Why do we need to allocate new Geos? // Geo p1 = new Geo(poly[0]); // Geo p2 = new Geo(poly[0]); Geo p1 = poly.get(0, new Geo()); Geo p2 = poly.get(0, new Geo()); Geo tmp = new Geo(); int polySize = poly.getSize(); for (int i = 1; i < polySize; i++) { // p2.initialize(poly[i]); p2 = poly.get(i, p2); /* * p1 and p2 are on different sides of the ray, and the great * acircle between p1 and p2 is on the side that counts; */ if ((p1.dot(ray) < 0.0) != (p2.dot(ray) < 0.0) && p1.intersect(p2, ray, tmp).dot(side) > 0.0) in = !in; p1.initialize(p2); } // Check for unclosed polygons, if the polygon isn't closed, // do the calculation for the last point to the starting // point. if (!poly.equals(0, p1)) { poly.get(0, p2); if ((p1.dot(ray) < 0.0) != (p2.dot(ray) < 0.0) && p1.intersect(p2, ray, tmp).dot(side) > 0.0) { in = !in; } } return in; } /** * Ask if a Geo point is in a polygon. * * @param x * @param poly float array where [lat, lon, lat, lon,...] * @param polyInDegrees true of poly floats represent decimal degrees. * @return true for Geo in poly */ public static boolean isPointInPolygon(Geo x, float[] poly, boolean polyInDegrees) { if (polyInDegrees) { return isPointInPolygon(x, GeoArray.Float.createFromLatLonDegrees(poly)); } else { return isPointInPolygon(x, GeoArray.Float.createFromLatLonRadians(poly)); } } /** * return true IFF some point of the first argument is inside the region * specified by the closed polygon specified by the second argument */ public static boolean isPolylineInsidePolygon(GeoArray poly, GeoArray region) { int polySize = poly.getSize(); Geo testPoint = new Geo(); for (int i = 0; i < polySize; i++) { poly.get(i, testPoint); if (isPointInPolygon(testPoint, region)) { return true; } } return false; } /** * Returns the point of intersection of two great circle segments defined by * the segments. (lat1, lon1) to (lat2, lon2) and (lat2, lon2) to (lat4, * lon4). All lat-lon values are in degrees. * * @return a float array of length 4 containing upto 2 valid lat-lon points * of intersection that lie on both segments. Positions in the array * not containing a valid lat/lon value are initialized to * Float.MAX_VALUE. */ public static float[] getSegIntersection(float lat1, float lon1, float lat2, float lon2, float lat3, float lon3, float lat4, float lon4) { // KRA 03SEP03: The original version of this consed 26+ Geo's. // This one conses 8+. WAIT! Now it uses 6 Geo p1 = new Geo(lat1, lon1); Geo p2 = new Geo(lat2, lon2); Geo p3 = new Geo(lat3, lon3); Geo p4 = new Geo(lat4, lon4); Geo[] results = getSegIntersection(p1, p2, p3, p4); Geo i1 = results[0]; Geo i2 = results[1]; float[] llp = new float[] { Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE }; // check if first point of intersection lies on both segments if (i1 != null) { llp[0] = ((float) i1.getLatitude()); llp[1] = ((float) i1.getLongitude()); } // check if second point of intersection lies on both segments if (i2 != null) { llp[2] = ((float) i2.getLatitude()); llp[3] = ((float) i2.getLongitude()); } return llp; } /** * Find the intersection(s) between [p1-p2] and [p3-p4] */ public static final Geo[] getSegIntersection(Geo p1, Geo p2, Geo p3, Geo p4) { Geo geoCross1 = p1.crossNormalize(p2); Geo geoCross2 = p3.crossNormalize(p4); // i1 is really geoCross1, i2 is really geoCross2, memory-wise. Geo i1 = geoCross1.crossNormalize(geoCross2, geoCross1); Geo i2 = i1.antipode(geoCross2); // check if the point of intersection lies on both segs // length of seg1 double d1 = p1.distance(p2); // length of seg2 double d2 = p3.distance(p4); // between seg1 endpoints and first point of intersection double d111 = p1.distance(i1); double d121 = p2.distance(i1); // between seg1 endpoints and second point of intersection double d112 = p1.distance(i2); double d122 = p2.distance(i2); // between seg2 endpoints and first point of intersection double d211 = p3.distance(i1); double d221 = p4.distance(i1); // between seg2 endpoints and second point of intersection double d212 = p3.distance(i2); double d222 = p4.distance(i2); Geo[] result = new Geo[] { null, null }; // check if first point of intersection lies on both segments if (d1 >= d111 && d1 >= d121 && d2 >= d211 && d2 >= d221) { result[0] = i1; } // check if second point of intersection lies on both segments if (d1 >= d112 && d1 >= d122 && d2 >= d212 && d2 >= d222) { result[1] = i2; } return result; } // /** // * returns the point of interection of two great circle segments // * defined by the segments. (lat1, lon1) to (lat2, lon2) and // * (lat2, lon2) to (lat4, lon4). All lat-lon values are in // * degrees. // * // * @return a float array of length 4 containing upto 2 valid // * lat-lon points of intersection that lie on both // * segments. Positions in the array not containing a valid // * lat/lon value are initialized to Float.MAX_VALUE. // */ // public static float[] getSegIntersectionOrig(float lat1, float // lon1, // float lat2, float lon2, // float lat3, float lon3, // float lat4, float lon4) { // // KRA 03SEP03: We can do better than this. // // float[] ll = getIntersection(lat1, // lon1, // lat2, // lon2, // lat3, // lon3, // lat4, // lon4); // // // check if the point of intersection lies on both segs // // // length of seg1 // double d1 = Geo.distance(lat1, lon1, lat2, lon2); // // length of seg2 // double d2 = Geo.distance(lat3, lon3, lat4, lon4); // // // between seg1 endpoints and first point of intersection // double d111 = Geo.distance(lat1, lon1, ll[0], ll[1]); // double d121 = Geo.distance(lat2, lon2, ll[0], ll[1]); // // // between seg1 endpoints and second point of intersection // double d112 = Geo.distance(lat1, lon1, ll[2], ll[3]); // double d122 = Geo.distance(lat2, lon2, ll[2], ll[3]); // // // between seg2 endpoints and first point of intersection // double d211 = Geo.distance(lat3, lon3, ll[0], ll[1]); // double d221 = Geo.distance(lat4, lon4, ll[0], ll[1]); // // // between seg2 endpoints and second point of intersection // double d212 = Geo.distance(lat3, lon3, ll[2], ll[3]); // double d222 = Geo.distance(lat4, lon4, ll[2], ll[3]); // // float[] llp = new float[] { Float.MAX_VALUE, Float.MAX_VALUE, // Float.MAX_VALUE, Float.MAX_VALUE }; // // // check if first point of intersection lies on both segments // if (d1 >= d111 && d1 >= d121 && d2 >= d211 && d2 >= d221) { // llp[0] = ll[0]; // llp[1] = ll[1]; // } // // // check if second point of intersection lies on both segments // if (d1 >= d112 && d1 >= d122 && d2 >= d212 && d2 >= d222) { // llp[2] = ll[2]; // llp[3] = ll[3]; // } // // return llp; // } /** * Does the segment come within near radians of the region defined by * rCenter at rRadius? */ public static final boolean isSegmentNearRadialRegion(GeoSegment segment, Geo rCenter, double rRadius, double near) { Geo[] s = segment.getSeg(); if (s != null && s.length == 2) { return isSegmentNearRadialRegion(s[0], s[1], rCenter, rRadius, near); } return false; } /** * Does the segment come within near radians of the region defined by * rCenter at rRadius? */ public static final boolean isSegmentNearRadialRegion(Geo s1, Geo s2, Geo rCenter, double rRadius, double near) { return s1.isInside(s2, near + rRadius, rCenter); } /** Is a segment horizontally within range of a Region region? */ public static final boolean isSegmentNearRegion(GeoSegment segment, double hrange, GeoRegion region) { // Need to be careful here - calling // region.isSegmentNear(segment, hrange) can result in // circular code if the region just calls this method, which // may seem reasonable, if you look at the API. return isSegmentNearPolyRegion(segment, region.getPoints(), hrange); } /**
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?