I am trying to draw a bus route as a simple sequence of lines. Nothing fancy. But instead of lines, I'm getting wedges. Initially I was fine with this, because the wedges sortof look like arrows and always face towards the second point. But now I want to improve the look, and the wedges are becoming a big problem.
My suspicion is some sort of floating-point issue due to the graphics transform (lat/lons are fed in and the transform turns them into x/y on the bitmap [assuming lat/lon is euclidean is accurate enough for my purposes], so the scaling is several orders of magnitude).
Screenshot:
It actually kind of looks like the line was split into two triangles but only one of them was drawn.
Relevant Code (note: drawing is done asynchronously, which is why I'm creating a bitmap):
'-- Creating the transform --'
Dim bitmap = New Bitmap(Math.Max(1, PictureBox1.Width), Math.Max(1, PictureBox1.Height))
Dim g = Graphics.FromImage(bitmap)
g.TranslateTransform(0, bitmap.Height)
g.ScaleTransform(1, -1)
g.ScaleTransform(CSng(bitmap.Width) / (maxLon - minLon), CSng(bitmap.Height) / (maxLat - minLat))
g.TranslateTransform(-minLon, -minLat)
'-- Drawing the lines (in a method called asynchronously) --'
using pen = New Pen(Brushes.Black, 0.0001)
Dim shapes = busData.TripsInGroup(tripGroup.Value).
Select(Function(e) e.Shape).
Distinct()
For Each shape In shapes
For i = 0 To shape.Points.Count - 2
Dim e1 = shape.Points(i)
Dim e2 = shape.Points(i + 1)
Dim p1 = New PointF(CSng(e1.Longitude), CSng(e1.Latitude))
Dim p2 = New PointF(CSng(e2.Longitude), CSng(e2.Latitude))
g.DrawLine(pen, p1, p2)
Next
Next
Example values:
cenLat = 44.657176
cenLon = -63.549471
spnLat = 0.071921
spnLon = 0.179729
minLat = cenLat - spnLat / 2
maxLat = cenLat + spnLat / 2
minLon = cenLon - spnLon / 2
maxLon = cenLon + spnLon / 2
shpts = {(Lat: 44.6518683235, Lon: -63.5930836628),
(Lat: 44.6512537117, Lon: -63.5927528307),
(Lat: 44.6508013753, Lon: -63.5924572976),
(Lat: 44.6503312812, Lon: -63.5921923044),
(Lat: 44.6503312812, Lon: -63.5921923044),
(Lat: 44.6502137576, Lon: -63.5921260568),
(Lat: 44.6495810455, Lon: -63.5917829189),
(Lat: 44.648893839, Lon: -63.5913776026),
(Lat: 44.6485468163, Lon: -63.5911976944),
(Lat: 44.6485468163, Lon: -63.5911976944),
(Lat: 44.6475084762, Lon: -63.5906617219),
(Lat: 44.6475084762, Lon: -63.5906617219)}
Notes and discoveries:
The drawLine() function is an inbuilt function in the GraphicsMagick library which is used to draw the line with specified coordinates.
DrawLine(Pen, Single, Single, Single, Single) Draws a line connecting the two points specified by the coordinate pairs. DrawLine(Pen, Point, Point) Draws a line connecting two Point structures.
In order to draw a line, you need to use the drawLine method of the Graphics class. This method takes four parameters, the starting x and y coordinates and the ending x and y coordinates.
A PaintEventArgs specifies the Graphics to use to paint the control and the ClipRectangle in which to paint.
I had this same issue, and stumbled across this thread. Unlike the OP I found that DrawLines did not solve the issue and suffered from the same problem as DrawLine.
Gabe is correct in that the issue is with regard to the precision of the internal drawing algorithms.
I solved the problem by scaling up the lat/long values by a factor of 10 (although if you are doing more zooming in you may need to scale up by more) before passing them to any drawing algorithm.
Self-answer:
Workaround the issue by using DrawLines instead of DrawLine. DrawLines, for whatever reason, doesn't have this issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With