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

Введение.
В связи с широким распространением компьютерных технологий, позволяющих осуществлять позиционирование объектов на земной поверхности, примерами которых являются 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 сайт компании-разработчика Вы можете связаться с нами по электронной почте.

Автор статьи: неизвестный | Дата публикации: 00:28 25.03.2017 Specfactor.Ru




Отзывы и комментарии
Ваше имя (псевдоним):
Проверка на спам:

Введите символы с картинки:



Натуральная косметика

Натуральная косметика


Обычно всем людям приходиться мечтать об отдыхе на мертвом море. Мертвое море эксклюзивно: только там находятся самые засоленные воды на планете. Именно поэтому лучшая натуральная косметика - это лече...


Клара Лучко: можно ли ради любимого прыгнуть с парашютом?

Клара Лучко: можно ли ради любимого прыгнуть ...


25 марта 2005 года резко ухудшилось состояние здоровья Клары Степановны Лучко. Через три с половиной месяца народная артистка СССР должна была отмечать свое 80-летие, но тот день, 25 марта, ...


Обзор нефти Brent на 24.10.2010 г.

Обзор нефти Brent на 24.10.2010 г.


Дневной график нефти brent Последнюю неделю нефть вырисовывала треугольник сходять к уровню B. Выход ее вероятнее на уровень С к отметке 87. 5. Вцелом фигура движения получилась в виде вымпела с начал...


Вкусные рецепты: Пирог из домашней лапши, Пирог рыбный, Буше а ля рэн - курица по-королевски

Вкусные рецепты: Пирог из домашней лапши, Пир...


Пирог из домашней лапшиДля этого пирога я взяла вчерашний суп из домашней лапши, он у меня получился густоватым. Туда я добавила манку, яйца, специи. По консистенции получилось тесто как на оладья. См...


Вкусные рецепты: Шоколадные пирожные, Желейное печенье, Багет "Epi de Ble" (колосок пшеницы)

Вкусные рецепты: Шоколадные пирожные, Желейно...


Шоколадные пирожныеКоржи: Взбить желтки с сахаром до белой пены, добавить растопленное масло (маргарин), какао, коньяк, разрыхлитель, муку, мускатный орех, хорошо все взбить. Отдельно взбить белки в к...


Радиаторы отопления

Радиаторы отопления


Так вышло что наш климат позволяет нам переживать 4 сезона года, теплые весенние дни, жаркие летние, прохладные осенние ночи и холодную зиму. Вроде бы нам повезло, что мы можем видеть все сезоны года ...


Стоит прочесть

Всё ли вам известно о пилках для ногтей?

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

Готический литературный проект из Крыма

Горный Крым - удивительный мир, в котором течение времени прихотливо, переменчиво и так непохоже на безумный ритм наших будней, заданный все возрастающими запросами общества глобального потребления. Э...

Как иностранцу оформить ВНЖ в 2016 году?

Иностранные граждане, которые получили разрешение на временное проживание, могут оформить себе вид на жительство в России. ВНЖ – документ, который дает иностранцу статус постоянно проживающего в РФ и...

Как организовать свадебный пир?

Свадебное пиршество — это один из важных моментов, когда в сборе все гости. Все, как говорили в старину, играют свадьбу… Как же устроить этот банкет? Здесь важно определиться с ...

Сколько стоит построить дом

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

Песок в строительстве

Песок – знакомый нам с детства материал, из которого так любят лепить и строить малыши. Взрослым тоже прекрасно известно, что на сегодняшний день без песка не может обойтись ни одно строительство. И...

Снижение веса вместе в пансионате

Невозможно разыскать кого-нибудь, не хотевшего иметь красивого и стройного тела. На какие только пытки не решаются девушки, чтобы достичь идеальной фигуры. Если вы занимались похудением, вы в курсе, ч...

Семейные традиции. Как жить ярко и интересно?

Есть такой старенький французский фильм «Бум». О сумасшедших родителях, не дающих скучать никому. О первой любви. И о потрясающем взаимопонимании в семье. Что бы ни случилось у папы с...

Выбор красивых мобильных номеров

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

Нижнее белье для беременной

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

Развивая портал:

Наш сайт является ресурсом, который включает в себя широкий каталог информативных и интересных статей. Каждый гость отыщет для себя что-нибудь полезное. Современный дизайн позволяет вам моментально находить нужную информацию. Самые разнообразные тематические статьи дают возможность вам совершенствоваться в той или иной сфере. Быть более начитанным и грамотным. Современный дизайн сайта позволяет просматривать статьи на всех гаджетах. Теперь найти требуемую информацию стало совершенно легко.

Мы подобрали для вас познавательные и отличные статьи. У нас портале вы найдете ответы на интересующие вас вопросы. Стандартная система поиска позволяет вам стремительно отыскать нужную информацию. Адаптированный дизайн позволяет вам просматривать информацию на любых электронных устройствах. Отныне, поиск подходящей информации будет занимать у вас считанные секунды.