quadcurve2d.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 676 行 · 第 1/2 页

JAVA
676
字号
		// of the rectangle crosses it horizontally - trivially accept
		if (c1tag * c2tag <= 0) {
			return true;
		}

		// Now we know that both the X and Y ranges intersect and that
		// the endpoint line segment does not directly cross the rectangle.
		//
		// We can almost treat this case like one of the cases above
		// where both endpoints are to one side, except that we will
		// only get one intersection of the curve with the vertical
		// side of the rectangle. This is because the endpoint segment
		// accounts for the other intersection.
		//
		// (Remember there is overlap in both the X and Y ranges which
		//  means that the segment must cross at least one vertical edge
		//  of the rectangle - in particular, the "near vertical side" -
		//  leaving only one intersection for the curve.)
		//
		// Now we calculate the y tags of the two intersections on the
		// "near vertical side" of the rectangle. We will have one with
		// the endpoint segment, and one with the curve. If those two
		// vertical intersections overlap the Y range of the rectangle,
		// we have an intersection. Otherwise, we don't.

		// c1tag = vertical intersection class of the endpoint segment
		//
		// Choose the y tag of the endpoint that was not on the same
		// side of the rectangle as the subsegment calculated above.
		// Note that we can "steal" the existing Y tag of that endpoint
		// since it will be provably the same as the vertical intersection.
		c1tag = ((c1tag * x1tag <= 0) ? y1tag : y2tag);

		// c2tag = vertical intersection class of the curve
		//
		// We have to calculate this one the straightforward way.
		// Note that the c2tag can still tell us which vertical edge
		// to test against.
		fillEqn(eqn, (c2tag < INSIDE ? x : x + w), x1, ctrlx, x2);
		int num = solveQuadratic(eqn, res);

		// Note: We should be able to assert(num == 2); since the
		// X range "crosses" (not touches) the vertical boundary,
		// but we pass num to evalQuadratic for completeness.
		evalQuadratic(res, num, true, true, null, y1, ctrly, y2);

		// Note: We can assert(num evals == 1); since one of the
		// 2 crossings will be out of the [0,1] range.
		c2tag = getTag(res[0], y, y + h);

		// Finally, we have an intersection if the two crossings
		// overlap the Y range of the rectangle.
		return (c1tag * c2tag <= 0);
	}

	private static final int BELOW = -2;
	private static final int LOWEDGE = -1;
	private static final int INSIDE = 0;
	private static final int HIGHEDGE = 1;
	private static final int ABOVE = 2;

	/*
	 * Determine where coord lies with respect to the range from low to high. It is assumed that low <= high.  The return value is one of the 5 values BELOW, LOWEDGE, INSIDE, HIGHEDGE, or ABOVE.
	 */
	private static int getTag(double coord, double low, double high) {
		if (coord <= low) {
			return (coord < low ? BELOW : LOWEDGE);
		}
		if (coord >= high) {
			return (coord > high ? ABOVE : HIGHEDGE);
		}
		return INSIDE;
	}

	/*
	 * Determine if the pttag represents a coordinate that is already in its test range, or is on the border with either of the two opttags representing another coordinate that is "towards the
	 * inside" of that test range. In other words, are either of the two "opt" points "drawing the pt inward"?
	 */
	private static boolean inwards(int pttag, int opt1tag, int opt2tag) {
		switch (pttag) {
			case BELOW :
			case ABOVE :
			default :
				return false;
			case LOWEDGE :
				return (opt1tag >= INSIDE || opt2tag >= INSIDE);
			case INSIDE :
				return true;
			case HIGHEDGE :
				return (opt1tag <= INSIDE || opt2tag <= INSIDE);
		}
	}

	public boolean intersects(Rectangle2D r) {
		return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
	}

	public boolean contains(double x, double y, double w, double h) {
		return (contains(x, y) && contains(x + w, y) && contains(x + w, y + h) && contains(x, y + h));
	}

	public boolean contains(Rectangle2D r) {
		return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
	}

	public Rectangle getBounds() {
		return getBounds2D().getBounds();
	}

	public PathIterator getPathIterator(final AffineTransform at) {
		return new PathIterator() {
			/** Current coordinate. */
			private int current;

			public int getWindingRule() {
				return WIND_NON_ZERO;
			}

			public boolean isDone() {
				return current < 2;
			}

			public void next() {
				current++;
			}

			public int currentSegment(float[] coords) {
				if (current == 0) {
					coords[0] = (float) getX1();
					coords[1] = (float) getY1();
					if (at != null)
						at.transform(coords, 0, coords, 0, 1);
					return SEG_MOVETO;
				}
				if (current == 1) {
					coords[0] = (float) getCtrlX();
					coords[1] = (float) getCtrlY();
					coords[2] = (float) getX2();
					coords[3] = (float) getY2();
					if (at != null)
						at.transform(coords, 0, coords, 0, 2);
					return SEG_QUADTO;
				}
				throw new NoSuchElementException("quad iterator out of bounds");
			}

			public int currentSegment(double[] coords) {
				if (current == 0) {
					coords[0] = getX1();
					coords[1] = getY1();
					if (at != null)
						at.transform(coords, 0, coords, 0, 1);
					return SEG_MOVETO;
				}
				if (current == 1) {
					coords[0] = getCtrlX();
					coords[1] = getCtrlY();
					coords[2] = getX2();
					coords[3] = getY2();
					if (at != null)
						at.transform(coords, 0, coords, 0, 2);
					return SEG_QUADTO;
				}
				throw new NoSuchElementException("quad iterator out of bounds");
			}
		};
	}
	public PathIterator getPathIterator(AffineTransform at, double flatness) {
		return new FlatteningPathIterator(getPathIterator(at), flatness);
	}

	/**
	 * Create a new curve of the same run-time type with the same contents as this one.
	 * 
	 * @return the clone
	 * 
	 * @exception OutOfMemoryError
	 *                If there is not enough memory available.
	 * 
	 * @since 1.2
	 */
	public Object clone() {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			throw (Error) new InternalError().initCause(e); // Impossible
		}
	}

	/**
	 * STUBS ONLY
	 */
	public static class Double extends QuadCurve2D {
		public double x1;
		public double y1;
		public double ctrlx;
		public double ctrly;
		public double x2;
		public double y2;

		public Double() {
		}

		public Double(double x1, double y1, double cx, double cy, double x2, double y2) {
			this.x1 = x1;
			this.y1 = y1;
			ctrlx = cx;
			ctrly = cy;
			this.x2 = x2;
			this.y2 = y2;
		}

		public double getX1() {
			return x1;
		}
		public double getY1() {
			return y1;
		}
		public Point2D getP1() {
			return new Point2D.Double(x1, y1);
		}

		public double getCtrlX() {
			return ctrlx;
		}
		public double getCtrlY() {
			return ctrly;
		}
		public Point2D getCtrlPt() {
			return new Point2D.Double(ctrlx, ctrly);
		}

		public double getX2() {
			return x2;
		}
		public double getY2() {
			return y2;
		}
		public Point2D getP2() {
			return new Point2D.Double(x2, y2);
		}

		public void setCurve(double x1, double y1, double cx, double cy, double x2, double y2) {
			this.x1 = x1;
			this.y1 = y1;
			ctrlx = cx;
			ctrly = cy;
			this.x2 = x2;
			this.y2 = y2;
		}
		public Rectangle2D getBounds2D() {
			double nx1 = Math.min(Math.min(x1, ctrlx), x2);
			double ny1 = Math.min(Math.min(y1, ctrly), y2);
			double nx2 = Math.max(Math.max(x1, ctrlx), x2);
			double ny2 = Math.max(Math.max(y1, ctrly), y2);
			return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1);
		}
	} // class Double

	/**
	 * STUBS ONLY
	 */
	public static class Float extends QuadCurve2D {
		public float x1;
		public float y1;
		public float ctrlx;
		public float ctrly;
		public float x2;
		public float y2;

		public Float() {
		}

		public Float(float x1, float y1, float cx, float cy, float x2, float y2) {
			this.x1 = x1;
			this.y1 = y1;
			ctrlx = cx;
			ctrly = cy;
			this.x2 = x2;
			this.y2 = y2;
		}

		public double getX1() {
			return x1;
		}
		public double getY1() {
			return y1;
		}
		public Point2D getP1() {
			return new Point2D.Float(x1, y1);
		}

		public double getCtrlX() {
			return ctrlx;
		}
		public double getCtrlY() {
			return ctrly;
		}
		public Point2D getCtrlPt() {
			return new Point2D.Float(ctrlx, ctrly);
		}

		public double getX2() {
			return x2;
		}
		public double getY2() {
			return y2;
		}
		public Point2D getP2() {
			return new Point2D.Float(x2, y2);
		}

		public void setCurve(double x1, double y1, double cx, double cy, double x2, double y2) {
			this.x1 = (float) x1;
			this.y1 = (float) y1;
			ctrlx = (float) cx;
			ctrly = (float) cy;
			this.x2 = (float) x2;
			this.y2 = (float) y2;
		}
		public void setCurve(float x1, float y1, float cx, float cy, float x2, float y2) {
			this.x1 = x1;
			this.y1 = y1;
			ctrlx = cx;
			ctrly = cy;
			this.x2 = x2;
			this.y2 = y2;
		}
		public Rectangle2D getBounds2D() {
			float nx1 = Math.min(Math.min(x1, ctrlx), x2);
			float ny1 = Math.min(Math.min(y1, ctrly), y2);
			float nx2 = Math.max(Math.max(x1, ctrlx), x2);
			float ny2 = Math.max(Math.max(y1, ctrly), y2);
			return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1);
		}
	} // class Float
} // class CubicCurve2D

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?