the following code works but is messy. can anyone help please.
the code draws a shape and highlights where a line intersects with the shape which appears when the mouse is pressed.
the problem lies with how I get the endpoints of the shapes line segments. i get the current item in loop and +1 but when get to the last line segment their is no +1 to get as reached end of array so get an error.
to overcome this I have added an if statement but it means that the code to check for intersection is copied and is basically poor coding.
can anyone help me with how to overcome this error issue or suggest a better/more elegant way of achieving this.
thanks for any help.
here's the code:
int spaces = 1;
Niche [] space = new Niche[spaces];
PVector intersection;
void setup() {
size (300,300);
smooth();
for(int i=0; i<space.length; i++) {
int id = i;
space[i] = new Niche(id);
}
}
void draw() {
background(80);
for(int i=0; i<space.length; i++) {
space[i].transmit();
}
if (mousePressed == true) {
PVector mouse = new PVector(mouseX,mouseY);
//set a line from mouse to check incidence with niche boundary
stroke(255,0,0);
ellipse(mouseX, mouseY, 8, 8);
line(mouse.x, mouse.y, width, mouse.y);
checkIntersection();
}
}
void checkIntersection() {
//based on Paul Bourkes breakdown of the maths to work out the intersection point of two lines
//and Ryan Alexanders code:
http://wiki.processing.org/w/Line-Line_intersection
float x1 = mouseX; //x1 and y1 are first endpoint of mouse line
float y1 = mouseY;
float x2 = width; //x2 and y2 are second endpoint of mouse line
float y2 = mouseY;
float x3;
float y3;
float x4;
float y4;
//to check if mouse line intersectss with niche boundary
//loop through niche nodes to determine intersection with boundary line segments (boundary links)
//boundary segments equate to x and y coords of each node as sorted in 'sortNodes'
//working around the niche as sorted: so first segment is 1st node (x3 and y3) and second node (x4 and y4)
//second segment is 2nd node (x3 and y3) and 3rd node (x4 and y4), and so forth.
for(int i=0; i<space.length; i++) {
int j = 0;
while(j <= space[i].nodes.length-1) {
x3 = space[i].nodes[j].pos.x;
y3 = space[i].nodes[j].pos.y;
////////////////////////////////////////////////////////////////////////////////////////////
//THIS SECTION OF CODE IS NECESSARY TO GET INTERSECTION OF LAST LINE SEGMENT
//OTHERWSIE GET AN ERROR AS "ARRAY OUT-OF-BOUNDS" DUE TO X4 BEING "+1" SEE BELOW CODE SECTION
if(j == numNodes-1) {
x4 = space[i].nodes[0].pos.x;
y4 = space[i].nodes[0].pos.y;
float L1x = x2 - x1;
float L1y = y2 - y1;
float L2x = x4 - x3;
float L2y = y4 - y3;
float d = ((L1x * L2y) - (L1y * L2x));
//calculate the intermediate fractional point that the lines potentially intersect
float n_a = x3-x1;
float n_b = y3-y1;
float ua = (n_a * L2y - n_b * L2x) / d;
float ub = (n_a * L1y - n_b * L1x) / d;
//if the fractional point is between 0 and 1 inclusive the lines intersect.
if((ua >= 0 && ua <= 1) && (ub >= 0 && ub <= 1)) {
//get the intersection point
intersection = new PVector(x1 + ua * L1x, y1 + ua * L1y);
stroke(255, 255, 0);
ellipse(intersection.x, intersection.y, 10, 10);
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
else {
x4 = space[i].nodes[j+1].pos.x;
y4 = space[i].nodes[j+1].pos.y;
//check if the denominator for both lines is common
//meaning that they are parallel - therefore do not intersect
float L1x = x2 - x1;
float L1y = y2 - y1;
float L2x = x4 - x3;
float L2y = y4 - y3;
float d = ((L1x * L2y) - (L1y * L2x));
//calculate the intermediate fractional point that the lines potentially intersect
float n_a = x3-x1;
float n_b = y3-y1;
float ua = (n_a * L2y - n_b * L2x) / d;
float ub = (n_a * L1y - n_b * L1x) / d;
//if the fractional point is between 0 and 1 inclusive the lines intersect.
if((ua >= 0 && ua <= 1) && (ub >= 0 && ub <= 1)) {
//get the intersection point
intersection = new PVector(x1 + ua * L1x, y1 + ua * L1y);
stroke(255, 255, 0);
ellipse(intersection.x, intersection.y, 10, 10);
}
}
j++;
}
}
}
class boundaryNode implements Comparable {
int id;
PVector pos;
PVector mouse; //for testing: can delete
PVector diff; //for testing: can delete
int Size = 10;
int deg;
boundaryNode(int identity) {
id = identity;
pos = new PVector(random(0,width), random(0,height));
}
void display() {
noStroke();
fill(255,90);
ellipse(pos.x, pos.y, Size, Size);
// println(id + ": " + deg);
getAngle();
}
void getAngle() {
//works out the angle between boundaryNode and nucleus
float angle = 0;
// Look through all the nodes
for(int i=0; i<space.length; i++) {
if(space[i].ref == id) {
// create a vector that points from center of boundaryNode to nucleus
PVector dir = PVector.sub(pos, space[i].nucleus.get());
//TEST: draw a line between nucleus and boundaryNodes
// stroke(200);
// line(pos.x, pos.y, space[i].nucleus.x, space[i].nucleus.y);
//create a variable to store heading/angle - from 0 to 360deg: working clockwise round from 0deg along left x-axis
angle = dir.heading2D() + PI;
}
}
deg = int(degrees(angle));
}
void select() {
//user interaction... //for testing: can delete
//if mouse over and pressed
//show associate links and drag to new position
if ((mouseX >= pos.x-(Size)) && (mouseX <= pos.x+(Size)) && (mouseY >= pos.y-(Size)) && (mouseY <= pos.y+(Size)) && (mousePressed == true)) {
//drag to new position
PVector mouse = new PVector(mouseX, mouseY);
PVector diff = PVector.sub(mouse, pos);
pos = mouse;
}
}
int compareTo(Object o) {
boundaryNode other = (boundaryNode) o;
if(other.deg > deg)
return -1;
if(other.deg == deg)
return 0;
else
return 1;
}
}
int numNodes = 10;
class Niche { //implements Comparable {
boundaryNode[] nodes;
Nucleus centre;
int ref;
PVector nucleus = new PVector();
Niche(int id) {
ref = id;
nodes = new boundaryNode[numNodes];
for (int i=0; i<numNodes; i++) {
nodes[i] = new boundaryNode(id);
//to calculate centre of niche on setup
//add the coordinates (PVectors) of boundaryNodes together
nucleus.add(nodes[i].pos);
}
//and then divide to get the centre
nucleus.div(nodes.length);
centre = new Nucleus(id);
}
void updateNucleus() {
//calculate the centre of niche
//drawn within the nucleus class
nucleus = new PVector();
for(int i=0; i<numNodes; i++) {
//add the coordinates (PVectors) of boundaryNodes together
nucleus.add(nodes[i].pos);
}
//and then divide to get the centre
nucleus.div(nodes.length);
}
void sortNodes() {
//to find the node with largest angle of repose
float biggestAngle = 0;
PVector biggestVertex = null;
// Look through all the nodes
for(int i=0; i<numNodes; i++) {
int ang = nodes[i].deg;
// println("id " + ref + ": " + i + ": " + ang);
//get the position of node with biggestAngle
if (ang > biggestAngle) {
biggestAngle = ang;
biggestVertex = nodes[i].pos;
}
}
//TEST: mark the boundaryNode located widest angle from nucleus
noStroke();
fill(255, 0, 0, 90);
ellipse(biggestVertex.x, biggestVertex.y, 20, 20);
//sort the nodes in order of ascending angle from nucleus
//so that vertices do not cross
Arrays.sort(nodes);
}
void transmit() {
for (int i=0; i<numNodes; i++) {
nodes[i].display();
nodes[i].select(); //for testing: can delete
stroke(255,80);
line(nodes[i % numNodes].pos.x, nodes[i % numNodes].pos.y, nodes[(i+1) % numNodes].pos.x, nodes[(i+1) % numNodes].pos.y);
//TEST: number the nodes to check order
textAlign(CENTER);
text(i, nodes[i].pos.x+10, nodes[i].pos.y-10);
}
centre.display();
updateNucleus();
sortNodes();
}
}
class Nucleus {
int id;
PVector pos;
PVector centre = new PVector();
PVector[] bNodes;
Nucleus(int identity) {
id = identity;
bNodes = new PVector[numNodes];
}
void display() {
stroke(200);
//need to run through each niche to access boundary nodes
for(int i=0; i<space.length; i++) {
centre = space[i].nucleus.get();
// println(centre);
for(int j=0; j<space[i].nodes.length; j++) {
// create a vector that points from center
PVector dir = PVector.sub(space[i].nodes[j].pos, centre);
//TEST: draw a line between nucleus and boundaryNodes
// line(centre.x, centre.y, space[i].nodes[j].pos.x, space[i].nodes[j].pos.y);
}
stroke(250,80);
noFill();
ellipse(centre.x, centre.y, 8, 8);
stroke(255);
point(centre.x, centre.y);
}
}
}
1