- •Оглавление
- •Введение
- •4.1 Введение
- •4.2 Общая структура
- •4.3 Программная реализация sc-памяти
- •4.4 Программная реализация интерпретатора языка sCp
- •4.5 Программная реализация компонентов ядра пользовательских интерфейсов
- •4.6 Компоненты ядра пользовательского интерфейса
- •4.7. Базовый набор операций
- •4.8 Описание принципов организации диалога системы с пользователем
- •4.9 Режим диалога с использованием sCn-кода
- •4.10 Режим диалога с использованием sCg-кода
- •4.11 Общая схема взаимодействия подсистем
- •4.12 Разработчикам
- •Заключение
- •Пояснительная записка
Оглавление
ВВЕДЕНИЕ 2
1.Основные принципы построения компонента просмотра 3
1.1.Понятие геоинформационной системы 4
1.2.Возможности геоинформационной системы 4
1.3.Понятие геоинформационных форматов *.mid, *.mif 4
2.Проектирование компонента просмотра SCs текстов 6
2.1.Выбор средств проектирования 6
2.2.Определение основных требований к разрабатываемому компоненту 6
3.Реализация компонента просмотра SCs текстов 8
3.1.Реализация компонента просмотра mid/mif форматов 8
3.2.Реализация парсера mid/mif форматов 19
4.Расчётная работа на тему «Документирование web-ориентированной реализации интерпретатора sc-моделей» 23
4.1 Введение 23
4.2 Общая структура 24
4.3 Программная реализация sc-памяти 25
4.4 Программная реализация интерпретатора языка SCp 26
4.5 Программная реализация компонентов ядра пользовательских интерфейсов 27
29
4.6 Компоненты ядра пользовательского интерфейса 29
4.7. Базовый набор операций 30
4.8 Описание принципов организации диалога системы с пользователем 31
32
4.9 Режим диалога с использованием SCn-кода 33
4.10 Режим диалога с использованием SCg-кода 34
4.11 Общая схема взаимодействия подсистем 35
4.12 Разработчикам 36
ЗАКЛЮЧЕНИЕ 37
Введение
На сегодняшний день, информация и данных хранятся в очень большом количестве форматов. Эти форматы в своём большинстве не предназначены для непосредственного восприятия их человеком, а просто служат удобной формой её хранения, с целью дальнейшей обработки, редактирования, визуализации и т.п. Поэтому, актуальной проблемой в настоящее время является проблема отображения их в той форме, в которой пользователю с ней будет "удобно" работать.
Программные системы, интерфейсы которых предоставляют конечному пользователю большое количество возможностей и, в то же время, не "перегруженные" сложными вариантами использования этих возможностей, удобные пользователю, способные настраиваться и расширяться под конкретные нужды пользователя, имеют большое преимущество даже перед теми системами, которым они уступают по функциональным возможностям.
Из всего вышесказанного следует, что при разработке различных систем, проектированию пользовательского интерфейса стоит уделять внимание не меньшее, чем для разработки функциональности системы, а, возможно, для некоторых систем, этому компоненту системы должно быть уделено основное время проектирования и разработки.
Основной целью данного курсового проекта является адаптация компонента просмотра mid/mifформатов под последнюю версию ядра ПИ.
Данную цель можно разбить на следующие подцели:
Проанализировать существующие инструментарии для создания компонента просмотра на языке программирования Python
Выбрать инструментарий для создания компонента просмотра mid/mifформатов
Реализовать парсер mid/mif форматов
Реализовать компонент просмотра mid/mifформатов
В рамках курсовой работы ставятся следующие задачи:
Разработать компонент просмотра mid/mifформатов
Адаптировать компонент просмотра данных форматов
Определить направления дальнейшего развития разработанного компонента
Основные принципы построения компонента просмотра
Понятие геоинформационной системы
Геоинформационная система - система сбора, хранения, анализа и графической визуализации пространственных данных и связанной с ними информацией о необходимых объектах.
Термин также используется в более узком смысле - ГИС как инструмент позволяющий пользователям искать, анализировать и редактировать цифровые карты, а также дополнительную информацию об объектах, например высоту здания, адрес, количество жильцов.
Возможности геоинформационной системы
Геоинформационные системы включают в себя возможности:
систем управления базами данных;
редакторов растровой и векторной графики;
редакторов аналитических средств;
Применяются в:
Картографии;
Геологии;
Метеорологии;
Замлеустройстве;
Экологии;
Транспорте;
Экономике;
Обороне и др.
Понятие геоинформационных форматов *.mid, *.mif
Mif/mid– открытый текстовый обменный формат для геоинформационных систем. Состоит и двух файлов:
.mif– описание проекций, трансформаций и прочих дополнительных сведений, а, главное, перечень пространственных объектов (точки, линии, полигоны) с их координатами.
.mid– одноименный сmifфайл, в котором для каждого пространственного объекта, описанного вmif, приводится строка с семантическими данными.
Проектирование компонента просмотра SCs текстов
Выбор средств проектирования
Вопрос выбора подхода проектирования и средств разработки является основополагающим для всего жизненного цикла разрабатываемой системы. Он определяет не только количество материальных и временных ресурсов, затраченных на разработку, но и дальнейшую работоспособность системы.
В первую очередь, для реализации поставленных целей необходимо написать парсер для mid/mifформатов.
Синтаксический анализатор— это программа или часть программы, выполняющая синтаксический анализ.
Cинтаксический анализ— это процесс сопоставления линейной последовательности лексем (слов, токенов) языка с его формальной грамматикой. Результатом обычно является дерево разбора (синтаксическое дерево). Обычно применяется совместно с лексическим анализом.
Прежде всего, необходимо определится с инструментарием для написания синтаксического анализатора.
Выбранный анализатор должен обладать следующими свойствами:
возможность генерации программного кода в язык Python
наличие графических средств разработки
наличие полной и доступной документации
Определение основных требований к разрабатываемому компоненту
Определим основные требования, предъявляемые к разрабатываемому компоненту:
Разрабатываемый компонент должен иметь возможность распознавать mid/mifформаты
Разрабатываемый компонент должен иметь возможность отображать данные форматы
Разрабатываемый компонент должен иметь возможность редактирования и прорисовки данных форматов
Реализация компонента просмотра SCs текстов
Реализация компонента просмотра mid/mif форматов
Приведём пример фрагмента реализации просмотра mid/mifформатов
class MapViewer(BaseModeLogic):
def __init__(self):
BaseModeLogic.__init__(self)
self.sceneNodeRect = render_engine.SceneManager.createSceneNode()
self.rect = None
self._createRect()
self.material = None
self.texture = None
self.origin = [0.5, 0.5]
self.field = None
self.drawer = None
self.mapSurface = None
self.layerData = []
self.zoomRectCorners = [[0, 0], [0, 0]]
self.tex_size = (1024, 1024)
self.appendMode(ois.KC_V, map_modes.MapViewMode(self))
self.switchMode(ois.KC_V)
def __del__(self):
BaseModeLogic.__del__(self)
def delete(self):
"""Deletion message
"""
BaseModeLogic.delete(self)
def _setSheet(self, _sheet):
BaseModeLogic._setSheet(self, _sheet)
_sheet.eventRootChanged = self._onRoot
self._createFieldFromContent()
self._createMaterial()
self.rect.setMaterial(self.getMaterialName())
self._redraw()
def _onRoot(self, _isRoot):
"""Notification on sheet root state changing
"""
if _isRoot:
self.controlPanel()
render_engine.SceneNode.addChild(self._getSheet().sceneNodeChilds, self.sceneNodeRect)
else:
render_engine.SceneNode.removeChild(self._getSheet().sceneNodeChilds, self.sceneNodeRect)
def _createRect(self):
""" Creates rectangle surface for root mode
"""
# FIXME: make thread safe
self.rect = ogre.Rectangle2D(True)
self.rect.setCorners(-1.0, 1.0, 1.0, -1.0)
self.rect.setRenderQueueGroup(ogre.RENDER_QUEUE_8)
self.rect.setBoundingBox(ogre.AxisAlignedBox(ogre.Vector3(-100000.0, -100000.0, -100000.0), ogre.Vector3(100000.0, 100000.0, 100000.0)))
self.sceneNodeRect.attachObject(self.rect)
def _destroyRect(self):
""" Destroys rectangle surface for root mode
"""
self.rect = None
# FIXME: scene node removing
def getMaterialName(self):
return str(self) + "material"
def _createMaterial(self):
self.material = ogre.MaterialManager.getSingleton().create(self.getMaterialName(), env.resource_group)
mpass = self.material.getTechnique(0).getPass(0)
mpass.setLightingEnabled(True)
mpass.setDiffuse(0.0, 1.0, 0.0, 1.0)
tex_name = str(self) + "tex"
self.texture = ogre.TextureManager.getSingleton().createManual(tex_name, env.resource_group,
ogre.TEX_TYPE_2D, self.tex_size[0], self.tex_size[1], 32,
5, ogre.PixelFormat.PF_A8R8G8B8,
ogre.TU_DYNAMIC_WRITE_ONLY_DISCARDABLE)
tus = mpass.createTextureUnitState(tex_name)
def _layerClick(self, list, pvt):
ind = list.getIndexSelected()
dir(list)
if ind >= 0 and ind < list.getItemCount():
name = list.getItemNameAt(ind)
for data in self.layerData:
layer = data["layer"]
itemName = unicode(name).split()[1]
list.setItemNameAt(ind, itemName)
if itemName == unicode(layer.name):
layer.visible = not layer.visible
itemName = {True:'O', False:'X'}[layer.visible] + " " + itemName
list.setItemNameAt(ind, itemName)
pref = ""
if not layer.visible:
pref = "in"
if not data["drawn"]:
self.drawer.drawIt(self.scaleManager.scale, self.layerData)
buff = self.texture.getBuffer()
lock = buff.lock(0, buff.getSizeInBytes(), ogre.HardwareBuffer.HBL_NORMAL)
self.drawMap()
buff.unlock()
break
def controlPanel(self):
gui = render_engine._gui
#self.x, self.y = render_engine._ogreRenderWindow.getWidth(), render_engine._ogreRenderWindow.getHeight()
wid = 200
hei = 400
horOffset = 5
window = gui.createWidgetT("Window", "Window", mygui.IntCoord(10, 10, wid + 10, hei + 10), mygui.Align(), "Overlapped", '')
layerList = window.createWidgetT("List", "List", mygui.IntCoord(horOffset, 20, wid - 2 * horOffset, hei - 60), mygui.Align())
layerList.subscribeEventMouseItemActivate(self,'_layerClick')
for layer in self.field.layers:
layerList.addItem("O " + unicode(layer.name))
return
#list = self.gui.createWidgetT("List", "List", mygui.IntCoord(20, 270, 140, 100), mygui.Align())
#list = self.gui.createWidgetT("List", "List", mygui.IntCoord(20, 270, 140, 100), mygui.Align())
begin = (self.x - self.butWidth*self.butAmount)
begin = begin/2
self.wpanel = self.gui.createWidgetT("Widget", "Panel", mygui.IntCoord(1, self.y - 40, self.x, 40), mygui.Align(), "Popup", '')
self.wpanel.setAlpha(1)
self.slider = self.wpanel.createWidgetT("HScroll", "HSlider", mygui.IntCoord(50, 5, 700, 5), mygui.Align())
self.slider.setScrollRange(100)
self.stopbut = self.wpanel.createWidgetT("Button", "Button", mygui.IntCoord(begin, 15, self.butWidth, self.butHeight), mygui.Align())
self.stopbut.setCaption("Stop")
self.stopbut.subscribeEventMouseButtonClick(self,'_stop')
begin = begin + self.butWidth
self.backbut = self.wpanel.createWidgetT("Button", "Button", mygui.IntCoord(begin, 15, self.butWidth, self.butHeight), mygui.Align())
self.backbut.setCaption("Back")
begin = begin + self.butWidth
self.plbut = self.wpanel.createWidgetT("Button", "Button", mygui.IntCoord(begin, 15, self.butWidth, self.butHeight), mygui.Align())
if self.audioPlayer.isPlaying():
self.plbut.setCaption("Pause")
else:
self.plbut.setCaption("Play")
self.plbut.subscribeEventMouseButtonClick(self,'_play_pause')
begin = begin + self.butWidth
self.forwbut = self.wpanel.createWidgetT("Button", "Button", mygui.IntCoord(begin, 15, self.butWidth, self.butHeight), mygui.Align())
self.forwbut.setCaption("Forward")
begin = begin + self.butWidth
self.volslider = self.wpanel.createWidgetT("HScroll", "HSlider", mygui.IntCoord(begin, 23, self.butWidth, 5), mygui.Align())
self.volslider.setScrollRange(100)
self.panel = True
def drawMap(self):
# setting variables SIZEX and SIZEY to the size of field in pixels
factor = self.scaleManager.getFactor()
SIZEX = SIZEY = self.drawer.standardConstrainPx * factor
self.ctx.set_source_rgba (1, 1, 1, 1)
self.ctx.rectangle(0, 0, SIZEX, SIZEY)
self.ctx.fill()
for data in self.layerData:
if data["layer"].visible:
self.ctx.set_source_surface(data["surface"])
self.ctx.paint()
self.ctx.set_source_surface(data["selected-surface"])
self.ctx.paint()
def screenToMap(self, pt):
tx, ty = 0, 0
factor = self.scaleManager.getFactor()
tx = (factor - 1) * self.origin[0]
ty = (factor - 1) * self.origin[1]
mx = pt[0] / render_engine.Window.width
my = pt[1] / render_engine.Window.height
res = [(tx + mx) / factor,
(ty + my) / factor]
return res
def zoomIn(self):
return self.scaleManager.increaseScale()
def zoomOut(self):
return self.scaleManager.decreaseScale()
def _redraw(self):
"""
"""
for data in self.layerData:
data["drawn"] = False
"""Redraws map
"""
buff = self.texture.getBuffer()
lock = buff.lock(0, buff.getSizeInBytes(), ogre.HardwareBuffer.HBL_NORMAL)
width = self.tex_size[0]
height = self.tex_size[1]
import ctypes, cairo, math
# creating buffer in memory from locked data
data_buff = (ctypes.c_uint8 * (4 * width * height)).from_address(ogre.CastInt(lock)) # allocate a buffer class
# creating surface for buffer in memory
surface = cairo.ImageSurface.create_for_data(data_buff, cairo.FORMAT_ARGB32, width, height)
# creating context for drawing
self.ctx = cairo.Context(surface)
# adjusting position to the center point
tx, ty = self.getTranslation()
#if self.mapSurface:
# self.mapSurface.finish()
# creating a surface for map only
for data in self.layerData:
layerSurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
# creating a context for it
layerCtx = cairo.Context(layerSurface)
layerCtx.translate(tx, ty)
layerCtx.rectangle(-tx, -ty,
width, height)
layerCtx.clip()
selSurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
# creating a context for it
selCtx = cairo.Context(selSurface)
selCtx.translate(tx, ty)
selCtx.rectangle(-tx, -ty,
width, height)
selCtx.clip()
data["surface"] = layerSurface
data["context"] = layerCtx
data["selected-surface"] = selSurface
data["selected-context"] = selCtx
# drawing to a map context
self.drawer.drawIt(self.scaleManager.scale, self.layerData)
self.drawMap()
buff.unlock()
def setOrigin(self, pt):
self.origin[0] = pt[0]
self.origin[1] = pt[1]
def moveOrigin(self, hor, ver):
factor = self.drawer.manager.getFactor()
if hor != 0:
self.origin[0] += .1 * hor / factor
if ver != 0:
self.origin[1] += .1 * ver / factor
print "origin: " + str(self.origin)
def drawLayerSelection(self, layer):
for data in self.layerData:
if data["layer"] == layer:
width = self.tex_size[0]
height = self.tex_size[1]
selSurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
# creating a context for it
selCtx = cairo.Context(selSurface)
tx, ty = self.getTranslation()
selCtx.translate(tx, ty)
selCtx.rectangle(-tx, -ty,
width, height)
selCtx.clip()
data["selected-surface"] = selSurface
data["selected-context"] = selCtx
buff = self.texture.getBuffer()
lock = buff.lock(0, buff.getSizeInBytes(), ogre.HardwareBuffer.HBL_NORMAL)
self.drawer.drawLayerData(data, True)
self.drawMap()
buff.unlock()
break;
def _createFieldFromContent(self):
"""Creates map field for drawing from node content
"""
data = self._getContent()
if data is None: return
parser = map_utils.map_parser.LayersParser()
#FIXME delete line with \n
list = data.split('\r\n')
parser.parseLayers(list)
self.drawer = fieldDrawer.FieldDrawer()
#self.field = field.Field()
self.drawer.field = field.Field()
self.scaleManager = self.drawer.manager
transformScale = (0.5, 1)
#classifier = self.field.classifier
self.drawer.standardConstrainPx = self.tex_size[1]
#layer = field.Layer()
width = self.tex_size[0]
height = self.tex_size[1]
layerNum = 0
for lay in parser.layers:
layer = field.Layer()
layer.name = parser.layer_name[layerNum]
layerNum += 1
for i in range(len(lay.mif_data)):
if lay.object_type[i] == 'REGION':
region = field.PolygonItem(lay.mif_data[i], transformScale)
region.type = int(lay.mid_data[i]['CODE'])
region.setAttributes(lay.mid_data[i])
layer.addItem(region)
elif lay.object_type[i] == 'LINE':
line = field.LineItem(lay.mif_data[i], transformScale)
line.type = int(lay.mid_data[i]['CODE'])
line.setAttributes(lay.mid_data[i])
layer.addItem(line)
elif lay.object_type[i] == 'PLINE':
pline = field.LineItem(lay.mif_data[i], transformScale)
pline.type = int(lay.mid_data[i]['CODE'])
pline.setAttributes(lay.mid_data[i])
#FIXME change LineItem (draw one part)
layer.addItem(pline)
elif lay.object_type[i] == 'POINT':
pass
self.drawer.field.addLayer(layer)
self.field = self.drawer.standardField = self.drawer.createStandardField()
#self.field
#print "lrs: " + str(self.field.layers);
for layer in self.field.layers:
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
ctx = cairo.Context(surface)
self.layerData.append({"layer": layer, "surface": surface, "context": ctx, "drawn": False})
def _getContent(self):
"""Returns node content
"""
session = core.Kernel.session()
_addr = self._getSheet()._getScAddr()
if _addr is not None:
_cont = session.get_content_const(_addr)
assert _cont is not None
_cont_data = _cont.convertToCont()
data = _cont.get_data(_cont_data.d.size)
#print data
return data
return None
Реализация парсера mid/mif форматов
Для написания выбран язык программирования Python. В инструментарии уже имеется большое количество классов с необходимой нам функциональностью. За основу мы будем брать имеющиеся классы и расширять их функциональность.
def mifParser(self, mifData):
self.setMifVersion(int(re.findall(r'\d+', mifData[0])[0]))
self.setMifDelimiter(mifData[1].strip()[-2])
items = re.findall(r'(\d+), *(\d+)', mifData[2])[0]
self.setMifCoord_Projection(int(items[0]), int(items[1]))
columns = []
regions = []
readLine = 3
while readLine < len(mifData):
if 'COLUMNS' in mifData[readLine]:
columns_num = int(re.findall(r'\d+', mifData[readLine])[0])
for i in range(columns_num):
readLine = readLine + 1
column_name, column_value = mifData[readLine].strip().split()
columns.append((column_name, column_value))
self.setMifColumns(columns)
if 'REGION' in mifData[readLine]:
region_num = int(re.findall(r'\d+', mifData[readLine])[0])
region = []
readLine = readLine + 1
while 'BRUSH' not in mifData[readLine]:
points = []
lines_num = int(re.findall(r'\d+', mifData[readLine])[0])
for i in range(lines_num):
readLine = readLine + 1
x, y = mifData[readLine].strip().split()
points.append([float(x), float(y)])
region.append(points)
readLine = readLine + 1
self.setMifData(region)
self.object_type.append('REGION')
if 'LINE' in mifData[readLine][0:4] :
x1,y1,x2,y2 = mifData[readLine][4:len(mifData[readLine])].strip().split()
line = []
points = []
points.append([float(x1), float(y1)])
points.append([float(x2), float(y2)])
line.append(points)
self.setMifData(line)
self.object_type.append('LINE')
if 'PLINE' in mifData[readLine]:
pline = []
points = []
if 'MULTIPLE' in mifData[readLine]:
num_plines = int(mifData[readLine][14:len(mifData[readLine])].strip())
while num_plines > 0:
points = []
readLine = readLine + 1
num_points = mifData[readLine].strip()
for i in range(int(num_points)):
readLine = readLine + 1
x, y = mifData[readLine].strip().split()
points.append([float(x), float(y)])
pline.append(points)
num_plines = num_plines - 1
else:
num_points = mifData[readLine][5:len(mifData[readLine])].strip()
for i in range(int(num_points)):
readLine = readLine + 1
x, y = mifData[readLine].strip().split()
points.append([float(x), float(y)])
pline.append(points)
self.setMifData(pline)
self.object_type.append('PLINE')
if 'POINT' in mifData[readLine]:
point = []
points = []
x,y = mifData[readLine][5:len(mifData[readLine])].strip().split()
points.append([float(x), float(y)])
point.append(points)
self.setMifData(point)
self.object_type.append('POINT')
readLine = readLine+1
def midParser(self, midData):
for line in midData:
items = line.split(',')
if(len(items[-1])>2):
if '"' in items[-1][-3]:
items[-2] = items[-2] + "," + items[-1]
items = items [:-1]
self.setMidData(items)
else:
self.setMidData(items)
def parseFromFiles(self, mifPath = "", midPath = ""):
mifFile = codecs.open(mifPath, mode='r')#, encoding='cp1251')
mifData = mifFile.readlines()
mifFile.close()
self.mifParser(mifData)
midFile = codecs.open(midPath, mode='r')#, encoding='cp1251')
midData = midFile.readlines()
midFile.close()
self.midParser(midData)
def parseFromString(self, data):
for i in range(len(data)):
if '#mif' in data[i]:
f = i+1
if '#mid' in data[i]:
d = i+1
self.mifParser(data[f:d-1])
self.midParser(data[d:])
Расчётная работа на тему «Документирование web-ориентированной реализации интерпретатора sc-моделей»