Страницы

Поиск по вопросам

суббота, 7 декабря 2019 г.

Как в SVG найти область обрамляемую путями

#javascript #алгоритм #svg #typescript


В SVG файле есть несколько путей path.

Мне нужно найти ту область, которая лежит между путей, обрамлена путями.

Это то, что получается в результате кнопки "Заливать замкнутые области" в Inkscape.

Возможно ли использовать библиотеки, предпочтительно SVG.js И её плагины.

Для чего мне это надо?

Хочу закрасить определённым образом, то что лежит внутри путей.

Пример: есть 4 пути.



Надо на JavaScript рассчитать, найти область внутри.



Может можно и без её расчёта сделать, но нужно что-то сделать, что бы я смог раскрасить
эту область на JavaScript.
    


Ответы

Ответ 1



Объединение нескольких path в один путь. В первом посте итак было два совершенно разных направления ответов, чтобы не запутать людей, которые возможно придут в этот топик, я сделаю дополнительный ответ по дополнительным комментариям автора вопроса. рассчитав точки пересечения, я могу вычислить и куски путей до этих пересечений, а потом объединить в один путь, хотя это конечно математически не совсем просто. Возьмем фигуру, составленную из четырех патчей, из предыдущего ответа: И объединим четыре патча из первого примера в один патч, который будет иметь четыре сабпатча (подпути). Надо только строго следить, чтобы каждый подпатч начинался с большой буквы "M" (абсолютное позиционирование начальной точки подпути). Копируем всё в один параметр Расчет длины суммарного патча,- используется метод - getTotalLength() JS
Расчетная длина суммарного патча составит - 2391px Когда приходит чёткое понимание, как можно сделать вручную объединение нескольких патчей в один, то наверное можно написать скрипт, который выполнит эту рутинную работу.

Ответ 2



Я не представляю, как можно объяснить плагину какой путь выбрать. Если только с помощью утилиты, где есть пипетка, например ColorMania навести её на определенный участок, скопировать код цвета #D62728 и затем по этому параметру найти конкретный путь, который закрашен этим цветом. Но это слишком непродуктивно. Я для себя выбрал другой, более короткий путь. Допустим у нас есть svg файл средней сложности: Ставлю единичку перед "М" в формуле пути d="1M83.21744517582593 и этот конкретный путь исчезает. Теперь я знаю какой конкретный путь отвечает за конкретную часть изображения. Если нужно одновременно перекрасить много участков с одинаковым цветом, то в Notepad++ делаю поиск с одновременной заменой по этому параметру #d62728 update по результатам уточнений в вопросе Взял ваш эскиз в качестве образца для SVG файла Ниже код svg Патчи не заполнены цветом. Только закрашены строки. Следующий пример с заполнением цветом. Видите как fill работает, если каждый конкретный path не замкнут,- распределение цвета идет по обе стороны от линии. Рассчитать точки пересечения патчей это одно, а вот вычислить, как будет распределен цвет, это уже более трудная задача и я не знаю, есть ли у неё простое решение. Так как просто рассчитать скриптом площадь такой криволинейной фигуры и то довольно сложная задача.

Ответ 3



В дополнение к ответу @Alexandr_TT ( суть которого в том, что несколько path-ей нужно собрать в один). Вижу довольно простое решение, которое однако может показаться математически не самым правильным: Растеризуем картинку с помощью canvas. Выполняем любую функцию заливки изображения цветом X (например самую простую постил здесь) в любой точке предполагаемой фигуры. Перебираем все пикселы цвета X в canvas, переводим координаты пикселов в координаты svg. Для каждого пиксела перебираем расстояние до каждой вершины в svg - и если оно меньше порогового (порог - размер пиксела x 2 в системе координат SVG) - значит мы нашли новую вершину нашей новой области! Осталось только последовательно соединить все найденные вершины - делается это просто, так как все отрезки записаны в path-ах. Если отрезок не найден - берётся крайняя ближайшая точка вне path-а: таким образом образуются стыки разных path-ей. Хорош своей простотой. Алгоритм #2: От конкретной точки предполагаемой фигуры проводятся воображаемые отрезки(назову их "лучи") до каждой из вершин каждого path-а. Для каждого луча проверяется пересечение с каждым отрезком каждого path-а (например таким алгоритмом проверки пересечения отрезков). Если луч не пересёк ни одного отрезка, бинго, вершина на конце луча - это одна из вершин фигуры, которую мы вычисляем. Таким образом перебрав все лучи мы получаем все вершины новой фигуры кроме угловых. Угловые вершины вычисляются отдельно пересечением угловых отрезков (т.к. они не относятся ни к одному из путей). Дальше сооственно все - последовательное расположение вершин будет новой фигурой. Хорош точностью. Есть одно большое но - заполнит только выпуклые фигуры - это решится усложнением алгоритма. В трёхмерной графике такие алгоритмы нередки для collision detection, это целая история - и оптимизировать их быстродействие можно годами :)

Комментариев нет:

Отправить комментарий