Данное руководство описывает действия, необходимые для открытия источника с данными и произведения с ними базовых манипуляций. Примеры, приведенные в данном руководстве можно выполнить в редакторе скриптов питона, который является частью приложения Axioma.GIS.
Для открытия таблицы с данными и последующей регистрации ее в каталоге с данными необходимо выполнить следующее:
import axioma.core
json = {"src":"C:\\SubjectRF.TAB"}
table = axioma.core.open_json(json)
axioma.app.mainWindow.registerDataObject(table)
При открытии таблицы из базы данных задание источника данных может выглядеть так:
json = {
"openWith": "PgDataProvider",
"src": "localhost",
"port": "5432",
"db": "esti",
"user": "postgres",
"password": "",
"sql": "select * from subjectrf",
}
table = axioma.core.open_json(json)
К полученному открытому источнику данных table для получения информации можно сделать запрос данных.
Для запроса всех записей в таблице используем метод allFeatures()
:
from axioma.core.dp import *
features = table.allFeatures()
Если необходимо ограничить количество полей указанным списком, то с методе selectToFeatureList()
задаем перечень полей:
features = table.selectToFeatureList(QuerySelectAll(["object", "OBL_NAME"]))
Получение перечня атрибутов таблицы attributeNames()
:
print(table.tableSchema().attributeNames())
Если необходимо ограничить количество запрашиваемых записей, используем PageRange
:
features = table.selectToFeatureList(QuerySelectAll(table.tableSchema().attributeNames()), PageRange(0, 10))
Это может быть полезно, если есть необходимость чтения данных порциями.
Если необходимо выполнить запрос с наложением фильтра в ограничивающем прямоугольнике, GeoRect
используем метод selectFeaturesInMbr()
:
geoRect = GeoRect(QRectF(33, 57, 10, 5), CoordSysFactory.defaultCoordSysFactory().LatLongCoordSystem())
features = table.selectFeaturesInMbr(geoRect)
Для определения положения атрибута с геометрией и ее оформления в структуре таблицы используем методы geometryIndex()
и styleIndex()
:
geomIndex = table.tableSchema().geometryIndex()
styleIndex = table.tableSchema().styleIndex()
Координатную систему таблицы получаем с помощью метода и coordSystem()
:
from axioma.cs import *
cs = table.coordSystem()
print("КС таблицы:", cs.prjStr())
Так же метаданные по геометрическому атрибуту можно получить из схемы таблицы GeometryAttributeDefinitionInterface
geomDef = table.tableSchema().at(geomIndex)
cs = geomDef.coordSystem()
rect = geomDef.boundingRectF()
Для доступа к каждому элементу после получения списка записей можно использовать цикл:
for feature in features:
print("id={} name={}".format(feature.id(), feature.getAttribute('OBL_NAME')))
Получить атрибут записи можно либо по имени либо по его индексу getAttribute()
. Геометрия и ее стиль определяется аналогично:
simpleAttr = feature.getAttribute('OBL_NAME')
simpleAttr = feature.getAttribute(2)
geomAttr = feature.getAttribute(geomIndex)
geomAttr = feature.getAttribute("object")
styleAttr = feature.getAttribute(styleIndex)
Полученные стиль и геометрию для наглядности можно представить в текстовом формате:
from axioma.mapinfo import MapBasicStyle
print("Геометрия в формате WKT", geomAttr.exportToWkt())
print ("Стиль в формате строки MapBasic", MapBasicStyle().stringFromStyle(styleAttr))
Перед проведением модификаций необходимо убедиться, что таблица поддерживает возможность изменения:
if isinstance(table, TransactionalTable):
print('Таблица доступна для изменений')
Проведем операцию вставки новой записи. Для этого вначале создадим новую запись Feature
, используя структуру (схему) открытой для изменения таблицы:
new_feature = Feature.createFeature(table.tableSchema())
Создадим геометрический объект-полигон и пометим его как измененный:
from PyQt5.QtGui import QPolygonF
from axioma.core.geometry import *
poly = QPolygonF();
poly << QPointF(50, 50) << QPointF(80, 50) << QPointF(80, 40) << QPointF(50, 40) << QPointF(50, 50)
polygon = Polygon(table.coordSystem(), poly)
new_feature.setAttribute(geomIndex, polygon)
new_feature.setModified(geomIndex, True)
Аналогично для стиля оформления:
style = MapBasicStyle().styleFromString('Pen (1,2,0) Brush (2, 65280, 16777215)')
new_feature.setAttribute(styleIndex, style)
new_feature.setModified(styleIndex, True)
И простой текстовый атрибут:
new_feature.setAttribute('OBL_NAME', 'Новый объект')
new_feature.setModified('OBL_NAME', True)
Далее сделаем вставку в транзакционную таблицу. При этом создается файл транзакций и основной файл остается неизменным.
table.insert([new_feature])
После проведения всех необходимых изменений сохраняем их в файле.
table.commit()
Отрисуем данные таблицы в растровый файл.
Для этого для начала создадим слой Layer
для отрисовки на базе таблицы createLayerForDataObject()
:
from axioma.render import *
layer = axioma.app.render.createLayerForDataObject(table)
Задаем прямоугольник на карте для отрисовки:
br = layer.boundingRect()
sceneRect = QRectF(br.left(), br.top(), br.width(), br.height())
И прямоугольник результирующего растра:
size = QSize(1000, 1000 * br.height() / br.width())
imRect = QRect(0, 0, size.width(), size.height())
На базе этой информации создаем MapViewport
:
viewport = MapViewport(QRectF(imRect), sceneRect, layer.coordSystem())
Создаем результирующий растр:
image = QImage(imRect.size(), QImage.Format_ARGB32_Premultiplied)
image.fill(Qt.white)
painter = QPainter(image)
Контекст, куда рисуем MapContext
:
context = MapContext(painter, viewport)
Непосредственно отрисовка слоя в контексте:
layer.render(context)
Сохранение результатов в файловой системе:
image.save('/tmp/out_raster.png')
Был представлен простейший вариант. Слои в данном случае отрисовываются последовательно друг за другом. Если мы хотим использовать параллельную отрисовку слоев, используя мультипроцессорную архитектуру, необходимо сделать следующее:
Создать объект-карту Map
и заполнить его слоями:
map = Map()
map.rootLayerGroup().append(layer)
map.rootLayerGroup().append(anotherLayer)
Далее, создаем объект, занимающийся многопоточной отрисовкой ConcurrentMapRenderer
и производим многопоточную отрисовку:
renderer = ConcurrentMapRenderer()
renderer.blockingRender(map, context)
Если мы хотим произвести вывод в координатной системе, отличной от КС таблицы, то изменения в коде будут следующие:
Создаем требуемую координатную систему посредством фабрики CoordSysFactory
:
from axioma.cs import *
cs_merc = CoordSysFactory.defaultCoordSysFactory().createFromPRJ("Earth Projection 10, 104, \"m\", 0")
Если это необходимо, производим преобразование ограничивающего прямоугольника таблицы в данную координатную систему:
transform = CoordTransform(layer.coordSystem(), cs_merc)
sceneRectMerc = transform.forward(sceneRect)
Или же задаем требуемый нам явно.
И наш MapViewport
будет выглядеть так:
viewport = MapViewport(QRectF(imRect), sceneRectMerc, cs_merc)
Создадим простой отчет размером 2 на 2 листа формата A4 с одним геометрическим элементом. Для начала нужно создать объект принтера. Печать будем производить в pdf файл.
from PyQt5.QtPrintSupport import QPrinter
printer = QPrinter(QPrinter.HighResolution)
printer.setPaperSize(QPrinter.A4)
printer.setOutputFormat(QPrinter.PdfFormat)
printer.setOutputFileName('/tmp/out_report.pdf')
Далее сам отчет Report
:
from axioma.render import *
report = axioma.render.Report()
report.setHorisontalPagesCount(2)
report.setVerticalPageCount(2)
report.setOptions(printer)
Создаем контекст для вывода:
deviceRect = sceneRect = QRectF(0, 0, 100, 100)
viewport = Viewport(deviceRect, sceneRect)
context = Context(painter, viewport)
Создаем элемент отчета типа геометрия и добавляем его в отчет:
cs_ne = CoordSysFactory.defaultCoordSysFactory().createFromPRJ("CoordSys Nonearth Units \"m\"" )
poly = QPolygonF()
poly << QPointF(20, 20) << QPointF(80, 50) << QPointF(120, 20) << QPointF(320, 320) << QPointF(120, 180) << QPointF(20, 20)
geom = Polygon(cs_ne, poly)
style = MapBasicStyle().styleFromString("Pen (1, 5, 16711935) Brush (8, 255, 16777215)")
geomItem = GeometryReportItem(report)
geomItem.setGeometry(geom)
geomItem.setStyle(style)
report.addItem(geomItem)
Отрисовка:
report.render(context)
painter = None
Откроем таблицу и добавим ее в окно карты и покажем в виде таблицы просмотра
import axioma.app from PyQt5.QtCore import QRectF, QPointF # Открываем таблицу table = axioma.core.open_json({"src" : "/tmp/world.tab"}) # Если нужно, чтобы пользователь видел таблицу в списке открытых данных, # добавляем её в каталог приложения axioma.app.mainWindow.dataCatalog().addDataObject(table) # Создаём слой для таблицы layer = axioma.app.render.createLayerForDataObject(table) # Создаём окно карты и показываем его в главном окне mapView = axioma.app.mainWindow.createMapViewForLayerList([layer], 'Моя карта') # Показываем таблицу в виде списка axioma.app.mainWindow.showTableData(table)
Добавим простую кнопку в панель инструментов, по нажатию которой выводится на консоль простое сообщение.
import axioma.gui
import PyQt5.QtGui
# Объявляем свой класс расширения
class ExampleActionExtension(axioma.gui.NativeActionExtension):
# Необходимо переопределить метод customizeAction, задав параметры для создаваемого объекта QAction
def customizeAction(self, action):
action.setText("Пример действия")
action.setIcon(PyQt5.QtGui.QIcon(":/icons/32px/run.png"))
action.triggered.connect(self.slot);
# Действие по нажатию
def slot(self):
print('Нажали кнопку')
# Регистрация в системе на новой закладке
ribbonExt = axioma.gui.extension.RibbonExtension()
ribbonExt.addTab("ExamplePluginTab", "Пример модуля")
actionExt = ExampleActionExtension("ActionExtensionId", axioma.gui.RibbonActionInfo())
ribbonExt.addAction("ActionExtensionId", "ExamplePluginTab", "") # Добавление в интерфейс
axioma.app.gui.prependExtensions([ribbonExt, actionExt]) # Регистрация
Добавим кнопку - инструмент окна карты в панель инструментов. Если выбрать данный инструмент и щелкнуть мышью в окне карты, будут выведены координаты этого места в координатах текущей проекции карты.
from PyQt5.QtGui import QMouseEvent, QIcon
from PyQt5.QtCore import Qt
from axioma.gui import *
# Определяем свой класс инструмента
class ExampleTool(Tool):
def mousePressEvent(self, event):
if event.button() != Qt.LeftButton:
return
posOnMap = self.widget().viewport().mapToScene(event.pos()) # Преобразуем координаты из окна в координаты карты
print("Координаты точки карты ({}, {})".format(posOnMap.x(), posOnMap.y())) # выводим полученную координату
return Tool.PassEvent
# Регистрируем наш инструемнт в виде расширения в системе.
ext = axioma.gui.extension.BasicToolExtension(ExampleTool, axioma.gui.MapView, "ExampleToolId", icon=QIcon("://icons/32px/info.png"), text="Координаты точки карты")
axioma.app.gui.prependExtension(ext)
# Добавляем инструмент в закладку карты
ribbonExt = axioma.gui.extension.RibbonExtension()
ribbonExt.addAction("ExampleToolId", "map", "operations")
axioma.app.gui.prependExtension(ribbonExt)