Click here to Skip to main content
15,890,123 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Dear Friends,

This is my first question here, so please be gentle :)

I am working on a VS2010 vb.net winform application. The form has one big picturebox (Picturebox1) and dynamically created small numbers of picturebox, named pin_00, pin_01 ... pin_nn, scattered around. The small picturebox has an image a small circle which is 14x14 in size and the small picturebox's sizeMode is set to AutoSize

The main aim is to draw a line from one pin to another with a line (ArrowAnchor caps) on picturebox. The line arrow acnchor head must point to the center of the small circle, which i have accomplished.

The problem is when the line is drawn, the Arrow Anchor Head (since the line extends up to the center of the small picturebox) is hidden by the small picturebox

Now, what i want is to make the line reach only to the circumference of the circle, so that the arrow head will be visible and still point to the center of the small picturebox.

I know that the solution is just plain circle and line equation finding the point of intersection. But i cant make it right. Please help.

Here is the code i have tried:

VB
 Dim mPen As Pen = New Pen(Brushes.RoyalBlue, 2)

mPen.EndCap = Drawing2D.LineCap.ArrowAnchor

gr = Graphics.FromImage(PictureBox1.Image)

Dim p1 As Point = New Point(startPIN.Location.X + (startPIN.Width / 2), _
                            startPIN.Location.Y + (startPIN.Height / 2)) 
'Since i want the line to start from the center i moved the coordinate to half of its height and width


Dim p2 As Point = New Point((endPIN.Location.X + (endPIN.Width / 2)), _
                                    (endPIN.Location.Y + (endPIN.Height / 2))) 'initially point to the center of the other pin



Dim pinRadius As Integer = endPIN.Width / 2

       
Dim m As Single = (p2.Y - p1.Y) / (p2.X - p1.X) 'slope of the line

         

p2 = New Point(p2.X + (pinRadius / Math.Sqrt(1 + (m ^ 2))), p2.Y + (pinRadius / Math.Sqrt(1 + (1 / (m ^ 2)))))


gr.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

Dim gpath As New Drawing2D.GraphicsPath
gpath.AddLine(p1, p2)



gr.DrawPath(mPen, gpath)
gr.FillPath(bbrush, gpath)

PictureBox1.Refresh()


I have searched on google but cant find anything more than how to use line and circle equation. Did i miss something or my deduced point of intersection formula is wrong?

here is a pic link of how i want and what i get so far http://tinypic.com/r/2pziudl/5[^]
Posted
Comments
Richard C Bishop 18-Jun-13 14:52pm    
While I can't help with your programming issue, I can say your post is very well done. You have followed the guidelines and it will fetch you an answer if the right person comes along.
David LNTA 18-Jun-13 15:00pm    
oh! thank you. Waiting ... :)

You are drawing on the big picture box, which it does correctly, but due to draw order, the big picture box is drawn, then the smaller ones, covering up the image in the big picture box.

Transparency works oddly in .NET, where the child control doesn't just "get" what is underneath the control, it requests the control under it to repaint (which it does, without your line), and uses that for the background of the control on top.

What you need to do is to draw on top of the form after all the controls have been painted, or place a transparent control over the big picturebox and paint on that after the controls underneath have been painted.
 
Share this answer
 
Comments
David LNTA 18-Jun-13 15:53pm    
Thanks for the quick reply Ron Beyer

I did your solution previously but my client wants it to exactly make the line point to the circumference of the small boxes (but accurately align with the center of the small picturebox). I drew the line on top of it and the line arrow anchor overlap the small picture box pointing exactly at the center, my client didnt want it.

In simple words the line must touch the circle (picturebox image) only at the circumference. Additionally i cannot paint the small picturebox on the big one because i have to assign event handlers for other purpose.
Sergey Alexandrovich Kryukov 18-Jun-13 16:27pm    
Trash PictureBox and you will get it...
—SA
Sergey Alexandrovich Kryukov 18-Jun-13 16:27pm    
Agree, a 5.
The real solution is to get rid of PictureBox. Please see my answer.
—SA
Here is the key: PictureBox is no help in your case. This is just a control, heavily overused. You rather should have rendered the whole scene at once, not using any controls except one representing the whole scene, using the method System.Windows.Forms.Control.OnPaint (or handling the event System.Windows.Forms.Control.Paint) and calling Invalidate if you want to move/change anything. It will also solve the problem of transparency: you can use it at the level of GDI+ object, but hardly controls. Also, to fight flicker, use double buffering.

Please see my past answers:

Append a picture within picturebox[^],
draw a rectangle in C#[^],
How do I clear a panel from old drawing[^];

Drawing Lines between mdi child forms[^],
capture the drawing on a panel[^],
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...))[^],
How to speed up my vb.net application?[^].

—SA
 
Share this answer
 
Comments
David LNTA 18-Jun-13 16:59pm    
Thanks Sergey Alexandrovich

I am no expert but i was afraid the solution would recommend leaving the pictureboxes and work solely on GDI+ and seems like it needs to.

I have gone through some of your solution that you gave while i started the project months ago and in fact i bookmarked them finding it very informative and helpful.

Initially the project was just to plot the small circles on a big picturebox with an image of a big map inside a panel (so that users can pan the map dragging). The small circle represents a location and when double clicked on, it displayed information of the location from a db source. Since i am a novice developer i use multiple picturebox assigning handler and deployed the application. (and yes, the application was heavy and memory hog :D )

Now to use your suggestion/solution i need to know (if possible) how to assign handlers to a painted location (co-ordinate) on a picturebox. A small code snipped if i am not asking too much :D
Sergey Alexandrovich Kryukov 18-Jun-13 17:11pm    
What handlers? Wait a second, what PictureBoxes? Are you getting rid of them or not? If not, nothing can help... Remember what Ron Beyer told you about transparency...
—SA
David LNTA 18-Jun-13 17:20pm    
I will use only one big picturebox and a panel so that the whole thing can be drag-able and pan-able. The small picturebox's (called pins for my application) containing are location and needs to be clickable. i can draw that on the big picturebox. But the problem would be how to make drawn circles click-able and reposition-able with the mouse?
Sergey Alexandrovich Kryukov 18-Jun-13 18:30pm    
OK... (sigh)... We can continue this discussion only if you forget about PictureBox. I tried to explain why. Are you getting it?
—SA
David LNTA 19-Jun-13 2:29am    
Yup got it Sergey Alexandrovich Kryukov, i studied and decided to change all my design and make a new application. Thanks so much :)
In light of all your answers i found my own solution or a new way of coding.

The answers really clears what i should use and what i shouldn't


Again thanks for the trouble specially to Sergey Alexandrovich Kryukov. It is your answer links and comments that brought light that graphical things should be handled only with minimal controls for easy handling.

Again thank you
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900