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

в 14:37, , рубрики: windows store, XAML, разработка под windows

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

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

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

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

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

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

ужас-ужас

Приложение Московское метро для Windows Store - 2
(кликабельно)

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

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

Приложение Московское метро для Windows Store - 3
(кликабельно)

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

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

вот так:

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

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

вот так:

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

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

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

Microsoft Expression Design:
Приложение Московское метро для Windows Store - 6
(кликабельно)

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. Несколько скриншотов построенных маршрутов (кликабельно)

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

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

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

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

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

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

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

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

6. Планы

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

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

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

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

Автор: infund

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js