2011-11-04 15 views
6

Próbuję narysować trasę autobusu jako prostą sekwencję linii. Nic fajnego. Ale zamiast linii, dostaję kliny. Początkowo było mi z tym dobrze, ponieważ kliny sortof wyglądają jak strzały i zawsze są zwrócone w stronę drugiego punktu. Ale teraz chcę poprawić wygląd, a kliny stają się dużym problemem.Dlaczego Graphics.DrawLine rysuje kształt klina?

Moje podejrzenie to kwestia zmiennoprzecinkowa z powodu transformacji grafiki (łaciny/lony są podawane, a transform przekształca je w x/y na mapie bitowej [zakładając, że lat/lon jest euklidesowe jest wystarczająco dokładne dla mojego celów], więc skalowanie jest kilka rzędów wielkości).

Zrzut ekranu:

'Wedge' line overlayed over a road

To faktycznie niby wygląda linia została podzielona na dwa trójkąty, ale tylko jeden z nich został sporządzony.

odpowiedni kod (uwaga: rysunek odbywa się asynchronicznie, dlatego tworzę 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 

Przykładowe wartości:

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

Uwagi i odkrycia:

  • Używanie DrawLines zamiast DrawLine rozwiązuje problem (ale dlaczego?)
  • Zwiększenie grubości pisaka powoduje, że problem zniknie (ale linie są zbyt grube)
  • Zmniejszenie (zwiększenie okna widoku lat/lon) sprawia, że ​​problem znika, ostatecznie (ale chcę powiększyć!)
+0

Powinieneś opublikować cały swój kod, łącznie z transformacjami. Nigdy wcześniej nie widziałem linii wydanej jako klina, bez czegoś niezwykłego. – MusiGenesis

+0

Dodałem trochę więcej kodu. –

+1

Tinker za pomocą pióra, zwłaszcza czapek. –

Odpowiedz

3

Miałem ten sam problem i natknąłem się na ten wątek. W przeciwieństwie do PO stwierdziłem, że DrawLines nie rozwiązało problemu i cierpiało z powodu tego samego problemu co DrawLine.

Gabe ma rację, ponieważ problem dotyczy precyzji algorytmów rysowania wewnętrznego.

Rozwiązałem problem przez skalowanie wartości liczb długich/dziesięciokrotnych o współczynnik 10 (chociaż jeśli robisz więcej powiększania, możesz powiększyć skalę o więcej) przed przekazaniem ich do dowolnego algorytmu rysowania.

2

Własna odpowiedź:

Obejść problem, używając DrawLines zamiast DrawLine. DrawLines, z jakiegokolwiek powodu, nie ma tego problemu.

Powiązane problemy