We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi,
I am working on a project that uses different methods of data visualisation as multimodal information design.
I do not know how to use the processing 2.x XML object so my code has been written using the processing 1.5 standard.
Full commentary of how things work has not been written yet, but every thing is really basic.
There are a few files in the project. The dataset and images used in the sketch can be found at http://fts.rca.ac.uk/?k=X6UnrEPinSbe1409098476. The zip file also contains the processing code posted below.
The null pointer exception error points to two lines of code in the file "RecordObject.pde". The lines are currently commented out but can be found at the bottom of the file.
The problem I am facing occurs while trying to create an arc diagram of the dataset.
/BPMA_v_.09.pde/
import processing.opengl.*;
ArrayList<RecordObject> recordObjectList = new ArrayList();
HashMap<String, RecordYear> recordYearHash = new HashMap();
HashMap<String, RecordFindNo> recordFindNoHash = new HashMap();
HashMap<String, RecordArtist> recordArtistHash = new HashMap();
ArrayList<RecordYear> uniqueRecordYears = new ArrayList();
ArrayList<RecordFindNo> uniqueRecordFindNumbs = new ArrayList();
ArrayList<RecordArtist> uniqueRecordArtists = new ArrayList();
String file = "rm_arch.xml"; //XML File with poster record information
String mode = new String();
PImage logo = new PImage();
int wiOffset; //content horizontal margin
int hiOffset; //content vertical margin
void setup()
{
size(screen.width, (screen.height-77), OPENGL); //sets the sketches width and height to the width and height of the monitor and renders using the openGL renderer
smooth(); //edge smoothing
frameRate(120); //sets the sketch's frame rate to 120 fps
logo = loadImage("logo_inv.png"); //lood the BPMA logo
wiOffset = logo.width + 50; //sets the the horizontal margin to the width of the logo + 50 pixels
hiOffset = logo.height+50; //sets the vertical margin to the height of the logo + 50 pixels
//Open the record file stream
getRecords(file); //call the method to open the records with
//Check for records and display message if file is missing or inaccessible or there are no records in the file
if (recordObjectList.size() == 0 || recordObjectList == null || recordObjectList.size() <= 1)
{
println("0 Records found. Can't open archive file or archive is empty.");
}
//Display the number of records found
else
{
println(recordObjectList.size() + " records found.");
}
}//end setup
void draw()
{
background(0); //sets the sketch background to black
//draw the BPMA Logo
image(logo, 20, 20); //draws the BPMA logo with a 20 pixel top and left margin
//display the trigger legend
text("A - Display 'Artist' view mode", 20, hiOffset);
float leading = 1.75*textAscent();
text("G - Display 'Grid' view mode", 20, leading+hiOffset);
text("T - Display 'Timeline' view", 20, (2*leading)+hiOffset);
text("R - Reset view", 20, (3*leading)+hiOffset);
for (RecordObject ro:recordObjectList)
{
ro.update();
ro.render();
//trigger actions
if (mode == "tl")
{
fill(255);
text(ro.yr, ro.tpos.x, height-30);
}
//not working yet
if(mode == "artist")
{
ro.mode = "artist";
}
}
}//end draw method
void getRecords(String fileName)
{
//get XML data
XMLElement xml = new XMLElement(this, fileName);
//get the total naumber of records in the data set
int tot = xml.getChildCount(); //record count
for (int i = 0; i < tot; ++i)
{
XMLElement progeny = xml.getChild(i);
//For each record on the list, create a record object
RecordObject ro = new RecordObject();
//store the record data
ro.title = progeny.getStringAttribute("title");
if (progeny.getStringAttribute("findNo").length() < 1)
{
ro.findNo = "0000";
}
else
{
ro.findNo = progeny.getStringAttribute("findNo");
}
ro.findNo = progeny.getStringAttribute("findNo");
ro.recImage = loadImage(progeny.getStringAttribute("findNo") + ".jpeg");
ro.desc = progeny.getStringAttribute("desc");
ro.yr = progeny.getStringAttribute("year");
ro.girth = progeny.getIntAttribute("w");
ro.tallness = progeny.getIntAttribute("h");
ro.artist = progeny.getStringAttribute("artist");
//set the initial position of the objects
ro.pos.x = width/2;
ro.pos.y = height/2;
//set the target position
ro.tpos.x = random(width/2)+wiOffset;
ro.tpos.y = (random((height-100)-random(ro.recImage.height)))+20;
//Are there already records of items from this year?
if (ro.yr != null)
{
recordObjectList.add(ro);
//does the year already exist in the list?
if (recordYearHash.containsKey(ro.yr))
{
/** IT DOES EXIST
* Get the year from the hash and find number from the record and add it to the hash
*/
RecordYear ry = recordYearHash.get(ro.yr);
++ry.count;
ry.recImg = ro.recImage = loadImage(progeny.getStringAttribute("findNo") + ".jpeg");
ry.yrs.add(ro);
}
else
{
/** NEITHER THE YEAR OR FIND NUMBER EXIST
* Happy New Year! It's a Jpeg!
*/
RecordYear ry = new RecordYear(); //Create a year object for the record
ry.theYear = ro.yr;
ry.count = 1;
ry.recImg = ro.recImage = loadImage(progeny.getStringAttribute("findNo") + ".jpeg");
ry.yrs.add(ro);
//Add the new year to the hash
recordYearHash.put(ro.yr, ry);
uniqueRecordYears.add(ry);
//Add the new Find Number to the hash
RecordFindNo rfn = new RecordFindNo();
rfn.theFindNo = ro.findNo;
rfn.count = 1;
rfn.findNumbs.add(ro);
recordFindNoHash.put(ro.findNo, rfn);
uniqueRecordFindNumbs.add(rfn);
//Add the new Artist to the hash
RecordArtist ra = new RecordArtist();
ra.theArtist = ro.artist;
ra.count = 1;
ra.recArts.add(ro);
recordArtistHash.put(ro.artist, ra);
uniqueRecordArtists.add(ra);
}
}
}
println(tot + " records processed.");
println("There should be " + recordObjectList.size()/5 + " rows.");
}
/** Pre-Condition:
*/
void artistView()
{
int cols = recordObjectList.size();
for (int i=0; i < recordObjectList.size(); ++i)
{
RecordObject rO = recordObjectList.get(i);
rO.scaleFact = .25;
rO.tpos.y = height/2;
int x = i%cols;
rO.tpos.x = (.75*(x*rO.scaleFact*rO.recImage.width)+wiOffset);
}
/** Arcs for posters with like artists needed*/
}//end artistView
/** Post-Condition:
*/
/** Pre-Condition:
*/
void gridView()
{
text("Yes", 50, 50);
int numCol = 10;
for (int i = 0; i < recordObjectList.size(); ++i)
{
int x = i%numCol;
int y = i/numCol;
RecordObject rec = recordObjectList.get(i);
rec.scaleFact = .375;
rec.tpos.x = (.75*(x*rec.scaleFact*rec.recImage.width)+wiOffset);
rec.tpos.y = (1.2*(y*rec.scaleFact*rec.tallness)+20);
}
}//end gridView
/** Post-Condition:
*/
/** Pre-Condition:
*/
void resetView()
{
for (int i = 0; i < recordObjectList.size(); ++i)
{
RecordObject ro = recordObjectList.get(i);
ro.scaleFact = .20;
//burst on the scene
ro.tpos.x = random(width/2)+wiOffset;
ro.tpos.y = (random((height-100)-random(ro.recImage.height)))+20;
}
}//end resetView
/** Post-Condition:
*/
/** Pre-Condition:
*/
void timeLine()
{
for (int i = 0; i < uniqueRecordYears.size(); ++i)
{
RecordYear ry = uniqueRecordYears.get(i);
for (int j = 0; j < ry.yrs.size(); ++j)
{
RecordObject record = ry.yrs.get(j);
record.scaleFact = .125;
record.tpos.x = ((i*record.scaleFact*record.recImage.width) + (record.scaleFact * (record.recImage.width)*(1+record.scaleFact)))+wiOffset;
record.tpos.y = (height - 150)-(record.scaleFact*(20 - record.tallness)) + (record.stackPosition*j*50);
}
}
}//end timeLine
/** Post-Condition:
*/
void keyPressed()
{
if (key == 'a')
{
mode = "artist";
artistView();
}
if (key == 'g')
{
mode = "grid";
gridView();
}
if (key == 'r')
{
mode = null;
resetView();
}
if (key == 't')
{
mode = "tl";
timeLine();
}
}
/RecordArtist.pde/
class RecordArtist
{
String theArtist;
int count = 0;
ArrayList<RecordObject> recArts = new ArrayList();
RecordArtist()
{
}
}
/RecordFindNo.pde/
class RecordFindNo
{
String theFindNo;
int count = 0;
PImage recImg = new PImage();
ArrayList<RecordObject> findNumbs = new ArrayList();
RecordFindNo()
{
}
}
/RecordObject.pde/<---Exception error points to this file
class RecordObject
{
//
PVector pos = new PVector(); //current position
PVector tpos = new PVector(); //target position
int dir = 1; //Direction, not used yet
double xSpeed = .04; //Horizontal speed
double ySpeed = .04; //Vertical speed
float alph = 0; //start opacity
float interalph;
float talph = 255; //target opacity
PImage recImage = new PImage(); //Item image
String title; //Item name
String desc; //Item description
String yr; //Item creation year
String findNo; //Item find number (used for images)
String artist; //Item designer
String mode; //trigger mode
int girth; //Item image width
int tallness; //Item image height
float scaleFact = .20;
int stackPosition = -1; //for stacking images vertically in 'timeline' mode
RecordObject()
{
}
//Update the position of the record's image
/** PREcondition:
*/
void update()
{
//easeing
pos.x+=(tpos.x - pos.x)*xSpeed;
pos.y+=(tpos.y - pos.y)*ySpeed;
}
/** POSTcondition:
*/
void render()
{
pushMatrix();
translate(pos.x, pos.y);
noStroke();
fill(255);
rect(-(scaleFact*6), -(scaleFact*6), scaleFact*(girth+12), scaleFact*(tallness+12));
image(recImage, 0, 0, (scaleFact*girth), (scaleFact*tallness));
if (mouseX > pos.x-(scaleFact*6) && mouseX < pos.x + (scaleFact*girth)+(scaleFact*6) && mouseY > pos.y-(scaleFact*6) && mouseY < pos.y + (scaleFact*tallness)+(scaleFact*6))
{
fill(200, 200, 60);
rect(-(scaleFact*6), -(scaleFact*6), scaleFact*(girth+12), scaleFact*(tallness+12));
image(recImage, 0, 0, (scaleFact*girth), (scaleFact*tallness));
}
popMatrix();
if (mouseX > pos.x-(scaleFact*6) && mouseX < pos.x + (scaleFact*girth)+(scaleFact*6) && mouseY > pos.y-(scaleFact*6) && mouseY < pos.y + (scaleFact*tallness)+(scaleFact*6))
{
image(recImage, width-(girth+20), 20, girth, tallness);
fill(255);
text(title, width-(girth+20), tallness+(5*textAscent()));
if (this.artist.length() < 1)
{
text("Artist: Unknown", width-(girth+20), tallness+(7*textAscent()));
}
if (this.artist != null)
{
text("Artist: " + artist + '\n', width-(girth+20), tallness+(7*textAscent()));
}
text("Year: " + yr + '\n', width-(girth+20), tallness+(9*textAscent()));
text("Find Number: " + findNo +'\n', width-(girth+20), tallness+(11*textAscent()));
}
if (this.mode == "artist")
{
//debug attempt
//RecordArtist Artist = recordArtistHash.get(artist);
//println(Artist.recArts);
//This does not work
/**
RecordArtist Artist = recordArtistHash.get(artist);
ArrayList<RecordObject> relatedObjects = Artist.recArts;
//Draw an arc from this record to all other records with the same artist
for(RecordObject rOb:relatedObjects)
{
text(rOb.artist,rOb.tpos.x,rOb.tpos.y+50);
//DRAW ARCS HERE
}
*/
//Neither does this
/**
ArrayList relatedObjects = recordArtistHash.get(artist).recArts;
for(int i = 0; i < relatedObjects.size(); ++i)
{
text(this.artist,this.tpos.x,this.tpos.y+50);
//DRAW ARCS HERE
}
*/
}
}
}
/RecordYear.pde/
class RecordYear
{
String theYear;
int count = 0;
PImage recImg = new PImage();
ArrayList<RecordObject> yrs = new ArrayList();
RecordYear()
{
}
}
Answers
in your debug
print out artist and Artist (on separate lines)
i think the problem is that artist is not in the hash so Artist is null. which is fine until you try and dereference it by, say, printing Artist.recArts.
(terrible naming btw, don't have variables that only differ by capitalisation)