Doube for loops for checking left and right node

world.objects.do{|o, i|	//iterate all objects in this world
		var distMinL = 3*width;
		var distMinR = 3*width;


		x[i]= o.loc[0];
		y[i]= o.loc[1];

		world.objects.do{ |oo, ii|
						
		
			var dist= o.loc.distance(oo.loc);
			if( (oo.loc[0]-o.loc[0]<0 ),
				{
					if(dist<distMinL and: dist!=0,
					{ distMinL = dist;
					  left[i] = ii;
						};
				
					);
				
				},
				{
					if(dist<distMinR and: dist!=0,
					{ distMinR = dist;
					  right[i] = ii;
						};
					
					);
					


				};

			);

                         ii.asString++left[0].asString.postln;

};

this is a simulation code fo get the left right value of the node. for example, If I set a 10 agent with index, It return the value index of left and right node.

but I feel like It is not properly working,
this is work on the base example of redunivers, but I feel like It isn’t that hard to understand the code, (just simple double for loop (world.objects|o|))
I don’t know which parts is going wrong for it. and for the world function caluclate so fast, and this function returns some weired values at some points does anyone recognized the issues about it?

 ii.asString++left[0].asString.postln;

and I want to check the value of 2nd loop with ii(number of index) + value but it is not properly working. how to check the values of it?

(ii.asString ++ left[0].asString).postln

(dist < distMinR).and(dist != 0)

Same thing as before I imagine.
You also might want to auto indent this (highlight all and press tab) and add some spaces between the operators so it is readable.

Something like…

if( (oo.loc[0] - o.loc[0]) < 0,  {

   if( (dist < distMinL).and(dist != 0), { 
      distMinL = dist;
      left[i] = ii;
   })
				
}, {
   ...
});
					



One extra thing

dist != 0

Asking if a float == or != a value is often wrong. Instead do

dist.abs < 0.000001 // or something sufficiently small
1 Like

For fun, I ended up rewriting this, because I realized you could cut the number of comparisons in half (and double the speed).

To get a correct result, each point needs to be compared against every other point. Taking 3 points as an example, A, B and C:

  • 1st pass: compare A against B and C. (Note that there is no reason to compare A vs A – but the original code snippet does do this.)
  • 2nd pass: compare B against A and C – but “B against A” was already done in the first pass. So you only need to do B vs C.
  • 3rd pass: compare C against A and B – but both of these were already done. So this entire inner loop can be skipped.

So it can be done with only 3 comparisons, where the original code would perform 9.

It can’t quite be inferred from the code example exactly what is the data structure, so I made up a different one. For this type of problem, I often use Event. Here, it lets me store a 2D point along with the comparison results, using descriptive names, making the code easier to read (I hope).

(
f = { |a|
	(a.size - 1).do { |i|  // n-1 times
		var thisPt = a[i];
		(i+1 .. a.size-1).do { |j|  // only points that haven't been checked
			var dist = thisPt[\point].dist(a[j][\point]);
			if(a[j][\point].x < thisPt[\point].x) {
				if(thisPt[\leftDist].isNil or: {
					dist < thisPt[\leftDist]
				}) {
					thisPt[\leftIndex] = j;
					thisPt[\leftDist] = dist;
					
					a[j][\rightIndex] = i;
					a[j][\rightDist] = dist;
				};
			};
			
			if(a[j][\point].x > thisPt[\point].x) {
				if(thisPt[\rightDist].isNil or: {
					dist < thisPt[\rightDist]
				}) {
					thisPt[\rightIndex] = j;
					thisPt[\rightDist] = dist;
					
					a[j][\leftIndex] = i;
					a[j][\leftDist] = dist;
				};
			};
		};
	};
	a
};
)

Test it:

(
~array = Array.fill(5, {
	(point: Point(1.0.rand2.round(0.001), 1.0.rand2.round(0.001)))
});
)

f.(~array);

~array.do(_.postln); ""
// e.g.
( 'point': Point( 0.62, 0.789 ), 'leftDist': 0.92818640369271, 'rightDist': 1.0064000198728, 'rightIndex': 3, 
  'leftIndex': 4 )
( 'point': Point( -0.006, -0.447 ), 'leftDist': 0.82633770336346, 'rightDist': 0.89250266106046, 'rightIndex': 3, 
  'leftIndex': 4 )
( 'point': Point( -0.795, 0.064 ), 'rightDist': 0.66189122973492, 'rightIndex': 4 )
( 'point': Point( 0.849, -0.191 ), 'leftDist': 0.89250266106046, 'leftIndex': 1 )
( 'point': Point( -0.201, 0.356 ), 'leftDist': 0.66189122973492, 'rightDist': 0.82633770336346, 'rightIndex': 1, 
  'leftIndex': 2 )

// and plot it, to check
(
var blk = Color.black, pt = Color(0.5, 1, 0.5);

w = Window("test", Rect(800, 200, 300, 300)).front;
w.layout = VLayout(
	u = UserView()
);

u.drawFunc_({ |view|
	var b = view.bounds.extent;
	var xscale = b.x * 0.5, yscale = b.y * 0.5;
	var scale = Point(xscale, yscale.neg);
	var offset = Point(xscale, yscale);
	Pen.color_(blk)
	.moveTo(Point(xscale, 0)).lineTo(Point(xscale, b.y))
	.moveTo(Point(0, yscale)).lineTo(Point(b.x, yscale))
	.stroke;
	~array.do { |pt, i|
		pt = pt.point * scale + offset;
		Pen.color_(pt);
		Pen.fillOval(Rect.aboutPoint(pt, 4, 4)).stroke;
		Pen.stringAtPoint(i.asString, pt + Point(0, -20), Font.default, blk);
	};
})
.refresh;
)

For my example run, the plot looks like this:

sc-point-dist

Taking point 4 as an example, the nearest point to the left is in fact 2 ('leftIndex': 2) and the nearest to the right is 1. (Point 2 doesn’t have a leftIndex because there is no point to its left; same for point 3’s missing rightIndex.)

The 0 here is probably okay because this would be the result when comparing a point against itself. (I got rid of the zero check by not comparing points against themselves.)

hjh

1 Like

Super :slight_smile:

I quick finish the draft with RedUnivers, so I am on it, but there are so many problems to solve. haha
It could be really helpful for optimization haha
reduce some calculation, and If the dot’s moving with the route, and It changes of the state, I will gonna update the values of left and right when only change the valuse.

anyway, thank you so much for writing long code from the botoom! amzaing!