Архив метки: Скриншоты

О том, как я на Yandex-карты попал

На самом деле на Yandex-карты я попал случайно: просто пошёл с коллегами на обед, мимо проезжала машина-шпион от yandex, которая нас сфотографировала, фотография получилась хорошей (хотя я себе на ней не нравлюсь), её выложили в интернет, коллеги заметили, сообщили мне, а я сообщил вам. Вот такая цепочка.

Я на Yandex-картах

Я на Yandex-картах

Разбиение полигонов

На работе я постоянно сталкиваюсь со множеством интересных задач. Недавно мне понадобилось построить тепловую карту практически на чистом SQL. Не знаю оптимально ли моё решение или нет, но я поступил следующим образом:

  1. Разбил участок карты на множество маленьких полигонов;
  2. Для каждого полигона вычислил «теплоту»;
  3. При отображении на клиенте каждый маленький полигон закрашивается своим цветом, зависящим от вычисленной на втором шаге «теплоты».

В результате на клиенте можно наблюдать подобные картины:

Тепловая карта

Тепловая карта

Приведённый ниже участок кода на T-SQL выполняет первый шаг описанного алгоритма — разбивает участок карты на множество маленьких квадратных полигонов. В этом коде нет ничего особого сложного или выдающегося, тем не менее, я надеюсь, что если вы столкнётесь с подобной задачей, мой код послужит основой для вашего решения.

  1. SET QUOTED_IDENTIFIER ON
  2. SET ANSI_NULLS ON
  3. GO
  4. — =============================================
  5. — Author:          Горьков А.Г.
  6. — Description:     Разбивает заданный полигон на множество «квадратных» полигонов
  7. — =============================================
  8. CREATE FUNCTION dbo.fnT_PolygonToGrid
  9.     (
  10.       @Polygon GEOMETRY — Обрабатываемый полигон
  11.     , @CellCount INT— Количество «квадратов» в результате разбиения
  12.     , @PartitionType INT  — 0 — в результате разбиения и по ширине, и по высоте будет НЕ БОЛЕЕ чем @CellCount «квадратов» 1 —  в результате разбиения и по ширине, и по высоте будет НЕ МЕНЕЕ чем @CellCount «квадратов»
  13.     )
  14. RETURNS @Grid TABLE
  15.     (
  16.       Cell GEOMETRY NOT NULLa
  17.     )
  18. AS
  19. BEGIN
  20.        — Получаем описывающий прямоугольник для участка
  21.     DECLARE @EnvelopePolygon GEOMETRY = @Polygon.STEnvelope()
  22.     DECLARE @EnvelopeWidth FLOAT = @EnvelopePolygon.STPointN(3).STX  @EnvelopePolygon.STPointN(1).STX
  23.     DECLARE @EnvelopeHeight FLOAT = @EnvelopePolygon.STPointN(3).STY  @EnvelopePolygon.STPointN(2).STY
  24.        — Получаем левый нижний угол описывающего прямоугольника
  25.     DECLARE @xStart FLOAT = @EnvelopePolygon.STPointN(1).STX
  26.     DECLARE @yStart FLOAT = @EnvelopePolygon.STPointN(1).STY
  27.        — Вычисляем шаги по широте и долготе
  28.     DECLARE @CellWidth FLOAT = @EnvelopeWidth / @CellCount
  29.     DECLARE @CellHeight FLOAT = @EnvelopeHeight / @CellCount
  30.        — Таблица с результирующей сеткой
  31.     DECLARE @RAWGrid TABLE ( geom GEOMETRY )
  32.        — Отдельная таблица для мультиполигонов, получившихся при разбиении
  33.     DECLARE @MultiPolygons TABLE
  34.         (
  35.           MultiPolygon GEOMETRY
  36.         )
  37.     DECLARE @MultiPolygon GEOMETRY= NULL
  38.     DECLARE @i INT = NULL
  39.        /*
  40.        В зависимости от типа разбиения подбираем длину стороны ячейки
  41.        */
  42.     IF @PartitionType = 1
  43.     BEGIN
  44.         IF @CellHeight < @CellWidth
  45.             SET @CellWidth = @CellHeight
  46.         ELSE
  47.             SET @CellHeight = @CellWidth
  48.     END
  49.     ELSE
  50.     BEGIN
  51.         IF @CellHeight > @CellWidth
  52.             SET @CellWidth = @CellHeight
  53.         ELSE
  54.             SET @CellHeight = @CellWidth
  55.     END
  56.        /*
  57.        Заполняем таблицу равномерной сеткой
  58.        В результате такого разбиения в ячейках могут присутствовать не только
  59.        обычные полигоны, но и мультиполигоны, с которыми мы разберемся ниже
  60.     */
  61.     DECLARE
  62.         @x INT = 0
  63.       , @y INT = 0
  64.     WHILE @y * @CellHeight <= @EnvelopeHeight
  65.     BEGIN
  66.         WHILE @x * @CellWidth <= @EnvelopeWidth
  67.         BEGIN
  68.             INSERT  INTO @RAWGrid
  69.             VALUES
  70.                     ( Geometry::STPolyFromText(‘POLYGON((‘ + CAST(@xStart + ( @x * @CellWidth ) AS VARCHAR(32)) + ‘ ‘ + CAST(@yStart + ( @y * @CellHeight ) AS VARCHAR(32)) + ‘,’ + CAST(@xStart + ( ( @x + 1 ) * @CellWidth ) AS VARCHAR(32)) + ‘ ‘ + CAST(@yStart + ( @y * @CellHeight ) AS VARCHAR(32)) + ‘,’ + CAST(@xStart + ( ( @x + 1 ) * @CellWidth ) AS VARCHAR(32)) + ‘ ‘ + CAST(@yStart + ( ( @y + 1 ) * @CellHeight ) AS VARCHAR(32)) + ‘,’ + CAST(@xStart + ( @x * @CellWidth ) AS VARCHAR(32)) + ‘ ‘ + CAST(@yStart + ( ( @y + 1 ) * @CellHeight ) AS VARCHAR(32)) + ‘,’ + CAST(@xStart + ( @x * @CellWidth ) AS VARCHAR(32)) + ‘ ‘ + CAST(@yStart + ( @y * @CellHeight ) AS VARCHAR(32)) + ‘))’ , 4326) )
  71.             SET @x = @x + 1
  72.         END
  73.         SET @x = 0
  74.         SET @y = @y + 1
  75.     END
  76.        /*
  77.        Сохраняем обычные полигоны в итоговую таблицу
  78.     */
  79.     INSERT  INTO @Grid
  80.             SELECT
  81.                 geom.STIntersection(@Polygon)
  82.             FROM
  83.                 @RAWGrid
  84.             WHERE
  85.                 ( 1 = 1 )
  86.                 AND ( geom.STIntersection(@Polygon).STGeometryType() = ‘Polygon’ )
  87.        /*
  88.        Сохраняем мультиполигоны во временную таблицу
  89.     */
  90.     INSERT  INTO @MultiPolygons
  91.             SELECT
  92.                 geom.STIntersection(@Polygon)
  93.             FROM
  94.                 @RAWGrid
  95.             WHERE
  96.                 ( 1 = 1 )
  97.                 AND ( geom.STIntersection(@Polygon).STGeometryType() = ‘MultiPolygon’ )
  98.        /*
  99.        Разбиваем мультиполигоны на обычные полигоны и переносим их в итоговую тбалицу
  100.        */
  101.     DECLARE c CURSOR
  102.     FOR
  103.     SELECT
  104.         @MultiPolygon
  105.     FROM
  106.         @MultiPolygons
  107.     OPEN c
  108.     FETCH c INTO @MultiPolygon
  109.     WHILE @@FETCH_STATUS = 0
  110.     BEGIN
  111.         SET @i = 1
  112.         WHILE @i <= @MultiPolygon.STNumGeometries()
  113.         BEGIN
  114.             INSERT  INTO @Grid
  115.                     ( Cell )
  116.             VALUES
  117.                     ( @MultiPolygon.STGeometryN(@i) )
  118.             SET @i = @i + 1
  119.         END
  120.         FETCH NEXT FROM c INTO @MultiPolygon
  121.     END
  122.     CLOSE c
  123.     DEALLOCATE c
  124.     RETURN
  125. END
  126. GO

Пожалуй, наиболее интересный момент здесь, это параметр — @PartitionType. Он показывает, как именно надо разбивать исходный полигон на части: чтобы в результате разбиения по ширине и высоте было НЕ БОЛЕЕ или НЕ МЕНЕЕ, чем @CellCount полигонов. Проще всего разницу пояснить на конкретном примере:

Виды разбиения

Виды разбиения

В первом случае @PartitionType=0, а во втором @PartitionType=1.

Монография по цифровой обработке изображений

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

Про github.com и лабораторные работы

Буквально вчера я решил прекратить порочную практику проверки практической части лабораторных работ по почте. Это только на первый взгляд кажется удобным, но на практике обнаруживается как минимум две серьёзные проблемы:

  1. Почтовые клиенты и серверы не очень любят отправлять и принимать исполняемые файлы;
  2. Cо временем, несмотря на все фильтры, почта превращается в большую свалку, где ничего невозможно найти.

Чтобы раз и навсегда разобраться с этими проблемами я решил обязать студентов выкладывать выполненные работы на github.

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

Первым делом необходимо зарегистрироваться на сайте github. Это процедура тривиальна, и расписывать её я не буду. Вторым шагом надо установить GUI-обертку для github. Конечно, настоящие программисты используют консоль, но у нас цель не команды git учить, а выложить лабораторную работу. После того, как приложение github установлено и запущено перед вами должен быть подобный экран:

Приложение github (без репозиториев)

Приложение github (без репозиториев)

Теперь мы готовы выкладывать выполненный проект. Для этого перетянем папку с выполненной работой на пустое место, github предложит нам создать репозиторий:

Приложение github (создание репозитория)

Приложение github (создание репозитория)

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

Приложение github (публикация репозитория)

Приложение github (публикация репозитория)

Перед публикацией репозитория необходимо создать новый коммит. Для этого надо задать название коммита (на рисунке текстовое поле Summury) и его описание (Description). Обычно первый коммит называют «Initial commit», хотя это и необязательно. После того, как поля заполнены, необходимо нажать кнопку «Commit to master». И в завершении публикации необходимо нажать кнопку «Publish Repository». На этом всё, проект опубликован и выложен на github.

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