Главный Каталог Статей РФ
85974 авторов, размещено 47108 статей, сейчас на сайте пользователей: 49 Статистика
Аватар Enterra

Использование WPF для визуализации картографических объектов

Категория:  ПО и игры  | Автор:  Enterra | Опубликовано: 19.02.2009
Введение.
В связи с широким распространением компьютерных технологий, позволяющих осуществлять позиционирование объектов на земной поверхности, примерами которых являются GPS и ГЛОНАС, появилась уникальная возможность создавать такие компьютерные системы, которые можно использовать в повседневной деятельности предприятия без значительных затрат. Всем известны такие системы отслеживания автотранспортных средств автобусных предприятий, медицинских учреждений, а также персональные автомобильные навигаторы. Все эти системы объединяет то, что они все в своей основе имеют картографический модуль, отображающий интерактивную карту и позволяющий каким- либо способом отслеживать заданный объект. Наша фирма тоже разработала систему для контроля автотранспортных средств предприятий. Система состоит из нескольких частей. Отображение карты и автотранспортных средств осуществляет клиентский модуль, написанный на C# .Net 3.5 WPF. Внешний вид клиентского модуля представлен на рисунке.

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

Хранилище данных
В настоящее время одним из самых широко распространенных форматов для хранения картографической информации являются файлы формата shp (ESRI Shapefile) [1]. Однако они не очень удобны в использовании , т.к. в стандарте не определены механизмы поиска и выборки объектов по определенным критериям. Хотя и сами разработчики и сторонние фирмы предпринимают попытки построения специальных индексных файлов для таких целей. Одним из таких бесплатно распространяемых компонентов является SharpMap [2]. Он позволяет осуществлять все необходимые действия при работе с геоинформационными данными, однако как показали тесты объем потребляемой памяти и производительность оставляют желать лучшего, кроме того компонент распространяется с лицензией LGPL, что не очень желательно для коммерческой разработки, т.к. при внесении изменений требуется осуществлять поставку с исходным кодом.

Геоинформационная система предполагает возможности изменения масштаба карты, а также перемещения и поиска картографических объектов, что вызывает ряд технических проблем, например, загрузка еще не загруженных областей, выгрузка неактуальной информации и т.п. Предварительные тесты показали неприемлемую производительность при использовании библиотеки SharpMap, поэтому было решено сделать импорт картографической информации в СУБД. В качестве СУБД на первоначальном этапе было решено использовать Microsoft SQL Server Compact Edition 3.5 [3]. Эта СУБД является встраеваемой в приложение, входит в поставку VisualStudio 2008, не имеет ограничений на распространение, обеспечивает хорошую производительность, легко может быть заменена практически на любую другую СУБД, обеспечивающую большую производительность, например на Microsoft SQL Server 2008 [4]. Это решение является очень гибким, т.к. позволяет осуществлять сегментирование программного продукта, т.е. версия программы не предназначенная для работы в сети может использовать локальные базы данных с картами, а в сетевой версии карты хранятся на центральном сервере, что имеет ряд своих преимуществ, например, легкое обновление.
После того, как была написана процедура импорта из файлов формата shp в СУБД и получены первые результаты по отображению картографической информации, возникло непреодолимое желание сравнить разные встраиваемые СУБД на производительность. Это было сделать легко, т.к. теперь запросы на выборку объектов осуществляются на стандартном SQL. Мы протестировали Firebird, SqLite, DBF, MSSQL, результаты приведены в таблице 1.

Таблица 1. Сравнение различных СУДБ по средней производительности.
Место СУБД
1 MSSQL 2008 на выделенном сервере
2 MSSQL 2008 на одной машине с клиентом
3 DBF
4 MSSQL CE 3.5
5 Firebird Embedded
6 SqLite

Подробности процедуры тестирования и обсуждение результатов выходят за рамки данной статьи. Внимательные читатели могут заметить, что мы не проводили испытания СУБД Oracle и могут провести эту процедуру сами. В рамках статьи мы будем рассматривать реализацию на MSSQL CE 3.5.

Для реализации нашей системы вполне достаточно одной таблицы со структурой, представленной в таблице 2 .

Таблица 2. Структура таблицы базы данных.
Имя Тип данных Описание
Id Int Первичный ключ
Name Nvarchar(255) Имя объекта
Description Nvarchar(255) Описание объекта
Data Image Данные
ObjectType TinyInt Тип объекта
ElementType TinyInt Тип элементов объекта
Zoom TinyInt Масштаб
ObjectId Int Идентификатор объекта
ElementId Int Идентификатор элемента объекта
Complex Bit Признак составного елемента


Выборка объектов для отображения для нужного масштаба легко осуществляется запросом вида:

select ObjectId, ObjectType, Name as ObjectName, ElementType, Data, Description, Complex, ElementId from MapObject where @Zoom = Zoom order by ObjectType

Подробности реализации этой функциональности можно посмотреть в прилагаемом примере.

Дополнительные функции легко реализуются изменением этой таблички, и возможно добавлением нескольких других. В реальном приложении у нас имеется 5 таблиц, из которых 3 предназначены для поиска объектов.

Выбор способа отрисовки.
WPF использует векторную графику как формат отрисовки, это означает что специальным образом сохраняется и передается подсистемы вывода набор инструкций, которые описывают как именно необходимо выполнить отрисовку, используя графические примитивы, такие как набор линий, кривых и других команд. Это позволяет легко осуществлять масштабирование без потери качества.
WPF предоставляет на выбор два способа отрисовки. Это объекты Drawing и Shape. Объекты Shape представлены набором примитивов Rectangle, Ellipse и т.д. И легко могут быть использованы непосредственно в разметке xaml, поддерживают выравнивание и обработку событий, однако производительность системы при отрисовке достаточно большого количества таких объектов оставляет желать лучшего.
Объекты DrawingVisual обеспечивают максимальную производительность при отрисовке фигур, картинок или текста. Это достигается за счет того, что они не поддерживают компоновки и событий. К тому же их нельзя описать в разметке. Для их использования необходимо создать контейнер, унаследованный от класса FrameworkElement. Для хранения объектов DrawingVisual нужно использовать класс VisualCollection. Для обеспечения компоновки контейнера необходимо перекрыть две простых функции.

public class BaseRenderer : FrameworkElement
{
//member for optimize
protected VisualCollection ObjectChildrenList;

protected override int VisualChildrenCount
{
get
{
return ObjectChildrenList.Count;
}
}

protected override Visual GetVisualChild(int index)
{
return ObjectChildrenList[index];
}
}

Созданные объекты DrawingVisual должны быть помещены в коллекцию ObjectChildrenList для того чтобы графическая подсистема WPF смогла осуществить их отрисовку. Причем, для максимального быстродействия необходимо использовать функцию Add и добавлять объекты последовательно. В ином случае, например при использовании функции Insert осуществляется пересчет визуального родителя у всех элементов с индексом, большим чем индекс вставки. Аналоичным образом ведет себя функция Remove. Поэтому лучше очищать коллекцию полностью. В этом легко убедиться использую любой профилировщик, например jetBrance[5] или посмотрев исходные коды, например, используя Reflector [6]. Итак, вначале создается объект MapDrawingVisual, который является наследником объекта DrawingVisual и имеет ссылку на бизнес объект карты, для выполнения процедуры HitTesting (проверка попадания). Затем получается стиль для отрисовки объекта, создается геометрия и производится сама отрисовка.

private void CreateDrawing(MapElement element, bool closed)
{
MapDrawingVisual drawingVisual = new MapDrawingVisual();
drawingVisual.MapObject = element.MapObject;
DrawingContext drawingContext = drawingVisual.RenderOpen();

GeometryStyle style = StyleManager.GetStyle(element);

Geometry geometry = CreateBaseGeometry(element, closed);
drawingContext.DrawGeometry(style.Brush, style.Pen, geometry);
drawingContext.Close();

AddDrawingVisual(drawingVisual);
}

private void AddDrawingVisual(DrawingVisual drawingVisual)
{
ObjectChildrenList.Add(drawingVisual);
}

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

private static Geometry CreateGeometry(Point[] points, bool closed, bool freeze)
{
Geometry geometry = new StreamGeometry();
using (StreamGeometryContext ctx = ((StreamGeometry)geometry).Open())
{
ctx.BeginFigure(points[0], true, closed);
ctx.PolyLineTo(points, true, false);
}
// Freeze the geometry (make it unmodifiable)
// for additional performance benefits.
if (freeze)
{
geometry.Freeze();
}
return geometry;
}

Кисти, перья, текст, перемещение объектов и прочие вопросы оптимизации
В силу специфики приложения приходится выполнять отрисовку объектов разных типов: дома, реки, дороги и прочее. Причем их количество измеряется сотнями. К сожалению, простейшее решение, приходящее на ум в этом случае, а именно использование одного объекта кисти для одного типа объекта, вызывает значительное замедление работы системы. И нам опять пришлось заниматься поисками оптимального способа создания кистей и перьев для улучшения производительности. Создание новой кисти непосредственно перед использованием также не привело к значительному улучшению производительности. Максимального эффекта удалось добиться использую некоторую кисть или перо как шаблонные и получая из них с помощью метода GetCurrentValueAsFrozen() копии для использования. Приведенный ниже код упрощен.

public GeometryStyle Clone()
{
return new GeometryStyle
{
Brush = (Brush)Brush.GetCurrentValueAsFrozen(),
Pen = (Pen)Pen.GetCurrentValueAsFrozen()
};
}

В примере к статье не приведена реализация подписей объектов, однако этот вопрос заслуживает того, чтобы сказать о нем несколько слов. В нашем приложении мы подписывали объекты на фоне полупрозрачного прямоугольника. Его размеры зависят от величины текста. Однако логичное решение использовать ширину и высоту объекта FormattedText для отрисовки прямоугольника, а затем отрисовки текста выше него не оптимально. Пересчет происходит неоднократно. Чтобы этого избежать, нужно сначала выполнить отрисовку текста, отрисовку прямоугольника, а затем добавить полученные объекты DrawingVisual в коллекцию визуальных объектов в нужном порядке.
Перемещиние карты с помощью мыши является довольно простой задачей и фактически состоит в правильном вычислении параметров для класса TranslateTransform выполняющего сдвиг объектов. Используя транформации можно создать ряд довольно замысловатых эффектов, например изменениу угла обзора, вращение карты и прочее, однако производительность оставляет желать лучшего.
Кроме того было обнаружено очень сильное падение прозводительности при отрисовке линий. Это является серьезной проблемой, т.к. совершенно необходимо выполнять отрисовку таких картографических объектов как дороги, реки, границы регионов и прочее. Поиски решения данной поблемы не увенчались сколь каким-нибудь успехом, единственным найденным способом хоть как-то ускорить отрисовку явилась рекомендация использовать только целые числа для задания толщины пера. Еще одним непонятным фактом является то, что при отключении антиалисинга поизводительность значительно снижается.
RenderOptions.SetEdgeMode(this, EdgeMode.Aliased);
Я надеюсь, что найдутся читатели, которые смогут объяснить такое поведение системы, а также способы повышения прозводительности.
При создании приложений WPF полезно скачать инструменты для профилирования производительности, например WPF Perforator [7], а также ознакомиться с рекомендациями Micrsoft, которые можно найти в MSDN.

Проверка попадания курсора
Проверка попадания курсора (Hit testing) в описываемом случае является очень простой задачей, и реализуется буквально в несколько строк. Собственно для этого и был написан простейший класс
MapDrawingVisual:
public class MapDrawingVisual : DrawingVisual
{
public MapObject MapObject;
}
Полный код процедуры проверки попадания курсора приведен ниже:
public MapInfo GetInfo(Point point)
{
MapInfo info = new MapInfo();
VisualTreeHelper.HitTest(Viewer, null,
delegate(HitTestResult result)
{
if (result.VisualHit is MapDrawingVisual
&& ((MapDrawingVisual)result.VisualHit).MapObject != null)
{
MapObject mapObject =
((MapDrawingVisual)result.VisualHit).MapObject;
if (!String.IsNullOrEmpty(mapObject.ObjectName))
{
info.Name = mapObject.ObjectName;
info.Description = mapObject.Description;
return HitTestResultBehavior.Stop;
}
}
// Stop the hit test enumeration of objects in the visual tree.
return HitTestResultBehavior.Continue;
}
, new PointHitTestParameters(point));
return info;
}

Заключение
Хочется отметить, что с выходом WPF разработка приложений значительно упростилась. Предлагаемые WPF возможности анимации, компоновки, проверки попадания и прочих довольно сложных вещей теперь реализуется буквально в несколько строк. Использование WPF оправдано, если не требуется выполнять отрисовку тысяч визуальных объектов и позволяет добиться довольно интересных эффектов. При отрисовке довольно большого количества объектов сложной формы и особенно линий, приходится серьезно задумываться над вопросами производительности. Представляется возможным использовать WPF если компьютеры, на которых предполагается использовать приложение будут мощными и стоит задуматься об иной альтернативе если компьютеры будут слабыми. Например, с нашим приложением невозможно работать на комьютере Celeron 2000 с видеокартой GeForce 4 MX400 и памятью 1Гб, хотя на нем вполне можно играть в компьютерные игры, такие, как Counter Strike.

http://www.techzone.enterra-inc.com сайт компании-разработчика Вы можете связаться с нами по электронной почте.
Комментарии
К этой статье пока нет комментариев. Станьте первым! У нас гости не могут комментировать статьи. Пожалуйста
авторизуйтесь или зарегистрируйтесь, чтобы прокомментировать.
Интересные статьи по теме
Аватар Виталий Эмула
Ретро игры-онлайн на игровом портале Коллекция игр от ретро консолей – это игры формата NES(известная как Денди), SMS(Sega Master System) и GBA(GAME BOY ADVANCE). ...
Категория: ПО и игры | Автор: Виталий Эмула | Добавлено: 24.08.2021
Аватар fly_e135
Настройка телефона Fly Мобильные телефоны есть почти у каждого в нашей стране,да и в мире тоже! Телефон - это сложный механизм, к которому нужно относиться бережно и тогда он будет служить долго. Прежде чем начать использов...
Категория: ПО и игры | Автор: fly_e135 | Добавлено: 25.11.2010
Аватар Anastasya
DVD-Audio авторинг с помощью DigiOnAudio2 Pro. Часть I Методология DVD-Audio авторинга в программе DigiOnAudio2 Pro. Детально рассмотрена технология создания навигации для DVD-Audio, от инсталляции DigiOnAudio2 Pro до записи проекта на лазерный диск....
Категория: ПО и игры | Автор: Anastasya | Добавлено: 17.02.2010
Аватар Excelskype
Excel – то, что нужно знать и уметь всем! Восемь самых востребованных возможностей программы Excel.Это необходимый минимум, которым должен владеть каждый, кто ежедневно использует Excel.Используй эти приемы, чтобы повысить эффективность своей...
Категория: ПО и игры | Автор: Excelskype | Добавлено: 05.04.2015
Аватар Maxim Sherbina
Как StarCraft 2 скачать и можно ли в него играть без battle.net? Все ждут и игру StarCraft 2! А что же она из себя представляет? Давайте вместе пробежимся по статье и узнаем много ценной информации как и для поклонников этой игры, так и для игроков всего мира!...
Категория: ПО и игры | Автор: Maxim Sherbina | Добавлено: 04.04.2010
Лучшие авторы
Аватар marijka
Пишу, размещаю, никого не трогаю, починяю примус.

Читать

Аватар Kolesnikov Pavel
Руководитель студии МТО 'Лидер студио'.

Читать

Аватар OlgaB
Здравствуйте, меня зовут Ольга. Два высших гуманит...

Читать

Аватар sharos
По образованию физик, в настоящий момент м.н.с. в ...

Читать

Аватар BoatProfi
Тюнинг и ремонт катеров

Читать

Свежие комментарии
Нормальная тема.

Читать

Талантливый человек талантлив во всём! Будь как Паша! А ещё ты можешь ...

Читать

Можно выбрать.

Читать

Ой, шутник.

Читать

https://priornews.ru/zastrojshhik-iz-hmao-sravnil-ufas-s-prestupnoj-gr...

Читать

Напишите нам