Sign in to follow this  
mark-w

drawing a 2D line

Recommended Posts

Hi, I have a 2D point I want to draw a line from. I know the length I need to draw, and the slope. I'm not sure how to go about doing this. I could keep drawing line segments at the given slope, and keep checking if I've overstepped the terminating length, but that doesn't seem like an efficient way to do it. Any ideas? Thanks, Mark

Share this post


Link to post
Share on other sites
Given that the slope is b = dy/dx, you should be able to calculate a target point as follows (you didn't mention a language, but I'll assume C/C++):
float dx = 1.0f;
float dy = b;
float length = std::sqrt(1.0f+dy*dy);
dy /= length;
dx /= length;
float target_x = start_x + dx * line_length;
float target_y = start_y + dy * line_length;
DrawLine(start_x, start_y, target_x, target_y); // You supply this function
I may have made a mistake somewhere, but something like that should work. That said, I would suggest not using a slope representation for the line if you can at all avoid it, since it doesn't handle lines with arbitrary orientation in a uniform manner.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Surely your graphics library does this for you? DX can draw 3D lines (just use a non-transforming shader), GDI+ has DrawLine, and I don't know about OpenGL, but I'm sure there's something.

Share this post


Link to post
Share on other sites
Hi jyk,

Thanks for a fast reply. What would you recommend instead of a slope to represent the line?

I'm trying to perform a rotation of a 2D line around its center point. I'm figuring if the user grabs an end point of the line, then moves the mouse to some arbitrary location,

line center = 5,5
line length = 20;

user moves mouse to screen point

34,28

then I can draw both halves of the line appearing as if it rotated by drawing a line from the center point at the slope:

29,23

so I draw a line from the center point at the above slope with a length of (20/2).

Sound good, bad? What do you think?

Thanks

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Surely your graphics library does this for you? DX can draw 3D lines (just use a non-transforming shader), GDI+ has DrawLine, and I don't know about OpenGL, but I'm sure there's something.
Well, he wants to draw a line using a start point and a slope, and at least some of the above APIs don't have any direct support for this.

Share this post


Link to post
Share on other sites
Quote:
Original post by mark-w
Hi jyk,

Thanks for a fast reply. What would you recommend instead of a slope to represent the line?

I'm trying to perform a rotation of a 2D line around its center point. I'm figuring if the user grabs an end point of the line, then moves the mouse to some arbitrary location,

line center = 5,5
line length = 20;

user moves mouse to screen point

34,28

then I can draw both halves of the line appearing as if it rotated by drawing a line from the center point at the slope:

29,23

so I draw a line from the center point at the above slope with a length of (20/2).

Sound good, bad? What do you think?

Thanks
I didn't quite follow all that, but one way or another you'll want to look into vectors (if you're not already familiar with them). There are some articles here on gdnet you could check out if you're new to vector math.

Also, what API are you using for drawing?

Share this post


Link to post
Share on other sites
When I did the exact same thing, drawing a line that needed to have its ends dragged, I just kept track of the two endpoints. Then, DrawLine(x1, y1, x2, y2) (if you have a funciton like that). What language / line-drawing routines do you have available to you?

EDIT: Oh, around it's center point... I would still keep track of the endpoint you're dragging, and subtract (2*x_offset) and (2*y_offset) from the x and y coordinate of it, respectively, to get the other tip of the line. (Where (x_offset) = (x coord of mouse - x coord of center) and (y_offset) = (y coord of mouse - y coord of center)).

Share this post


Link to post
Share on other sites
Yeah sorry this is a little funky. If I know the user clicked on the end point of my line, then they drag the mouse to some other location on the screen - how could I rotate all the points in the line?

The method I came up with just uses the slope from the center point of the line to the point the user has their mouse at - and keeps filling those points in up until the length of the line is reached.

I'm using GDI, there's no rotate line function. If anyone knows how to rotate a line using only the two end points that would be great. I have to make sure the center point remains in place during the rotation and that the length of the line doesn't change during rotation,

Thanks

Share this post


Link to post
Share on other sites
Quote:
Original post by mark-w
The method I came up with just uses the slope from the center point of the line to the point the user has their mouse at - and keeps filling those points in up until the length of the line is reached.


Yeh, I guess that's pretty much what I said in my EDIT above (minus the "filling in each point"... you shouldn't have to do that much work in GDI).

Quote:
Original post by mark-w
I'm using GDI, there's no rotate line function.


But is there a line drawing routine? Or are you calculating + drawing one dot at a time? If the latter, you should go with Bresenham's, as mentioned above. But that's kinda low-level for GDI.

EDIT: Drawing a line in GDI.

Share this post


Link to post
Share on other sites
Yeah hmm I guess I need a function that just looks like:


void ConnectPoints(xStart, yStart, int nRise, int nRun, int nLength)
{
// In here points keep getting added starting at xStart/yStart at
// the passed rise/run until the passed length is reached.
// ...
}


I have a function which implements Bresenhams line drawing algorithm, but it takes a start point and an end point and fills the points in between. Here the problem is I know the start point but not the end point - but I have the slope and the length the line should be.

Share this post


Link to post
Share on other sites
Quote:
Original post by mark-w
Yeah hmm I guess I need a function that just looks like:


void ConnectPoints(xStart, yStart, int nRise, int nRun, int nLength)
{
// In here points keep getting added starting at xStart/yStart at
// the passed rise/run until the passed length is reached.
// ...
}


I have a function which implements Bresenhams line drawing algorithm, but it takes a start point and an end point and fills the points in between. Here the problem is I know the start point but not the end point - but I have the slope and the length the line should be.
Looking at the link posted previously, it looks like GDI has functions available for drawing a line from one point to another. Why do you want to do it manually as in your above example?

In any case, I would again recommend vectors over the slope form. Just calculate the vector from the line center to the mouse position, normalize it, scale it by half of the line length (we'll call the resulting vector direction), and draw a line from start to start - direction, and from start to start + direction.

If you're intent on the slope approach, check out my first reply, which shows how to compute the end points of the line from this information.

Share this post


Link to post
Share on other sites
jyk, my problem is that I don't know what the second point is - I only have the first point, the slope, and the length it should be - from those I'm hoping to figure out what that second point is - then I can use GDI to draw the actual line (it needs to be supplied with start point and end point to work).

I can use vectors to do it but I'm not familiar with them really (been awhile) which is why I was trying to use slope at first.

So in your first response, where does the 1.0 come from for dx? And dy is just (rise/run) to start right?

Thanks

Share this post


Link to post
Share on other sites
Here ya go:

(Mx, My) = mouse coordinates
(Cx, Cy) = "center of line" coordinates
(Wx, Wy) = "wanted" coordinates ($50,000 reward ;)

Wx = Cx + (Cx - Mx)
Wy = Cy + (Cy - My)

DrawLine( Mx, My, Wx, Wy ); // Point 1 = (Mx, My), Point 2 = (Wx, Wy)

Look into vectors though, learn 'em again. They're easy and cool and useful (oh my!).

Share this post


Link to post
Share on other sites
Hi discman,

Would that just draw a line from the center point to the mouse position? The target end point has to match the original length of the line - ie. if I rotate by 45 degrees, it should still be the same exact length as before. Please let me know if I'm reading it right,

Thanks

Share this post


Link to post
Share on other sites
The snippet of pseudocode I posted will make the line twice as long as the distance from the mouse point to the center point. So, the line's length would change if you moved the mouse point far away. If you want the line to stay the same length...

Say you want it to be length L, always.

(Mx, My) = mouse coordinates
(Cx, Cy) = "center of line" coordinates
(W1x, W1y) = "wanted" coordinates #1 ($50,000 reward ;)
(W2x, W2y) = "wanted" coordinates #2 ($150,000 reward ;)

len = sqrt( (Mx - Cx)^2 + (My - Cy)^2 );
W1x = Cx + L*(Mx-Cx)/(len);
W1y = Cy + L*(My-Cy)/(len);
W2x = Cx - W1x;
W2y = Cy - W1y;

DrawLine( W1x, W1y, W2x, W2y );


I didn't test this, so my math might be off... tired. But I think this is right. This should give you one of those spinning fireworks, so to speak. Always same length, same center. Maybe a see-saw is a better metaphor.

Share this post


Link to post
Share on other sites
Since you're using GDI and you have the center point, angle and line length,
why not use the GDI function AngleArc:

MoveToEx(bufferDC, centerX, centerY, 0); /* moves current position to center */
AngleArc(bufferDC, centerX, centerY, linelen/2, angle, 0); /* line segment from center to angle */
AngleArc(bufferDC, centerX, centerY, linelen/2, angle+180, 0); /* other half of line */

AngleArc draws a line from a center to a point on a line given an angle and then draws an arc from that point given a second angle (that's the last argument, which will be 0 in your case)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this