2016-11-18 8 views
0

У меня есть простой эскиз обработки, рисующий сплошную линию эллипсов диаметром 20 пикселей. Есть ли способ изменить эскиз так, чтобы он рисовал векторные фигуры вместо пикселей?Обработка: рисовать вектор вместо пикселей

void setup() { 
    size(900, 900); 
    background(110, 255, 94); 

} 

void draw() { 
    ellipse(mouseX, mouseY, 20, 20); 
fill(255); 
} 

Спасибо всем, кто может предоставить некоторые полезные советы.

+0

Не могли бы вы прояснить? «рисование ** непрерывной ** линии эллипсов с диаметром 20 пикселей» - если ваша мышь движется быстрее, при вашей текущей реализации линия не будет непрерывной. Что касается векторных фигур, вы рисуете их как фигуры. Вы можете сохранить эти фигуры в векторном формате, используя [встроенную библиотеку PDF] (https://processing.org/reference/libraries/pdf/index.html) –

+0

@GeorgeProfenza Спасибо, спасибо, спасибо за ваш быстрый ответ, обычный. Мои извинения за формулировку неясно, постоянно я просто подразумевал, что программа продолжает рисовать, когда я перемещаю мышь. Пробелы, возникающие из-за перемещения указателя мыши быстрее, на данный момент не являются проблемой. – JoSch

+1

Прохладный, в этом случае ваша программа выше уже делает то, что вам нужно: D. Вам просто нужно добавить подробные описания экспорта в pdf. Он также находится в одном из встроенных примеров: * Обработка> Примеры> Библиотеки> Экспорт PDF> MousePress * –

ответ

3

Расширение мой комментарий выше, есть несколько вещей, чтобы решить:

  1. нарисовав непрерывную линию эллипсов с диаметром 20px

  2. черпает векторные фигуры

В настоящее время вы рисуете эллипсы на основе движения мыши. Побочным эффектом является то, что если вы двигаете мышью достаточно быстро, у вас будут промежутки между эллипсами.

Чтобы заполнить пробелы, вы можете определить расстояние между двумя эллипсами. Если расстояние больше размеров этих двух эллипсов, вы можете нарисовать их между ними.

Класс PVector предоставляет функцию lerp(), которая позволяет легко интерполировать между двумя точками. Вы можете прочитать больше об этом и привести несколько примеров. here

Используя соотношение между этими расстояниями между двумя точками и размером эллипса, количество точек, необходимых между ними. Вот пример, который хранит местоположение мыши в список PVectors, как вы переместите мышь:

//create an array list to store points to draw 
ArrayList<PVector> path = new ArrayList<PVector>(); 
//size of each ellipse 
float size = 20; 
//how tight will the extra ellipses be drawn together 
float tightness = 1.25; 

void setup() { 
    size(900, 900); 
} 

void draw() { 
    background(110, 255, 94); 
    fill(255); 

    //for each point in the path, starting at 1 (not 0) 
    for(int i = 1; i < path.size(); i++){ 

    //get a reference to the current and previous point 
    PVector current = path.get(i); 
    PVector previous = path.get(i-1); 

    //calculate the distance between them 
    float distance = previous.dist(current); 

    //work out how many points will need to be added in between the current and previous points to keep the path continuous (taking the ellipse size into account) 
    int extraPoints = (int)(round(distance/size * tightness)); 

    //draw the previous point 
    ellipse(previous.x,previous.y,size,size); 

    //if there are any exta points to be added, compute and draw them: 
    for(int j = 0; j < extraPoints; j++){ 

     //work out a normalized (between 0.0 and 1.0) value of where each extra point should be 
     //think of this as a percentage along a line: 0.0 = start of line, 0.5 = 50% along the line, 1.0 = end of the line 
     float interpolation = map(j,0,extraPoints,0.0,1.0); 

     //compute the point in between using PVector's linear interpolation (lerp()) functionality 
     PVector inbetween = PVector.lerp(previous,current,interpolation); 

     //draw the point in between 
     ellipse(inbetween.x,inbetween.y,size,size); 
    } 

    } 

    //draw instructions 
    fill(0); 
    text("SPACE = clear\nLEFT = decrease tightness\nRIGHT = increase tightness\ntightness:"+tightness,10,15); 
} 

void mouseDragged(){ 
    path.add(new PVector(mouseX,mouseY)); 
} 
void keyPressed(){ 
    if(keyCode == LEFT) tightness = constrain(tightness-0.1,0.0,3.0); 
    if(keyCode == RIGHT) tightness = constrain(tightness+0.1,0.0,3.0); 
    if(key == ' ') path.clear(); 
} 

Обратите внимание, что интерполяция между точками линейным. Это самое простое, но, как следует из названия, это все о линиях: он всегда соединяет две точки по прямой, а не кривые.

Я добавил опцию, чтобы контролировать, как плотно интерполированные эллипсы будут упакованы вместе. Вот несколько скриншотов с различными уровнями герметичности. Вы заметите, как герметичность увеличивается, линии станут более очевидными:

tightness 0

tightness 1.5

tightness 3.0

Вы бежите код ниже:

//create an array list to store points to draw 
 
var path = []; 
 
//size of each ellipse 
 
var ellipseSize = 20; 
 
//how tight will the extra ellipses be drawn together 
 
var tightness = 1.25; 
 

 
function setup() { 
 
    createCanvas(900, 900); 
 
} 
 

 
function draw() { 
 
    background(110, 255, 94); 
 
    fill(255); 
 
    
 
    //for each point in the path, starting at 1 (not 0) 
 
    for(var i = 1; i < path.length; i++){ 
 
    
 
    //get a reference to the current and previous point 
 
    var current = path[i]; 
 
    var previous = path[i-1]; 
 
    
 
    //calculate the distance between them 
 
    var distance = previous.dist(current); 
 
    
 
    //work out how many points will need to be added in between the current and previous points to keep the path continuous (taking the ellipse size into account) 
 
    var extraPoints = round(distance/ellipseSize * tightness); 
 
    
 
    //draw the previous point 
 
    ellipse(previous.x,previous.y,ellipseSize,ellipseSize); 
 
    
 
    //if there are any exta points to be added, compute and draw them: 
 
    for(var j = 0; j < extraPoints; j++){ 
 
     
 
     //work out a normalized (between 0.0 and 1.0) value of where each extra point should be 
 
     //think of this as a percentage along a line: 0.0 = start of line, 0.5 = 50% along the line, 1.0 = end of the line 
 
     var interpolation = map(j,0,extraPoints,0.0,1.0); 
 
     
 
     //compute the point in between using PVector's linear interpolation (lerp()) functionality 
 
     var inbetween = p5.Vector.lerp(previous,current,interpolation); 
 
     
 
     //draw the point in between 
 
     ellipse(inbetween.x,inbetween.y,ellipseSize,ellipseSize); 
 
    } 
 
    
 
    } 
 
    
 
    //draw instructions 
 
    fill(0); 
 
    text("BACKSPACE = clear\n- = decrease tightness\n+ = increase tightness\ntightness:"+tightness,10,15); 
 
} 
 

 
function mouseDragged(){ 
 
    path.push(createVector(mouseX,mouseY)); 
 
} 
 
function keyPressed(){ 
 
    if(keyCode == 189) tightness = constrain(tightness-0.1,0.0,3.0); 
 
    if(keyCode == 187) tightness = constrain(tightness+0.1,0.0,3.0); 
 
    if(keyCode == BACKSPACE) path = []; 
 
} 
 

 
//https://stackoverflow.com/questions/40673192/processing-draw-vector-instead-of-pixels
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>

Если вы хотите более гладкие линии, вам потребуется использовать другую интерполяцию, такую ​​как квадратичная или кубическая интерполяция.Вы можете начать с существующих функций обработки для кривых рисования, таких как curve() или bezier(), и вы найдете полезные ресурсы, не связанные с обработкой here, here и here.

На векторных форм

Вы не работаете непосредственно с pixels[], вы рисуете формы. Эти формы можно легко сохранить в PDF с помощью Processing's PDF library Проверьте Одиночный кадр из анимации (с экраном) пример.

Вот версия, которая сохраняет в PDF при нажатии на «s» ключ:

import processing.pdf.*; 

//create an array list to store points to draw 
ArrayList<PVector> path = new ArrayList<PVector>(); 
//size of each ellipse 
float size = 20; 
//how tight will the extra ellipses be drawn together 
float tightness = 1.25; 

//PDF saving 
boolean record; 

void setup() { 
    size(900, 900); 

} 

void draw() { 
    background(110, 255, 94); 
    fill(255); 

    //if we need to save the current frame to pdf, begin recording drawing instructions 
    if (record) { 
    // Note that #### will be replaced with the frame number. Fancy! 
    beginRecord(PDF, "frame-####.pdf"); 
    } 

    //for each point in the path, starting at 1 (not 0) 
    for(int i = 1; i < path.size(); i++){ 

    //get a reference to the current and previous point 
    PVector current = path.get(i); 
    PVector previous = path.get(i-1); 

    //calculate the distance between them 
    float distance = previous.dist(current); 

    //work out how many points will need to be added in between the current and previous points to keep the path continuous (taking the ellipse size into account) 
    int extraPoints = (int)(round(distance/size * tightness)); 

    //draw the previous point 
    ellipse(previous.x,previous.y,size,size); 

    //if there are any exta points to be added, compute and draw them: 
    for(int j = 0; j < extraPoints; j++){ 

     //work out a normalized (between 0.0 and 1.0) value of where each extra point should be 
     //think of this as a percentage along a line: 0.0 = start of line, 0.5 = 50% along the line, 1.0 = end of the line 
     float interpolation = map(j,0,extraPoints,0.0,1.0); 

     //compute the point in between using PVector's linear interpolation (lerp()) functionality 
     PVector inbetween = PVector.lerp(previous,current,interpolation); 

     //draw the point in between 
     ellipse(inbetween.x,inbetween.y,size,size); 
    } 

    } 
    //once what we want to save has been recorded to PDF, stop recording (this will skip saving the instructions text); 
    if (record) { 
    endRecord(); 
    record = false; 
    println("pdf saved"); 
    } 

    //draw instructions 
    fill(0); 
    text("SPACE = clear\nLEFT = decrease tightness\nRIGHT = increase tightness\ntightness:"+tightness+"\n's' = save PDF",10,15); 
} 

void mouseDragged(){ 
    path.add(new PVector(mouseX,mouseY)); 
} 
void keyPressed(){ 
    if(keyCode == LEFT) tightness = constrain(tightness-0.1,0.0,3.0); 
    if(keyCode == RIGHT) tightness = constrain(tightness+0.1,0.0,3.0); 
    if(key == ' ') path.clear(); 
    if(key == 's') record = true; 
} 
2

В дополнении к большому ответу Джорджа (который я + +1), я хотел бы предложить более базовый вариант:

Проблема, как сказал Джордж, заключается в том, что при перемещении мыши вы фактически пропускаете кучу пикселей. Поэтому, если вы нарисуете только эллипсы или очки на mouseX, mouseY, тогда вы получите пробелы.

Неправильное исправление: Переменные pmouseX и pmouseY сохраняют предыдущую позицию курсора.

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

void draw(){ 
line(pmouseX, pmouseY, mouseX, mouseY); 
} 

Shameless самореклама: я написал учебник на получение пользовательского ввода в обработке имеющихся here.

Примечания: Это немое решение будет работать только если вы не перерисовки фона каждый кадр. Если вам нужно перерисовать все кадры, тогда ответ Джорджа - это путь.

 Смежные вопросы

  • Нет связанных вопросов^_^