Добавление потрясающих новых функций в мою графическую библиотеку!

Часть 4 (ссылки на другие части здесь!)

"Ноутбук"

В моей последней статье я оставил свой код с несколькими очевидными проблемами, в первую очередь с невозможностью изменить цвет каких-либо конкретных объектов внутри композиции независимо. Это был большой недостаток, так как это означало, что мне мешало отсутствие цвета для различения разных данных, а также означало, что анализируемые формы имели тот же ход, что и две оси, что, конечно же, было не так. оптимально. Однако мне удалось заставить диспетчерскую службу Джулии работать для DataFrames и Arrays одновременно с одной и той же пользовательской командой.

Исправление этой проблемы с инсультом - это то, чего я немного боялся, потому что это будет приличная работа, но никакой работы не будет слишком много, когда на горизонте оптимальное улучшение!

Исправляем нашу проблему

Как я, вероятно, объяснял ранее, эта проблема вызвана тем, что все наши объекты рисуются в одном контексте, и будет решена путем создания нового контекста в композиции. Вот пример композиции с двумя контекстами:

Здесь вам пригодится метод introspect (). Если мы рассмотрим эту композицию, мы сможем ясно увидеть оба наших контекста:

Желто-коричневые точки - это точки контекста, за которыми следуют их соответствующие формы, R и C - с синими квадратами, а красные треугольники представляют свойства, которые применяются к объектам в этом конкретном контексте, в этом примере красный треугольник представляет fill () метод. Давайте начнем с того, что сначала установим другой цвет между осью и точками в нашей исходной функции _arrayscatter (). Первое, что я собираюсь сделать, это добавить строковый код для нового контекста для осевых линий:

И второй контекст после этой строки предназначен для наших входящих данных. Чтобы завершить эту функцию, мне нужно добавить второй набор скобок в конец выражения, чтобы закрыть контекст, а также метод компоновки. Я также взял на себя смелость переместить эти две однострочные петли for в другие петли, на чем я откладывал без особой причины.

Теперь о функции _dfscatter ()!

Это будет не так просто, как функция разброса массива, потому что на этот раз нам нужно будет добавить несколько контекстов итеративно внутри цикла парсинга zip.

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

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

Я также добавил значение по умолчанию для этого параметра, чтобы мы могли иметь обводку, не запрашивая обводку, что довольно удобно. Теперь обрисовываем это:

Оно работает!

Теперь давайте протестируем другую функцию, _dfscatter (). Сначала я собираюсь создать очень большой DataFrame с кучей разных массивов.

А затем я создам новый массив, который будет содержать наши формы, которые функция будет принимать:

shapes = [Circle(.5,.5,.01,:orange),Circle(.5,.5,.01,:blue),Circle(.5,.5,.01,:purple)]

И вставьте наши ценности:

plot = Scatter(df,:Y,shapes, false)

Выглядит отлично!

Ради интереса, давайте посмотрим на дерево для этого!

В этом должно быть много всего, потому что с самоанализом явно что-то пошло не так!

Новые объекты

В прошлой статье я добавил новую форму, объект Rectangle, но в этой у меня есть желание поднять его на ступеньку выше с помощью сетки. У меня было несколько разных мыслей об интересных способах создания пользовательской сетки, но мне пришло в голову, что некоторые другие вещи, которые я планирую реализовать, сделают многие мои идеи возможными без необходимости в пользовательских сетках. Поэтому я решил вместо этого разрешить пользователю добавлять определенное количество разделов. Что мы можем сделать для обработки количества делений, так это просто разделить единицу на число, например, если бы нашим числом было 4, то мы получили бы число 0,25. Вот как это переводится на Джулию:

function Grid(divisions,colorx=:lightblue,colory=:lightblue,thickness=.02)
    division_amount = 1 / divisions

Затем нам нужна общая сумма для предстоящего цикла, которую мы можем использовать для создания наших строк. Конечно, пока это будет ноль. Нам также нужно будет создать контекст, как обычно.

total = 0
Xexpression = "(context(), "

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

while total < 1
        total = total + division_amount
        linedraw = Line([(0,total),(1,total)],:lightblue,thickness)
        exp = linedraw.update(:This_symbol_means_nothing)
        Xexpression = string(Xexpression,exp)
    end

Обратите внимание, что положение линии X на самом деле изменяется по оси Y, но переносится по оси X, поэтому координаты X составляют 0 процентов и 100 процентов. В наших четырех примерах, о которых я говорил ранее, где размер нашего деления составляет 25 процентов или число с плавающей запятой 0,25, мы добавляем сумму деления (0,25) к общей сумме, а затем проводим линию через это положение на оси Y до 100. процентов от оси X. После этого выражение будет добавлено, и цикл начнется снова, и наша сумма теперь будет добавлена ​​к 0,5, и так до тех пор, пока цикл не будет прерван линиями, превышающими или равными 100 процентам холста.

Затем мы повторим то же самое для Y. После этого мы сложим их все вместе, как и со всеми другими функциями для конечного продукта, который выглядит примерно так:

Осталось сделать одну вещь - добавить наш тип return внизу вместе с нашим методом обновления для возврата тега.

update() = string(composeexp)
(var)->(update;composexp)

Чтобы проверить это, мы просто добавим тег в начало нашей функции разброса массива.

Теперь проверим это:

Не сработало.

Как ни странно, это вернуло ошибку синтаксического анализа из-за регулярного выражения \ ”, используемого в объекте Line ... Это странно, потому что функция _arrayscatter () отлично работает, используя тот же самый объект с тем же точным выражением, так что это меня немного в тупике. Как видите, я также распечатал выражение, и оно выглядит идеально, поэтому я действительно не уверен, в чем может быть проблема. Хотя это может быть довольно серьезная проблема, я уверен, что мы сможем решить ее в следующей статье, но пока давайте перейдем к

Поддержка пользовательских тегов

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

Легкий!

Вывод

Хорошая новость заключается в том, что синтаксические анализаторы координат и диспетчеризация работают очень хорошо, а на самом деле работают даже лучше. Плохая новость в том, что мне не удалось создать сетку из-за этой странной проблемы с регулярным выражением. Последнее, что я затронул, это то, что меня действительно волнует. Пользовательские теги позволяют пользователю настраивать свои собственные расширения и делиться ими, и это программное обеспечение для построения графиков, эквивалентное включению редактора карт в видеоигру. Я обязательно буду демонстрировать это в будущем!