//AList Exits, Ramps, Corridors, Aisles, Rows; //AList ExitNodes, RampNodes, CorridorNodes, AisleNodes, RowNodes; AList ExitNodes, Ramps, Corridors, Aisles, Rows, Bombs, FieldExitNodes, FieldExitCorridors, BottomRows; class Graph { int numAgents, agentSize; //UNITS in FT static final float ftPerInputUnit = 5; //3.65; //How many feet per unit? Lets us use standard units static final float secsPerStep = 0.25; static final float personWalkPerSec = 10.0 / ftPerInputUnit; static final float personWalkPerStep = personWalkPerSec * secsPerStep; // 1 (square meter) = 10.7639104 square feet float crowdedDensity = 4 / 10.7639 * sq(ftPerInputUnit); //4 people per square meter float trampleDensity = 5*crowdedDensity; static final float singleFileWidth = 1.5/ftPerInputUnit; static final float widthOfRow = 1.5 * singleFileWidth; static final float widthOfAisle = 2.0 * singleFileWidth; static final float widthOfCorridor = 12.0 * singleFileWidth; static final String Exit = "Exit"; static final String Ramp = "Ramp"; static final String Corridor = "Corridor"; static final String Aisle = "Aisle"; static final String Row = "Row"; static final String ExitList = "ExitList"; static final String MinExit = "MinExit"; static final String ExitDistances = "ExitDistances"; // static final String BombData = "BombData"; static final String BombStep = "BombStep"; static final String BombRadius = "BombRadius"; static final String SavedLabel = "SavedLabel"; static final String FieldExitNode = "FieldExitNode"; static final String FieldExitCorridor = "FieldExitCorridor"; static final String BottomRow = "BottomRow"; int nodeRadius = 0, nodeShape = Node.POINT, steps = 0; boolean useLights = false, showLabels = false, useIDLabels = false; static final float bombWeight = 100.0f, randomAgents = .2f; color nodeColor = color(128), edgeColor = color(0,255,255, 50); // REMIND: Make defaults in class. color rampColor = color(0,255,0, 50), corridorColor = color(50,100,255, 100); color aisleColor = color(0,255,0, 50), rowColor = color(255,255,0, 50), bombColor = color(255,0,0, 128); color injuredColor = color(255,0,0); boolean useBlenderCoords = true; //Whether stadium and agent I/O should presume blender coords. // ========== Construction ========== Graph (int numAgents, int agentSize) { Agents.clear(); InjuredAgents.clear(); Edges.clear(); Nodes.clear(); this.numAgents = numAgents; this.agentSize = agentSize; } void registerGraph() { Nodes.setShowLabel(showLabels); Edges.setShowLabel(showLabels); Nodes.setDataByData(SavedLabel,Base.Label); Edges.setDataByData(SavedLabel,Base.Label); //Exits = Edges.with(Base.Type, Exit); Ramps = Edges.with(Base.Type, Ramp); Corridors = Edges.with(Base.Type, Corridor); Aisles = Edges.with(Base.Type, Aisle); Rows = Edges.with(Base.Type, Row); Bombs = Nodes.with(BombStep); ExitNodes = Nodes.with(Base.Type, Exit); FieldExitNodes = Nodes.with(Base.Type, FieldExitNode); FieldExitCorridors = Edges.with(Base.Type, FieldExitCorridor); BottomRows = Edges.with(Base.Subtype, BottomRow); //RampNodes = Nodes.with(Base.Type, Ramp); //CorridorNodes = Nodes.with(Base.Type, Corridor); //AisleNodes = Nodes.with(Base.Type, Aisle); //RowNodes = Nodes.with(Base.Type, Row); //println("SavedLabel Test Ramps:"+arrayListToString(Ramps.map(SavedLabel))); createAgents(numAgents, personWalkPerStep); // create agents b4 floodfill: it readjusts agents too. setupLineGraphs(); InjuredAgents.clear(); numExitedAgents = 0; deathDueToTrampling = 0; Rows.ask(new ModifyWeight(1.5f)); Corridors.ask(new ModifyWeight(.75f)); floodFill(ExitNodes); setAgentExits(); Ramps.setColor(rampColor); Corridors.setColor(corridorColor); Aisles.setColor(aisleColor); Rows.setColor(rowColor); } int getBiasedEdge(AList edges, float w[]) { float total = 0; Edge e; for (int i=0; i< w.length; i++) { total += w[i]; } float pick = random(total); total = 0; int j = 0; while (total < pick && j < w.length) { total += w[j]; j ++; } j--; return j; } void createAgents(int numAgents, float initialSpeed){ int maxTrys = 100; int j,pick; float w[] = new float[Rows.size()]; for (int i=0; i0.50?initialSpeed:-initialSpeed; Agent a = new RibbonAgent(e, randomBrightColor(), agentSize, speed * (random(0.1) + 0.95), percent); //no label or breed/type } for (int i=0; i 0) continue; ran += a.setAgentExit(confusion); goTowardExit(a); } println("setAgentExits: setting n random exits, n="+ran); } float distanceToNode(Agent a, Node n) { //only nodes of a's current exit if (n == a.edge().n0()) return a.percent * a.edge().len(); if (n == a.edge().n1()) return (1.0 - a.percent) * a.edge().len(); return 0.; } void goTowardExit(Agent a) { float d1,d2; d1 = getDistanceToExit(a.toNode(), a.getCurrentExit()) + distanceToNode(a, a.toNode()); d2 = getDistanceToExit(a.edge().nOther(a.toNode()), a.getCurrentExit()) + distanceToNode(a, a.edge().nOther(a.toNode())); if (d2 < d1) a.speed *= -1; } float getDistanceToExit(Node n, int i) { float d1 = ((Float) ((ArrayList) n.getData(Graph.ExitDistances)).get(i)).floatValue(); return d1; } // ========== General I/O used for writing Graph and Agents ========== void writeAgents(Writer agentWriter) { StringBuffer s = new StringBuffer(); s.append(""+steps); for(int i = 0; i 0)) { floodFill(ExitNodes); setAgentExits(); } for(int i = 0; i=0 && agent.percent<=1)) agent.percent = 0.5; } double mean = (agentVelocitySum / agentCount); //("agentVelSum: " + agentVelocitySum + " agentVelSqSum: " + agentVelocitySquareSum); //out.println( "Num agents: " + agentCount + " Avg velocity: " + mean + " Var: " + (agentVelocitySquareSum/agentCount - mean*mean)); stepBombs(); steps++; } void setLabelState(int i) { if (i == 0) { Nodes.setShowLabel(false); Edges.setShowLabel(false); } else if (i==1) { Nodes.setShowLabel(true); Edges.setShowLabel(true); Nodes.setLabelByData(Base.ID); Edges.setLabelByData(Base.ID); } else if (i == 2) { Nodes.setShowLabel(true); Edges.setShowLabel(true); Nodes.setLabelByData(Base.Type); Edges.setLabelByData(Base.Type); } else if (i == 3) { Nodes.setShowLabel(true); Edges.setShowLabel(true); Nodes.setLabelByData(SavedLabel); Edges.setLabelByData(SavedLabel); } } // ========== Floodfill ========== // Floodfill adds these data entries: // ExitDistances: AList of distances. ExitDistances[0] is distance for EdgeNodes[0] etc. // void floodFill(AList exits) { Nodes.setData(ExitList, exits); // probably could just use global ExitNodes Nodes.setData(ExitDistances, null); // allows recalling floodfill for(int i = 0; i 0) { n = (Node)stack.remove(0); int nDist = n.distToBottom; AList edges = n.getEdges(); for(int i = 0; inodeRadius) n.setShape(bombColor,Node.SPHERE,radius); else { n.setShape(nodeColor,Node.POINT,nodeRadius); //bombs.remove(n); } } } } } class Bounds { float minX = Float.MAX_VALUE, minY = Float.MAX_VALUE, minZ = Float.MAX_VALUE; float maxX = Float.MIN_VALUE, maxY = Float.MIN_VALUE, maxZ = Float.MIN_VALUE; float lenX, lenY, lenZ, midX, midY, midZ; void update(Node n) { minX=min(minX,n.x); minY=min(minY,n.y); minZ=min(minZ,n.z); maxX=max(maxX,n.x); maxY=max(maxY,n.y); maxZ=max(maxZ,n.z); lenX = abs(maxX-minX); lenY = abs(maxY-minY); lenZ = abs(maxZ-minZ); midX = (minX+maxX)/2f; midY = (minY+maxY)/2f; midZ = (minZ+maxZ)/2f; } String toString() { return "[["+ minX+" "+maxX+" "+midX+" "+lenX+"] ["+ minY+" "+maxY+" "+midY+" "+lenY+"] ["+ minZ+" "+maxX+" "+midZ+" "+lenZ+"]]"; } }