[英]How to draw a line from point to point in Processing
我正在嘗試生成一個圖形,繪制出貨路徑,從原點到目的地。 我已經將緯度和經度數據轉換為適合美國地圖的像素(1620,1080)。
它當前寫入的方式是按照在我的csv文件中排序的方式順序繪制的。 但是,我希望這些線從原點輻射到目的地。 現在我只能弄清楚如何放下已繪制的線條。
我認為代碼的相關部分在// Draw Lines
。
long current;
int x;
int y;
ArrayList loads;
void setup() {
size(1620, 1080);
background(55);
smooth();
frameRate(15);
// Draw US Map
String[] lines = loadStrings("Map2.csv"); // File containing coordinates to plot US Map
stroke(55);
strokeWeight(1);
smooth();
String[] pieces = split(lines[0], ',');
for ( int i = 0; i < lines.length; i++) {
fill(0);
beginShape();
current = int(pieces[0]);
while ( current == int(pieces[0]) & i < lines.length) {
x = int(pieces[2]);
y = int(pieces[1]);
vertex(x, y);
i++;
if ( i < lines.length) {
pieces = split(lines[i], ',');
}
}
endShape();
}
// Add Lakes to Map
String[] lines2 = loadStrings("Water.csv"); // File containing coordinates to plot great lakes
smooth();
fill(22, 25, 180);
String[] pieces2 = split(lines2[0], ',');
for (int i = 0; i < lines2.length; i++)
{
fill(110);
beginShape();
current = int(pieces2[0]);
while (current == int(pieces2[0]) & i < lines2.length) {
x = int(pieces2[2]);
y = int(pieces2[1]);
vertex(x, y);
i++;
if (i < lines2.length) {
pieces2 = split(lines2[i], ',');
}
}
endShape();
}
// Draw Lines
loads = new ArrayList();
String[] loadset = loadStrings("data1.csv");
for ( int i3 = 0; i3 < loadset.length; i3++) {
String[] loads2 = split(loadset[i3], ',');
loads.add( new Lane(int(loads2[0]), int(loads2[1]), int(loads2[2]), int(loads2[3])) );
}
}
int i=1;
int imax = 1;
int incmult = 1;
void draw() {
if (i < loads.size()-imax){
for(int iadd = 0; iadd < imax; iadd++)
{
Lane Lane = (Lane) loads.get(iadd);
Lane.display();
Lane = (Lane) loads.get(i+iadd);
Lane.display();
}
i +=imax;
}
imax = imax + incmult;
}
class Lane {
int x;
int y;
int x2;
int y2;
Lane( int tempX, int tempY, int tempX2, int tempY2) {
x = tempX;
y = tempY;
x2 = tempX2;
y2 = tempY2;
}
void display() {
int r = 65;
int g = 255;
int b = 35;
strokeWeight(1);
stroke(r, g, b, 55);
line(x, y, x2, y2);
stroke(255, 255, 255); // Origin
fill(255, 255, 255, 55);
ellipse(x, y, 3, 3);
stroke(171, 62, 193); // Destination
fill(171, 62, 193);
ellipse(x2, y2, 3, 3);
}
}
我的data1.csv
文件包含四列x, y, x2, y2
,其中(x, y)
表示原點, (x2, y2)
表示目標坐標。
// data.csv
data[0] data[1] data[2] data[3]
929 327 602 507
1335 458 1327 782
1422 325 848 744
1302 280 1118 458
1041 583 1193 666
1267 616 1058 394
1215 671 1351 857
1334 851 1410 946
1334 851 1409 916
828 761 861 653
1386 323 1203 594
1037 293 1013 522
908 869 958 532
1029 331 1053 409
906 357 828 761
. . . .
. . . .
更新我添加了我的數據的鏈接,因為我仍然在繪制圖像時遇到了一些困難,正如我所設想的那樣。
data1 <“https://docs.google.com/spreadsheets/d/1QzbCGW8H6PZgLkmWN8OyplVNTJhp3tlPGxR_Zv6lttM/pub?output=csv”>
目前問題不是很清楚,所以這個答案的當前形式是不完整的。
以下是一些可能簡化代碼的建議,希望有助於實現最終目標:
這是使用此TSV的基本示例,基於上面保存為data.tsv的數據
Table data;
PShape dataPlot;
size(1620, 1080,P2D);
//create a group to store the lines from each row
dataPlot = createShape();
//load the data, specifying it has a header and it's tab separated
data = loadTable("data.tsv", "header, tsv");
//traverse each row
dataPlot.beginShape(LINES);
for(TableRow row : data.rows()){
//extract each value
int x1 = row.getInt("x1");
int y1 = row.getInt("y1");
int x2 = row.getInt("x2");
int y2 = row.getInt("y2");
//add the coordinates as lines to the group
dataPlot.stroke(160);
dataPlot.vertex(x1,y1);
dataPlot.stroke(0);
dataPlot.vertex(x2,y2);
}
dataPlot.endShape();
//render the plot
shape(dataPlot);
使用暗到淺灰色顯示路徑的原點和目的地,這是使用部分樣本數據的結果:
如果在創建PShape實例后需要訪問每個頂點,可以使用getVertex() 。 它需要您可能想要檢索的頂點的索引。 例如, dataPlot.getVertex(0);
和dataPlot.getVertex(1);
將返回第一行的坐標dataPlot.getVertex(2);
和dataPlot.getVertex(2);
將返回第二行的坐標,依此類推。
如果管理類似層次結構的樹而不是頂點索引更容易,則可以創建PShape組。 唯一需要注意的是,創建的以下子PShape實例將使用前綴為set的函數繪制,而不是典型的stroke()
/ fill()
/ etc。 你已經習慣了: setStroke()
/ setFill()
/ setFill()
這是使用PShape組並將距離映射到線條顏色和粗細的代碼示例:
Table data;
PShape dataPlot;
size(1620, 1080, P2D);
//create a group to store the lines from each row
dataPlot = createShape(GROUP);
//load the data, specifying it has a header and it's tab separated
data = loadTable("data.tsv", "header, tsv");
//traverse each row
for (TableRow row : data.rows ()) {
//extract each value
int x1 = row.getInt("x1");
int y1 = row.getInt("y1");
int x2 = row.getInt("x2");
int y2 = row.getInt("y2");
//add the coordinates as lines to the group
PShape line = createShape(LINE, x1, y1, x2, y2);
float dist = dist(x1, y1, x2, y2);
line.setStroke(color(map(dist, 0, height, 160, 0)));
line.setStrokeWeight(map(dist, 0, height, 10.0, 1.0));
dataPlot.addChild(line);
}
//render the plot
shape(dataPlot);
在這種情況下,檢索第一行將如下所示:
PShape line0 = dataPlot.getChild(0);
你允許你訪問它的兩個頂點:
println(line0.getVertex(0));
println(line0.getVertex(1));
如果要為這些位置設置動畫,可以在單個值或PVector的lerp()方法(對於PVectors :)上輕松使用lerp() )。 此函數將期望一對開始/結束值和一個標准化值(介於0.0和1.0之間)並返回其間的值。 把它想象成你路徑上的一個百分比:
這是在遍歷每一行時繪制橢圓的基本示例,它的顏色表示開始(黑色)或結束(白色)位置(拖動應允許手動控制將X軸映射到行遍歷):
Table data;
PShape plot;
void setup(){
size(1620, 1080, P2D);
//create a group to store the lines from each row
plot = createShape(GROUP);
//load the data, specifying it has a header and it's tab separated
data = loadTable("data.tsv", "header, tsv");
//traverse each row
for (TableRow row : data.rows ()) {
//extract each value
int x1 = row.getInt("x1");
int y1 = row.getInt("y1");
int x2 = row.getInt("x2");
int y2 = row.getInt("y2");
//add the coordinates as lines to the group
PShape line = createShape(LINE, x1, y1, x2, y2);
float dist = dist(x1, y1, x2, y2);
line.setStroke(color(map(dist, 0, height, 160, 0)));
line.setStrokeWeight(map(dist, 0, height, 10.0, 1.0));
plot.addChild(line);
}
}
void draw(){
background(255);
//render the plot
shape(plot);
//animate the trajectories
//use normalized (between 0.0 and 1.0) value to traverse the paths (think of it as 0 and 100%, 0 is at the start 100% is at the end)
//if can be interactive
float traversal;
if(mousePressed) {
traversal = map(mouseX,0,width,0.0,1.0);
}else{//or time based, up to you :)
traversal = map(sin(frameCount * 0.1),-1.0,1.0,0.0,1.0);
}
//for each trajectory
for(int i = 0 ; i < plot.getChildCount(); i++){
PShape line = plot.getChild(i);
//access each line's start and end points
PVector start = line.getVertex(0);
PVector end = line.getVertex(1);
//calculate the linearly interpolated point in between start end using the traversal value and lerp()
PVector inbetween = PVector.lerp(start,end,traversal);
//use the interpolated value to draw
fill(traversal * 255);
ellipse(inbetween.x,inbetween.y,15,15);
}
}
這是一個非常類似的例子,只是淡化點:
Table data;
PShape plot;
void setup(){
size(1620, 1080, P2D);
//create a group to store the lines from each row
plot = createShape(GROUP);
//load the data, specifying it has a header and it's tab separated
data = loadTable("data.tsv", "header, tsv");
//traverse each row
for (TableRow row : data.rows ()) {
//extract each value
int x1 = row.getInt("x1");
int y1 = row.getInt("y1");
int x2 = row.getInt("x2");
int y2 = row.getInt("y2");
//add the coordinates as lines to the group
PShape line = createShape(LINE, x1, y1, x2, y2);
float dist = dist(x1, y1, x2, y2);
line.setStroke(color(map(dist, 0, height, 160, 0)));
line.setStrokeWeight(map(dist, 0, height, 10.0, 1.0));
plot.addChild(line);
}
//clear the background
noStroke();
shape(plot);//this needs to be drawn at least once it seems
background(255);
}
void draw(){
//hacky fade effect, change the alpha (16) transparency value to experiment with fade amount
fill(255,16);
rect(0,0,width,height);
//animate the trajectories
//use normalized (between 0.0 and 1.0) value to traverse the paths (think of it as 0 and 100%, 0 is at the start 100% is at the end)
//if can be interactive
float traversal;
if(mousePressed) {
traversal = map(mouseX,0,width,0.0,1.0);
}else{//or time based, up to you :)
traversal = map(sin(frameCount * 0.01),-1.0,1.0,0.0,1.0);
}
//for each trajectory
for(int i = 0 ; i < plot.getChildCount(); i++){
PShape line = plot.getChild(i);
//access each line's start and end points
PVector start = line.getVertex(0);
PVector end = line.getVertex(1);
//calculate the linearly interpolated point in between start end using the traversal value and lerp()
PVector inbetween = PVector.lerp(start,end,traversal);
//use the interpolated value to draw
fill(lerpColor(color(255,0,0),color(0,255,0),traversal));
ellipse(inbetween.x,inbetween.y,15,15);
}
}
這是另一個有趣的小變化:
Table data;
PShape plot;
void setup(){
size(1620, 1080, P2D);
smooth(8);
//create a group to store the lines from each row
plot = createShape(GROUP);
//load the data, specifying it has a header and it's tab separated
data = loadTable("data.tsv", "header, tsv");
//traverse each row
for (TableRow row : data.rows ()) {
//extract each value
int x1 = row.getInt("x1");
int y1 = row.getInt("y1");
int x2 = row.getInt("x2");
int y2 = row.getInt("y2");
//add the coordinates as lines to the group
PShape line = createShape(LINE, x1, y1, x2, y2);
plot.addChild(line);
}
shape(plot);
strokeWeight(5.0);
}
void draw(){
//hacky fade effect, change the alpha/transparency value to experiment with fade amount
background(255);
//animate the trajectories
//use normalized (between 0.0 and 1.0) value to traverse the paths (think of it as 0 and 100%, 0 is at the start 100% is at the end)
//if can be interactive
float traversal;
if(mousePressed) {
traversal = map(mouseX,0,width,0.0,1.0);
}else{//or time based, up to you :)
traversal = map(sin(frameCount * 0.01),-1.0,1.0,0.0,1.0);
}
beginShape(LINES);
//for each trajectory
for(int i = 0 ; i < plot.getChildCount(); i++){
PShape line = plot.getChild(i);
//access each line's start and end points
PVector start = line.getVertex(0);
PVector end = line.getVertex(1);
//calculate the linearly interpolated point in between start end using the traversal value and lerp()
PVector inbetween = PVector.lerp(start,end,traversal);
//use the interpolated value to draw
stroke(64);
vertex(start.x,start.y);
stroke(160);
vertex(inbetween.x,inbetween.y);
}
endShape();
}
視頻演示在這里
如果線性插值不夠,您需要更多控制時序或插值類型,請查看BenediktGroß的Ani庫
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.