Центральным для приложения является вопрос хранения данных: в каком формате их сохранять (xml, json…), какой инструмент использовать (СУБД, специфические библиотеки).
Архитектура системы накладывает следующие ограничения на СУБД:
- возможность отображения дерева с разделением и выводом узлов (функциональное ограничение);
- возможность работы в браузере;
- возможность работы в in-memory режиме;
- легковесность.
Подходящие технологии:
- https://github.com/cfu288/SylvieJS
- https://rxdb.info/
- https://good-db.github.io/
- https://github.com/tducasse/js-db
- https://github.com/JamesMGreene/nestdb
Референс: Camunda Modeler использует bpmn-moodle, который основан на moodle. Moodle по своей сути позволяет описывать метамодели и конкретные модели; т. е. это документно-ориентированная СУБД, хотя авторы её такой не рассматривают.
Здесь встаёт вопрос: где грань между библиотекой, которая позволяет оперировать, к примеру, XML и XML-СУБД?
Объекты на холсте можно выделять не только точным касанием по ним, но и нечётко: то есть касанием в определённом радиусе (радиусе люфта, backlash).
Реализация нечёткого выделения возможна двумя принципиальными путями:
- курсор считается точкой, а объекты принимаются за нечёткие;
- курсор считается нечётким, а объекты — чёткими.
Второй путь, как показывает практика, реализовать намного проще. В текущей реализации все объекты, кроме курсора — чёткие, а курсор представляет собой окружность с радиусом люфта.
Касание точки происходит, если она находится внутри или на границе круга, центром которого является курсор, а радиусом — радиус люфта.
Математически это условие задаётся неравенством круга: \[ (C_x - A_x)^2 + (C_y - A_y)^2 \leq R^2, \] где C — курсор, A — точка, R — радиус люфта.
Точки, в которых курсор касается отрезком являются решением системы
\[\begin{cases}
Ax + By + C = 0,
(x - X)^2 + (y - Y)^2 = R^2,
\end{cases}\]
где A, B, C — коэффициенты прямой, на которой лежит отрезок, (X, Y) — координаты курсора, R — радиус люфта.
Решением системы являются корни квадратного уравнения. Коэффициенты уравнения будут рассчитываются в зависимости от значения коэффициента прямой B. Возможны два случая:
-
$$B ≠ 0$$ , тогда
\[\begin{cases}
y = \frac{-Ax - C}{B},
a = 1 + (\frac{A}{B})^2, \
b = \frac{2AC}{B^2} + \frac{2AY}{B} - 2X, \
C = (\frac{C}{B})^2 + \frac{2CY}{B} + X^2 + Y^2 - R^2;
\end{cases}\]
-
$$B = 0$$ , тогда
\[\begin{cases}
x = -\frac{C}{A},
a = 1, \
b = -2Y, \
c = (\frac{C}{A})^2 + \frac{2CX}{A} + X^2 + Y^2 - R^2.
\end{cases}\]
Полученные в результате точки будут лежать на заданной прямой. Однако, это не значит, что они будут лежать в границах отрезка. Проверка этого выполняется равенством \[ d(S,E) = d(S,p) + d(p, E), \] где d() — функция расстояния, (S, E) — точки начала и конца отрезка, p — проверяемая точка касания.
Для описанного выше способа важны коэффициенты прямой. Необходимо ответить на два вопроса:
- почему выбрано именно уравнение прямой, а не линейной функции;
- как находятся коэффициенты.
Уравнение прямой было выбрано потому, что оно одно способно вполне описать все случаи прямых. Случай
Коэффициенты прямой, проходящей через точки
Ax_2 + By_2 + C = 0.
\end{cases}\]
Неизвестных в системе больше, чем уравнений. Решение можно найти, если одну из переменных принять за свободную и дать ей произвольное значение. Эти значения выбираются по следующему соглашению:
\[\begin{cases}
B = 0, & x_1 = x_2,
A = 0, & y_1 = y_2, \
B = 1, & \begin{cases} x_1 ≠ x_2, \ y_1 ≠ y_2 \end{cases}.
\end{cases}\]
Очевидно, что нечёткое касание прямоугольника может быть выведено из случая отрезка. Однако такое решение будет весьма громоздким, его математическая точность просто не требуется, её никто не оценит.
Поэтому случай прямоугольников реализован проще, касание прямоугольника задаётся условием:
\[\begin{cases}
C_x - S_x \geq -R,
C_y - S_y \geq -R, \
C_x - E_x \leq R, \
C_y - E_y \leq R,
\end{cases}\]
где (S, E) — точки начала и окончания отрезка, R — радиус люфта.
Это условие проверяет, что курсор находится в рамке, которая отстоит от прямоугольника на R.