Подтвердить что ты не робот

Применение закругленных углов к дорожкам/полигонам

Я собираю информацию о проекте, который должен начаться через несколько недель. Этот проект содержит инструмент рисования на основе браузера, в котором пользователи могут добавлять предопределенные формы или сами формировать фигуры. Формы должны выбираться, свободно масштабироваться и поворачиваться с помощью Illustrator-подобного transformtool (ручки). Предопределенные формы, которые мы имеем в виду: прямоугольники, эллипсы, полуэллипсы и (равнобедренные) треугольники.

До сих пор так хорошо, для достижения этого я думал о RaphaelJS или FabricJS, но... Каждая фигура (полигон/путь) должна быть нарисована с помощью определенного угла. И cornerradius должен поддерживаться при масштабировании, поэтому никаких искажений не возникает. Пользователь может указать округление по вводу.

Есть несколько препятствий/вопросов:

  • Есть ли какая-то унифицированная математическая формула, чтобы применить угловую форму к фигурам, которые я упомянул? Или каждая форма должна рассматриваться как сам мини-проект? Я хочу вернуть его как путь или поли, поэтому его можно нарисовать с помощью SVG или холста.
  • Каждая операция масштабирования или поворота, перетаскивая манипуляторы преобразования, приведет к (массивным) вычислениям для получения обновленной формы, я думаю. Прямоугольники являются самыми легкими для достижения и, кроме эллипсов, все остальные формы будут намного сложнее вычислять. Есть ли способ ускорить процесс?

Я нашел сайт, на котором пользователи могут рисовать блок-схемы и применять угловую форму почти на всех фигурах. Он работает так гладко, я не могу прибить, как они это сделали. Ссылка: https://www.lucidchart.com/ (кнопка "Попробовать" )

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

Спасибо заранее.

BTW. Производительность является ключевым в этом проекте. Вывод чертежа должен быть форматом SVG.

4b9b3361

Ответ 1

У меня возникла аналогичная проблема, и я не смог найти простое решение. В конце концов я написал довольно общую функцию округления углов, основанную на работе Adobe Illustrator. Он использует кривые Безье вместо дуг, но я думаю, что результат довольно приличный.

Он поддерживает округление с радиусом, заданным в координатном пространстве изображения SVG, или как часть расстояния между углом и его соседями.

Чтобы использовать это, включите rounding.js в свой проект и вызовите функцию:

roundPathCorners(pathString, radius, useFractionalRadius)

Код и несколько тестовых путей находятся здесь: http://embed.plnkr.co/kGnGGyoOCKil02k04snu/preview

Вот как выглядят примеры из рендера Plnkr:

SVG Path Rounding Examples

Ответ 2

Отправной точкой может быть использование-svg-curve-to-imitate-rounded-corner. Принцип состоит в том, чтобы преобразовать каждый угол с сокращенной относительной кубической (ыми). Этот пример очень простой и работает только с двумя возможными угловыми случаями.

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

Ответ 3

Несмотря на то, что этот вопрос существует некоторое время, некоторые могут остановиться и попробовать это решение:

var BORDER_RADIUS = 20;

function roundedPath( /* x1, y1, x2, y2, ..., xN, yN */ ){
    context.beginPath();
    if (!arguments.length) return;

    //compute the middle of the first line as start-stop-point:
    var deltaY = (arguments[3] - arguments[1]);
    var deltaX = (arguments[2] - arguments[0]);
    var xPerY = deltaY / deltaX;
    var startX = arguments[0] + deltaX / 2;
    var startY = arguments[1] + xPerY * deltaX / 2;

    //walk around using arcTo:
    context.moveTo(startX, startY);
    var x1, y1, x2, y2;
    x2 = arguments[2];
    y2 = arguments[3];
    for (var i = 4; i < arguments.length; i += 2) {
        x1 = x2;
        y1 = y2;
        x2 = arguments[i];
        y2 = arguments[i + 1];
        context.arcTo(x1, y1, x2, y2, BORDER_RADIUS);
    }

    //finally, close the path:
    context.arcTo(x2, y2, arguments[0], arguments[1], BORDER_RADIUS);
    context.arcTo(arguments[0], arguments[1], startX, startY, BORDER_RADIUS);
    context.closePath();
}

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

Теперь вам просто нужно найти способ выразить все ваши фигуры как полигоны.