Векторные формы морфинга более чем на 100% (экстраполяция формы)

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

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

Следующий пример был сделан с помощью команды Blend в Illustrator. Самая большая форма была нарисована вручную, поэтому я ожидаю, что экстраполяция векторной формы будет работать.

экстраполированные формы

Я уверен, что математика, стоящая за этим, достаточно проста, но в настоящее время я бы предпочел не копаться в программировании Безье.

Привет и добро пожаловать в GD.SE!

Ответы (1)

Это просто линейная интерполяция позиций точек. Вот краткий пример сценария иллюстратора:

#target illustrator


var sel = app.activeDocument.selection; 

if (sel.length === 2){
    if(sel[0].typename == "PathItem" && 
       sel[1].typename == "PathItem") {
         for (var incr=-0.4; incr < 1.5; incr += 0.2){
             if (incr != 0 && incr !=1)
                  interpolate2Curves(sel[0], sel[1], incr);
         }
    }
} else { 
    alert("select 2 curves");
}

function interpolate2Curves(c1,c2, amount) {
     var pts1 = sel[0].pathPoints;
     var pts2 = sel[1].pathPoints;
     var target = sel[0].duplicate();
     var t = target.pathPoints;
     for (var i=0;i<pts1.length;i++){
         var p1 = pts1[i].anchor;
         var p2 = pts2[i].anchor;
         t[i].anchor=[p1[0]+ amount*(p2[0]-p1[0]),
                      p1[1] + amount*(p2[1]-p1[1])];

         var p1 = pts1[i].rightDirection;
         var p2 = pts2[i].rightDirection;
         t[i].rightDirection=[p1[0]+ amount*(p2[0]-p1[0]),
                              p1[1] + amount*(p2[1]-p1[1])];

         var p1 = pts1[i].leftDirection;
         var p2 = pts2[i].leftDirection;
         t[i].leftDirection=[p1[0]+ amount*(p2[0]-p1[0]), 
                             p1[1] + amount*(p2[1]-p1[1])];

         }
}

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

результат

Изображение 1 : Интерполяция двух линий, цветов и аннотаций, добавленных для ясности.

что-то в JavaScript внутри браузера

function interpolate2Curves(t){
    var path1 = document.getElementById('a');
    var path2 = document.getElementById('b');
    var path3 = document.getElementById('t');
    var sl1 = path1.pathSegList;
    var sl2 = path2.pathSegList;
    var sl3 = path3.pathSegList;
    for (var i=0,len=sl3.numberOfItems;i<len;++i){
        var s1 = sl1.getItem(i);
        var s2 = sl2.getItem(i);
        var s3 = sl3.getItem(i);
        s3.x = s1.x + t*(s2.x - s1.x);
        s3.y = s1.y + t*(s2.y - s1.y);

        s3.x1 = s1.x1 + t*(s2.x1 - s1.x1);
        s3.y1 = s1.y1 + t*(s2.y1 - s1.y1);

        s3.x2 = s1.x2 + t*(s2.x2 - s1.x2);
        s3.y2 = s1.y2 + t*(s2.y2 - s1.y2);
    }
}

См. тестовый документ в этой скрипке: https://jsfiddle.net/5j48geLj/

Я не искал конкретное решение JS (в противном случае я бы спросил в SO), но и ИИ, и браузерный скрипт отлично справляются со своей задачей, спасибо. Я думаю, мне придется как-то это исправить, чтобы хорошо интерполировать между сегментами линии и сегментами Безье.
Вы можете попытаться сначала удлинить ручки линии, сохраняя при этом линию.
@ordo как jsfiddle.net/5j48geLj/1 Конечно, есть неограниченные способы интерполяции вещей, особенно строк.
Я имею в виду более тривиальные проблемы, например, пути с одинаковым количеством вершин могут иметь разную структуру команд пути SVG, поэтому их следует сначала преобразовать, чтобы они соответствовали друг другу. Похоже, это хороший вопрос для SO, но я думаю, что сторонние библиотеки (snap.svg) могут помочь.