Расширение мой комментарий выше, есть несколько вещей, чтобы решить:
-
нарисовав непрерывную линию эллипсов с диаметром 20px
-
черпает векторные фигуры
В настоящее время вы рисуете эллипсы на основе движения мыши. Побочным эффектом является то, что если вы двигаете мышью достаточно быстро, у вас будут промежутки между эллипсами.
Чтобы заполнить пробелы, вы можете определить расстояние между двумя эллипсами. Если расстояние больше размеров этих двух эллипсов, вы можете нарисовать их между ними.
Класс 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();
}
Обратите внимание, что интерполяция между точками линейным. Это самое простое, но, как следует из названия, это все о линиях: он всегда соединяет две точки по прямой, а не кривые.
Я добавил опцию, чтобы контролировать, как плотно интерполированные эллипсы будут упакованы вместе. Вот несколько скриншотов с различными уровнями герметичности. Вы заметите, как герметичность увеличивается, линии станут более очевидными:
Вы бежите код ниже:
//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;
}
Не могли бы вы прояснить? «рисование ** непрерывной ** линии эллипсов с диаметром 20 пикселей» - если ваша мышь движется быстрее, при вашей текущей реализации линия не будет непрерывной. Что касается векторных фигур, вы рисуете их как фигуры. Вы можете сохранить эти фигуры в векторном формате, используя [встроенную библиотеку PDF] (https://processing.org/reference/libraries/pdf/index.html) –
@GeorgeProfenza Спасибо, спасибо, спасибо за ваш быстрый ответ, обычный. Мои извинения за формулировку неясно, постоянно я просто подразумевал, что программа продолжает рисовать, когда я перемещаю мышь. Пробелы, возникающие из-за перемещения указателя мыши быстрее, на данный момент не являются проблемой. – JoSch
Прохладный, в этом случае ваша программа выше уже делает то, что вам нужно: D. Вам просто нужно добавить подробные описания экспорта в pdf. Он также находится в одном из встроенных примеров: * Обработка> Примеры> Библиотеки> Экспорт PDF> MousePress * –