问题描述
我有一个简单的处理草图",绘制了一条直径为20px的椭圆形连续线.有没有一种方法可以修改草图,使其绘制矢量形状而不是像素?
I have a simple Processing Sketch, drawing a continuous line of ellipses with a 20px diameter. Is there a way to modify the sketch so that it draws vector shapes instead of pixels?
void setup() {
size(900, 900);
background(110, 255, 94);
}
void draw() {
ellipse(mouseX, mouseY, 20, 20);
fill(255);
}
感谢所有能提供一些有用建议的人.
Thanks to everyone who can provide some helpful advice.
推荐答案
在上面扩展我的评论,有几件事需要解决:
Expanding my comment above, there a couple of things to tackle:
当前,您正在根据鼠标移动绘制椭圆.副作用是,如果鼠标移动得足够快,则椭圆之间会留有空隙.
Currently you're drawing ellipses based on mouse movement.A side effect is that if you move the mouse fast enough you will have gaps in between ellipses.
要填补空白,您可以算出每两个椭圆之间的距离.如果距离大于这两个椭圆的大小,则可以在两个椭圆之间画一些.
To fill the gaps you can work out the distance between every two ellipses.If the distance is greater than the sizes of these two ellipses you can draw some in between.
PVector类提供了lerp()函数,使您可以轻松地在两个点之间进行插值.您可以在此阅读更多内容并在此处运行一些示例>
The PVector class provides a lerp() function that allows you easily interpolate between two points.You can read more on this and run some examples here
使用两点之间的距离与椭圆尺寸之间的比例来确定两者之间的比例.这是一个在您拖动鼠标时将鼠标位置存储到PVectors列表中的示例:
Using the ratio between these distance of two points and the ellipse size the number of points needed in between.Here is an example that stores mouse locations to a list of PVectors as you drag the mouse:
//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();
}
请注意,点之间的插值是线性.这是最简单的方法,但是顾名思义,这全都是关于行的:它总是以直线连接两个点,而不是曲线.
Note that the interpolation between points is linear.It's the simplest, but as the name implies, it's all about lines:it always connects two points in a straight line, not curves.
我添加了用于控制将内插椭圆压缩在一起的选项.这是几个具有不同紧密度级别的屏幕截图.您会注意到,随着紧密度的增加,线条会变得更加明显:
I've added the option to control how tight interpolated ellipses will be packed together. Here are a couple of screenshots with different tightness levels. You'll notice as tightness increases, the lines will become more evident:
您在下面运行代码:
//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(),您会发现一些与处理此处,此处和此处.
If you want smoother lines you will need to use a different interpolation such as quadratic or cubic interpolation. You can start with existing Processing functions for drawing curves such as curve() or bezier(),and you'll find some helpful resources unrelated to Processing here,here and here.
在矢量形状上
您不是直接使用 pixels [] ,而是在绘制形状.可以使用加工的PDF库轻松将这些形状保存为PDF.查看动画中的单帧(带屏幕显示)示例.
You're not directly working with pixels[], you're drawing shapes.These shapes can easily be saved to PDF using Processing's PDF libraryCheck out the Single Frame from an Animation (With Screen Display) example.
以下是按"s"键时保存为PDF的版本:
Here is a version that saves to PDF when pressing the 's' key:
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;
}
这篇关于处理:绘制矢量而不是像素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!