Использование 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




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

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



Вкусные рецепты: Печеночный тортик, Рулет «Березовое полено», Рисовые шарики

Вкусные рецепты: Печеночный тортик, Рулет «Бе...


Печеночный тортикПечень пропустить через мясорубку Добавить яйца,молоко,муку,растит.масло,соль,взбить Все ингридиенты перемешать Испечь тонкие (у меня получились)блины Начинка: Лук мелко порезать морк...


Пейзажи Голландии Айвана Майгуа

Пейзажи Голландии Айвана Майгуа


Фотограф Айван Майгуа (Ivan Maigua) родился в городе Отавало в Эквадоре, но в настоящее время живет в Амстердаме, Голландия. Айван работает фотографом и графическим дизайнером. Его фотографии отличают...


Как стать студентом Венского университета в Австрии. Необходимые документы.

Как стать студентом Венского университета в А...


Для тех, кто все же решился продолжить свое пребывание на просторах свободной Европы в стенах высших учебных заведений. Речь пойдет о Венском университете.    Сертификат, подтверждающи...


Василий Верещагин: как художник боролся против войны?

Василий Верещагин: как художник боролся проти...


Известный русский художник Василий Васильевич Верещагин родился 26 октября 1842 года в городе Череповце. Известны восторженные высказывания о творчестве русского баталиста Верещагина австрийской...


Чехлы интернет - магазина «Itsell» - стильная защита

Чехлы интернет - магазина «Itsell» - стильная...


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


Как носить контактные линзы и сберечь свои глаза?

Как носить контактные линзы и сберечь свои гл...


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


Самое интересное

Как не разбудить весь дом? Исповедь слонопотама

Ранее-раннее утро. Скрип двери. Топот. Шуршание, громыхание, звон. Потом гнетущая тишина и… обрушивающийся на спящий рассудок поток звуков, появившийся оттого, что кто-то опять что-то уронил! ...

Кадастровый учет и внесение изменений: основные ню

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

Какие придворные чины существовали на Руси?

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

Трудности, возникающие при заказе гостиницы

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

Меня кинули, не кинули, а так, положили на полочку

Меня кинули. Да нет, даже не бросили, а так, положили на дальнюю полку, как использованную игрушку, которая надоела, а выкинуть вроде жалко. Когда я захотела выяснить наши отношения и расставить все т...

Установить счётчик горячей воды

Во-первых, счётчик горячей воды должен иметь срок поверки не позже двух месяцев со дня своего производства. Дата выпуска должна быть указана в паспорте водомера. Если вы случайно приобрели «просроченн...

Вкусные рецепты: Греческий торт, Салат с беконом.,

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

Что делать, если ребенок отрывает вас от дел?

«Иногда кажется, что мои дети не испытывают никакого уважения к тому, что я делаю, если это не связано с ними. Чтобы я ни делала — готовила обед, накладывала макияж, разговаривала с с...

Болезнь – не наказание, а дар Свыше

Существует множество различных мнений относительно природы различных заболеваний. Одни говорят, что болезни – следствие стрессов, другие – отрицательных мыслей и действий, кто-то объясняет это родовым...

Правильно выбираем полочные стеллажи

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

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

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

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