finding nearest neighbor & point to point morphing (transitioning)
in
Programming Questions
•
2 years ago
i'm trying to use two arrays of PVector points and compare and match them up based on the proximity of the points to each other.
so in Array A i have a collection of points
- PVector[] pointListA = {
- new PVector(0,0),
- new PVector(20,10),
- new PVector(30,20),
- new PVector(40,60)
- };
and then i create an Array B with new points.
- PVector[] pointListB = {
- new PVector(10,0),
- new PVector(30,0),
- new PVector(50,20),
- new PVector(20,10)
- };
i would go through the lists of arrays and based on distance and pair the the arrays up so that the points closest to one another are correlated.
after "matching" up the arrays the ideas is that i would then "lerp" the a points pointListA to their corresponding point of pointListB.
and then repeat.
essentially morphing a set of points into the other
here's some "simplified" code of what i have working thus far but as you'll see it seems to find the nearest points, but then instead of "transitioning" from point to point it seems like the points get reduced. and after 10seconds all of the points have the same coordinates
i'm explaining this in a terrible way, so i hope someone out there understands what i'm looking for and can help.
- //-----------------------------------------------------------------------------
- // properties
- //-----------------------------------------------------------------------------
- FPointSet fpoints;
- ArrayList npoints;
- void setup() {
- size(720,480);
- //smooth();
- initialize();
- }
- void draw() {
- background(0);
- /*
- * points
- */
- fpoints.update();
- fpoints.draw();
- if( !fpoints.running() ) {
- next();
- }
- }
- //-----------------------------------------------------------------------------
- // methods
- //-----------------------------------------------------------------------------
- void initialize() {
- //------------------------------------
- // points
- //------------------------------------
- //fpoints = new ArrayList();
- fpoints = new FPointSet();
- npoints = new ArrayList();
- //start out with 20 random points
- for(int i=0; i<20; i++) {
- FPoint fp = new FPoint( new PVector(random(width), random(height)) );
- fpoints.add(fp);
- }
- next();
- }
- //-----------------------------------------------------------------------------
- void next() {
- npoints = createRandom(20);
- fpoints.findNearest(npoints);
- }
- /*
- * create NUM random points
- */
- ArrayList createRandom(int num) {
- ArrayList newPoints = new ArrayList();
- for(int i=0; i<num; i++) {
- newPoints.add(new PVector(random(width), random(height) ));
- }
- return newPoints;
- }
- /**
- * class for defining and finding a list of nearest points
- * witin a series of points modified from http://processing.org/discourse/yabb2/YaBB.pl?num=1244097116
- *
- * Define a neighbour node:
- * distance to initial point and reference to the goto point
- */
- public class NearPoint {
- float dist;
- PVector pos = new PVector();
- //-----------------------------------------------------------------------------
- // Constructor
- //-----------------------------------------------------------------------------
- public NearPoint() {
- // Initialize with the biggest distance we can have
- dist = Float.MAX_VALUE;
- }
- public NearPoint(float d, PVector _pos) {
- dist = d;
- pos = _pos.get();
- }
- }
- class NearPoints {
- //-----------------------------------------------------------------------------
- // Properties
- //-----------------------------------------------------------------------------
- public LinkedList nearest = new LinkedList();
- //-----------------------------------------------------------------------------
- // Constructor
- //-----------------------------------------------------------------------------
- public NearPoints(int num) {
- for (int i=0; i<num; i++) {
- // Initialize with empty far nodes
- NearPoint nn = new NearPoint();
- nearest.add(nn);
- }
- }
- //-----------------------------------------------------------------------------
- // Methods
- //-----------------------------------------------------------------------------
- /**
- * The algorithm to test if given node is closer than the stored ones
- */
- public void CheckDist(float d, PVector n) {
- /*
- * First node is always the farthest,
- * we keep the linked list sorted
- * (by inserting at the right place)
- */
- NearPoint fnn = (NearPoint) nearest.getFirst();
- if (d < fnn.dist) {
- // Found an element closer
- // Remove the far element
- nearest.remove();
- // To add
- NearPoint nnn = new NearPoint(d, n);
- // Walk the list until we find a node which is farther than this one
- Iterator it = nearest.iterator();
- int index = -1;
- while (it.hasNext ()) {
- NearPoint nn = (NearPoint) it.next();
- index++;
- if (d > nn.dist) {
- // Found, we add the node before this one
- nearest.add(index, nnn);
- return;
- }
- }
- // Not found, ie. found the smallest distance, put it at end
- nearest.add(nnn);
- }
- }
- }
- /**
- * a point class that makes easing and tweening
- * much easier
- */
- public class FPoint {
- //-----------------------------------------------------------------------------
- // properties
- //-----------------------------------------------------------------------------
- public PVector pos = new PVector();
- protected PVector destination = new PVector();
- private boolean bArrived = false;
- private float lerpAmt = 0.0f;
- //-----------------------------------------------------------------------------
- // constructor
- //-----------------------------------------------------------------------------
- public FPoint(PVector _pos) {
- //new points initialized with same pos and destination
- pos = _pos.get();
- setDestination(pos);
- }
- //-----------------------------------------------------------------------------
- // methods
- //-----------------------------------------------------------------------------
- public void update() {
- if(lerpAmt >= 1.0) {
- bArrived = true;
- pos = destination.get();
- //destination = null;
- } else {
- lerpAmt += 0.01;
- pos = plerp(pos,destination, lerpAmt);
- bArrived = false;
- }
- }
- //-----------------------------------------------------------------------------
- public void reset() {
- bArrived = false;
- lerpAmt = 0.0;
- }
- //-----------------------------------------------------------------------------
- PVector plerp(PVector pt1, PVector pt2, float amt) {
- float x = lerp(pt1.x, pt2.x, amt);
- float y = lerp(pt1.y, pt2.y, amt);
- return new PVector(x,y);
- }
- //-----------------------------------------------------------------------------
- // sets
- //-----------------------------------------------------------------------------
- public void setDestination(PVector _dest) {
- if(_dest != destination) reset();
- destination = _dest.get();
- }
- //-----------------------------------------------------------------------------
- // gets
- //-----------------------------------------------------------------------------
- public boolean arrived() {
- return bArrived;
- }
- }
- public class FPointSet {
- //-----------------------------------------------------------------------------
- // properties
- //-----------------------------------------------------------------------------
- protected ArrayList fpoints = new ArrayList();
- public int size = 0;
- private boolean bRunning = true;
- //-----------------------------------------------------------------------------
- // constructor
- //-----------------------------------------------------------------------------
- public FPointSet() {
- }
- //-----------------------------------------------------------------------------
- // methods
- //-----------------------------------------------------------------------------
- public void update() {
- for(int i=0; i<fpoints.size(); i++) {
- FPoint fp = (FPoint) fpoints.get(i);
- fp.update();
- if(fp.arrived()) bRunning = false;
- else bRunning = true;
- }
- }
- public void draw() {
- noFill();
- for(int i=0; i<fpoints.size(); i++) {
- FPoint fp = (FPoint) fpoints.get(i);
- //points
- PVector pt1 = fp.pos;
- stroke(0,255,255);
- point(pt1.x,pt1.y);
- PVector pt2 = fp.destination;
- stroke(255,0,255);
- ellipse(pt2.x,pt2.y, 9,9);
- //line
- strokeWeight(1);
- stroke(255, norm(i,0,fpoints.size())*255, 0);
- line(pt1.x,pt1.y, pt2.x,pt2.y);
- }
- }
- //-----------------------------------------------------------------------------
- public void findNearest(ArrayList npointSet) {
- int num = fpoints.size();
- // create a list of nearest points
- NearPoints nearPoints = new NearPoints(num);
- for (int i=0; i<fpoints.size(); i++) {
- FPoint fp = (FPoint) fpoints.get(i);
- PVector fpt = fp.pos;
- for (int j=0; j<npointSet.size(); j++) {
- PVector npt = (PVector) npointSet.get(j);
- // Check if closer than the previous checked one
- // and if so, replace the farthest
- nearPoints.CheckDist(fpt.dist(npt), fpt);
- }
- }
- println(fpoints.size() + " --VS-- " + nearPoints.nearest.size());
- //return nearPoints.nearest;
- //update fpoints list
- for(int i=0; i<fpoints.size(); i++) {
- FPoint fp = (FPoint) fpoints.get(i);
- NearPoint np = (NearPoint) nearPoints.nearest.get(i);
- PVector npt = np.pos;
- fp.setDestination(np.pos);
- }
- }
- //-----------------------------------------------------------------------------
- // sets
- //-----------------------------------------------------------------------------
- public void add(FPoint fpoint) {
- fpoints.add(fpoint);
- size = fpoints.size();
- }
- public void clear() {
- fpoints.clear();
- size = fpoints.size();
- }
- public void remove(int index) {
- fpoints.remove(index);
- size = fpoints.size();
- }
- //-----------------------------------------------------------------------------
- // gets
- //-----------------------------------------------------------------------------
- public boolean running() {
- return bRunning;
- }
- public FPoint getFPoint(int index) {
- return (FPoint) fpoints.get(index);
- }
- }
1