import processing.opengl.*; import traer.animation.*; import traer.physics.*; import javax.media.opengl.*; import javax.media.opengl.glu.*; int year = 2007; /** *

Die Parteilisten werden am Anfang zufällig verteilt und ziehen sich entsprechend der Stärke * ihres Panaschierstimmenaustauschs an bzw. stossen sich entsprechend ab. Alle ca. 5 Sekunden wird eine einzelne * Liste zufällig aus ihrer Position geworfen und sucht sich dann wieder ihren Platz. *

Tastenbefehle *
- 0 / 1 / 5 / 9: keine / wenig / viel / sehr viel tremor *
- : neue zufällige Startverteilung *
- l: Linien (on/off) *
- z: einmaliges zufälliges Verschieben einer einzelnen Liste *
- y: dito, aber laufend automatisch alle paar Sekunden (on/off) *
- + / -: Zusammenrücken, Auseinanderdriften *

*/ String inputFile; ParticleSystem physics; Particle[] particles; Color[] colors; float[] dot_size; int gridSizefo = 10; String parteien[]; final float STRENGTH = 0.1; final float DAMPING = 0.1; final float NODE_SIZE = 10; float fac = 1.0; float gray_start = 20000; float gray = gray_start; float angle = 0.0; Smoother3D centroid; float tremor = 0; float distances[]; float chi2min = Float.POSITIVE_INFINITY; PFont font, font1; boolean withLines = true; int nParties; int springs; float factor = 1.0; float initFactor = -1.0; float x_moved, y_moved, chi2_moved; float chi2, millis_moved, millis_written; Particle p; boolean spicked = true; boolean withSpick = true; float expTotal; float lengthFactor; float xLeft, yMed; float deltaX, deltaY; float xMin, yMin, xMax, yMax; void setup() { size(440, 440); expTotal = 1.25; lengthFactor = 40; if (year == 2007) { inputFile = "federn29a.txt"; } else { inputFile = "federn32g.txt"; } smooth(); fill(0); frameRate(24); int ii = 0; springs = 0; String lines[]; float weight[]; nParties = 0; StringTokenizer stval; physics = new ParticleSystem(0.0, 0.05); centroid = new Smoother3D(0.8); physics.clear(); centroid.setValue(0, 0, 0.0); lines = loadStrings(inputFile, "UTF-16"); println("there are " + lines.length + " lines in the dataset"); stval = new StringTokenizer(lines[0]); nParties = Integer.parseInt(stval.nextToken()); weight = new float[nParties]; distances = new float[nParties * (nParties - 1)]; parteien = new String[nParties]; particles = new Particle[nParties]; colors = new Color[nParties]; dot_size = new float[nParties]; println("there are " + nParties + " parties"); for (int i = 0; i < nParties; i++) { ii++; stval = new StringTokenizer(lines[ii]); parteien[i] = stval.nextToken(); int par = Integer.parseInt(stval.nextToken()); weight[i] = Float.parseFloat(stval.nextToken()); int red = Integer.parseInt(stval.nextToken()); int green = Integer.parseInt(stval.nextToken()); int blue = Integer.parseInt(stval.nextToken()); dot_size[i] = Float.parseFloat(stval.nextToken()); colors[i] = new Color(red, green, blue); particles[i] = physics.makeParticle(1.0, random(width-5), random(height-5), 0.0); println(par + ". " + parteien[i] + " " + weight[i]); if (dot_size[i] == 0) dot_size[i] = 0.25; dot_size[i] = sqrt(dot_size[i]); } ii++; println(); for (int i=ii; i < lines.length; i++) { stval = new StringTokenizer(lines[i]); int par1 = Integer.parseInt(stval.nextToken()); int par2 = Integer.parseInt(stval.nextToken()); float dist = Float.parseFloat(stval.nextToken()); // int toSelect = Integer.parseInt(stval.nextToken()); if (par1 > par2) { println(par1 +"-" + par2 + " / " + parteien[par1-1] + "-" + parteien[par2-1] + " " + dist); float dd = sqrt(dist); dd = lengthFactor * pow(dist, expTotal); physics.makeSpring(particles[par1-1], particles[par2-1], STRENGTH, DAMPING, dd); distances[springs] = dd; springs++; } } println(springs + " springs"); println(); font = loadFont("AgencyFB-Reg-48.vlw"); textFont(font); font1 = loadFont("CourierNewPSMT-14.vlw"); textFont(font1); if (withSpick) spick(); } void draw() { smooth(); physics.tick(0.25); if (physics.numberOfParticles() > 1) updateCentroid(); centroid.tick(); rotate(angle); shuffle(); background(255); translate(width / 2, height / 2); scale(centroid.z()); translate(-centroid.x(), -centroid.y()); background(255); drawConnections(); drawCenters(); if (withSpick && (millis() - millis_moved > 5000)) spick(); } void spick() { p = physics.getParticle(int(random(physics.numberOfParticles()))); x_moved = p.position().x(); y_moved = p.position().y(); chi2_moved = chi2; millis_moved = millis(); spicked = true; float dx = deltaX / 1.5; float dy = deltaY / 1.5; p.moveBy(random(-dx, dx),random(-dy, dy), 0.0); gray = gray_start; } void drawConnections() { chi2 = 0.0; noFill(); if (withLines) beginShape(LINES); strokeWeight(1); for (int i = 0; i < springs; ++i) { Spring e = physics.getSpring(i); Particle a = e.getOneEnd(); Particle b = e.getTheOtherEnd(); float dist = sqrt(sq(b.position().x()-a.position().x()) + sq(b.position().y()-a.position().y())); chi2 += sq((dist - distances[i]))/distances[i]; if (withLines) { int g = min(255, max(0,round(255 - 255 * (gray / gray_start)))); stroke(g); gray--; int col2 = 188; if (dist > distances[i]) { stroke(255, col2, col2); } else { stroke(col2, 255, col2); } if (dist < 1.25 * distances[i] && dist > (1.0 / 1.33) * distances[i]) stroke(244); // all gray: stroke(240); vertex(a.position().x(), a.position().y()); vertex(b.position().x(), b.position().y()); } } if (withLines) endShape(); if (chi2 < chi2min) chi2min = chi2; fill(0, 0, 200); textSize(10); } void drawCenters() { textSize(factor / initFactor * 14); noStroke(); int r, g, b; r = 0; g = 0; b = 0; textAlign(LEFT); for (int i = 0; i < nParties; i++) { Particle v = physics.getParticle(i); r = colors[i].getRed(); g = colors[i].getGreen(); b = colors[i].getBlue(); fill(r, g, b); float nSize; nSize = factor/initFactor * dot_size[i] * NODE_SIZE; ellipse(v.position().x(), v.position().y(), nSize, nSize); fill(0, 0, 0); text(parteien[i], v.position().x() + nSize/3, v.position().y() - nSize/3); } stroke(0); fill(255); } void updateCentroid() { xMax = Float.NEGATIVE_INFINITY; xMin = Float.POSITIVE_INFINITY; yMin = Float.POSITIVE_INFINITY; yMax = Float.NEGATIVE_INFINITY; for (int i = 0; i < physics.numberOfParticles(); ++i) { Particle p = physics.getParticle(i); xMin = min(xMin, p.position().x()); xMax = max(xMax, p.position().x()); yMin = min(yMin, p.position().y()); yMax = max(yMax, p.position().y()); } deltaX = xMax - xMin; deltaY = yMax - yMin; yMed = (yMax - yMin) / 2.0; xLeft = xMin; double ff = 0.03; xMin -= ff * deltaX; yMin -= ff * deltaY; xMax += ff * deltaX; yMax += ff * deltaY; deltaX = fac * (xMax - xMin); deltaY = fac * (yMax - yMin); if ( deltaY > deltaX ) centroid.setTarget( xMin + 0.5f*deltaX, yMin +0.5f*deltaY, height/(deltaY+50) ); else centroid.setTarget( xMin + 0.5f*deltaX, yMin +0.5f*deltaY, width/(deltaX+50) ); float scaleX = deltaX / width; float scaleY = deltaY / height; factor = max(scaleX, scaleY); if (initFactor < 0) initFactor = factor; } void modifySprings(float exponent) { expTotal = pow(expTotal, exponent); println("exponent: " + expTotal); for (int i = 0; i < springs; ++i) { Spring e = physics.getSpring(i); float rl = e.restLength(); e.setRestLength(pow(rl, exponent)); } } void setShuffle(float u) { tremor = u; } void shuffle() { if (tremor == 0) return; if (tremor < 0) { for (int i = 0; i < physics.numberOfParticles(); i++) { Particle p = physics.getParticle(i); float dx = noise(-tremor); float dy = random(-tremor); p.moveBy(dx, dy, 0.0); } } else { for (int i = 0; i < physics.numberOfParticles(); i++) { Particle p = physics.getParticle(i); float dx = random(tremor) - tremor / 2; float dy = random(tremor) - tremor / 2; p.moveBy(dx, dy, 0.0); } } } void keyPressed() { switch(key) { case '0': setShuffle(0); break; case '1': setShuffle(3); break; case '2': setShuffle(-0.2); break; case '5': setShuffle(50); break; case '9': setShuffle(100); break; case 'r': angle += PI / 32.0; break; case 'R': angle -= PI / 32.0; break; case 'l': case 'L': withLines = !withLines; break; case 'y': case 'Y': withSpick = !withSpick; if (withSpick) spick(); break; case 'z': case 'Z': p = physics.getParticle(int(random(physics.numberOfParticles()))); p.moveBy(random(-400, 400),random(-400, 400), 0.0); gray = gray_start; break; case ' ': for (int i = 0; i < physics.numberOfParticles(); i++) { p = physics.getParticle(i); p.moveTo(random(width - 5), random(height - 5), 0.0); gray = gray_start; } break; case '+': modifySprings(1.1); break; case '-': modifySprings(1.0/1.1); break; } } void mouseReleased() { return; } void mousePressed() { // selection disabled print(mouseX + "/" + mouseY + " "); return; } static public String[] loadStrings(File file, String _enc) { InputStream is = openStream(file); if (is != null) return loadStrings(is, _enc); return null; } public String[] loadStrings(String filename, String _enc) { InputStream is = openStream(filename); if (is != null) return loadStrings(is,_enc); System.err.println("The file \"" + filename + "\" " + "is missing or inaccessible, make sure " + "the URL is valid or that the file has been " + "added to your sketch and is readable."); return null; } static public String[] loadStrings(InputStream input, String _enc) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(input, _enc)); String lines[] = new String[100]; int lineCount = 0; String line = null; while ((line = reader.readLine()) != null) { if (lineCount == lines.length) { String temp[] = new String[lineCount << 1]; System.arraycopy(lines, 0, temp, 0, lineCount); lines = temp; } lines[lineCount++] = line; } reader.close(); if (lineCount == lines.length) { return lines; } // resize array to appropriate amount for these lines String output[] = new String[lineCount]; System.arraycopy(lines, 0, output, 0, lineCount); return output; } catch (IOException e) { e.printStackTrace(); //throw new RuntimeException("Error inside loadStrings()"); } return null; }