Отмывка рельефа
Оцифровка планшета, создание классификаторов. Определение ограничений целостности. Реализация подключаемого модуля. Построение TIN-модели рельефа, взаимодействие с пользователем. Программа проверки корректности данных. Пример модуля раскраски рельефа.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | курсовая работа |
Язык | русский |
Дата добавления | 25.05.2013 |
Размер файла | 3,0 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Размещено на http://www.allbest.ru/
[Введите текст]
САМАРСКИЙ ГОСУДАРСТВЕННЫЙ АЭРОКОСМИЧЕСКИЙ УНИВЕРСИТЕТ ИМЕНИ АКАДЕМИКА С.П. КОРОЛЕВА
Факультет информатики
Кафедра геоинформатики
Курсовая работа
по дисциплине «Геоинформационные системы»
Тема: «Отмывка рельефа»
Самара 2009
Техническое задание
Общий план:
Оцифровка планшета;
Создание внешнего подключаемого модуля для «Ингео», позволяющего выполнять отмывку (раскраску) рельефа.
Интегрирование разработанного модуля посредством использования встроенного в «Ингео» интерпретатора скриптового языка программирования.
Часть 1. Оцифровка планшета
Ввести в ГИС «Ингео» информацию с отсканированной копии планшета городской застройки масштаба 1:500.
Геометрическая трансформация и подключение к «Ингео» с помощью программы "Менеджер растров".
Создание классификатора
Необходимо создать классификатор на следующие слои:
здания, стили:
контур здания (полигон);
текстовая подпись этажности и типа постройки;
текстовая подпись адреса.
сооружения, стили:
контур здания (полигон);
текстовая подпись типа здания;
текстовая подпись адреса.
ограждения (деревянные) со стилем - контур ограждения.
линии инженерные коммуникации одного вида, которые встречаются на планшете (вода, газ, канализация), стили:
наземная линия;
подземная линия;
назначение;
диаметр.
колодцы на инженерных коммуникациях выбранного типа:
колодец (точечный объект);
текстовая подпись отметок высот.
проезжие части улиц, стили:
граница проезжей части (полигон);
ось (линейный объект);
текстовая подпись наименования.
Между слоями необходимо установить межслойные топологические отношения и разработать структуру семантической базы данных. Создать справочник улиц с полями «код» и «наименование», чтобы при оцифровке семантическое поле «улица» у слоев зданий, и проезжих частей улиц заполнялось из справочника.
Написание программ (скрипов) проверки корректности данных. Скрипты должны проверять:
обязательное наличие соединения концов трубопровода с колодцами;
для трубопроводов автоматически заполнять в зависимости от стиля семантическое поле «тип трубопровода» - надземный или подземный;
при удалении колодца проверять, есть ли подсоединенные к нему трубопроводы и при их наличии не давать удалить объект.
Оцифровка и занесение семантической информации по слоям созданного классификатора (возможно по части планшета).
Часть 2. Создание подключаемого модуля
Главной функцией разрабатываемого модуля является отмывка (раскраска) рельефа.
Входными данными для работы модуля служат пространственные координаты вершин, характеризующих форму рельефа. Выходными данными являются треугольники, описывающие TIN-модель, построенную по входным данным.
Каждому треугольнику ставится в соответствие признак освещённости, который и представляет цвет участка поверхности.
Часть 3. Интегрирование модуля
Интегрирование модуля заключается в написание программы на встроенном в «Ингео» скриптовом языке, которая реализует команды пользователя «Ингео» по отмывке рельефа посредством вызова соответствующих функций подключаемого модуля. Таким образом, главной функцией программы является реализация интерфейса взаимодействия с пользователем.
Введение
С того самого момента, как появились первые карты, перед картографами встала проблема, как отразить трехмерный рельеф на двухмерной карте.
Были использованы горизонтали (линии равных высот), на картах давалась отмывка (штриховка) рельефа, разные высоты рельефа местности выделялись окраской с различной тональностью.
Но и сегодня развитие картографии не стоит на месте и, с развитием компьютерной техники, появляются новые возможности представления рельефа местности. Все большую популярность приобретает трехмерная визуализация модели рельефа, так как она позволяет даже профессионально неподготовленным людям, получить достаточно полное представление о рельефе. Современные технологии трехмерной визуализации позволяют «взглянуть» на рельеф местности из любой точки пространства и под любым углом.
В основном, отмывку рельефа, как способа изображения рельефа местности, производят методом теневой пластики при косом, реже отвесном освещении. Также возможна отмывка как пластическое полутоновое изображение рельефа путем наложения теней. Отмывка создаёт иллюзию выпуклости изображённого рельефа, и ее использование делает карту внешне более привлекательной.
Обычно отмывку применяют при боковом освещении (когда источник света находится в левом верхнем углу карты), отвесном освещении (когда свет падает сверху) или при комбинированном освещении (когда местность считается освещенной с разных сторон).
1. Оцифровка планшета
1.1 Создание классификаторов
К системе ИнГео был подключен дополнительный модуль Менеджер растров на уровне Базы Данных. При помощи данного модуля геометрическая трансформация и подключение к ИнГео растрового файла «218.bmp» - копии планшета городской застройки.
С помощью стандартных средств ИнГео был создан новый проект, на него была добавлена растровая карта, для которой созданы следующие слои:
Здания и сооружения;
ограждения;
коммуникации;
колодцы;
проезжая часть улицы;
высоты
Рельеф.
Рис. 1
Для слоя Здания и сооружения было создано три стиля отображения:
контур здания (способ отображения - полигон);
текстовая подпись (способ отображения - текстовый);
адрес (способ отображения - текстовый).
Рис. 2
Также для каждого слоя была создана соответствующая семантическая таблица, соответственно:
Здания (с полями ID, этажность, тип, материал);
номер (ID, номер, улица);
коммуникации (ID, назначение, диаметр);
колодцы (ID, высота);
улицы (ID, название);
вершины (ID, высота).
Для слоя Здания и сооружения были созданы стили отображения:
полигон (стандартный метод отображения);
текстовая подпись адреса (метод отображения - текстовый);
жилые (метод отображения - текстовый);
нежилые (метод отображения - текстовый);
кирпичный жилой (метод отображения - текстовый);
кирпичный нежилой (метод отображения - текстовый).
Рис. 3
Для слоя Ограждения создан стиль Контур ограждения со стандартным методом отображения.
Рис. 4
Для слоя Коммуникации было создано три стиля отображения:
Текстовая подпись назначения (метод отображения - текстовый);
Трубопровод подземный (метод отображения - текстовый);
Трубопровод надземный (метод отображения - стандартный).
Рис. 5
Для слоя Колодцы было создано два стиля отображения:
Колодец (метод отображения - символьный);
Подпись отметок высот (метод отображения - текстовый).
Рис. 6
Для слоя Проезжая часть улицы было создано три стиля отображения:
Граница проезжей части (метод отображения - стандартный);
Осевая (метод отображения - символьный);
Текстовая подпись наименования (метод отображения - текстовый).
Рис. 7
Для слоя Высоты создан стиль Вершина с символьным методом отображения.
Рис. 8
Для слоя Рельеф было создано два стиля отображения:
Освещенная поверхность (метод отображения - полигон);
Скрытая поверхность (метод отображения - полигон).
Рис. 9
Были установлены следующие топологические связи между слоями:
Здания и сооружения - Здания и сооружения;
Здания и сооружения - Ограждения;
Здания и сооружения - Коммуникации;
Ограждения - Ограждения;
Ограждения - Проезжая часть улицы;
Коммуникации - Коммуникации;
Колодцы - Колодцы;
Проезжая часть улицы - Проезжая часть улицы.
1.2 Определение ограничений целостности
Для проверки корректности данных было разработано несколько скриптов, обеспечивающих целостность данных в следующих случаях.
Обязательное наличие соединения концов трубопровода с другими элементами сети.
Трубопровод обязательно должен быть соединён обоими концами с колодцем или зданием/сооружением. Связь эта осуществляется посредством топологических соединений при редактировании карты. Поэтому была разработана программа, отслеживающая создание объектов слоя Коммуникации. Если вновь созданный объект-трубопровод не имеет топологических связей со зданиями или колодцами на обоих своих концах, то программа отменяет создание объекта и информирует об этом пользователя через диалоговое окно.
Для трубопроводов автоматически заполнять в зависимости от стиля семантическое поле «тип трубопровода» - надземный или подземный.
После создания объекта-трубопровода из слоя Коммуникации проверяется идентификатор его стиля, в соответствии которым в таблицу семантических данных объекта записывается значение - надземный или подземный.
При удалении колодца проверять, есть ли подсоединенные к нему трубопроводы и при их наличии не давать удалить объект.
Корректность данной операции проверяется скриптовой программой через исследование имеющихся топологических связей объекта-колодца с объектами слоев Коммуникации и Здания. Если такие связи отсутствуют, то объект-колодец удаляется, иначе производится отмена удаления объекта, о чём пользователю сообщается через диалоговое окно.
1.3 Оцифровка планшета
Рис. 10 - Оцифровка зданий и сооружений
Рис. 11 - Оцифровка колодцев и коммуникаций:
Рис. 12 - Оцифровка ограждений и проезжей части улицы
2. Реализация подключаемого модуля
2.1 Описание рельефа
Для описания рельефа местности требуются векторные данные, характеризующие пространственные координаты поверхности. Таким объектом являются вершины.
В дальнейшем для описания рельефа предполагается использование трёхмерной Декартовой системы координат. Таким образом, вершина характеризуется двумя координатами на плоскости и одной координатой, соответствующей высоте точки рельефа.
В терминах ГИС «Ингео» это означает, что векторный объект - вершина кроме своих пространственных координат - X и Y, имеет также семантические данные, содержащие информацию о высоте точки рельефа.
Вершины позволяют некоторым образом описать рельеф, для визуализации же требуются другие объекты.
Далее предполагается, что поверхность рельефа аппроксимируется TIN-моделью. Таким образом, для визуализации рельефа требуются объекты - треугольники. Кроме того отмывка рельефа подразумевает разделение освещённых участков рельефа и скрытых. В «Ингео» это означает наличие векторных треугольных объектов двух стилей - освещённых и скрытых.
2.2 Построение TIN-модели рельефа
Работа модуля отмывки рельефа основана на построении триангуляционной модели по набору точек (вершин), описывающих поверхность. Данная операция является наиболее важной и вычислительно-затратной в работе модуля.
Триангуляцию некоторого набора точек можно выполнить различным образом. Среди множества различных триангуляций выделяют триангуляцию Делоне, которая является единственной для имеющегося набора точек. Определение триангуляции Делоне на плоскости выглядит следующим образом:
Триангуляцией Делоне для множества точек S на плоскости называют триангуляцию DT(S) такую, что никакая точка A из S не содержится внутри окружности, описанной вокруг любого треугольника из DT(S), такого, что ни одной из вершин его не является точка A.
В дальнейшем для построения TIN-модели рельефа будем использовать триангуляцию Делоне. Реализация триангуляции Делоне в подключаемом модуле основана на алгоритме Уотсона, схема которого приведена на рисунке 13.
Рис. 13 - Алгоритм Уотсона построения триангуляции Делоне
Процедура образования нового разбиения при добавлении новой точки заключается в следующем. Сначала выбираются треугольники, описанная вокруг которых окружность содержит добавляемую точку. По определению эти треугольники не могут входить в триангуляцию Делоне, поэтому их следует удалить из разбиения. Выбранные треугольники разбиваются на отрезки, дублирующиеся отрезки удаляются. Оставшиеся отрезки формируют границу выпуклого многоугольника, который разбивается на новые треугольники простым соединением вершин с добавляемой точкой. Данная процедура схематично показана на рисунке 14.
Рис. 14 - Процедура разбиения алгоритма Уотсона: а) - исходное разбиение; б) - выбор треугольников, описанная вокруг которых окружность содержит новую точку; в) - удаление треугольников; г) - разбиение выпуклого многоугольника
После удаления супертреугольника граничные вершины снова проверяются на возможность построения треугольников, удовлетворяющих условию Делоне, и в разбиение добавляются недостающие треугольники. Полученная в итоге триангуляция будет триангуляцией Делоне.
2.3 Раскраска рельефа
После построения TIN-модели, рельеф можно подвергнуть раскраске. Раскраска заключается в разделении треугольников, описывающих рельеф на два класса: освещённые и скрытые. Положение источника света полагается на северо-западе. В зависимости от того как повёрнута плоскость треугольника к источнику, треугольник либо является освещённым, либо скрытым.
Процедура раскраски приведена на рисунке 15.
Рис. 15 - Процедура раскраски рельефа
2.4 Взаимодействие с пользователем
Для выполнения функций раскраски рельефа служит скрипт, написанный на встроенном в «Ингео» языке. Данный скрипт, реагирует на нажатие соответствующего пункта в меню. После выбора пункта меню происходит сбор требуемой информации и вызов соответствующего метода подключаемого модуля. Далее выполняется удаление старых данных о раскраске рельефа и создаются новые векторные объекты, соответствующие результатам работы модуля.
2.5 Результат работы модуля
Программа предоставляет пользователю возможность осуществлять раскраску рельефа в двух режимах: либо по всем вершинам, либо по выбранному набору вершин.
Вершины, по которым программа строит модель рельефа, создаются как объекты слоя «Высоты» с указанием семантических данных о значении высот вершин. После того как объекты-вершины созданы (как минимум три) программа может выполнить раскраску рельефа. Для этого необходимо выбрать вершины, по которым требуется построить рельеф, и выбрать в главном меню пункт Рельеф >> Рельеф по выбранным вершинам, либо сразу выбрать пункт меню Рельеф >> Рельеф по всем вершинам, при этом выбор вершин не требуется.
На рисунке 16 приведён результат работы программы для 19 вершин.
Рис. 16 - Результат работы модуля раскраски рельефа для 19 вершин
Приложение A
Программа проверки корректности данных
' Идентификатор слоя "коммуникации"
PIPE_LAYER_ID = "000100000405"
' Идентификатор слоя "коммуникации"
PIPE_LAYER_ID = "000100000405"
' Идентификатор стиля "надземный трубопровод"
OVERGROUND_PIPE_STYLE = "000100000418"
' Идентификатор стиля "подземный трубопровод"
UNDERGROUND_PIPE_STYLE = "000100000417"
' Название семантической таблицы слоя "коммуникации"
PIPE_SEM_DATA_TABLE = "коммуникации"
' Название поля типа трубопровода в семантической таблице слоя "коммуникации"
PIPE_TYPE_FIELD = "тип"
' Значение поля типа трубопровода для трубопровода "надземного стиля"
PIPE_OVERGROUND_TYPE_VALUE = "надземный"
' Значение поля типа трубопровода для трубопровода "подземного стиля"
PIPE_UNDERGROUND_TYPE_VALUE = "подземный"
' Идентификатор слоя "здания"
HOUSE_LAYER_ID = "0001000003F1"
' Идентификатор слоя "колодцы"
WELL_LAYER_ID = "00010000040E"
' Сообщение об ошибке при создании объекта слоя "коммуникации" без
' необходимых топологических связей
ERR_NOT_LINKED_PIPE = "Невозможно создать объект ТРУБОПРОВОД." + chr(13) +
"Отсутствуют необходимые топологические связи."
' Сообщение об ошибке при удалении объекта слоя "колодцы", который имеет
' топологические связи
ERR_LINKED_WELL = "Невозможно удалить объект КОЛОДЕЦ." + chr(13) +
"Существуют топологические связи."
'----------------------------------------------------
' Вызывается после создания пространственного объекта
'----------------------------------------------------
sub DbMapObjects_CreateComplete(aMapObjectID, aMy)
' объекты активной базы данных
dim mapObjects
set mapObjects = Application.ActiveDb.MapObjects
' созданный объект
dim createdObject
set createdObject = mapObjects.GetObject(aMapObjectID)
' если был создан трубопровод
if createdObject.LayerID = PIPE_LAYER_ID then
if not isLinkedPipe(createdObject) then
' если у трубопровода отсутствуют необходимые
` топологические связи
mapObjects.DeleteObject(aMapObjectID)
mapObjects.UpdateChanges()
MsgBox ERR_NOT_LINKED_PIPE, 0, "Ошибка"
else
' если объект трубопровода создан корректно
dim styleID
styleID = createdObject.Shapes.Item(0).StyleID
dim semData
if styleID = OVERGROUND_PIPE_STYLE then
set semData = createdObject.SemData
semData.SetValue PIPE_SEM_DATA_TABLE, PIPE_TYPE_FIELD,
PIPE_OVERGROUND_TYPE_VALUE, 0
mapObjects.UpdateChanges()
elseif styleID = UNDERGROUND_PIPE_STYLE then
set semData = createdObject.SemData
semData.SetValue PIPE_SEM_DATA_TABLE, PIPE_TYPE_FIELD,
PIPE_UNDERGROUND_TYPE_VALUE, 0
mapObjects.UpdateChanges()
end if
end if
end if
end sub
'-----------------------------------------------------
' Вызывается перед удалением пространственного объекта
'-----------------------------------------------------
sub DbMapObjects_WillDelete(aMapObjectID)
' объекты активной базы данных
dim mapObjects
set mapObjects = Application.ActiveDb.MapObjects
' удаляемый объект
dim deletedObject
set deletedObject = mapObjects.GetObject(aMapObjectID)
' если удаляется колодец
if deletedObject.LayerID = WELL_LAYER_ID and
isLinkedWell(deletedObject) then
err.raise 60000, "", ERR_LINKED_WELL
end if
end sub
'-------------------------------------------------------------------------
' Проверка необходимых связей окончаний объекта "трубопровода" с объектами
' слоев "колодцы" и "здания и сооружения"
'-------------------------------------------------------------------------
function isLinkedPipe(pipeObject)
' объекты активной базы данных
dim mapObjects
set mapObjects = Application.ActiveDb.MapObjects
' получить координаты окончаний объекта
dim x1
dim y1
dim x2
dim y2
getPipeEnds pipeObject, x1, y1, x2, y2
' топологические связи "трубопровода"
dim topoLinks
set topoLinks = pipeObject.TopoLinks
dim end1Linked
end1Linked = false
dim end2Linked
end2Linked = false
dim linkedObject
dim i
i = 0
' обход всех топологических связей "трубопровода"
while (not end1Linked or not end2Linked) and (i < topoLinks.Count)
set linkedObject = mapObjects.GetObject(topoLinks.Item(i))
'если очередной топологически связанный объект является объектом
'слоя "колодец" или "здания и сооружения"
if linkedObject.LayerID = WELL_LAYER_ID or
linkedObject.LayerID = HOUSE_LAYER_ID then
' если топологически связанный объект содержит первую
' точку окончания "трубопровода"
if isContourTouched(linkedObject, x1, y1) then
end1Linked = true
end if
' если топологически связанный объект содержит вторую
' точку окончания "трубопровода"
if isContourTouched(linkedObject, x2, y2) then
end2Linked = true
end if
end if
i = i + 1
wend
isLinkedPipe = end1Linked and end2Linked
end function
'------------------------------------------------
' Проверка наличия связей колодца с трубопроводом
'------------------------------------------------
function isLinkedWell(wellObject)
' объекты активной базы данных
dim mapObjects
set mapObjects = Application.ActiveDb.MapObjects
' топологические связи "колодца"
dim topoLinks
set topoLinks = wellObject.TopoLinks
dim linked
linked = false
dim linkedObject
dim i
i = 0
' обход всех топологических связей "колодца"
while (not linked) and (i < topoLinks.Count)
set linkedObject = mapObjects.GetObject(topoLinks.Item(i))
'если очередной топологически связанный объект является объектом
'слоя "коммуникации"
if linkedObject.LayerID = PIPE_LAYER_ID then
linked = true
end if
i = i + 1
wend
isLinkedWell = linked
end function
'----------------------------------------------------
' Получить координаты окончаний объекта "трубопровод"
'----------------------------------------------------
sub getPipeEnds(pipeObject, x1, y1, x2, y2)
dim shapes
set shapes = pipeObject.Shapes
dim contour
set contour = shapes.Item(0).Contour
dim contourPart
set contourPart = contour.Item(0)
dim convexity
' получение координат первого окончания "трубопоровода"
contourPart.sGetVertex 0, x1, y1, convexity
set contour = shapes.Item(shapes.Count - 1).Contour
set contourPart = contour.Item(contour.Count - 1)
' получение координат второго окончания "трубопоровода"
contourPart.sGetVertex contourPart.VertexCount - 1, x2, y2, convexity
end sub
'-------------------------------------------------------------
' Проверить лежит ли точка (x, y) на контуре объекта mapObject
'-------------------------------------------------------------
function isContourTouched(mapObject, x, y)
' создание конутра, состоящего только из точки (x, y)
dim vertex
set vertex = Application.CreateObject(TIngeoObjectClass.inocContour, 0)
dim vertexPart
set vertexPart = vertex.Insert(0)
vertexPart.InsertVertex 0, x, y, 0
dim shapes
set shapes = mapObject.Shapes
dim touched
touched = false
dim contour
dim contourRelation
dim i
i = 0
' обход всех фигур объекта mapObject
while (not touched) and (i < shapes.Count)
set contour = shapes.Item(i).Contour
' определение связи контура очередной фигуры с точкой (x, y)
contourRelation = contour.TestRelation(vertex)
' если точка (x, y) лежит на контуре очередной фигуры
if contourRelation = TIngeoContourRelation.incrTouched then
touched = true
end if
i = i + 1
wend
isContourTouched = touched
end function
Приложение Б
Модуль раскраски рельефа
рельеф модуль программа целостность
Основной класс модуля
/// <summary>
/// Класс <c>ForInGEO</c> реализует методы построения поверхности рельефа.
/// </summary>
[ClassInterface(ClassInterfaceType.None)]
public class ForInGEO : IForInGEO
{
/// <summary>Вектор направления солнечных лучей.</summary>
private Vector sun = new Vector(1.0, 1.0, 0.0);
/// <summary>Точки построения поверхности рельефа.</summary>
private IDictionary<Point, string> points =
new Dictionary<Point, string>();
/// <summary>
/// Алгоритм, реализующий триангуляцию поверхности рельефа.
/// </summary>
private IDelaunay delaunay = new WatsonAlgorithm();
/// <summary>Элементы построенной поверхности рельефа.</summary>
private ReliefFace[] faces = null;
/// <summary>Задать направление солнечных лучей.</summary>
/// <param name="x">
/// компонента направляющего вектора по оси <c>x</c>.
/// </param>
/// <param name="y">
/// компонента направляющего вектора по оси <c>y</c>.
/// </param>
/// <param name="z">
/// компонента направляющего вектора по оси <c>z</c>.
/// </param>
public void setSunDirection(double x, double y, double z)
{
sun = new Vector(x, y, z);
}
/// <summary>Добавить точку определяющую рельеф.</summary>
/// <param name="id">идентификатор точки.</param>
/// <param name="x">координата поси <c>x</c>.</param>
/// <param name="y">координата поси <c>y</c>.</param>
/// <param name="z">координата поси <c>z</c>.</param>
public void addPoint(string id, double x, double y, double z)
{
Point3D p = new Point3D(x, y, z);
points.Add(p, id);
}
/// <summary>Удалить все точки для построения рельефа.</summary>
public void removePoints()
{
points.Clear();
}
/// <summary>Построить рельеф.</summary>
public void buildRelief()
{
ICollection<TriangulationStructure> triangulation =
delaunay.buildTriangulation(points.Keys);
faces = new ReliefFace[triangulation.Count];
convert(triangulation, faces);
illuminate(faces, sun);
contrast(faces);
shlColor(faces, 8);
}
/// <summary>
/// Получить количесво элементов поверхности рельефа.
/// </summary>
/// <returns>количество элеметов поверхности рельефа.</returns>
public int numReliefFaces()
{
return faces == null ? 0 : faces.Length;
}
/// <summary>Получить элемент поверхности рельефа.</summary>
/// <param name="numFace">номер элемента.</param>
/// <returns>элемент поверхности рельефа.</returns>
public ReliefFace getReliefFace(int numFace)
{
if (faces != null && numFace >= 0 && numFace < faces.Length)
{
return faces[numFace];
}
else
{
return null;
}
}
/// <summary>
/// Преобразовать триангуляцию в элементы поверхности рельефа.
/// </summary>
/// <param name="trian">преобразуемая триангуляция.</param>
/// <param name="faces">
/// массив для сохранения элементов поверхности.
/// </param>
private void convert(ICollection<TriangulationStructure> trian,
ReliefFace[] faces)
{
IEnumerator<TriangulationStructure> enumer =
trian.GetEnumerator();
Triangle t;
Point3D p;
string id;
ReliefFace rf;
ReliefVertex rv1, rv2, rv3;
int i = 0;
while (enumer.MoveNext())
{
t = enumer.Current.getTriangle();
p = (Point3D) t.getVertex(0);
points.TryGetValue(p, out id);
rv1 = new ReliefVertex(id, p.x, p.y, p.z);
p = (Point3D) t.getVertex(1);
points.TryGetValue(p, out id);
rv2 = new ReliefVertex(id, p.x, p.y, p.z);
p = (Point3D)t.getVertex(2);
points.TryGetValue(p, out id);
rv3 = new ReliefVertex(id, p.x, p.y, p.z);
rf = new ReliefFace(rv1, rv2, rv3);
faces[i] = rf;
++i;
}
}
/// <summary>
/// Выполнить освещение элементов поверхности рельефа.
/// </summary>
/// <param name="faces">элементы поверхности рельефа.</param>
/// <param name="sun">вектор направления лучей солнца.</param>
private static void illuminate(ReliefFace[] faces, Vector sun)
{
ReliefFace rf;
Point3D p1, p2, p3;
Vector normal;
for (int i = 0; i < faces.Length; ++i)
{
rf = faces[i];
p1 = vertexToPoint3D(rf.vertex1);
p2 = vertexToPoint3D(rf.vertex2);
p3 = vertexToPoint3D(rf.vertex3);
normal = Geom3DUtil.normal(p1, p2, p3);
correctNormal(normal);
double cos = Geom3DUtil.cosBetween(normal, sun);
if (cos < 0.0)
{
rf.color = convertToLight(-cos);
}
else
{
rf.color = convertToDark(cos);
}
}
}
/// <summary>
/// Преобразовать значение модуля косинуса угла между нормалью и
/// направлением источника света в оттенок тёмного цвета.
/// </summary>
/// <param name="abscos">модуль косинуса угла.</param>
/// <returns>значение цвета.</returns>
private static long convertToDark(double cos)
{
return (long) (128 + 127 * cos);
}
/// <summary>
/// Преобразовать значение модуля косинуса угла между нормалью и
/// направлением источника света в оттенок светлого цвета.
/// </summary>
/// <param name="abscos">модуль косинуса угла.</param>
/// <returns>значение цвета.</returns>
private static long convertToLight(double cos)
{
return (long) (127 * cos);
}
/// <summary>
/// Откантрастировать раскраску элементов поверхности.
/// </summary>
/// <param name="faces">элементы поверхности.</param>
private static void contrast(ReliefFace[] faces)
{
long minLight = long.MaxValue;
long maxLight = long.MinValue;
long minDark = long.MaxValue;
long maxDark = long.MinValue;
long color;
for (int i = 0; i < faces.Length; ++i)
{
color = faces[i].color;
if (color < 128)
{
if (color < minLight)
{
minLight = color;
}
if (color > maxLight)
{
maxLight = color;
}
}
else
{
if (color < minDark)
{
minDark = color;
}
if (color > maxDark)
{
maxDark = color;
}
}
}
double[][] A = new double[2][];
A[0] = new double[2];
A[1] = new double[2];
A[0][0] = minLight;
A[0][1] = 1;
A[1][0] = maxLight;
A[1][1] = 1;
double[] b = new double[2];
b[0] = 127;
b[1] = 0;
double[] light = LinearUtil.solve2x2(A, b);
A[0][0] = minLight;
A[0][1] = 1;
A[1][0] = maxLight;
A[1][1] = 1;
b[0] = 128;
b[1] = 255;
double[] dark = LinearUtil.solve2x2(A, b);
for (int i = 0; i < faces.Length; ++i)
{
color = faces[i].color;
if (color < 128)
{
faces[i].color = (long)(color * light[0] + light[1]);
}
else
{
faces[i].color = (long)(color * dark[0] + dark[1]);
}
}
}
/// <summary>
/// Сдвинуть битовое представление цветов элементов поверхности влево.
/// </summary>
/// <param name="faces">элементы поверхности.</param>
/// <param name="count">сдвиг.</param>
private static void shlColor(ReliefFace[] faces, int count)
{
long color;
for (int i = 0; i < faces.Length; ++i)
{
color = faces[i].color;
faces[i].color = color << count;
}
}
/// <summary>
/// Скорректировать вектор по следующему правилу:
/// если вектор направлен в сторону уменьшения координаты <c>z</c>, то
/// инвертировать его компоненты, иначе оставить вектор бех изменения.
/// </summary>
/// <param name="normal">вектор для корректировки.</param>
private static void correctNormal(Vector normal)
{
if (Geom3DUtil.cosBetween(normal, Vector.k) < 0)
{
normal.invert();
}
}
/// <summary>
/// Преобразовать вершину поверхности рельефа в трёхмерную точку.
/// </summary>
/// <param name="v">вершина поверхности рельефа.</param>
/// <returns>соответствующая точка.</returns>
private static Point3D vertexToPoint3D(ReliefVertex v)
{
return new Point3D(v.x, v.y, v.z);
}
}
Класс, реализующий триангуляцию
/// <summary>
/// Класс <c>WatsonAlgorithm</c> реализует алгоритм Уотсона для построения
/// триангуляции Делоне. Алгоритм заключается в следующем:
/// 1. Сначала строится супертреугольник, заключающий все вершины
/// триангуляции.
/// 2. Далее поочерёдно в имеющуюся триангуляцию добавляются новые
/// вершины.
/// 2.1 Все треугольники, для которых условие Делоне нарушается при
/// добавлении очередной вершины, удаляются.
/// 2.2 В области, образованной при удалении треугольников, создаются
/// новые треугольники путём соединения граничных вершин
/// образованной области с вновь добавляемой вершиной.
/// 3. После добавления в триангуляцию всех образующих её вершин,
/// супертреугольник построенный в пункте (1) удаляется.
/// 3.1 Удаляются все треугольники, имеющие вершиной вершину
/// супертреугольника.
/// 3.2 Все вершины внешней границы триангуляции, полученной после
/// удаления супертреугольника, проверяются на возможность
/// построения нового треугольника.
/// 3.2.1 Каждая тройка граничных вершин проверяется на выполнение
/// условия Делоне с остальными вершинами триангуляции.
/// 3.2.2 Если условие выполнено, то в триангуляцию добавляется
/// новый треугольник, составленный из даннной тройки
/// граничных вершин.
/// </summary>
public class WatsonAlgorithm : IDelaunay
{
/// <summary>Построить триангуляцию Делоне по набору точек.</summary>
/// <param name="points">набор точек для триангуляции.</param>
/// <returns>
/// набор триангуляционных структур, составляющих триангуляцию.
/// </returns>
public ICollection<TriangulationStructure>
buildTriangulation(ICollection<Point> points)
{
ICollection<TriangulationStructure> triangulation =
new LinkedList<TriangulationStructure>();
// построение супертреугольника.
Triangle superTriangle = DelaunayUtil.buildSuperTriangle(points);
TriangulationStructure ts =
new TriangulationStructure(superTriangle);
triangulation.Add(ts);
IEnumerator<Point> pEnumer = points.GetEnumerator();
IEnumerator<TriangulationStructure> tsEnumer;
ICollection<TriangulationStructure> tsViolated =
new LinkedList<TriangulationStructure>();
Line[] edges;
Line edge;
Point p;
while (pEnumer.MoveNext())
{
// очередная добавляемая точка
p = pEnumer.Current;
// поиск всех треугольников, нарушающих условие Делоне для
// очередной добавляемой точки
tsEnumer = triangulation.GetEnumerator();
tsViolated.Clear();
while (tsEnumer.MoveNext())
{
ts = tsEnumer.Current;
if (!DelaunayUtil.delaunayCondition(ts.getTriangle(), p))
{
tsViolated.Add(ts);
}
}
// удаление всех треугольников нарушающих условие Делоне
// для очередной добавляемой точки
tsEnumer = tsViolated.GetEnumerator();
while (tsEnumer.MoveNext())
{
ts = tsEnumer.Current;
remove(triangulation, ts);
}
// переразбиение на треугольники области триангуляции, которую
// занимали треугольники, нарушевшие условие Делоне
tsEnumer = tsViolated.GetEnumerator();
ICollection<TriangulationStructure> temp;
while (tsEnumer.MoveNext())
{
ts = tsEnumer.Current;
temp = new LinkedList<TriangulationStructure>(tsViolated);
temp.Remove(ts);
edges = ts.getTriangle().getEdges();
for (int i = 0; i < 3; ++i)
{
edge = edges[i];
if (find(temp, edge) == null)
{
Triangle t = new Triangle(p, edge.getEnd(0),
edge.getEnd(1));
add(triangulation, t);
}
}
}
}
// удаление супертреугольника
Point vertex;
TriangulationStructure[] forRemove;
ICollection<Point> bound = new LinkedList<Point>();
for (int i = 0; i < 3; ++i)
{
vertex = superTriangle.getVertex(i);
forRemove = find(triangulation, vertex);
for (int j = 0; j < forRemove.Length; ++j)
{
ts = forRemove[j];
remove(triangulation, ts);
for (int v = 0; v < 3; ++v)
{
p = ts.getTriangle().getVertex(v);
if (!superTriangle.hasVertex(p) && !bound.Contains(p))
{
bound.Add(p);
}
}
}
}
// восстановление недостающих граничных треугольников
IEnumerator<Point> p1Enumer = bound.GetEnumerator();
ICollection<Triangle> tested = new LinkedList<Triangle>();
Point p1, p2, p3;
while (p1Enumer.MoveNext())
{
p1 = p1Enumer.Current;
IEnumerator<Point> p2Enumer = bound.GetEnumerator();
while (p2Enumer.MoveNext())
{
p2 = p2Enumer.Current;
if (p2 == p1)
{
continue;
}
IEnumerator<Point> p3Enumer = bound.GetEnumerator();
while (p3Enumer.MoveNext())
{
p3 = p3Enumer.Current;
if (p3 == p1 || p3 == p2)
{
continue;
}
Triangle t = new Triangle(p1, p2, p3);
if (!contains(tested, t))
{
pEnumer = points.GetEnumerator();
bool delaunay = true;
while (pEnumer.MoveNext())
{
p = pEnumer.Current;
if (p != p1 && p != p2 && p != p3 &&
!DelaunayUtil.delaunayCondition(t, p))
{
delaunay = false;
break;
}
}
if (delaunay)
{
add(triangulation, t);
}
tested.Add(t);
}
}
}
}
return triangulation;
}
/// <summary>
/// Удалить из триангулляции указанную триангуляционную структуру.
/// </summary>
/// <param name="triangulation">триангуляция.</param>
/// <param name="ts">удаляемая триангуляционная структура.</param>
private static void
remove(ICollection<TriangulationStructure> triangulation,
TriangulationStructure ts)
{
Line[] edges = ts.getTriangle().getEdges();
for (int i = 0; i < 3; ++i)
{
ts.setEdgeNeighbor(null, edges[i]);
}
triangulation.Remove(ts);
}
/// <summary>
/// Добавить к триангулляции новую триангуляционную структуру.
/// </summary>
/// <param name="triangulation">триангуляция.</param>
/// <param name="t">
/// треугольник, соответствующий новой триангуляционной структуре.
/// </param>
/// <returns>новая добавленная триангуляционная структура.</returns>
private static TriangulationStructure
add(ICollection<TriangulationStructure> triangulation,
Triangle t)
{
TriangulationStructure ts = new TriangulationStructure(t);
Line[] edges = ts.getTriangle().getEdges();
Line edge;
TriangulationStructure neighbor;
for (int i = 0; i < 3; ++i)
{
edge = edges[i];
neighbor = find(triangulation, edge);
if (neighbor != null)
{
ts.setEdgeNeighbor(neighbor, edge);
}
}
triangulation.Add(ts);
return ts;
}
/// <summary>
/// Найти триангуляционную структуру с указанным ребром.
/// </summary>
/// <param name="triangulation">триангуляция.</param>
/// <param name="edge">ребро дя поиска.</param>
/// <returns>первая найденная триангуляционная структура.</returns>
private static TriangulationStructure
find(ICollection<TriangulationStructure> triangulation,
Line edge)
{
IEnumerator<TriangulationStructure> enumer =
triangulation.GetEnumerator();
TriangulationStructure ts;
while (enumer.MoveNext())
{
ts = enumer.Current;
if (ts.getTriangle().hasEdge(edge))
{
return ts;
}
}
return null;
}
/// <summary>
/// Найти все триангуляционные структуры, имеющие указаннуб вершину.
/// </summary>
/// <param name="triangulation">триангуляция.</param>
/// <param name="vertex">вершина для поиска.</param>
/// <returns>найденные триангуляционные структуры.</returns>
private static TriangulationStructure[]
find(ICollection<TriangulationStructure> triangulation,
Point vertex)
{
ICollection<TriangulationStructure> found =
new LinkedList<TriangulationStructure>();
IEnumerator<TriangulationStructure> enumer =
triangulation.GetEnumerator();
TriangulationStructure ts;
while (enumer.MoveNext())
{
ts = enumer.Current;
if (ts.getTriangle().hasVertex(vertex))
{
found.Add(ts);
}
}
TriangulationStructure[] result =
new TriangulationStructure[found.Count];
found.CopyTo(result, 0);
return result;
}
/// <summary>
/// Проверить содержит ли набор идентичный треугольник.
/// </summary>
/// <param name="triangles">набор треугольников.</param>
/// <param name="t">проверяемый треугольник.</param>
/// <returns>
/// <c>true</c>, если набор содержит треугольник с
/// эквивалентными вершинами.
/// </returns>
private static bool contains(ICollection<Triangle> triangles,
Triangle t)
{
IEnumerator<Triangle> enumer = triangles.GetEnumerator();
Triangle ct;
while (enumer.MoveNext())
{
ct = enumer.Current;
if (ct.hasVertex(t.getVertex(0)) &&
ct.hasVertex(t.getVertex(1)) &&
ct.hasVertex(t.getVertex(2)))
{
return true;
}
}
return false;
}
}
Скрипт, связывающий модуль с «Ингео»
// Название COM-объекта, осуществляющего раскраску рельефа.
var RELIEF_COM_APPLICATION = "ReliefDepiction.ForInGEO";
// Идентификатор слоя рельефа
var RELIEF_ID = "000100000494";
// Идентификатор слоя высот
var HEIGHTS_ID = "000100000490";
// Идентификатор стиля "Освещённая поверхность"
var LIGHT_FACE_ID = "000100000496";
// Идентификатор стиля "Скрытая поверхность"
var DARK_FACE_ID = "000100000497";
// Название таблицы семантических данных вершин
var VERTEX_TABLE = "Вершины";
// Название поля, содержащего семантические данные высот вершин
var VERTEX_FIELD = "Высота";
// Объект, реализующий триангуляцию
var relief = new ActiveXObject(RELIEF_COM_APPLICATION);
// Вызывается сразу после запуска программного модуля
function Module_StartComplete() {
// Направление источника света
relief.setSunDirection(1.0, -1.0, 0.0);
Module.LoadActions(Script.ContextCard, "ReliefActions",
Application.MainWindow.Actions);
Module.LoadMenu(Script.ContextCard, "ReliefMenu",
Application.MainWindow.Menu.Items);
}
// Построить рельеф по всем вершинам
function ReliefByAllVertices() {
Relief(false);
}
// Построить рельеф по выделенным вершинам
function ReliefBySelectedVertices() {
Relief(true);
}
// Построить рельеф
// onlySelected - если true, то рельеф строится только по выбранным вершинам,
// иначе по всем вершинам
function Relief(onlySelected) {
// Очистка прежних данных
relief.removePoints();
// Получение пространственных объектов
var mapObjects = Application.ActiveDB.MapObjects;
var selection = Application.Selection;
// Получение идентификаторов объектов слоя VectorMap.Высоты
var verticesIterator = mapObjects.QueryByLayers(HEIGHTS_ID);
verticesIterator.Reset();
// Обход и получение всех объектов слоя VectorMap.Высоты
var vertex;
var x, y, z;
while (!verticesIterator.EOF) {
// Идентификатор объекта
id = verticesIterator.ObjectID;
if (onlySelected && !selection.IsSelected(id))
{
verticesIterator.MoveNext();
continue;
}
vertex = mapObjects.GetObject(id);
// Координаты объекта
x = (vertex.X1 + vertex.X2) / 2;
y = (vertex.Y1 + vertex.Y2) / 2;
z = vertex.SemData.GetValue(VERTEX_TABLE, VERTEX_FIELD, 0);
// Передаём идентификатор и координаты очередной точки
relief.addPoint(id, x, y, z);
verticesIterator.MoveNext();
}
// Построение рельефа
relief.buildRelief();
}
// Вызывается после рисования каждого слоя
function DbPaint_LayerPaintComplete(aSurface, aLayerID, aVisible) {
if (aLayerID == RELIEF_ID && aVisible) {
// Параметры рисования
aSurface.Brush.Style = TInBrushStyle.inbsSolid;
aSurface.Pen.Color = 0;
aSurface.Pen.Mode = TInPenMode.inpmBlack;
aSurface.Pen.Style = TInPenStyle.inpsSolid;
// Количество элеметов поверхности рельефа.
var size = relief.numReliefFaces();
// Добавление рельефа на карту
var face;
var v1, v2, v3;
var triangle;
for (var i = 0; i < size; ++i) {
// Очередной элемент поверхности рельефа.
face = relief.getReliefFace(i);
v1 = face.vertex1;
v2 = face.vertex2;
v3 = face.vertex3;
// Преобразование элемента поверхности в треугольный контур
triangle =
Application.CreateObject(TIngeoObjectClass.inocContour, 0);
var vertices = triangle.Insert(0);
vertices.InsertVertex(-1, v1.x, v1.y, 0);
vertices.InsertVertex(-1, v2.x, v2.y, 0);
vertices.InsertVertex(-1, v3.x, v3.y, 0);
vertices.Closed = true;
// Настройка цвета отрисовки треугольника
aSurface.Brush.BackColor = face.color;
// Отрисовка очередного треугольника
aSurface.PaintContour(triangle, true);
}
}
}
Размещено на Allbest.ru
...Подобные документы
Последовательность построения поверхностей, картографирования значений глубин и сравнения полученных моделей при помощи модуля Geostatistical Analyst. Визуализация рельефа и создание 3D-моделей местности в ArcGIS. Создание видео-обзора 3D-поверхностей.
курсовая работа [5,5 M], добавлен 23.04.2012Разработка программного обеспечения по моделированию рельефа местности на основе топографических карт и прочих объектов на ней. Цифровые модели рельефа. Бикубическая интерполяция высотных данных. Технические требования к программному изделию.
отчет по практике [246,4 K], добавлен 06.04.2013Составляющие цифровой модели рельефа. Назначение и области применения программного комплекса Credo_Топоплан, обзор основных функций системы. Создание ЦМР по тахеометрической съемке местности и с помощью растровой подложки; работа в Credo_Transform.
курсовая работа [7,3 M], добавлен 19.04.2012Исследование планеты Марс с использованием многоцелевых космических автоматических станций. Фотограмметрическая обработка исходных изображений, построение и анализ полученной цифровой модели рельефа поверхности Марса; радиометрическая коррекция снимков.
дипломная работа [5,2 M], добавлен 17.10.2013Разработка функциональной и структурной схемы программного средства. Реализация основного модуля программы. Реализация модуля печати и модуля обновлений. Изучение взаимодействия информационных технологий, методов их интеграции и обмена данными.
дипломная работа [3,2 M], добавлен 27.10.2017Разработка концептуальной модели базы данных. Реализация алгоритмов и разработка управляющей программы. Разработка структуры системы управления данными. Методика проведения и результаты тестирования. Функционирование разработанного программного модуля.
курсовая работа [550,5 K], добавлен 08.06.2023Постановка задачи для модуля 1С. Бухгалтерия 3.0. Анализ существующих разработок в области интегрирования данных. Информационное обеспечение модуля "Связь 1С Предприятия 8.2. с "Казначейством". Программное и технологическое обеспечение данного модуля.
курсовая работа [1,5 M], добавлен 10.06.2013Разработка модуля для вычисления значения функции, который впоследствии подключается к программе ввода исходных данных с контролем допусимого значения в таблицу. Проектирование модуля для работы со строками и для обработки массивов текстовой информации.
курсовая работа [17,8 K], добавлен 24.09.2010Структурная диаграмма программного модуля. Разработка схемы программного модуля и пользовательского интерфейса. Реализация программного модуля: код программы; описание использованных операторов и функций. Вид пользовательской формы с заполненной матрицей.
курсовая работа [215,3 K], добавлен 01.09.2010Характеристика ОАО Завод пивоваренный "Моршанский". Характеристика структуры и состояния информационного пространства организации. Построение модели данных модуля для учета реализации товаров. Расчет показателей экономической эффективности проекта.
дипломная работа [3,4 M], добавлен 20.05.2013Разработка алгоритма фильтрации данных, полученных с систем спутниковой навигации с помощью GNSS-модуля. Анализ работы фильтра Калмана, его программная реализация под конкретную задачу. Выбор навигационных модулей для получения данных позиционирования.
дипломная работа [3,6 M], добавлен 12.01.2016Проектирование модуля регистрации документов. Анализ предметной области, спецификация требований. Построение диаграммы прецедентов Анализ архитектуры модуля в "OpenText Content Server 16.2". Разработка программы регистрации документов, ее тестирование.
дипломная работа [1,9 M], добавлен 25.08.2017Написание модуля на языке Ассемблер для вычисления значения выражения. Составление программы корректного ввода исходных данных в таблицу и вывода результата в виде таблицы. Создание модуля для обработки строк и программы корректного ввода исходных данных.
курсовая работа [36,8 K], добавлен 18.09.2010Освоение методов манипуляции параметрами SVG изображений при помощи JavaScript и возможности по анимации в современных браузерах. Интерфейс и структура модуля визуализации данных. Определение аномальных данных и их определение, реализованные типы.
курсовая работа [1,7 M], добавлен 20.05.2014Определение иерархии системы управления и контроля, а также структуры АСКУЭ. Разработка программного модуля обработки данных счётчиков электроэнергии. Определение технико-экономической актуальности, необходимости и возможности модернизации системы.
дипломная работа [1,0 M], добавлен 20.05.2017Проектирование программного модуля: сбор исходных материалов; описание входных и выходных данных; выбор программного обеспечения. Описание типов данных и реализация интерфейса программы. Тестирование программного модуля и разработка справочной системы.
курсовая работа [81,7 K], добавлен 18.08.2014Несколько определений ERP системы. Происхождение, развитие, признаки. Что дает внедрение. Особенности разработки программ на Java. Проектирование и реализация модуля ERP системы. Экономическая схема торговой деятельности. Пример реализации схемы.
курсовая работа [1,1 M], добавлен 10.09.2008Создание цифровой модели рельефа топокарт, проектирование на ее основе 3D-модели и растрового изображения топокарты. Используемые средства и технологии, модуль ArcGIS Spatial Analyst. Последовательность и этапы создания геоинформационной модели.
курсовая работа [4,1 M], добавлен 12.06.2013Создание приложения, которое на вход получает компьютерную структуру, обрабатывает ее и выводит на экран. Краткое описание используемых пространств имен и классов. Файлы программного модуля Beta. Пример его работы, порядок подключения к Веб-странице.
дипломная работа [1,3 M], добавлен 06.07.2015Информационные задачи и круг пользователей системы. Выработка требований и ограничений. Разработка проекта базы данных. Программная реализация проекта базы данных. Разработка хранимых процедур для поддержки сложных ограничений целостности в базе данных.
курсовая работа [706,2 K], добавлен 17.06.2012