Обработка семантики (атрибутов) объектов на python

Печать Предыдущая страница Стартовая страница Следующая страница

Семантика объекта состоит из набора характеристик, имеющих числовой код, ключ (имя поля), название, тип значения. Значение семантики может выбираться из справочника, содержать ссылку на файл или вычисляться динамически (семантика типа формула). Если семантическая характеристика имеет признак «Повторяемая», то у объекта может быть несколько семантик с одним кодом (и ключом).

 

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

 

Для выбора семантики из списка в диалоге может быть применен стандартный компонент tkinter.

 

def ConvertSemanticAltitude(hmap:maptype.HMAP, hobj:maptype.HOBJ) -> float: #caption:Пересчитать высоту в семантике в футы или метры

 

   root = tkinter.Tk()

   root.title("Пересчитать высоту в семантике")

 

   src_label = tkinter.Label(text="Входная семантика: ")

   out_label = tkinter.Label(text="Выходная семантика: ")

   src_label.grid(row=0, column=0, sticky="w")

   out_label.grid(row=1, column=0, sticky="w")

 

   src_value = tkinter.IntVar()

   out_value = tkinter.IntVar()

   src_entry = tkinter.Entry(width=10, textvariable=src_value)

   out_entry = tkinter.Entry(width=10, textvariable=out_value)

   src_entry.grid(row=0,column=1, padx=5, pady=5)

   out_entry.grid(row=1,column=1, padx=5, pady=5)

 

   semname = mapsyst.WTEXT(64)

   hrsc = rscapi.mapGetRscIdent(hmap, hmap)

   rscapi.mapGetRscSemanticNameUn(hrsc, 4, semname, semname.size())

   select_src = tkinter.Button(text=semname.string())

   select_out = tkinter.Button(text=semname.string())

   src_value.set(4)

   out_value.set(4)

 

   def SelectSemanticSrc():

       parm = maptype.TASKPARMEX()

       parm.Handle = mapapi.mapGetHandleForMessage()

       semcode = mapselec.selSemanticSelectInit(hrsc, ctypes.byref(parm), src_value.get())

       if semcode != 0:

           src_value.set(semcode)

           rscapi.mapGetRscSemanticNameUn(hrsc, semcode, semname, semname.size())

           select_src.configure(text=semname.string())

 

   def SelectSemanticOut():

       parm = maptype.TASKPARMEX()

       parm.Handle = mapapi.mapGetHandleForMessage()

       semcode = mapselec.selSemanticSelectInit(hrsc, ctypes.byref(parm), src_value.get())

       if semcode != 0:

           out_value.set(semcode)

           rscapi.mapGetRscSemanticNameUn(hrsc, semcode, semname, semname.size())

           select_out.configure(text=semname.string())

 

   select_src.configure(command=SelectSemanticSrc)

   select_src.grid(row=0, column=2, padx=10, sticky="w")

   select_out.configure(command=SelectSemanticOut)

   select_out.grid(row=1, column=2, padx=10, pady=2, sticky="w")

 

   type_value = tkinter.IntVar()

   type_value.set(1)

   met2feet = tkinter.Radiobutton(root, text="в футы", variable=type_value, value=1).grid(row=2, column=1, sticky="w")

   feet2met = tkinter.Radiobutton(root, text="в метры", variable=type_value, value=2).grid(row=2, column=2, sticky="w")

 

   ret_value = tkinter.IntVar()

   ret_value.set(0)

   multi_f = 1. / 0.3048

   multi_m = 0.3048

 

   def Run():

       type = type_value.get()

       if type == 2:

          multi = multi_m

       else:

          multi = multi_f

 

       ret = SemanticAltitudeToFeet(hmap, hobj, src_value.get(), out_value.get(), multi)

       ret_value.set(ret)

       root.destroy()

 

   def Close():

       root.destroy()

 

   message_button = tkinter.Button(text="Выполнить", command=Run)

   message_button.grid(row=3,column=1, padx=5, pady=5, sticky="e")

   message_button = tkinter.Button(text="Отменить", command=Close)

   message_button.grid(row=3,column=2, padx=5, pady=5, sticky="w")

 

   root.eval('tk::PlaceWindow . center')

   root.mainloop()

   return float(ret_value.get())

 

dialog

 

Для работы с классификатором необходимо получить идентификатор HRSC.

 

hrsc = rscapi.mapGetRscIdent(hmap, hmap)

 

Для вызова стандартных диалогов ГИС необходимо объявить структуру TASKPARMEX.

 

       parm = maptype.TASKPARMEX()

       parm.Handle = mapapi.mapGetHandleForMessage()

 

Для выбора семантики из списка можно применить функцию mapselec.selSemanticSelectInit.

 

       semcode = mapselec.selSemanticSelectInit(hrsc, ctypes.byref(parm), src_value.get())

 

dialog4

 

 

Для передачи и получения в функции MAPAPI строк в кодировке UTF-16 (WCHAR/WCHAR2) применяется класс mapsyst.WTEXT. В объявлении класса указывается предельный размер буфера строки.

 

   semname = mapsyst.WTEXT(64)

 

В функции MAPAPI, которые возвращают значение в виде строки, передается имя переменной класса и размер буфера.

 

   rscapi.mapGetRscSemanticNameUn(hrsc, semcode, semname, semname.size())

 

Полученная строка может быть использована как строка python с помощью метода string().

 

   select_out.configure(text=semname.string())

 

Получив коды обрабатываемых семантик можно выполнить обработку соответствующих полей в записи с помощью функций MAPAPI.

 

# Convert object altitude to feet or meters

def ObjectAltitudeToFeet(hobj:maptype.HOBJ, srccode, outcode, multi) -> int:

   if hobj == 0:

      return 0

   srcnumber = mapapi.mapSemanticCodeValuePro(hobj, srccode, None, 0, 1, 0)

   if srcnumber == 0:

      return 0

   value = mapapi.mapSemanticCodeDoubleValue(hobj, srccode, 1)

   value = value * multi

   if srccode == outcode:

      return mapapi.mapSetSemanticDoubleValue(hobj, srcnumber, value)

   else:

      outnumber = mapapi.mapSemanticCodeValuePro(hobj, outcode, None, 0, 1, 0)

      if outnumber > 0:

         return mapapi.mapSetSemanticDoubleValue(hobj, outnumber, value)

      else:

         return mapapi.mapAppendSemanticDouble(hobj, outcode, value)

 

Для поиска характеристики, имеющей заданный код, можно применить функцию  mapapi.mapSemanticCodeValuePro.

 

   srcnumber = mapapi.mapSemanticCodeValuePro(hobj, srccode, None, 0, 1, 0)

 

Если значение семантики планируется обрабатывать в символьном виде, то запрос может иметь вид:

 

   semvalue = mapsyst.WTEXT(1024)

   srcnumber = mapapi.mapSemanticCodeValuePro(hobj, srccode, semvalue, semvalue.size(), 1, 0)

 

Если ожидается повторяемое значение семантики, то после поля размера буфера строки в байтах указывается порядковый номер запрос может иметь вид:

 

   srcnumber = mapapi.mapSemanticCodeValuePro(hobj, srccode, semvalue, semvalue.size(), number, 0)

   number += 1

 

Значение семантики может быть запрошено в числовом виде (Long или Double) по коду с учетом повторяемого значения.

 

   value = mapapi.mapSemanticCodeDoubleValue(hobj, srccode, 1)

 

Быстрее выполнится запрос чтения значения по номеру характеристики в записи семантики.

 

   value = mapSemanticDoubleValue(hobj, srcnumber)

 

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

 

   outnumber = mapapi.mapSemanticCodeValuePro(hobj, outcode, None, 0, 1, 0)

   if outnumber > 0:

       return mapapi.mapSetSemanticDoubleValue(hobj, outnumber, value)

   else:

       return mapapi.mapAppendSemanticDouble(hobj, outcode, value)

 

Если добавляемая характеристика не имеет признак «Повторяемая», то второе значение заменит первое автоматически и функция mapapi.mapAppendSemantic сработает как mapapi.mapSetSemantic. После редактирования семантики порядок полей может измениться. В некоторых случаях обновляемое поле удаляется и записывается в конец с новым значением.