我想画一个"像素化" Java中的一行。这是我的意思的一个例子"像素化"行:
这是我的代码试图做的。假设该行从(x1, y1)
到(x2, y2)
并且我想要一行10"块"它们之间的长度(我称之为像素,但它们将使用许多像素显示):
(x1, y1)
为(0, 0)
且宽度为x2 - x1
且高度为y2 - y1
的矩形。cOriginal
。grid
。(0, 0)
到左下角,标记作为行的一部分的网格空间为true
。我确信我的Bresenham算法适用于所有象限和所有情况。这是我有点模糊的部分。目前,我首先定义了2个"向上扩展"网格。这些定义如下:
float widthScalingFactor =(float)widthOriginal /(float)newWidth; float heightScalingFactor =(float)heightOriginal /(float)newHeight;
(我不知道为什么不格式化...)接下来我循环grid
如果grid[i][j]
(是true
),我绘制一个宽度和高度为的矩形10 (x1 + (i * widthScalingFactor), yOffset + (j * heightScalingFactor))
。
这是目前的方法:
public static void drawPixelatedLine(Graphics g, int x1, int y1, int x2, int y2) {
int widthOriginal = x2 - x1;
int heightOriginal = y2 - y1;
if(widthOriginal <= 0 && heightOriginal <= 0){
int temp = x2;
x2 = x1;
x1 = temp;
temp = y2;
y2 = y1;
y1 = temp;
}
double cOriginal = Math.sqrt(widthOriginal * widthOriginal + heightOriginal * heightOriginal);
double shrinkingFactor = 10d / cOriginal;
int newWidth = (int) Math.round(shrinkingFactor * widthOriginal);
int newHeight = (int) Math.round(shrinkingFactor * heightOriginal);
newWidth = (newWidth <= 0 ? 1 : newWidth);
newHeight = (newHeight <= 0 ? 1 : newHeight);
boolean[][] grid = new boolean[newWidth][newHeight];
int rescaledX1 = 0;
int rescaledY1 = 0;
int rescaledX2 = newWidth - 1;
int rescaledY2 = newHeight - 1;
int x = rescaledX1;
int y = rescaledY1;
int dx = Math.abs(rescaledX2 - rescaledX1);
int dy = Math.abs(rescaledY2 - rescaledY1);
int s1 = Utils.sign(rescaledX2 - rescaledX1);
int s2 = Utils.sign(rescaledY2 - rescaledY1);
boolean swap = false;
if (dy > dx) {
int temp = dx;
dx = dy;
dy = temp;
swap = true;
}
int D = 2 * dy - dx;
for (int i = 0; i < dx; i += 1) {
grid[x][y] = true;
while (D >= 0) {
D = D - 2 * dx;
if (swap) {
x += s1;
}
else {
y += s2;
}
}
D = D + 2 * dy;
if (swap) {
y += s2;
}
else {
x += s1;
}
}
int xOffset = x1;
int yOffset = y1;
float widthScalingFactor = (float) widthOriginal / (float) newWidth;
float heightScalingFactor = (float) heightOriginal / (float) newHeight;
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(grid[i][j]){
g.fillRect((int) (xOffset + (i * widthScalingFactor)), (int) (yOffset + (j * heightScalingFactor)), 10, 10);
}
}
}
现在这个代码部分工作在任何基本方向和西北和东南方向绘制时,虽然我绘制的矩形的大小似乎是错误的(这可能是因为我试图绘制10个大小为10的正方形距离可能超过~140像素。但是,当我尝试画一条东北或西南的线时,它只画一条水平线。这里有一些例子。
这是一条向东北方向行的线路,你可以看到它只是一条直线,从原点到目的地的x位置。当向西南方向绘制线条时会发生类似的事情,除非它向南移动并停在目的地的y位置。
目前,你可以看到这条线是否向西北方向移动,我只是翻转了2个点,所以它向东南方向移动。但是,我觉得我目前的方法并不是很正确,需要进行大量修改才能适应最后两种情况。
如何修改我当前的算法或创建一个新的算法来绘制像素化的#34;线吗
答案 0 :(得分:3)
此代码演示了一种方法,其中所有坐标都缩放到较低的分辨率,然后以较低的分辨率绘制线,同时在绘图(x,y)函数中再次放大。
明显的副作用是线端点受到舍入(实际上是截断)到较低分辨率。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class BresenhamBlocky {
static class TestPanel extends JPanel {
public TestPanel() {
setPreferredSize(new Dimension(800, 800));
}
@Override
protected void paintComponent(final Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
g.setColor(Color.GRAY);
g.fillRect(0, 0, w, h);
g.setColor(Color.BLUE);
drawLine(g, w >> 1, h >> 1, targetX, targetY, 10);
}
}
public static void main(String[] argv) {
SwingUtilities.invokeLater(() -> { showTest(); });
}
static int targetX, targetY;
static void showTest() {
JFrame frame = new JFrame("Test");
JComponent test = new TestPanel();
test.setFocusable(true);
test.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
targetX = e.getX();
targetY = e.getY();
e.getComponent().repaint();
}
});
frame.setLayout(new BorderLayout());
frame.add(test, BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public static void drawLine(Graphics g, int x0, int y0, int x1, int y1, int blockSize) {
int scaledX0 = x0 / blockSize;
int scaledY0 = y0 / blockSize;
int scaledX1 = x1 / blockSize;
int scaledY1 = y1 / blockSize;
int dx = scaledX1 - scaledX0;
int dy = scaledY1 - scaledY0;
int stepX = Integer.signum(dx);
int stepY = Integer.signum(dy);
dx = Math.abs(dx);
dy = Math.abs(dy);
int dx2 = dx << 1;
int dy2 = dy << 1;
int x = scaledX0;
int y = scaledY0;
int error;
if (dx >= dy) {
error = dy2 - dx;
do {
plot(g, x, y, blockSize);
if (error > 0) {
y += stepY;
error -= dx2;
}
error += dy2;
x += stepX;
} while (x != scaledX1);
} else {
error = dx2 - dy;
do {
plot(g, x, y, blockSize);
if (error > 0) {
x += stepX;
error -= dy2;
}
error += dx2;
y += stepY;
} while (y != scaledY1);
}
}
static void plot(Graphics g, int x, int y, int blockSize) {
int x0 = x * blockSize;
int y0 = y * blockSize;
int w = blockSize;
int h = blockSize;
g.fillRect(x0, y0, w, h);
}
}
(使用鼠标单击移动线的一个端点)