1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
647 * @since 1.2
648 */
649 public static double getFlatness(double x1, double y1,
650 double ctrlx, double ctrly,
651 double x2, double y2) {
652 return Line2D.ptSegDist(x1, y1, x2, y2, ctrlx, ctrly);
653 }
654
655 /**
656 * Returns the square of the flatness, or maximum distance of a
657 * control point from the line connecting the end points, of the
658 * quadratic curve specified by the control points stored in the
659 * indicated array at the indicated index.
660 * @param coords an array containing coordinate values
661 * @param offset the index into {@code coords} from which to
662 * to start getting the values from the array
663 * @return the flatness of the quadratic curve that is defined by the
664 * values in the specified array at the specified index.
665 * @since 1.2
666 */
667 public static double getFlatnessSq(double coords[], int offset) {
668 return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1],
669 coords[offset + 4], coords[offset + 5],
670 coords[offset + 2], coords[offset + 3]);
671 }
672
673 /**
674 * Returns the flatness, or maximum distance of a
675 * control point from the line connecting the end points, of the
676 * quadratic curve specified by the control points stored in the
677 * indicated array at the indicated index.
678 * @param coords an array containing coordinate values
679 * @param offset the index into {@code coords} from which to
680 * start getting the coordinate values
681 * @return the flatness of a quadratic curve defined by the
682 * specified array at the specified offset.
683 * @since 1.2
684 */
685 public static double getFlatness(double coords[], int offset) {
686 return Line2D.ptSegDist(coords[offset + 0], coords[offset + 1],
687 coords[offset + 4], coords[offset + 5],
688 coords[offset + 2], coords[offset + 3]);
689 }
690
691 /**
692 * Returns the square of the flatness, or maximum distance of a
693 * control point from the line connecting the end points, of this
694 * {@code QuadCurve2D}.
695 * @return the square of the flatness of this
696 * {@code QuadCurve2D}.
697 * @since 1.2
698 */
699 public double getFlatnessSq() {
700 return Line2D.ptSegDistSq(getX1(), getY1(),
701 getX2(), getY2(),
702 getCtrlX(), getCtrlY());
703 }
704
705 /**
780 * and offset as the {@code src} array.
781 * Note that the last point in the first subdivided curve is the
782 * same as the first point in the second subdivided curve. Thus,
783 * it is possible to pass the same array for {@code left} and
784 * {@code right} and to use offsets such that
785 * {@code rightoff} equals {@code leftoff} + 4 in order
786 * to avoid allocating extra storage for this common point.
787 * @param src the array holding the coordinates for the source curve
788 * @param srcoff the offset into the array of the beginning of the
789 * the 6 source coordinates
790 * @param left the array for storing the coordinates for the first
791 * half of the subdivided curve
792 * @param leftoff the offset into the array of the beginning of the
793 * the 6 left coordinates
794 * @param right the array for storing the coordinates for the second
795 * half of the subdivided curve
796 * @param rightoff the offset into the array of the beginning of the
797 * the 6 right coordinates
798 * @since 1.2
799 */
800 public static void subdivide(double src[], int srcoff,
801 double left[], int leftoff,
802 double right[], int rightoff) {
803 double x1 = src[srcoff + 0];
804 double y1 = src[srcoff + 1];
805 double ctrlx = src[srcoff + 2];
806 double ctrly = src[srcoff + 3];
807 double x2 = src[srcoff + 4];
808 double y2 = src[srcoff + 5];
809 if (left != null) {
810 left[leftoff + 0] = x1;
811 left[leftoff + 1] = y1;
812 }
813 if (right != null) {
814 right[rightoff + 4] = x2;
815 right[rightoff + 5] = y2;
816 }
817 x1 = (x1 + ctrlx) / 2.0;
818 y1 = (y1 + ctrly) / 2.0;
819 x2 = (x2 + ctrlx) / 2.0;
820 y2 = (y2 + ctrly) / 2.0;
821 ctrlx = (x1 + x2) / 2.0;
822 ctrly = (y1 + y2) / 2.0;
834 }
835 }
836
837 /**
838 * Solves the quadratic whose coefficients are in the {@code eqn}
839 * array and places the non-complex roots back into the same array,
840 * returning the number of roots. The quadratic solved is represented
841 * by the equation:
842 * <pre>
843 * eqn = {C, B, A};
844 * ax^2 + bx + c = 0
845 * </pre>
846 * A return value of {@code -1} is used to distinguish a constant
847 * equation, which might be always 0 or never 0, from an equation that
848 * has no zeroes.
849 * @param eqn the array that contains the quadratic coefficients
850 * @return the number of roots, or {@code -1} if the equation is
851 * a constant
852 * @since 1.2
853 */
854 public static int solveQuadratic(double eqn[]) {
855 return solveQuadratic(eqn, eqn);
856 }
857
858 /**
859 * Solves the quadratic whose coefficients are in the {@code eqn}
860 * array and places the non-complex roots into the {@code res}
861 * array, returning the number of roots.
862 * The quadratic solved is represented by the equation:
863 * <pre>
864 * eqn = {C, B, A};
865 * ax^2 + bx + c = 0
866 * </pre>
867 * A return value of {@code -1} is used to distinguish a constant
868 * equation, which might be always 0 or never 0, from an equation that
869 * has no zeroes.
870 * @param eqn the specified array of coefficients to use to solve
871 * the quadratic equation
872 * @param res the array that contains the non-complex roots
873 * resulting from the solution of the quadratic equation
874 * @return the number of roots, or {@code -1} if the equation is
875 * a constant.
876 * @since 1.3
877 */
878 public static int solveQuadratic(double eqn[], double res[]) {
879 double a = eqn[2];
880 double b = eqn[1];
881 double c = eqn[0];
882 int roots = 0;
883 if (a == 0.0) {
884 // The quadratic parabola has degenerated to a line.
885 if (b == 0.0) {
886 // The line has degenerated to a constant.
887 return -1;
888 }
889 res[roots++] = -c / b;
890 } else {
891 // From Numerical Recipes, 5.6, Quadratic and Cubic Equations
892 double d = b * b - 4.0 * a * c;
893 if (d < 0.0) {
894 // If d < 0.0, then there are no roots
895 return 0;
896 }
897 d = Math.sqrt(d);
898 // For accuracy, calculate one root using:
1019 * {@inheritDoc}
1020 * @since 1.2
1021 */
1022 public boolean contains(Point2D p) {
1023 return contains(p.getX(), p.getY());
1024 }
1025
1026 /**
1027 * Fill an array with the coefficients of the parametric equation
1028 * in t, ready for solving against val with solveQuadratic.
1029 * We currently have:
1030 * val = Py(t) = C1*(1-t)^2 + 2*CP*t*(1-t) + C2*t^2
1031 * = C1 - 2*C1*t + C1*t^2 + 2*CP*t - 2*CP*t^2 + C2*t^2
1032 * = C1 + (2*CP - 2*C1)*t + (C1 - 2*CP + C2)*t^2
1033 * 0 = (C1 - val) + (2*CP - 2*C1)*t + (C1 - 2*CP + C2)*t^2
1034 * 0 = C + Bt + At^2
1035 * C = C1 - val
1036 * B = 2*CP - 2*C1
1037 * A = C1 - 2*CP + C2
1038 */
1039 private static void fillEqn(double eqn[], double val,
1040 double c1, double cp, double c2) {
1041 eqn[0] = c1 - val;
1042 eqn[1] = cp + cp - c1 - c1;
1043 eqn[2] = c1 - cp - cp + c2;
1044 return;
1045 }
1046
1047 /**
1048 * Evaluate the t values in the first num slots of the vals[] array
1049 * and place the evaluated values back into the same array. Only
1050 * evaluate t values that are within the range <0, 1>, including
1051 * the 0 and 1 ends of the range iff the include0 or include1
1052 * booleans are true. If an "inflection" equation is handed in,
1053 * then any points which represent a point of inflection for that
1054 * quadratic equation are also ignored.
1055 */
1056 private static int evalQuadratic(double vals[], int num,
1057 boolean include0,
1058 boolean include1,
1059 double inflect[],
1060 double c1, double ctrl, double c2) {
1061 int j = 0;
1062 for (int i = 0; i < num; i++) {
1063 double t = vals[i];
1064 if ((include0 ? t >= 0 : t > 0) &&
1065 (include1 ? t <= 1 : t < 1) &&
1066 (inflect == null ||
1067 inflect[1] + 2*inflect[2]*t != 0))
1068 {
1069 double u = 1 - t;
1070 vals[j++] = c1*u*u + 2*ctrl*t*u + c2*t*t;
1071 }
1072 }
1073 return j;
1074 }
1075
1076 private static final int BELOW = -2;
1077 private static final int LOWEDGE = -1;
1078 private static final int INSIDE = 0;
1079 private static final int HIGHEDGE = 1;
|
1 /*
2 * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
647 * @since 1.2
648 */
649 public static double getFlatness(double x1, double y1,
650 double ctrlx, double ctrly,
651 double x2, double y2) {
652 return Line2D.ptSegDist(x1, y1, x2, y2, ctrlx, ctrly);
653 }
654
655 /**
656 * Returns the square of the flatness, or maximum distance of a
657 * control point from the line connecting the end points, of the
658 * quadratic curve specified by the control points stored in the
659 * indicated array at the indicated index.
660 * @param coords an array containing coordinate values
661 * @param offset the index into {@code coords} from which to
662 * to start getting the values from the array
663 * @return the flatness of the quadratic curve that is defined by the
664 * values in the specified array at the specified index.
665 * @since 1.2
666 */
667 public static double getFlatnessSq(double[] coords, int offset) {
668 return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1],
669 coords[offset + 4], coords[offset + 5],
670 coords[offset + 2], coords[offset + 3]);
671 }
672
673 /**
674 * Returns the flatness, or maximum distance of a
675 * control point from the line connecting the end points, of the
676 * quadratic curve specified by the control points stored in the
677 * indicated array at the indicated index.
678 * @param coords an array containing coordinate values
679 * @param offset the index into {@code coords} from which to
680 * start getting the coordinate values
681 * @return the flatness of a quadratic curve defined by the
682 * specified array at the specified offset.
683 * @since 1.2
684 */
685 public static double getFlatness(double[] coords, int offset) {
686 return Line2D.ptSegDist(coords[offset + 0], coords[offset + 1],
687 coords[offset + 4], coords[offset + 5],
688 coords[offset + 2], coords[offset + 3]);
689 }
690
691 /**
692 * Returns the square of the flatness, or maximum distance of a
693 * control point from the line connecting the end points, of this
694 * {@code QuadCurve2D}.
695 * @return the square of the flatness of this
696 * {@code QuadCurve2D}.
697 * @since 1.2
698 */
699 public double getFlatnessSq() {
700 return Line2D.ptSegDistSq(getX1(), getY1(),
701 getX2(), getY2(),
702 getCtrlX(), getCtrlY());
703 }
704
705 /**
780 * and offset as the {@code src} array.
781 * Note that the last point in the first subdivided curve is the
782 * same as the first point in the second subdivided curve. Thus,
783 * it is possible to pass the same array for {@code left} and
784 * {@code right} and to use offsets such that
785 * {@code rightoff} equals {@code leftoff} + 4 in order
786 * to avoid allocating extra storage for this common point.
787 * @param src the array holding the coordinates for the source curve
788 * @param srcoff the offset into the array of the beginning of the
789 * the 6 source coordinates
790 * @param left the array for storing the coordinates for the first
791 * half of the subdivided curve
792 * @param leftoff the offset into the array of the beginning of the
793 * the 6 left coordinates
794 * @param right the array for storing the coordinates for the second
795 * half of the subdivided curve
796 * @param rightoff the offset into the array of the beginning of the
797 * the 6 right coordinates
798 * @since 1.2
799 */
800 public static void subdivide(double[] src, int srcoff,
801 double[] left, int leftoff,
802 double[] right, int rightoff) {
803 double x1 = src[srcoff + 0];
804 double y1 = src[srcoff + 1];
805 double ctrlx = src[srcoff + 2];
806 double ctrly = src[srcoff + 3];
807 double x2 = src[srcoff + 4];
808 double y2 = src[srcoff + 5];
809 if (left != null) {
810 left[leftoff + 0] = x1;
811 left[leftoff + 1] = y1;
812 }
813 if (right != null) {
814 right[rightoff + 4] = x2;
815 right[rightoff + 5] = y2;
816 }
817 x1 = (x1 + ctrlx) / 2.0;
818 y1 = (y1 + ctrly) / 2.0;
819 x2 = (x2 + ctrlx) / 2.0;
820 y2 = (y2 + ctrly) / 2.0;
821 ctrlx = (x1 + x2) / 2.0;
822 ctrly = (y1 + y2) / 2.0;
834 }
835 }
836
837 /**
838 * Solves the quadratic whose coefficients are in the {@code eqn}
839 * array and places the non-complex roots back into the same array,
840 * returning the number of roots. The quadratic solved is represented
841 * by the equation:
842 * <pre>
843 * eqn = {C, B, A};
844 * ax^2 + bx + c = 0
845 * </pre>
846 * A return value of {@code -1} is used to distinguish a constant
847 * equation, which might be always 0 or never 0, from an equation that
848 * has no zeroes.
849 * @param eqn the array that contains the quadratic coefficients
850 * @return the number of roots, or {@code -1} if the equation is
851 * a constant
852 * @since 1.2
853 */
854 public static int solveQuadratic(double[] eqn) {
855 return solveQuadratic(eqn, eqn);
856 }
857
858 /**
859 * Solves the quadratic whose coefficients are in the {@code eqn}
860 * array and places the non-complex roots into the {@code res}
861 * array, returning the number of roots.
862 * The quadratic solved is represented by the equation:
863 * <pre>
864 * eqn = {C, B, A};
865 * ax^2 + bx + c = 0
866 * </pre>
867 * A return value of {@code -1} is used to distinguish a constant
868 * equation, which might be always 0 or never 0, from an equation that
869 * has no zeroes.
870 * @param eqn the specified array of coefficients to use to solve
871 * the quadratic equation
872 * @param res the array that contains the non-complex roots
873 * resulting from the solution of the quadratic equation
874 * @return the number of roots, or {@code -1} if the equation is
875 * a constant.
876 * @since 1.3
877 */
878 public static int solveQuadratic(double[] eqn, double[] res) {
879 double a = eqn[2];
880 double b = eqn[1];
881 double c = eqn[0];
882 int roots = 0;
883 if (a == 0.0) {
884 // The quadratic parabola has degenerated to a line.
885 if (b == 0.0) {
886 // The line has degenerated to a constant.
887 return -1;
888 }
889 res[roots++] = -c / b;
890 } else {
891 // From Numerical Recipes, 5.6, Quadratic and Cubic Equations
892 double d = b * b - 4.0 * a * c;
893 if (d < 0.0) {
894 // If d < 0.0, then there are no roots
895 return 0;
896 }
897 d = Math.sqrt(d);
898 // For accuracy, calculate one root using:
1019 * {@inheritDoc}
1020 * @since 1.2
1021 */
1022 public boolean contains(Point2D p) {
1023 return contains(p.getX(), p.getY());
1024 }
1025
1026 /**
1027 * Fill an array with the coefficients of the parametric equation
1028 * in t, ready for solving against val with solveQuadratic.
1029 * We currently have:
1030 * val = Py(t) = C1*(1-t)^2 + 2*CP*t*(1-t) + C2*t^2
1031 * = C1 - 2*C1*t + C1*t^2 + 2*CP*t - 2*CP*t^2 + C2*t^2
1032 * = C1 + (2*CP - 2*C1)*t + (C1 - 2*CP + C2)*t^2
1033 * 0 = (C1 - val) + (2*CP - 2*C1)*t + (C1 - 2*CP + C2)*t^2
1034 * 0 = C + Bt + At^2
1035 * C = C1 - val
1036 * B = 2*CP - 2*C1
1037 * A = C1 - 2*CP + C2
1038 */
1039 private static void fillEqn(double[] eqn, double val,
1040 double c1, double cp, double c2) {
1041 eqn[0] = c1 - val;
1042 eqn[1] = cp + cp - c1 - c1;
1043 eqn[2] = c1 - cp - cp + c2;
1044 return;
1045 }
1046
1047 /**
1048 * Evaluate the t values in the first num slots of the vals[] array
1049 * and place the evaluated values back into the same array. Only
1050 * evaluate t values that are within the range <0, 1>, including
1051 * the 0 and 1 ends of the range iff the include0 or include1
1052 * booleans are true. If an "inflection" equation is handed in,
1053 * then any points which represent a point of inflection for that
1054 * quadratic equation are also ignored.
1055 */
1056 private static int evalQuadratic(double[] vals, int num,
1057 boolean include0,
1058 boolean include1,
1059 double[] inflect,
1060 double c1, double ctrl, double c2) {
1061 int j = 0;
1062 for (int i = 0; i < num; i++) {
1063 double t = vals[i];
1064 if ((include0 ? t >= 0 : t > 0) &&
1065 (include1 ? t <= 1 : t < 1) &&
1066 (inflect == null ||
1067 inflect[1] + 2*inflect[2]*t != 0))
1068 {
1069 double u = 1 - t;
1070 vals[j++] = c1*u*u + 2*ctrl*t*u + c2*t*t;
1071 }
1072 }
1073 return j;
1074 }
1075
1076 private static final int BELOW = -2;
1077 private static final int LOWEDGE = -1;
1078 private static final int INSIDE = 0;
1079 private static final int HIGHEDGE = 1;
|