Чтение и вывод данных о долготе и широте в 2 колоннах - PullRequest
1 голос
/ 21 сентября 2019

Я новичок в VB.NET и пытаюсь разработать ГИС-систему.Существует текстовый файл, подобный этому.

the data file

Я хочу прочитать долготу и широту, но я не знаю, как читать их в два разных массива.Кроме того, в файле есть строка "# -b", я не знаю, как пропустить эти строки.
Я использую такой код, но он не работает.

FileOpen(1, "coastline.dat", OpenMode.Input)
            Input(1, longtitude)
            Do While Not EOF(1)
                Input(1, latitude)
                longtitude = latitude = ""
                Do Until longtitude = "#" Or EOF(1)
                    i = 0
                    Input(1, longtitude)
                    Input(1, latitude)
                    x(i) = (Val(longtitude) + 180) * Me.Width / 360
                    y(i) = (90 - Val(latitude)) * Me.Height / 180
                    i = i + 1
                Loop
                count = i - 1
                For i = 0 To count
                    map.DrawLine(pen1, x(i), y(i), x(i + 1), y(i + 1))
                Next i
            Loop
            FileClose()

Ответы [ 2 ]

0 голосов
/ 21 сентября 2019

Для работы со строками # -b символ хеша (#) используется в качестве маркера комментария во многих форматах текстовых файлов.Игнорируйте строки, где первый непробельный символ является хешем, и игнорируйте пустые строки.

Это не так, давайте перейдем к некоторому коду.Во-первых, создайте класс для хранения данных:

Public Class GeoLocation
    Public Property Latitude As Double
    Public Property Longitude As Double   

    Public Shared Function Parse(input As String) As GeoLocation
        Dim ms = Matcher.Matches(input)
        If ms.Count = 2 then
            Return New GeoLocation With {.Latitude = Double.Parse(ms(0).Groups(0).Value), .Longitude = Double.Parse(ms(1).Groups(0).Value)}
        End If
        Return Nothing
    End Function

    Private Shared Matcher As New RegEx("(-?\d{1,3}[.]\d{6})")
End Class

Теперь вы можете использовать этот класс для чтения файла:

Public Function ReadCoastlineData(fileName As String) As IEnumerable(Of GeoLocation)
    Return File.ReadLines("coastline.dat").
                Select(Function(line) line.Trim()).             'Sanitize
                Where(Function(line) Not String.IsNullOrWhitespace(line) AndAlso 
                           Not line.StartsWith("#"c)).          'Filter
                Select(Function(line) GeoLocation.Parse(line))  'Parse                  
End Function

Затем существующий код может вызывать метод ииспользуйте его, чтобы нарисовать карту следующим образом:

Dim first As Boolean = True
Dim PrevX, PrevY As Single

For Each c As GeoLocation In ReadCoastlineData("coastline.dat")
    Dim X As Single = (c.Longitude + 180) * Me.Width / 360
    Dim Y As Single = (90 - c.Latitude) * Me.Height / 180

    If Not First Then
        map.DrawLine(pen1, PrevX, PrevY, X, Y)
    End If

    First = False
    PrevX = X
    PrevY = Y
Next

Что бы вы ни делали, пройдите мимо этого старомодного FileInput() и API друзей.Эти методы древние и существуют только для совместимости с очень старым кодом.Более новый код должен использовать API System.IO.

0 голосов
/ 21 сентября 2019

Старые функции EOF, FileClose, Input и т. Д. Являются наследием старого, старого VB (например, оригинального VB) - я не рекомендую использовать их сегодня.

Я думаю, что ваш код хочет прочитать файл построчно, а затем нарисовать строку после прочтения каждой входной строки.Ваш код не должен этого делать, потому что вы смешиваете проблемы (ввод-вывод файла и рисование на экране).Это также означает, что вашему приложению нужно будет перечитывать файл каждый раз, когда ему нужно перекрасить карту (при условии, что вы рисуете непосредственно в окно, а не на Bitmap поверхности).

Я предлагаю вам сначаласчитайте файл в память (т. е. в ОЗУ, переменные программы) как объект List(Of T), а затем раскрасьте карту.

Сначала вам нужно определить пользовательские сложные (не скалярные) данные.тип, называемый Structure, который представляет каждую запись в файле - в этом случае каждая запись представляет собой кортеж широты и долготы, представленный в виде точных десятичных чисел (не неточных чисел с плавающей запятой), поэтому вы должны использовать Decimal вместо Single или Double (поскольку Decimal является точным типом, Single и Double не являются).

Public Structure LatLong
    Public Lat As Decimal
    Public Lng As Decimal
End Structure

Тогда нам нужно прочитать это. Как я уже говорил ранее, яне рекомендуется использовать старый файловый IO API, вместо этого вы должны использовать FileStream и StreamReader, например:

Dim list As New List(Of LatLong)

Using fs As New FileStream( "coastline.dat", FileMode.Open, FileAccess.Read )
    Using reader As New StreamReader( fs )

        Dim line As String
        Do
            line = reader.ReadLine();
            If line = Nothing Then
                Exit Do
            End If

            If line.StartsWith("#") Or String.IsNullOrWhiteSpace( line ) Then
                Continue
            End If

            Dim fields() As String
            fields = line.Split( Nothing, StringSplitOptions.RemoveEmptyEntries )
            If fields.Length = 2 Then

                Dim lat As Decimal
                Dim lng As Decimal
                If Decimal.TryParse( fields(0), lat ) AndAlso Decimal.TryParse( fields(1), lng ) Then
                    Dim ll As New LatLong
                    ll.Lat = lat
                    ll.Lng = lng

                    list.Add( ll )
                End If

            End If

        Loop

    End Using
End Using

' Then paint them (put this in a separate function):

For i As Integer = 0 To list.Count - 2
    Dim ll0, ll1 As LatLong
    ll0 = list(i)
    ll1 = list(i + 1)

    Dim x0, x1, y0, y1 As Integer

    x0 = ( ( ll0.Lng + 180 ) * Me.Width ) / 360
    y0 = ( ( 90 - ll0.Lat ) * Me.Height ) / 180

    x1 = ( ( ll1.Lng + 180 ) * Me.Width ) / 360
    y1 = ( ( 90 - ll1.Lat ) * Me.Height ) / 180

    map.DrawLine( pen1, x0, y0, x1, y1 )

Next
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...