Reputation: 680
I'm trying to create a graphic that plots a map of the United States using coordinates stored in Map2.csv
. Then I add the great lakes using information from Water.csv
. I then have origin and destination coordinates for various shipments that were made stored in data1.csv
.
I want processing to draw a line from origin to destination slowly enough that you can track the path of the shipment with your eye. I'd like there to be a sequential element so the lines could be drawn in certain orders by sorting the data1.csv
file accordingly, but that's not a necessity.
Written as is, the lines draw very nicely, however my map of the US will not draw and I get an error stating
The sketch has been automatically resized to fit the screen resolution
If I delete P2D
from size(1620,1080, P2D)
the map will draw, but the lines will no longer move.
My code is below along with links to the relevant data.
Table data;
PShape plot;
long current;
int x;
int y;
void setup(){
size(1620, 1080, P2D);
background(55);
smooth();
// 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();
}
//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("data2.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(1.0);
}
void draw(){
//hacky fade effect, change the alpha/transparency value to experiment with fade amount
background(55);
int r = 65;
int g = 255;
int b = 35;
stroke(r, g, b);
//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();
}
data1 <"https://docs.google.com/spreadsheets/d/1QzbCGW8H6PZgLkmWN8OyplVNTJhp3tlPGxR_Zv6lttM/edit?usp=sharing">
Upvotes: 2
Views: 820
Reputation: 42174
You've got a couple questions here, but I'll try to go through them one at a time.
Written as is, the lines draw very nicely, however my map of the US will not draw and I get an error stating
The sketch has been automatically resized to fit the screen resolution.
My best guess is that Processing can't create windows that are bigger than the resolution of the screen. You can create a full-screen application, but really it shouldn't matter: you shouldn't tie yourself to one screen size; you should write your code so any window size will work. More on that later.
Anyway, to get rid of your first error, let's just use a smaller size:
size(810, 540, P2D);
But now you only see some of your lines, since you're always drawing to the same coordinates regardless of the window's size. Let's change that.
Notice these lines at the end of your draw()
function:
stroke(64);
vertex(start.x,start.y);
stroke(160);
vertex(inbetween.x,inbetween.y);
Notice that you're using the x
and y
values of the vertex
directly. This will only work as long as your window and vertex values are using the same scale. Instead, you should scale your vertex values so that they take into account the width
and height
of the window. One way to do that is this:
stroke(64);
vertex(width/1620.0 * start.x, height/1080.0 * start.y);
stroke(160);
vertex(width/1620.0 * inbetween.x, height/1080.0 * inbetween.y);
Cool, now we've got your lines drawing in a more reasonable scale. Next problem:
however my map of the US will not draw
Notice where you're drawing your map. You're only drawing it once, in your setup()
function. But then you just draw over it in the draw()
function with the background()
call, so you never see it!
Since you're drawing the map and lakes as you load the file, doing that from the draw()
function will slow your sketch down. Instead of moving any of your logic around, you could just draw your map and lakes to a PGraphics
in setup()
, then just draw that PGraphics
in your draw()
function.
To do that, you first have to declare a PGraphics
variable at the top of your sketch:
PGraphics mapGraphics;
Then you'd change your drawing code to use that PGraphics
instead:
// Draw US Map
String[] lines = loadStrings("Map2.csv"); // File containing coordinates to plot US Map
mapGraphics = createGraphics(width, height);
mapGraphics.beginDraw();
mapGraphics.stroke(55);
mapGraphics.strokeWeight(1);
mapGraphics.smooth();
String[] pieces = split(lines[0], ',');
for ( int i = 0; i < lines.length; i++) {
mapGraphics.fill(0);
mapGraphics.beginShape();
current = int(pieces[0]);
while ( current == int(pieces[0]) & i < lines.length) {
x = int(pieces[2]);
y = int(pieces[1]);
mapGraphics.vertex(width/1620.0 * x, height/1080.0 * y);
i++;
if ( i < lines.length) {
pieces = split(lines[i], ',');
}
}
mapGraphics.endShape();
}
// Add Lakes to Map
String[] lines2 = loadStrings("water.csv"); // File containing coordinates to plot great lakes
mapGraphics.smooth();
mapGraphics.fill(22, 25, 180);
String[] pieces2 = split(lines2[0], ',');
for (int i = 0; i < lines2.length; i++)
{
mapGraphics.fill(110);
mapGraphics.beginShape();
current = int(pieces2[0]);
while (current == int(pieces2[0]) & i < lines2.length) {
x = int(pieces2[2]);
y = int(pieces2[1]);
mapGraphics.vertex(width/1620.0 * x, height/1080.0 * y);
i++;
if (i < lines2.length) {
pieces2 = split(lines2[i], ',');
}
}
mapGraphics.endShape();
}
mapGraphics.endDraw();
Notice that I've also added the logic for scaling the map- otherwise, your map would be too big for the window!
Then you just need to draw that PImage
from your draw()
function:
void draw() {
//hacky fade effect, change the alpha/transparency value to experiment with fade amount
background(55);
image(mapGraphics, 0, 0);
//...
Upvotes: 3