We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › trouble sorting an aray
Page Index Toggle Pages: 1
trouble sorting an aray (Read 987 times)
trouble sorting an aray
Jun 3rd, 2009, 11:31pm
 
this is a conceptual problem. I kind of get what the comparator does but I don't see how it can work in my situation - I am looking for advice on how to sort a series of objects by their proximity to a given other object. These distances are not stored in the class so I am not sure how you could sort given the methods of the comparable interface.

The examples I have seen sort objects that are measurable in and of themselves - they use strings, values in class' fields etc etc but it's about measuring one things against another. My example is about measuring the relationship between two objects - can more than just an array be pased to the comparator interface?

Just to be clear I have two lists of points - one much smaller than the other. I need to find the closest handful of points to each point(separately) in he smaller list. I have looked and looked and I am not sure what the right way to atack this is...

thanks for any advice in advance...
Re: trouble sorting an aray
Reply #1 - Jun 4th, 2009, 1:07am
 
I am not sure I fully understand the problem.
You can do any operation in the comparator, but basically you compare two things in the same list, not against another list.
You can use the other list in the comparison method, but you have to get the items yourself, they won't be fed by the comparator.
Re: trouble sorting an aray
Reply #2 - Jun 4th, 2009, 9:30am
 
it's the "getting the other list yourself" par that is a problem for me to understand. Like I said I have two lists - one with about 5 objects which has a vector as one of its fields, the other with about a 100, also with embedded vectors. For EACH of the 5 in the smaller list, I want to find its 3-5 closest from the bigger lst. The only way I can see doing this now is one of two ways, both of which seem convoluted:

1 - embed the distances between each of the 100 and each of the 5 in each of the 100s fields and then use the compareto function sorting by that number... and would mean addind 500 vectors to memory...

2 - write a separate comparator for each of the 5 objects - this way I have to also specify which comparator I am using as I cycle through the list of 5.

I basically want to use a typical for loop for each of the five that sorts the same list each loop according to its particular position...

so is there a better way than the two I mentioned - I hope so...
Re: trouble sorting an aray
Reply #3 - Jun 5th, 2009, 7:47am
 
i find it hard to believe that this is a new problm - it seems like a very standard computational problem. how do find the n-closest points to a given sample.

searching through google there are various names for these problems - nearet neighbours, proximity searches...but nowhere can I find an actual pattern. mostly examples try and break the problem into a faster algorithm than just a shere brute force method that measure each rel'p . I don't mind taking the brute force route since it all happens in the setup loop (my points are fixed) and I have no great performance issues.

so, again, any ideas on how to do this?
Re: trouble sorting an aray
Reply #4 - Jun 5th, 2009, 8:18am
 
i think I found a decent solution - I just added a field to my class of points that I could set with each measurmement of distance to my sample points and then I only need one comparator for each cycle on that particular float....
Re: trouble sorting an aray
Reply #5 - Jun 5th, 2009, 8:20am
 
There are indeed some smart solutions like partitioning the area, but since I haven't tried them I won't comment on them.
Using brute force, well, smart brute force... is possible.
You might not need sorting, though.

Let see: you need, say to find the 4 closest points of 5 points among 100 candidates.
A possible way I see is to have an array of 4 coordinates for each of the 5 points (let's call it dists). For each of these points, walk the big array and compute the distance between the current point and one of the big array.
Then sort dists and compare to the biggest distance. If found dist is bigger, just drop this node (initialize dists with MAX_INT first!). If smaller, replace the biggest distance of dists with this dist. You must keep a parallel array with big array's indexes too...

Not sure if that's clear, not even sure if it works!
You might want to try and implement it, and I might try myself a bit later this evening.
This isn't very efficient, but given the numbers you gave, it should be nearly instantaneous! Would be more problematic with millions of nodes!
Re: trouble sorting an aray
Reply #6 - Jun 6th, 2009, 10:19am
 
I implemented my algorithm with success...
Code:
int PLAIN_NODE_NB = 100;
int PLAIN_NODE_RADIUS = 8;
int MASTER_NODE_NB = 7;
int MASTER_NODE_RADIUS = 16;
int NEIGHT_NB = 5;

Node[] nodes = new Node[PLAIN_NODE_NB];
MasterNode[] masterNodes = new MasterNode[MASTER_NODE_NB];

void setup()
{
size(800, 800);
smooth();

for (int i = 0; i < PLAIN_NODE_NB; i++)
{
nodes[i] = new Node(
random(PLAIN_NODE_RADIUS, width - PLAIN_NODE_RADIUS),
random(PLAIN_NODE_RADIUS, height - PLAIN_NODE_RADIUS));
}
for (int i = 0; i < MASTER_NODE_NB; i++)
{
masterNodes[i] = new MasterNode(
random(MASTER_NODE_RADIUS, width - MASTER_NODE_RADIUS),
random(MASTER_NODE_RADIUS, height - MASTER_NODE_RADIUS));
}
}

void draw()
{
background(#DDFFEE);
for (int i = 0; i < PLAIN_NODE_NB; i++)
{
nodes[i].Display();
}
for (int i = 0; i < MASTER_NODE_NB; i++)
{
masterNodes[i].Display();
}
}

void mouseMoved()
{
for (int i = 0; i < MASTER_NODE_NB; i++)
{
masterNodes[i].HandleMouse();
}
}

// A node, a simple circle with position, radius, color (normal and highlighted) and state.
class Node
{
float posX, posY;
float radius = PLAIN_NODE_RADIUS;
// Fill and stroke colors
color fColor = #FFFF00, sColor = #0000FF;
// Highlighted colors
color hfColor = #FFFFFF, hsColor = #5555FF;
boolean bHighlighted;

Node(float px, float py)
{
posX = px; posY = py;
}

void Display()
{
if (!bHighlighted)
{
fill(fColor);
stroke(sColor);
}
else
{
fill(hfColor);
stroke(hsColor);
}
ellipse(posX, posY, radius, radius);
}

void Highlight(boolean bLight)
{
bHighlighted = bLight;
}

public String toString()
{
return "N[" + int(posX) + ", " + int(posY) + "]";
}
}

// A master node, they check what are the closest plain nodes around them
// and highlight them when hovered.
class MasterNode extends Node
{
// The list of closest neighbour nodes
NeighbourNodes neighNodes = new NeighbourNodes();

MasterNode(float px, float py)
{
super(px, py);
radius = MASTER_NODE_RADIUS;
fColor = #00FF00; sColor = #0080FF;
hfColor = #55FFEE; hsColor = #5080FF;
CheckDistances();
}

// Handle hovering
void HandleMouse()
{
if (dist(posX, posY, mouseX, mouseY) <= radius/2)
{
// Hovered: highlight the closest nodes
bHighlighted = true;
neighNodes.Highlight(true);
}
else
{
if (bHighlighted)
{
// Was hovered but no longer: remove the highlighting
bHighlighted = false;
neighNodes.Highlight(false);
}
}
}

void Display()
{
// Display as a simple node
super.Display();
// But if highlighted, also display connections to the nearest nodes
if (bHighlighted)
{
neighNodes.Connect(this);
}
}

// Build the list of closest neighbours
void CheckDistances()
{
// For each plain node
for (int i = 0; i < PLAIN_NODE_NB; i++)
{
Node n = nodes[i];
// Check if closer than the previous checked one and if so, replace the farthest
neighNodes.CheckDist(dist(posX, posY, n.posX, n.posY), n);
}
}

public String toString()
{
return "M" + super.toString() + "[" + neighNodes + "]";
}
}

class NeighbourNodes
{
// Define a neighbour node: distance to master node and reference to the plain node
class NeighbourNode
{
float dist;
Node node;

NeighbourNode()
{
// Initialize with the biggest distance we can have
dist = Float.MAX_VALUE;
}
NeighbourNode(float d, Node n)
{
dist = d;
node = n;
}

public String toString()
{
return "NN[" + int(dist) + ", " + node + "]";
}
}
LinkedList neighbours = new LinkedList();

NeighbourNodes()
{
// Initialize with empty far nodes
for (int i = 0; i < NEIGHT_NB; i++)
{
NeighbourNode nn = new NeighbourNode();
neighbours.add(nn);
}
}

// The algorithm to test if given node is closer than the stored ones
void CheckDist(float d, Node n)
{
// First node is always the farthest, as we keep the linked list sorted (by inserting at the right place)
NeighbourNode fnn = (NeighbourNode) neighbours.getFirst();
if (d < fnn.dist)
{
// Found an element closer
// Remove the far element
neighbours.remove();
// To add
NeighbourNode nnn = new NeighbourNode(d, n);
// Walk the list until we find a node which is farther than this one
Iterator it = neighbours.iterator();
int idx = -1;
while (it.hasNext())
{
NeighbourNode nn = (NeighbourNode) it.next();
idx++;
if (d > nn.dist)
{
// Found, we add the node before this one
neighbours.add(idx, nnn);
return;
}
}
// Not found, ie. found the smallest distance, put it at end
neighbours.add(nnn);
}
}

public void Highlight(boolean bHighlight)
{
Iterator it = neighbours.iterator();
while (it.hasNext())
{
NeighbourNode nn = (NeighbourNode) it.next();
nn.node.Highlight(bHighlight);
}
}

public void Connect(Node mNode)
{
Iterator it = neighbours.iterator();
while (it.hasNext())
{
NeighbourNode nn = (NeighbourNode) it.next();
stroke(#0000FF);
line(nn.node.posX, nn.node.posY, mNode.posX, mNode.posY);
}
}

public String toString()
{
StringBuilder sb = new StringBuilder("NNs[");
Iterator it = neighbours.iterator();
while (it.hasNext())
{
NeighbourNode nn = (NeighbourNode) it.next();
sb.append(nn.toString() + ", ");
}
sb.delete(sb.length() - 2, sb.length() - 1).append("]");
return sb.toString();
}
}

Once you understood it, adapt it to your needs. I just added comments to help understanding.
Page Index Toggle Pages: 1