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