Как стать автором
Поиск
Написать публикацию
Обновить

Приложение Московское метро для Windows Store

Время на прочтение5 мин
Количество просмотров13K


Сделать приложение Московского метро мне захотелось сразу же, как только Артемий Лебедев и его студия нарисовали схему метро в нынешнем виде.

1. Исходные данные


Сейчас официальную схему метро можно загрузить в PDF с официального сайта Московского метрополитена. На момент создания приложения (середина 2013 года) схема была доступна в виде .ai файла (Adobe Illustrator) на сайте студии Лебедева. В любом случае, следующий этап — это подготовка данных в Illustrator'e.

2. Подготовка данных


Открываем PDF в Illustrator, включаем режим preview и падаем в обморок.

ужас-ужас

(кликабельно)

После долгой и кропотливой работы (тут мне пригодился многолетний опыт работы в московской рекламной газете, сначала в отделе дизайна и вёрстки, затем в IT-отделе)

получилось следующее

(кликабельно)

Что было сделано:

  • удален многочисленный мусор, надписи и пр.
  • каждая линия метро была разбита на участки между станциями. Линии разбивались под рисунками станций, чтобы при отрисовке построенных маршрутов не было видно стыков и разрывов.

вот так:


— все «кусочки» линий и все станции, относящиеся к каждой линии, сгруппированы по слоям, в порядке их следования.

вот так:


3. Преобразуем графику в XAML


Для перевода графики в XAML используется Microsoft Expression Design. Тут всё просто — открываем ai-файл, экспортируем в XAML.

Microsoft Expression Design:

(кликабельно)

4. Начинаем программирование (наконец-то)


В настоящий момент времени для разработки используется Visual Studio 2015 и MVVM-фреймворк MVVM-light. К сожалению, XAML-файл, полученный на предыдущем этапе, напрямую в приложении использовать не получится, кроме статичного слоя с реками и маршрутами «аэроэкспрессов».

Поэтому еще немного работы вручную — и в ресурсах приложения формируем окончательный XML-файл, используемый для рендеринга схемы метро. При его загрузке формируются объекты линий метро, станций метро, формируются связи между станциями в пределах одной линии, переходы между линиями, «замыкаются» кольцевые линии. К слову, переходы между линиями формируются программно. Между двумя станциями — проводятся линии с градиентом заливки, между тремя станциями — строятся дуги окружности, построенной по трём точкам — центрам станций, из которых состоит переход.

Пример View-слоя, отвечающего за отрисовку дуг переходов между тремя станциями (для краткости удалены ресурсы, отвечающие за анимацию и пр.):

<ItemsControl x:Name="ArcCrossings" ItemsSource="{Binding CrossingArcTypeList}" Visibility="Visible" Height="1760" Width="1765">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Grid x:Name="grid" Opacity="{Binding Dimmed, Converter={StaticResource BooleanToOpacityConverter}}">
                                <Path StrokeThickness="7.7" Stroke="{Binding CrossBrush}">
                                    <Path.Data>
                                        <PathGeometry>
                                            <PathGeometry.Figures>
                                                <PathFigureCollection>
                                                    <PathFigure StartPoint="{Binding GradientLineStartPoint}">
                                                        <PathFigure.Segments>
                                                            <PathSegmentCollection>
                                                                <ArcSegment Point="{Binding GradientLineEndPoint}" Size="{Binding ArcSize}" SweepDirection="Clockwise"/>
                                                            </PathSegmentCollection>
                                                        </PathFigure.Segments>
                                                    </PathFigure>
                                                </PathFigureCollection>
                                            </PathGeometry.Figures>
                                        </PathGeometry>
                                    </Path.Data>
                                </Path>
                                <Path StrokeThickness="2.4" Stroke="{Binding SettingsVM.BackMainBrush, Source={StaticResource Locator}}">
                                    <Path.Data>
                                        <PathGeometry>
                                            <PathGeometry.Figures>
                                                <PathFigureCollection>
                                                    <PathFigure StartPoint="{Binding BlackLineStartPoint}">
                                                        <PathFigure.Segments>
                                                            <PathSegmentCollection>
                                                                <ArcSegment Point="{Binding BlackLineEndPoint}" Size="{Binding ArcSize}" SweepDirection="Clockwise"/>
                                                            </PathSegmentCollection>
                                                        </PathFigure.Segments>
                                                    </PathFigure>
                                                </PathFigureCollection>
                                            </PathGeometry.Figures>
                                        </PathGeometry>
                                    </Path.Data>
                                </Path>
                            </Grid>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <Canvas/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>

Для поиска маршрутов используется волновой алгоритм с небольшими вариациями. Например, в случае, если находится оптимальный маршрут, содержащий два и более переходов, строятся дополнительные маршруты, в которых запрещено использовать «промежуточные» линии метро. В результате иногда получаются крайне парадоксальные и неожиданные варианты проезда (смотрите скриншоты ниже).

Для поиска необходимого вагона для удобного перехода на другую линию метро использовался следующий подход: у каждой линии установлено направление «вперед» и «назад». Соответственно, нам важно, с какой стороны мы подъехали к станции перехода, и иногда нам еще важно, в каком направлении мы поедем по той линии, на которую переходим.

Фрагмент XML-файла, описывающий станцию «Китай-город» Таганско-Краснопресненской линии и ее характерный переход на Калужско-Рижскую линию:

<Station name="Китай-город" lat="55.755361" lon="37.632361" Width="16.8277" Height="16.8282" Canvas.Left="1011.71" Canvas.Top="741.034" Data="F1 M 1017.45,746.771C 1015.97,748.25 1015.97,750.646 1017.45,752.125C 1018.93,753.604 1021.33,753.603 1022.8,752.125C 1024.29,750.646 1024.28,748.25 1022.81,746.77C 1021.33,745.292 1018.93,745.292 1017.45,746.771 Z M 1014.2,755.425C 1010.91,752.15 1010.88,746.824 1014.15,743.524C 1017.43,740.225 1022.75,740.2 1026.05,743.473C 1029.35,746.744 1029.38,752.071 1026.1,755.371C 1022.83,758.672 1017.51,758.695 1014.2,755.425 Z " TextLabel.Left="2" TextLabel.Top="-15" ShowPad="1" IsCrossPlatform="true" CrossPlatformColor="FFF37025">
          <transfers>
            <forward>
              <transfer LineID="400" station="Китай-город">
                <forward vagons="11111"/>
                <backward vagons="00100"/>
              </transfer>
            </forward>
            <backward>
              <transfer LineID="400" station="Китай-город">
                <forward vagons="00100"/>
                <backward vagons="11111"/>
              </transfer>
            </backward>
          </transfers>
</Station>

5. Несколько скриншотов построенных маршрутов (кликабельно)


Неожиданный маршрут от Киевской-Кольцевой до Курской-Кольцевой:


Ещё более неожиданный маршрут от Александровского сада до Боровицкой:


От Охотного ряда до Площади Революции:


Вполне заурядно от Шаболовской до Тульской


Другой маршрут от Шаболовской до Тульской в светлом режиме схемы


Общий вид схемы (светлый режим)


Общий вид схемы (тёмный режим)


Поиск станции (все, начинающиеся на 'П')


6. Планы


На момент начала разработки приложения (напомню — это начало-середина 2013 года) речь шла об Windows 8 — 8.1. Собственно, приложение до сих пор «не-UWP». Соответственно, у приложения до сих пор есть «родимые пятна» Windows 8.1, в частности, неоднозначное расположение настроек приложения. Чего уж говорить, в Windows 10 «шарм» настроек «а-ля Windows 8.1» смотрится слегка чужеродно. Со временем, вероятно, это будет изменено.

как это сейчас:


В последнее обновление пришлось «выпилить» информацию о выходах в город (т.е., сейчас нет подсказки, в какой вагон садиться, чтобы было удобно выйти в город). Это в ближайших планах.
Теги:
Хабы:
Всего голосов 47: ↑47 и ↓0+47
Комментарии62

Публикации

Ближайшие события