geo.java
来自「OpenMap是一个基于JavaBeansTM的开发工具包。利用OpenMap你」· Java 代码 · 共 1,182 行 · 第 1/3 页
JAVA
1,182 行
right.add(l1b); left.add(r1b); } // advance normals l0 = l1b; r0 = r1b; } else { // otherwise, compute a more complex shape // these are the right and left on the g0 side of g1 Geo r1a = g1.add(n0); Geo l1a = g1.subtract(n0); double handed = g0.cross(g1).dot(g2); // right or left handed // divergence if (handed > 0) { // left needs two points, right needs 1 if (err > 0) { Geo[] arc = approximateArc(g1, l1b, l1a, err); for (int j = arc.length - 1; j >= 0; j--) { right.add(arc[j]); } } else { right.add(l1a); right.add(l1b); } l0 = l1b; Geo ip = Intersection.segmentsIntersect(r0, r1a, r1b, g2.add(n1)); // if they intersect, take the intersection, else use the // points and punt if (ip != null) { left.add(ip); } else { left.add(r1a); left.add(r1b); } r0 = ip; } else { Geo ip = Intersection.segmentsIntersect(l0, l1a, l1b, g2.subtract(n1)); // if they intersect, take the intersection, else use the // points and punt if (ip != null) { right.add(ip); } else { right.add(l1a); right.add(l1b); } l0 = ip; if (err > 0) { Geo[] arc = approximateArc(g1, r1a, r1b, err); for (int j = 0; j < arc.length; j++) { left.add(arc[j]); } } else { left.add(r1a); left.add(r1b); } r0 = r1b; } } // advance points g0 = g1; n0 = n1; g1 = g2; } // finish it off Geo rn = g1.subtract(n0); Geo ln = g1.add(n0); if (capp && err > 0) { // end cap Geo[] arc = approximateArc(g1, ln, rn, err); for (int j = arc.length - 1; j >= 0; j--) { right.add(arc[j]); } } else { right.add(rn); left.add(ln); } int ll = right.size(); int rl = left.size(); Geo[] result = new Geo[ll + rl]; for (int i = 0; i < ll; i++) { result[i] = (Geo) right.get(i); } int j = ll; for (int i = rl - 1; i >= 0; i--) { result[j++] = (Geo) left.get(i); } return result; } /** simple vector angle (not geocentric!) */ static double simpleAngle(Geo p1, Geo p2) { return Math.acos(p1.dot(p2) / (p1.length() * p2.length())); } /** * compute a polygonal approximation of an arc centered at pc, beginning at * p0 and ending at p1, going clockwise and including the two end points. * * @param pc center point * @param p0 starting point * @param p1 ending point * @param err The maximum angle between approximates allowed, in radians. * Smaller values will look better but will result in more returned * points. * @return */ public static final Geo[] approximateArc(Geo pc, Geo p0, Geo p1, double err) { double theta = angle(p0, pc, p1); // if the rest of the code is undefined in this situation, just skip it. if (Double.isNaN(theta)) { return new Geo[] { p0, p1 }; } int n = (int) (2.0 + Math.abs(theta / err)); // number of points // (counting the end // points) Geo[] result = new Geo[n]; result[0] = p0; double dtheta = theta / (n - 1); double rho = 0.0; // angle starts at 0 (directly at p0) for (int i = 1; i < n - 1; i++) { rho += dtheta; // Rotate p0 around this so it has the right azimuth. result[i] = Rotation.rotate(pc, 2.0 * Math.PI - rho, p0, new Geo()); } result[n - 1] = p1; return result; } public final Geo[] approximateArc(Geo p0, Geo p1, double err) { return approximateArc(this, p0, p1, err); } /** @deprecated use </b>#offset(double, double) */ public Geo geoAt(double distance, double azimuth) { return offset(distance, azimuth); } /** * Returns a Geo that is distance (radians), and azimuth (radians) away from * this. * * @param distance distance of this to the target point in radians. * @param azimuth Direction of target point from this, in radians, clockwise * from north. * @note this is undefined at the north pole, at which point "azimuth" is * undefined. */ public Geo offset(double distance, double azimuth) { return offset(distance, azimuth, new Geo()); } /** * Returns a Geo that is distance (radians), and azimuth (radians) away from * this. * * @param distance distance of this to the target point in radians. * @param azimuth Direction of target point from this, in radians, clockwise * from north. * @note this is undefined at the north pole, at which point "azimuth" is * undefined. * @return ret Do not pass in a null value. */ public Geo offset(double distance, double azimuth, Geo ret) { // m is normal the the meridian through this. Geo m = this.crossNormalize(north, ret); // p is a point on the meridian distance <tt>distance</tt> from this. // Geo p = (new Rotation(m, distance)).rotate(this); Geo p = Rotation.rotate(m, distance, this, ret); // Rotate p around this so it has the right azimuth. return Rotation.rotate(this, 2.0 * Math.PI - azimuth, p, ret); } public static Geo offset(Geo origin, double distance, double azimuth) { return origin.offset(distance, azimuth); } /** * * @param origin * @param distance * @param azimuth * @param ret * @return ret Do not pass in a null value. */ public static Geo offset(Geo origin, double distance, double azimuth, Geo ret) { return origin.offset(distance, azimuth, ret); } /* * //same as offset, except using trig instead of vector mathematics public * Geo trig_offset(double distance, double azimuth) { double latr = * getLatitudeRadians(); double lonr = getLongitudeRadians(); * * double coslat = Math.cos(latr); double sinlat = Math.sin(latr); double * cosaz = Math.cos(azimuth); double sinaz = Math.sin(azimuth); double sind = * Math.sin(distance); double cosd = Math.cos(distance); * * return makeGeoRadians(Math.asin(sinlat * cosd + coslat * sind * cosaz), * Math.atan2(sind * sinaz, coslat * cosd - sinlat * sind * cosaz) + lonr); } */ // // Follows are a series of Geo array operations as useful utilities // /** * convert a String containing space-separated pairs of comma-separated * decimal lat-lon pairs into a Geo array. */ public static Geo[] posToGa(String coords) { return posToGa(coords.split(" ")); } /** * Convert an array of strings with comma-separated decimal lat,lon pairs * into a Geo array */ public static Geo[] posToGa(String[] coords) { // convert to floating lat/lon degrees Geo[] ga = new Geo[coords.length]; for (int i = 0; i < coords.length; i++) { String[] ll = coords[i].split(","); ga[i] = Geo.makeGeoDegrees(Double.parseDouble(ll[0]), Double.parseDouble(ll[1])); } return ga; } /** * Convert a Geo array into a floating point lat lon array (alternating lat * and lon values). * * @return the ll array provided, or a new array of lla is null. */ public static double[] GaToLLa(Geo[] ga, double[] lla) { if (lla == null) { lla = new double[2 * ga.length]; } for (int i = 0; i < ga.length; i++) { Geo g = ga[i]; lla[i * 2] = g.getLatitude(); lla[i * 2 + 1] = g.getLongitude(); } return lla; } /** * Convert a Geo array into a floating point lat lon array (alternating lat * and lon values). * * @return the ll array provided, or a new array of lla is null. */ public static float[] GaToLLa(Geo[] ga, float[] lla) { if (lla == null) { lla = new float[2 * ga.length]; } for (int i = 0; i < ga.length; i++) { Geo g = ga[i]; lla[i * 2] = (float) g.getLatitude(); lla[i * 2 + 1] = (float) g.getLongitude(); } return lla; } /** * Convert a Geo array into a floating point lat lon array (alternating lat * and lon values) */ public static float[] GaToLLa(Geo[] ga) { return GaToLLa(ga, new float[2 * ga.length]); } /** * Return a Geo array with the duplicates removed. May arbitrarily mutate * the input array. */ public static Geo[] removeDups(Geo[] ga) { Geo[] r = new Geo[ga.length]; int p = 0; for (int i = 0; i < ga.length; i++) { if (p == 0 || !(r[p - 1].equals(ga[i]))) { r[p] = ga[i]; p++; } } if (p != ga.length) { Geo[] x = new Geo[p]; System.arraycopy(r, 0, x, 0, p); return x; } else { return ga; } } /** * Convert a float array of alternating lat and lon pairs into a Geo array. */ public static Geo[] LLaToGa(float[] lla) { return LLaToGa(lla, true); } /** * Convert a float array of alternating lat and lon pairs into a Geo array. */ public static Geo[] LLaToGa(float[] lla, boolean isDegrees) { Geo[] r = new Geo[lla.length / 2]; for (int i = 0; i < lla.length / 2; i++) { if (isDegrees) { r[i] = Geo.makeGeoDegrees(lla[i * 2], lla[i * 2 + 1]); } else { r[i] = Geo.makeGeoRadians(lla[i * 2], lla[i * 2 + 1]); } } return r; } /** * Convert a double array of alternating lat and lon pairs into a Geo array. */ public static Geo[] LLaToGa(double[] lla) { return LLaToGa(lla, true); } /** * Convert a double array of alternating lat and lon pairs into a Geo array. */ public static Geo[] LLaToGa(double[] lla, boolean isDegrees) { Geo[] r = new Geo[lla.length / 2]; for (int i = 0; i < lla.length / 2; i++) { if (isDegrees) { r[i] = Geo.makeGeoDegrees(lla[i * 2], lla[i * 2 + 1]); } else { r[i] = Geo.makeGeoRadians(lla[i * 2], lla[i * 2 + 1]); } } return r; } /** * return a float array of alternating lat lon pairs where the first and * last pair are the same, thus closing the path, by adding a point if * needed. Does not mutate the input. */ public static float[] closeLLa(float[] lla) { int l = lla.length; int s = (l / 2) - 1; if (lla[0] == lla[s * 2] && lla[1] == lla[s * 2 + 1]) { return lla; } else { float[] llx = new float[l + 2]; for (int i = 0; i < l; i++) { llx[i] = lla[i]; } llx[l] = lla[0]; llx[l + 1] = lla[1]; return llx; } } /** * return a Geo array where the first and last elements are the same, thus * closing the path, by adding a point if needed. Does not mutate the input. */ public static Geo[] closeGa(Geo[] ga) { int l = ga.length; if (ga[0].equals(ga[l - 1])) { return ga; } else { Geo[] x = new Geo[l + 1]; System.arraycopy(ga, 0, x, 0, l); x[l] = ga[0]; return x; } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?