Question How to find attributes of a previously drawn line?

dHeather

Active member
Joined
Jun 18, 2012
Messages
27
Programming Experience
Beginner
Hello,

I am currently working on a form on which the user can draw a continuos line made up of lines and arc segments. (See example) I am drawing to a bitmap using DrawLine and DrawArc. I have got this working fine. What I am struggling with is how the user can edit a line once drawn. I would like them to be able to click on a previously drawn line (red in the example) and its attributes come up (length, Radius, Degrees etc. These I have stored in arrays) which the user can update. I will then run a refresh routine (written and working) to redraw the line from the data in the arrays. As I am only ever working with a continuos line this is very simple to do.

As stated I am currently storing the line lengths, radius, degrees and the opening X,Y co-ordinates of my line in arrays so that I can redraw it. I can identify when I have clicked on a line simply by checking the pixel colour of my click, but I can't find a way of knowing which segment of line I am in (third on the example) to be able to reference my array and tweak the attributes.

I have considered adding a hot zone to each line segment, a few pixels wide, in a different colour which the user would click to edit, but this seems a little primative. I have also looked at storing every point my line runs through and comparing my click against that, but I'm worried that I'll end up creating a monster trying to record every X,Y point I pass through.

Is there another way?

Thanks for taking the time to look at this. Your help would be much appreciated.

Example:
Line Example.jpg
 
Last edited:
If you can find another way there's a fortune to be made! Few (if any) graphics programs allow you to re-select a previously drawn line and adjust it so, whether you consider it primitive or not, if you can find a way to do it using hot zones you're already way ahead of them!
 
Hello,

Thanks for your reply. I don't think my post is very clear. I'm not trying to do anything that hasn't been done many times before. I am looking to produce similar funtionality to that of any CAD program but on a much, much simpler scale. I want to click a pre-drawn line (red in the example) amend it's attributes which I have recorded in an existing array and then with the new information redraw the whole line (nine segments in the example) to accomodate the new sizes of the amended segment.

The bit I am struggling with is how to know which segment of line a user has clicked on whitout recording every X, Y co-ordinated that the line runs through?

I can write the code to record every X, Y co-ordinate if needs be, but I just figured that there is probably a more elegant way locked away in .NET somewhere.

Thanks again for your help
 
No, your post is clear. You now know why CAD programs tend to be a little pricey. There really isn't a simple way to do what you want, ie. click on a point in a graphics area and thereby select a line (a whole line and nothing but the line) nor could there be if you think about it. The only information available from a clicked point is location and colour (and that's only useful anyway if the line is thick enough to be sure that you're clicking on the graphic rather than the background). You might be able to get enough information to be sure that you are on a line but there is no inherent information as to how any particular pixel is related to any other. You can probably save yourself some grief by having a slightly more liberal tracking regime than every pixel (groups of 4 maybe) but ultimately the only way a pixel can be 'self-aware' is to be provided with a 'permanent' record.
 
OK,

Thanks for your help and quick responses. I will probably take a diffing approach if that is the case then. I think I'll introduce a ListView to the form and record the users line selection there. They can then edit the line details there and I can redraw the line after that.

Thanks again
 
A typical way to make a multi-line drawing is to store each line as Drawing2D.GraphicsPath, adding it to a List(Of GraphicsPath) to represent the whole drawing. You can use GraphicsPath.IsOutlineVisible for hit testing on a path with a margin of error. For example to check if a given point is within 2 pixels either side of the path, you could write:
VB.NET:
Dim hit As Boolean
Dim p As Point = PictureBox1.PointToClient(MousePosition)
Using pn As New Pen(Brushes.Black, 5)
    hit = myPath.IsOutlineVisible(r.Location, pn)
End Using
Since you want to edit individual segments, you could define each segment as a separate GraphicsPath. Then each drawn line could become a List of such segments. I would think about defining separate classes for objects like Drawing, DrawnLine, LineSegment, ArcSegment etc. The data you are currently storing such as length, radius etc. would become properties of the appropriate classes.

Don't worry too much about the amount of data stored: it has to be stored somewhere if you are going to edit it. A collection of paths with 10,000 PointFs isn't all that much to draw on a modern PC. If rendering starts getting too slow you could render everything but the line you are currently drawing or editing to a bitmap, which you then treat as a background image.

Vic
 
Last edited:
Thanks for the info. I have tackled the problem in a differing way (as above) but the above information is really useful. I will certainly save it for further projects. Thank you very much.
 
Back
Top