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 + -
显示快捷键?