dcsimg
Results 1 to 21 of 21

Thread: Gallery - Drawing tangents to circles

  1. #1

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Gallery - Drawing tangents to circles

    Recently I decided to write an algorithm that draws the path of a chain (like a bike chain) as it runs around a set of cogs. Cogs can have any position and radius. However, they must be listed in clockwise order. I've just got it working and i want to post some pictures for your delectation.

    I'll post the code at some point (VB.Net).

    8 cogs, 3 of them anticlockwise rotation (detected automatically by the alg)...
    Attached Images Attached Images  
    I don't live here any more.

  2. #2

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Re: Gallery - Drawing tangents to circles

    Similar but with a nice blue fill.
    Attached Images Attached Images  
    I don't live here any more.

  3. #3

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Re: Gallery - Drawing tangents to circles

    Define a new region for a form, passes the fanbelt.path object to form.region.

    I moved the first cog up a bit so you can see the titlebar of the form, and move it around.
    Attached Images Attached Images  
    I don't live here any more.

  4. #4

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Arrow Re: Gallery - Drawing tangents to circles

    OK, here's the first practical demo of how it could be useful...

    Race track designer.

    (There's a weird artifact in some of the tighter corners, I'll have to find a way to cure that).
    Attached Images Attached Images  
    I don't live here any more.

  5. #5

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Improved Race Track!

    OK, solved the artefacts by using 2 paths instead of one.


    Note to hyper geeks: look closely at the bend in the centre of the image. you'll see that one section of white kerb is longer than the others. That is where the 2 ends of the curve path meet each other and overlap. I'm working on a way to eliminate this buts only a geek would notice it





    This looks much better...
    Attached Images Attached Images  
    I don't live here any more.

  6. #6
    Not NoteMe SLH's Avatar
    Join Date
    Mar 2002
    Location
    192.168.0.1 Preferred Animal: Penguin Reason for errors: Line#38
    Posts
    3,051

    Re: Gallery - Drawing tangents to circles

    Very nice stuff!!

    Is the width of the track done using 2 paths ment to vary?
    Quotes:
    "I am getting better then you guys.." NoteMe, on his leet english skills.
    "And I am going to meat her again later on tonight." NoteMe
    "I think you should change your name to QuoteMe" Shaggy Hiker, regarding NoteMe
    "my sweet lord jesus. I've decided never to have breast implants" Tom Gibbons
    Have I helped you? Please Rate my posts.


  7. #7

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Re: Gallery - Drawing tangents to circles

    Quote Originally Posted by SLH
    Very nice stuff!!

    Is the width of the track done using 2 paths ment to vary?
    I used different radii for the two paths. Insolent oik!

    Real racetracks are not a constant width all the way around.
    Last edited by wossname; Jul 1st, 2005 at 10:18 AM.
    I don't live here any more.

  8. #8

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Re: Gallery - Drawing tangents to circles

    Man, I wish I still had the code for this. Anyone know where I put it?

    Seriously.
    I don't live here any more.

  9. #9
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    9,569

    Re: Gallery - Drawing tangents to circles

    No idea, but this is pretty bad bass. I'd like to work up an algorithm and post it with you.

  10. #10

    Re: Gallery - Drawing tangents to circles

    ill use this as a pattern to follow

  11. #11
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,110

    Re: Gallery - Drawing tangents to circles

    Hi Woss, I suspect that Dave is preoccupied with his latest bundle of joy so maybe I can step in with my own "algorithm". I'll assume you want to create a track from any arrangement of corners, not just those you have illustrated; and you work around the track clockwise.

    1. Let's suppose each corner of the track is represented by a point P, an inner radius r and an outer radius R.
    2. The points P can be connected up as a polygon which has convex and concave vertices. Get the convexity of each vertex (see code below).
    3. Start building the outer graphicspath with the outer radius R1 of the first vertex. Then for each vertex Pn:

    4. If the next vertex Pn+1 has the same convexity as Pn you need to find the outer tangent (one which does not cross the line between the centres) for the same radius (inner or outer). So if you are creating the outer path for Pn (Rn), you need the tangent to the outer radius of Pn+1 (Pn+1R). To find the external tangent from PnR to Pn+1R:
    a. Get the slope mn between the centres, i.e. Pn-Pn+1, using Math.Atan2.
    b. Get the distance Dn between the centres Pn - Pn+1 (by Pythagorus).
    c. Find the difference between the radii e.g. diffRn = Pn+1R - PnR. The result can be positive or negative.
    d. Get the relative tangent slope, which (I think) will be mRn = Math.ASin(Dn/diffRn). This can also be positive or negative.
    e. Subtract the relative slope from the slope between centres: mTn =mn - mRn. This is the actual slope of the tangent. Convert it from radians to degrees and save it.

    5. If the next vertex Pn+1 has opposite convexity to Pn, then you need to find the cross tangent (which passes through the line between the circle centres) to the opposite radius (outer or inner). For example, if you are creating the outer path from PnR and Pn is convex, you need the cross-tangent to Pn+1r.
    a, b. Get the slope between centres mn and the distance Dn as in 4.
    c. Find the sum of the radii sumn = Rn + rn+1 or rn + Rn+1 depending on whether you are going from convex to concave or vice-versa. Make it positive if you are going from convex to concave, and negative from concave to convex.
    d. Get the relative tangent slope of the cross tangent nn = Math.Asin(Dn/sumn). This will be correspondingly positive or negative.
    e. Add the relative slope to (5a) to get the tangent slope: mTn = mn + nn.

    6. If you've survived this far, you have list of tangent angles for each vertex of the outer path. Now you need to find the arc around each vertex and add it to the path.
    7. To get the start angle for the arc for vertex Pn, get the tangent slope mTn-1 for the previous vertex. Subtract 90 degrees to get the normal to the tangent.
    8. To get the sweep angle for the arc of vertex Pn, get the tangent slope mTn and subtract 90 degrees. Then subtract the start angle. If Pn is concave, make the result negative.
    9. Add the arc to the path. There is no need to add the tangents themselves to the path. Just add the arcs and use GraphicsPath.CloseFigure.

    10. To get the inner path, repeat all of the above starting from the inner radius of P1. Maybe a few things will have to be the other way round. I'm exhausted already.

    Oh yes, here's my simple code for getting the convexity of a polygon vertex. It just removes the vertex from the polygon, then checks if the vertex is inside or outside the resulting polygon. It works reliably for non self-intersecting polygons.
    Code:
    	Private Function VertexIsConcave(polygon As PointF(), vertex As PointF) As Boolean
    		Dim vertices As New List(Of PointF)(polygon)
    		vertices.Remove(vertex)
    		Dim gp As New Drawing2D.GraphicsPath
    		gp.AddPolygon(vertices.ToArray)
    		Return gp.IsVisible(vertex)
    	End Function
    BB

  12. #12

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Re: Gallery - Drawing tangents to circles

    Yes, I think you've formally stated in mathematical terms all the stuff that was floating around in my brain while I was writing my old code.

    I remember it well. To be honest, I have no idea what is the current state of the art as far as non-accelerated graphics in .Net is. Last time I did this I was hacking around with Brush, Pen, GraphicsPaths and Lockbits and huge amounts of "unmanaged" pointer math code in order to get the framerate up. I have not programmed C# seriously in any IDE more recent than VS2005 so I can only be of limited assistance.

    Looks like you've got a good handle on it though. I eagerly await your first screenshots
    I don't live here any more.

  13. #13
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    9,569

    Re: Gallery - Drawing tangents to circles

    I'm glad I didn't tackle this, I'm terrible in math.

  14. #14

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Re: Gallery - Drawing tangents to circles

    Heh, me too. Luckily there's not too much math involved, the trigonometry is little more than atan2() and a bit of logic to decide if 3 consecutive points go clockwise or anticlockwise. The hardest part was actually fixing the weird .Net graphical issues.

    You should give it a shot too, it's good fun to mess with C# graphics in a simple 2D context like this. I learned a lot from this old project.
    I don't live here any more.

  15. #15

    Thread Starter
    type Woss is new Grumpy; wossname's Avatar
    Join Date
    Aug 2002
    Location
    #!/bin/bash
    Posts
    5,683

    Re: Gallery - Drawing tangents to circles

    Hmm, I wonder if my old code is on that old maxtor caddy at the back of my shelf...
    I don't live here any more.

  16. #16
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,110

    Re: Gallery - Drawing tangents to circles

    Quote Originally Posted by wossname View Post
    Yes, I think you've formally stated in mathematical terms all the stuff that was floating around in my brain while I was writing my old code.

    I remember it well. To be honest, I have no idea what is the current state of the art as far as non-accelerated graphics in .Net is. Last time I did this I was hacking around with Brush, Pen, GraphicsPaths and Lockbits and huge amounts of "unmanaged" pointer math code in order to get the framerate up. I have not programmed C# seriously in any IDE more recent than VS2005 so I can only be of limited assistance.

    Looks like you've got a good handle on it though. I eagerly await your first screenshots
    I'll see if I can work something out in the weekend (see also my PM). I'm sure GDI+ will be fast enough for designing the track. Getting the cars to race around it convincingly may be another story.

    Edit: @dave. Once the track is designed, I assume you could port the design as a texture, together with the path boundaries as polygons, to XNA. I would happily leave that to an XNAxpert.

    BB

  17. #17
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    9,569

    Re: Gallery - Drawing tangents to circles

    Sounds simple enough, I actually have a method that converts bitmaps to Texture2ds which is what this would entail. If I have the track, I could certainly build something that would make cars move around that track.

  18. #18
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,110

    Re: Gallery - Drawing tangents to circles

    Let those who thought I couldn't do it weep. Here's a pic of how the race track looks in Edit mode. The light gray dots are the corner centres, which can be dragged to any position. The yellow dot is the selected dot. The dashed circles around it are the corner's inner and outer radii, which you can adjust with the mouse wheel. These details are hidden in Play mode. The dashed kerb was no problem whatsoever (Pen.DashPattern) but the logic of the tangent angles and arcs kept me up all night. There's a few minor bugs (aren't there always) still to sort out and a few features still to implement (adding/deleting corners in Edit mode).

    Name:  RaceTrack1.png
Views: 122
Size:  63.8 KB

  19. #19
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    9,569

    Re: Gallery - Drawing tangents to circles

    Alright boops boops, I've tried my hand at following your math, but I must say that I'm just ignorant when it comes to math... Here are my classes:

    Code:
    Option Strict On
    Option Explicit On
    Public Class Cog
    
    #Region "Properties"
    
        Private pt As PointF
        <System.ComponentModel.Description("Gets/Sets the center point of the cog.")> _
        Public Property Location() As PointF
            Get
                Return pt
            End Get
            Set(ByVal value As PointF)
                pt = value
            End Set
        End Property
    
        Private iRadius As Single
        <System.ComponentModel.Description("Gets/Sets the distance in pixels from the Location to the inner radius of the cog.")> _
        Public Property InnerRadius() As Single
            Get
                Return iRadius
            End Get
            Set(ByVal value As Single)
                iRadius = value
            End Set
        End Property
    
        Private oRadius As Single
        <System.ComponentModel.Description("Gets/Sets the distance in pixels from the Location to the outer radius of the cog.")> _
        Public Property OuterRadius() As Single
            Get
                Return oRadius
            End Get
            Set(ByVal value As Single)
                oRadius = value
            End Set
        End Property
    
    #End Region
    
    #Region "New Constructors"
    
        Sub New()
            pt = New Point(0, 0)
            iRadius = 1
            oRadius = 2
        End Sub
    
        Sub New(ByVal inner As Single, ByVal outer As Single)
            iRadius = inner
            oRadius = outer
        End Sub
    
    #End Region
    
    End Class
    And...

    Code:
    Option Strict On
    Option Explicit On
    Public Class Track
        Inherits System.Windows.Forms.Control
    
    #Region "Properties"
    
        Private cogCollection As Cog()
        <System.ComponentModel.Description("Gets the collection of cogs that make up the track. NOTE: The order of the cogs plays a huge importance in the layout of the track.")> _
        Public ReadOnly Property Cogs() As Cog()
            Get
                Return cogCollection
            End Get
        End Property
    
        Private isDash As Boolean
        <System.ComponentModel.Description("Gets/Sets if the outside border of the track is dashed.")> _
        Public Property DashTrack() As Boolean
            Get
                Return isDash
            End Get
            Set(ByVal value As Boolean)
                isDash = value
            End Set
        End Property
    
        Private dashPrim As Color
        <System.ComponentModel.Description("Gets/Sets the primary dash color of the track if the DashTrack property is True.")> _
        Public Property PrimaryDashColor() As Color
            Get
                Return dashPrim
            End Get
            Set(ByVal value As Color)
                dashPrim = value
            End Set
        End Property
    
        Private dashSecond As Color
        <System.ComponentModel.Description("Gets/Sets the secondary dash color of the track if the DashTrack property is True.")> _
        Public Property SecondaryDashColor() As Color
            Get
                Return dashSecond
            End Get
            Set(ByVal value As Color)
                dashSecond = value
            End Set
        End Property
    
    #End Region
    
    #Region "Methods"
    
        'Public Methods
        Public Sub Add(ByVal cog As Cog)
            'Convert the cogCollection to a list and add the cog to that list
            'Convert the list back to an array
            Dim l As List(Of Cog) = cogCollection.ToList
            l.Add(cog)
            cogCollection = l.ToArray
        End Sub
    
        Public Sub AddRange(ByVal cogs() As Cog)
            'Convert the cogCollection to a list and add the cogs to that list
            'Convert the list back to an array
            Dim l As List(Of Cog) = cogCollection.ToList
            l.AddRange(cogs)
            cogCollection = l.ToArray
        End Sub
    
        Public Sub ChangeOrder(ByVal priorIndex As Integer, ByVal newIndex As Integer)
            'Convert the cogCollection to a list and get the cog at the prior index
            'Insert the cog at the new index
            'Convert the list back to an array
            Dim l As List(Of Cog) = cogCollection.ToList
            Dim c As Cog = l.Item(priorIndex)
            l.Remove(c)
            l.Insert(newIndex, c)
            cogCollection = l.ToArray
        End Sub
    
        Public Sub Remove(ByVal cog As Cog)
            'Convert the cogCollection to a list and remove the cog from that list
            'Convert the list back to an array
            Dim l As List(Of Cog) = cogCollection.ToList
            l.Remove(cog)
            cogCollection = l.ToArray
        End Sub
    
        Public Sub RemoveAt(ByVal index As Integer)
            'Convert the cogCollection to a list and remove the cog by it's index
            'Convert the list back to an array
            Dim l As List(Of Cog) = cogCollection.ToList
            l.RemoveAt(index)
            cogCollection = l.ToArray
        End Sub
    
        'Private Methods
        Private Function CreatePath() As Drawing2D.GraphicsPath
            Dim path As List(Of PointF) = New List(Of PointF)
            Dim oRadius As List(Of Drawing2D.GraphicsPath) = New List(Of Drawing2D.GraphicsPath)
            Dim iRadius As List(Of Drawing2D.GraphicsPath) = New List(Of Drawing2D.GraphicsPath)
    
            For Each c As Cog In cogCollection
                'Get the inner and outer radius rectangle of the cog
                Dim iRect As RectangleF = New RectangleF(New PointF(c.Location.X - c.InnerRadius, c.Location.Y - c.InnerRadius), New SizeF(c.InnerRadius * 2, c.InnerRadius * 2))
                Dim oRect As RectangleF = New RectangleF(New PointF(c.Location.X - c.OuterRadius, c.Location.Y - c.OuterRadius), New SizeF(c.OuterRadius * 2, c.OuterRadius * 2))
    
                'Add the inner radius of the cog to a graphics path for the inner rectangle
                Dim iGraphics As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
                iGraphics.AddEllipse(iRect)
    
                'Add the outer radius of the cog to a graphics path for the inner rectangle
                Dim oGraphics As Drawing2D.GraphicsPath = New Drawing2D.GraphicsPath
                oGraphics.AddEllipse(oRect)
    
                'Add the inner and outer radius graphics path to their list
                iRadius.Add(iGraphics)
                oRadius.Add(oGraphics)
            Next
    
            'Add the outer radius of the first vertex
            path.Add(oRadius.Item(0).PathPoints(0))
    
            'Loop through each vertex
            For i As Integer = 0 To oRadius.Item(0).PathPoints.Count - 1
    
            Next
    
            Return Nothing
        End Function
    
        'Thank you boops boops for this function
        Private Function VertexIsConcave(ByVal polygon As PointF(), ByVal vertex As PointF) As Boolean
            Dim vertices As List(Of PointF) = New List(Of PointF)(polygon)
            vertices.Remove(vertex)
            Dim gp As New Drawing2D.GraphicsPath
            gp.AddPolygon(vertices.ToArray)
            Return gp.IsVisible(vertex)
        End Function
    
    #End Region
    
    #Region "Events"
    
        Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaint(e)
    
    
        End Sub
    
    #End Region
    
    End Class
    I cannot get past step 3!!!

  20. #20
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,110

    Re: Gallery - Drawing tangents to circles

    G'day dday,

    Your step 3 is only part of the story as far as I am concerned. I frittered away many a frustrated hour trying to develop my initial attempt into a bug-free track designer with "a few extra features". Well, that was in January and February: by mid March I had an imaginary sign flashing in front of my screen every few minutes with the message "get a life!" Still, most of it is now working as intended. I'll send you a PM with a link to my code.

    Here's a new pic illustrating features like overlapping and multiple paths:

    Name:  racetrack_pink.jpg
Views: 96
Size:  42.4 KB

    A comment about your code. Wouldn't it be easier to declare CogCollection as a List(Of Cog)? Then you wouldn't need those conversion methods.

    BB

  21. #21
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    9,569

    Re: Gallery - Drawing tangents to circles

    A comment about your code. Wouldn't it be easier to declare CogCollection as a List(Of Cog)? Then you wouldn't need those conversion methods.
    That is how I initially had it, and to be honest I don't know why I changed it.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width