Почему Graphics.DrawLine рисует форму клина? - PullRequest
6 голосов
/ 04 ноября 2011

Я пытаюсь нарисовать автобусный маршрут в виде простой последовательности линий. Ничего фантастического. Но вместо линий я получаю клинья. Первоначально я был в порядке с этим, потому что клинья подобны стрелам и всегда обращены ко второй точке. Но теперь я хочу улучшить внешний вид, и клинья становятся большой проблемой.

Я подозреваю, что это какая-то проблема с плавающей точкой из-за графического преобразования (вводится широта / долгота, и преобразование превращает их в x / y на растровом изображении [при условии, что широта / долгота является евклидовой, достаточно точна для моих целей ], поэтому масштабирование составляет несколько порядков).

Скриншот:

'Wedge' line overlayed over a road

На самом деле это выглядит так, будто линия была разделена на два треугольника, но только один из них был нарисован.

Соответствующий код (примечание: рисование выполняется асинхронно, поэтому я создаю растровое изображение):

'-- 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

Пример значения:

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)}

Примечания и открытия:

  • Использование DrawLines вместо DrawLine решает проблему (но почему?)
  • Увеличение толщины пера устраняет проблему (но линии слишком толстые)
  • Уменьшение (увеличение окна просмотра широты / долготы), в конце концов, устраняет проблему (но я хочу увеличить!)

Ответы [ 2 ]

3 голосов
/ 09 марта 2012

У меня была такая же проблема, и я наткнулся на эту тему.В отличие от ОП я обнаружил, что DrawLines не решили проблему и страдали от той же проблемы, что и DrawLine.

Гейб прав в том, что проблема связана с точностью внутренних алгоритмов рисования.

Я решил проблему, увеличив значения широты / долготы в 10 раз (хотя, если вы делаете больше масштабирования, вам может потребоваться увеличить масштаб еще), прежде чем передавать их в любой алгоритм рисования.

2 голосов
/ 04 ноября 2011

Self-ответ:

Обойти проблему, используя DrawLines вместо DrawLine. У DrawLines, по любой причине, нет этой проблемы.

...