在Java中获得QuadCurve2D的真正界限

时间:2010-06-23 15:12:06

标签: java bounds

我想知道如何获得QuadCurve2D的界限。我找到了一种从CubicCurve2D获取边界的方法。

使用此方法可以将其更改为使用QuadCurve2D吗?

    private static void ProcessMonotonicCubic(double[] coords, double[] bbox ) {
        if (bbox[0] > coords[0]) bbox[0] = coords[0];
        if (bbox[1] > coords[1]) bbox[1] = coords[1];
        if (bbox[2] < coords[0]) bbox[2] = coords[0];
        if (bbox[3] < coords[1]) bbox[3] = coords[1];

        if (bbox[0] > coords[6]) bbox[0] = coords[6];
        if (bbox[1] > coords[7]) bbox[1] = coords[7];
        if (bbox[2] < coords[6]) bbox[2] = coords[6];
        if (bbox[3] < coords[7]) bbox[3] = coords[7];
    }

    /*
     * Bite the piece of the cubic curve from start point till the point
     * corresponding to the specified parameter then call ProcessCubic for the
     * bitten part.
     * Note: coords array will be changed
     */
    private static void ProcessFirstMonotonicPartOfCubic(double[] coords,
                                                         double[] bbox,
                                                         double t)
    {
        double[] coords1 = new double[8];
        double tx, ty;

        coords1[0] = coords[0];
        coords1[1] = coords[1];
        tx = coords[2] + t*(coords[4] - coords[2]);
        ty = coords[3] + t*(coords[5] - coords[3]);
        coords1[2] =  coords[0] + t*(coords[2] - coords[0]);
        coords1[3] =  coords[1] + t*(coords[3] - coords[1]);
        coords1[4] = coords1[2] + t*(tx - coords1[2]);
        coords1[5] = coords1[3] + t*(ty - coords1[3]);
        coords[4] = coords[4] + t*(coords[6] - coords[4]);
        coords[5] = coords[5] + t*(coords[7] - coords[5]);
        coords[2] = tx + t*(coords[4] - tx);
        coords[3] = ty + t*(coords[5] - ty);
        coords[0]=coords1[6]=coords1[4] + t*(coords[2] - coords1[4]);
        coords[1]=coords1[7]=coords1[5] + t*(coords[3] - coords1[5]);

        ProcessMonotonicCubic(coords1, bbox);
    }

    /*
     * Split cubic curve into monotonic in X and Y parts. Calling
     * ProcessMonotonicCubic for each monotonic piece of the curve.
     *
     * Note: coords array could be changed
     */
    private static void ProcessCubic(double[] coords, double[] bbox) {
        /* Temporary array for holding parameters corresponding to the extreme
         * in X and Y points
         */
        double params[] = new double[4];
        double eqn[] = new double[3];
        double res[] = new double[2];
        int cnt = 0;

        /* Simple check for monotonicity in X before searching for the extreme
         * points of the X(t) function. We first check if the curve is
         * monotonic in X by seeing if all of the X coordinates are strongly
         * ordered.
         */
        if ((coords[0] > coords[2] || coords[2] > coords[4] ||
             coords[4] > coords[6]) &&
            (coords[0] < coords[2] || coords[2] < coords[4] ||
             coords[4] < coords[6]))
        {
            /* Searching for extreme points of the X(t) function  by solving
             * dX(t)
             * ----  = 0 equation
             *  dt
             */
            eqn[2] = -coords[0] + 3*coords[2] - 3*coords[4] + coords[6];
            eqn[1] = 2*(coords[0] - 2*coords[2] + coords[4]);
            eqn[0] = -coords[0] + coords[2];

            int nr = QuadCurve2D.solveQuadratic(eqn, res);

            /* Following code also correctly works in degenerate case of
             * the quadratic equation (nr = -1) because we do not need
             * splitting in this case.
             */
            for (int i = 0; i < nr; i++) {
                if (res[i] > 0 && res[i] < 1) {
                    params[cnt++] = res[i];
                }
            }
        }

        /* Simple check for monotonicity in Y before searching for the extreme
         * points of the Y(t) function. We first check if the curve is
         * monotonic in Y by seeing if all of the Y coordinates are strongly
         * ordered.
         */
        if ((coords[1] > coords[3] || coords[3] > coords[5] ||
             coords[5] > coords[7]) &&
            (coords[1] < coords[3] || coords[3] < coords[5] ||
             coords[5] < coords[7]))
        {
            /* Searching for extreme points of the Y(t) function by solving
             * dY(t)
             * ----- = 0 equation
             *  dt
             */
            eqn[2] = -coords[1] + 3*coords[3] - 3*coords[5] + coords[7];
            eqn[1] = 2*(coords[1] - 2*coords[3] + coords[5]);
            eqn[0] = -coords[1] + coords[3];

            int nr = QuadCurve2D.solveQuadratic(eqn, res);

            /* Following code also correctly works in degenerate case of
             * the quadratic equation (nr = -1) because we do not need
             * splitting in this case.
             */
            for (int i = 0; i < nr; i++) {
                if (res[i] > 0 && res[i] < 1) {
                    params[cnt++] = res[i];
                }
            }
        }

        if (cnt > 0) {
            /* Sorting parameter values corresponding to the extreme points
             * of the curve
             */
            Arrays.sort(params, 0, cnt);

            /* Processing obtained monotonic parts */
            ProcessFirstMonotonicPartOfCubic(coords, bbox,
                                             (float)params[0]);
            for (int i = 1; i < cnt; i++) {
                double param = params[i] - params[i-1];
                if (param > 0) {
                    ProcessFirstMonotonicPartOfCubic(coords, bbox,
                        /* Scale parameter to match with rest of the curve */
                        (float)(param/(1.0 - params[i - 1])));
                }
            }
        }

        ProcessMonotonicCubic(coords, bbox);
    }

    private Rectangle2D.Double getCurveBounds(CubicCurve2D curve) {
        double minX = Double.MAX_VALUE, minY = Double.MAX_VALUE;
        double maxX = Double.MIN_VALUE, maxY = Double.MIN_VALUE;
        double [] bbox = new double[] {Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Double.MIN_VALUE};
        ProcessCubic(new double[] {curve.getP1().getX(), curve.getP1().getY(),
                     curve.getCtrlP1().getX(), curve.getCtrlP1().getY(), curve.getCtrlP2().getX(),
                     curve.getCtrlP2().getY(), curve.getP2().getX(), curve.getP2().getY()}, bbox);
        return new Rectangle2D.Double(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]);
    }

1 个答案:

答案 0 :(得分:2)

“你对”bounds“一词的使用与getBounds()的结果有何不同?” 获取边界2D抓取控制点,我想要一个不包裹控制点的矩形。

稍微测试一下我发现在同一站点中可以更改为使用QuadCurve2D的另一种方法。 这是代码:

private Rectangle2D.Double getCurveBounds(QuadCurve2D.Double curve) {
    double flatness = 0.01;
    PathIterator pit = curve.getPathIterator(null, flatness);
    double[] coords = new double[2];
    double minX = Double.MAX_VALUE, minY = Double.MAX_VALUE;
    double maxX = Double.MIN_VALUE, maxY = Double.MIN_VALUE;
    while(!pit.isDone()) {
        int type = pit.currentSegment(coords);
        switch(type) {
            case PathIterator.SEG_MOVETO:
                // fall through
            case PathIterator.SEG_LINETO:
                if(coords[0] < minX) minX = coords[0];
                if(coords[0] > maxX) maxX = coords[0];
                if(coords[1] < minY) minY = coords[1];
                if(coords[1] > maxY) maxY = coords[1];
                break;
        }
        pit.next();
    }
    return new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY);
}
希望它对某人有所帮助。 :d