我有一些限制类型的ax + by> = c(1)和x> = z和y> = k(2)。限制(1)和(2)构成一个区域。我需要找到这些区域的交集并填充其他颜色。我怎么能在JavaFX中做到这一点?我可以使用Canvas来解决这个问题吗?
答案 0 :(得分:0)
当然,只需使用多边形颜色填充所有内容,然后为每个区域填充不在具有背景颜色的区域中的所有内容。
请注意,这样就可以填充整个Canvas
,但背景颜色的多边形除外。
public class Area {
private final double x;
private final double y;
private final double threshold;
private final int minCorner;
public Area(double x, double y, double threshold, boolean greater) {
if (x == 0 && y == 0) {
throw new IllegalArgumentException();
}
if (greater) {
x *= -1;
y *= -1;
threshold *= -1;
}
this.x = x;
this.y = y;
this.threshold = threshold;
boolean yPos = y > 0;
// find corner with minimum result for evaluate
this.minCorner = x < 0 ? (yPos ? 1 : 2) : (yPos ? 0 : 3);
}
public Area(double x, double y, double threshold) {
this(x, y, threshold, false);
}
private static final int[][] CORNER_FACTORS = {
{0, 0},
{1, 0},
{1, 1},
{0, 1}
};
public boolean contains(double x, double y) {
return evaluate(x, y) <= threshold;
}
public double hLineIntersection(double y) {
if (x == 0) {
return this.y * y == threshold ? Double.POSITIVE_INFINITY : Double.NaN;
} else {
return (threshold - this.y * y) / this.x;
}
}
public double vLineIntersection(double x) {
if (y == 0) {
return this.x * x == threshold ? Double.POSITIVE_INFINITY : Double.NaN;
} else {
return (threshold - this.x * x) / this.y;
}
}
private double evaluate(double x, double y) {
return this.x * x + this.y * y;
}
public void fillCleanArea(GraphicsContext gc, double w, double h) {
double[] xcoords = new double[5];
double[] ycoords = new double[5];
int[] factors = CORNER_FACTORS[minCorner];
boolean inside = contains(factors[0] * w, factors[1] * h);
int ptIndex = 0;
for (int i = minCorner, max = minCorner + 4; i < max; i++) {
factors = CORNER_FACTORS[i % 4];
double x = factors[0] * w;
double y = factors[1] * h;
boolean nowInside = contains(x, y);
if (inside != nowInside) {
// add intersection point with side
if ((i & 1) == 0) {
ycoords[ptIndex] = vLineIntersection(x);
xcoords[ptIndex++] = x;
} else {
xcoords[ptIndex] = hLineIntersection(y);
ycoords[ptIndex++] = y;
}
inside = nowInside;
// stop, if the end point is inside the area again
if (inside) {
break;
}
}
// add corners outside the bounds to polygon
if (!inside) {
xcoords[ptIndex] = x;
ycoords[ptIndex++] = y;
}
}
// draw polygon
if (ptIndex > 0) {
gc.fillPolygon(xcoords, ycoords, ptIndex);
}
}
}
public static void draw(Canvas canvas, Paint fill, Paint background, Area... areas) {
GraphicsContext gc = canvas.getGraphicsContext2D();
double w = canvas.getWidth();
double h = canvas.getHeight();
// fill everything with polygon color
gc.setFill(fill);
gc.fillRect(0, 0, w, h);
// fill everything outside the polygon with background color
gc.setFill(background);
for (Area area : areas) {
area.fillCleanArea(gc, w, h);
}
}
@Override
public void start(Stage primaryStage) {
Canvas canvas = new Canvas(400, 400);
draw(canvas, Color.BLUE, Color.WHITE,
new Area(1, 1, 400), new Area(1, -1, 100), new Area(1, -1, -100, true), new Area(1, 2, 250, true));
StackPane root = new StackPane(canvas);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
虽然这不会给你多边形的角点......