T_01
T_01

Reputation: 1379

Get all pixels between two pixels

Im writing a small painting programm in java, and im stucked on the pen:

Therory: When im dragging the mouse i have to fill the circles between P(draggedX|draggedY) and P2(mouseX|mouseY) with circles. So i have to create a line / a path (?..) and calculate all points that are on it.

What ive tried:

double m = 0;
int width = draggedX - mouseX;
int height = draggedY - mouseY;
if(draggedX - mouseX != 0){
    m = (draggedY - mouseY) / (draggedX - mouseX);
}
if(width > 0){
    for(int i = 0; i < width; i++) {
        double x = mouseX + i;
        double y = mouseY + (m * i);
        g.fillOval((int) x, (int) y, 5, 5);
    }
}
else if(width < 0){
    for(int i = -width; i > 0; i--) {
        double x = mouseX + i;
        double y = mouseY + (m * i);
        g.fillOval((int) x, (int) y, 5, 5);
    }
}
else{
    if(height > 0){
        for(int i = 0; i < height; i++){
            g.fillOval(mouseX, (int) i + mouseY, 5, 5);
        }
    }
    else if(height < 0){
        for(int i = -height; i > 0; i--){
            g.fillOval(mouseX, (int) i + mouseY, 5, 5);
        }
    }
}

It didnt work correct. sometimes curious lines splashed up and circles werent painted, like this:

paint fail

Any other ideas, how to solve it? Thank you!

Upvotes: 1

Views: 798

Answers (3)

tucuxi
tucuxi

Reputation: 17945

Java will not generate events for all intermediate points - you can test this by drawing a point at each place where you actually receive an event. If the mouse moves too quickly, you will miss points. This happens in all drawing programs.

Bresenham's line-drawing algorithm is the traditional way to find integer pixels between two pixels coordinates. But you are programming in Java, and you have something much better: you can trace arbitrary paths, defined through coordinates. Two flavors are available,

The old Graphics version (g is a Graphics, possibly from your paintComponent() method):

// uses current g.setColor(color)
g.drawPolyline(xPoints, yPoints, int nPoints); // xPoints and yPoints are integer arrays

And the new Shape-based version (g2d is a Graphics2D; your Graphics in Swing can be cast to Graphics2D without problems):

// uses current stroke
g2d.draw(p); // p is a Path2D, build with successive moveTo(point) and lineTo(point)

I recommend the second version, since the stroke offers a lot more flexibility (line width, dashes, ...) than just simple colors

Upvotes: 1

user1118321
user1118321

Reputation: 26395

In addition to what the other answer said, you also need to do your drawing differently if the absolute value of m is greater than 1 or not. If it's 1 or less, then you'll want to iterate along the x direction and calculate the y from the slope. Otherwise, you'll need to iterate along the y direction and calculate the m from the (inverse) slope. You have the right idea in the code, but it's not quite implemented correctly. It should be something more like this:

if (abs(m) <= 1)
{
    for (int i = startX; i < endX; i++)
    {
        float y = startY + (float)i * m;
        float x = i;
        g.fillOval(x, y, 5, 5);
    }
}
else
{
    for (int i = startY; i < endY; i++)
    {
        float x = startX + (float)i / m;
        float y = i;
        g.fillOval(x, y, 5, 5);
    }
}

Upvotes: 0

Joni
Joni

Reputation: 111349

The division between two integers discards the fractional part: for example 2/3 returns 0. You can use floating point types for computation to keep the fractional parts.

double m;
m = (double) (draggedY - mouseY) / (draggedX - mouseX);

Upvotes: 0

Related Questions