Смешивание векторных путей в JavaScript или Обработка - PullRequest
1 голос
/ 23 августа 2011

Я пытаюсь написать какое-нибудь программное обеспечение, которое будет делать что-то похожее на инструмент смешивания Adobe Illustrator. Цель состоит в том, чтобы создать новые пути, используя сохраненные пути в качестве базовых ингредиентов с разным весом (то есть 30% путь1 70% путь2). Для тех, кто незнаком, пример Adobe Illustrator выглядит так: 3 steps between two vector paths

Проблема в том, что я действительно не знаю, с чего начать. В идеале это можно было бы запустить в браузере, поэтому я надеялся сделать это на JavaScript. Я рассмотрел использование SVG с Raphael.js и стандартными векторами на холсте html5, но важно иметь возможность импортировать векторную графику из Illustrator тем или иным способом (синтаксический анализ файлов SVG вручную не представляет проблем, так как это всего лишь xml).

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

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

1 Ответ

7 голосов
/ 28 августа 2011

Вы упомянули SVG / JS / Raphael.js и геомеративный.Насколько я могу судить, вас интересует бит интерполяции, а не бит загрузки / обработки вектора (который будет зависеть от того, какую версию вы будете использовать JS / Java).

Пока вы 'Если у вас есть вершины формы, которую вы хотите смешать, и вершины фигуры, с которой вы хотите смешать (количество вершин будет одинаковым для обоих наборов вершин), все, что вам нужно сделать, это интерполировать значения.Это будет что-то вроде: (1-t)*start+t*end;, где t - это величина наложения, значение от 0 (начальная форма) до 1 (конечная форма).

Вот функция, которая интерполирует два набора точек (сохраненных как PVectorэкземпляры):

void interpolateVerts(float t,ArrayList<PVector> start,ArrayList<PVector> end,ArrayList<PVector> current){
  int numVerts = start.size();
  while(numVerts-- > 0) current.get(numVerts).set(PVector.add(PVector.mult(start.get(numVerts),(1-t)),PVector.mult(end.get(numVerts),t)));
}

Ожидается t (сумма смешивания), начальная и конечная позиции, а также вектор для сохранения текущих смешанных позиций.

Вы можете увидеть быстрое и грязное демо здесь (обратите внимание на форму вокруг наложения значка «Стоп»).

Другой способ добиться этого - использовать функцию lerp () , которая предназначена для интерполяции между двумяценности.Вы будете интерполировать каждую координату для своей фигуры, а метод PShapes ' getVertex () возвращает координаты xy в число с плавающей точкой [].Я предполагаю, что зацикливание, хотя один массив и «lerp» более прост и более переносим, ​​чем использование PVector:

void lerpArray(float t,float[] start,float[] end, float[] current){
  int i = start.length;
  while(i-- > 0) current[i] = lerp(start[i],end[i],t);
}

А вот краткий набросок тестового эскиза, чтобы проиллюстрировать идею (mouseX = количество смеси):

float[] start,end,current;
int len = 8;
void setup(){
  size(200,200);
  smooth();
  start = new float[len];
  end = new float[len];
  current = new float[len];
  setSquare(start,50,50,100,100);
  setSquare(current,50,50,100,100);
  setSquare(end,25,20,150,50);
}
void draw(){
  background(0);
  lerpArray((float)mouseX/width,start,end,current);
  beginShape();
  for(int i = 0 ; i < len; i+=2) vertex(current[i],current[i+1]);
  endShape();
}
void lerpArray(float t,float[] start,float[] end, float[] current){
  int i = start.length;
  while(i-- > 0) current[i] = lerp(start[i],end[i],t);
}
void setSquare(float[] verts,float x,float y,float width,float height){
  verts[0] = x+width;
  verts[1] = y;
  verts[2] = x+width;
  verts[3] = y+height;
  verts[4] = x;
  verts[5] = y+height;
  verts[6] = x;
  verts[7] = y;
}

Обновление

Хммм ... оказывается, это немного сложнее, чем это.Получение вершин не проблема.Перерисовка фигуры одна.Вершины PShape имеют типы (VERTEX, BEZIER_VERTEX и т. Д.), Поэтому после интерполяции вершины необходимо будет перерисовать.Я пытался расширить PShape и PShapeSVG, но столкнулся с проблемами быстро (из-за древовидной структуры PShape).Поскольку обработка является открытым исходным кодом, из любопытства я настроил класс PShape, добавив сеттеры для позиций вершин и геттеры / сеттеры для цвета заливки, а затем перекомпилировал библиотеку (core.jar)

BlendShape1BlendShape2BlendShape3

Вы можете скачать проект eclipse здесь , который включает в себя перекомпилированный файл core.jar в папке пользователя.Обратите внимание, что это НЕ рекомендуемый способ решения проблем.Для справки здесь используется код:

package svgblend;

import processing.core.PApplet;
import processing.core.PShape;

public class SVGBlend extends PApplet {
    PShape start,end,current;

    public void setup(){
      size(200,200);
      smooth();
      start   = loadShape("start.svg").getChild("start");
      end     = loadShape("end.svg").getChild("end");
      current = loadShape("start.svg").getChild("start");
      println(current.getFamily());
    }
    public void draw(){
      background(255);
      blendShape(start,end,current,(float)mouseX/width);
      shape(current,0,0);
    }
    void blendShape(PShape start,PShape end, PShape current,float amt){
        int i = start.getVertexCount();
        //verts
        while(i-- > 0) {
          float[] s = start.getVertex(i);
          float[] e = end.getVertex(i);
          current.setVertexX(i, lerp(s[0],e[0],amt));
          current.setVertexY(i, lerp(s[1],e[1],amt));
        }
        //colour
        int sFill = start.getFillColor();
        int eFill = end.getFillColor();
        current.setFillColor((int)lerpColor(sFill,eFill,amt));
    }
}

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

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

Goodluck!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...