Skip to main content
Inspiring
October 25, 2023
Question

Recursive expression with sampleimage

  • October 25, 2023
  • 3 replies
  • 1007 views

Hi

I have a project were I try to put one layer (dot) on another layer (circle) with an expression. My plan was to

 

1. Find a random position for the dot layer.

2. Check if that position is on top of the circle layer, using sampleImage.

3. If it isn't, run a recursive call of the function.

 

It doesn't seem to work. I'm almost sure the expression is correct, but AE keep crashing. As if I had made an endless loop recursive call. Of course I could be missing something.

 

The expression looks like this:

 

function findPointOnLayer(targetLayer, functionSeed)
{
	seedRandom(functionSeed, true);
	var rndX = Math.random();
	var rndY = Math.random();

	var posX = thisComp.width * rndX;
	var posY = thisComp.height * rndY;
	var p = [posX, posY];
	
	var sample = targetLayer.sampleImage(p, [0.5, 0.5]);
	var sampleAlpha = sample[3];
	
	if( sampleAlpha < 0.2 )
	{
		p = findPointOnLayer(targetLayer, functionSeed+1);
	}
	
	return p;
}

var circleLayer = thisComp.layer("circle");
var seed = effect("seed")("Slider");

findPointOnLayer(circleLayer, seed);

 

To trouble shoot. I have tried the expression below, which will likewise check if the dot layers is postioned on top of the circle layer. If it isn't, instead of the recursive call, it will set p to [0,0]. That works.

function findPointOnLayer(targetLayer, functionSeed)
{
	seedRandom(functionSeed, true);
	var rndX = Math.random();
	var rndY = Math.random();

	var posX = thisComp.width * rndX;
	var posY = thisComp.height * rndY;
	var p = [posX, posY];
	
	var sample = targetLayer.sampleImage(p, [0.5, 0.5]);
	var sampleAlpha = sample[3];
	
	if( sampleAlpha < 0.2 )
	{
		p = [0, 0];
	}
	
	return p;
}

var circleLayer = thisComp.layer("circle");
var seed = effect("seed")("Slider");

findPointOnLayer(circleLayer, seed);

 

Sample project is attached. Any help is much appreciated.

 

- Jakob

This topic has been closed for replies.

3 replies

Inspiring
October 26, 2023

I found a solution. But I don't understand this. The following will break AE:

 

var circleLayer = thisComp.layer("circle");
var seed = effect("seed")("Slider");
var sampleAlpha = 0;
var p = [0, 0];

while (sampleAlpha<0.2)
{
	seedRandom(seed, true);
	var rndX = Math.random();
	var rndY = Math.random();

	var posX = thisComp.width * rndX;
	var posY = thisComp.height * rndY;
	
	p = [posX, posY];
	
	var sample = circleLayer.sampleImage(p, [0.5, 0.5]);
	sampleAlpha = sample[3];
	
	seed++;
}

p;

 

However, the following will work. Which i don't understand because that means the sampleAlpha must change to something higher than 0.2. So if it does, why doesn't the above while statement exit loop?

 

var circleLayer = thisComp.layer("circle");
var seed = effect("seed")("Slider");
var sampleAlpha = 0;
var p = [0, 0];

var i = 0;

while (i<100)
{
	seedRandom(seed, true);
	var rndX = Math.random();
	var rndY = Math.random();

	var posX = thisComp.width * rndX;
	var posY = thisComp.height * rndY;
	
	p = [posX, posY];
	
	var sample = circleLayer.sampleImage(p, [0.5, 0.5]);
	sampleAlpha = sample[3];
	
	if(sampleAlpha>0.2)
	{
		break;
	}

	i++;
	seed++;
}

p;

 

Weirdly, the following will also break AE. Shouldn't it simply "break" like the working example above? (note true in while statement)

 

var circleLayer = thisComp.layer("circle");
var seed = effect("seed")("Slider");
var sampleAlpha = 0;
var p = [0, 0];

var i = 0;

while (true)
{
	seedRandom(seed, true);
	var rndX = Math.random();
	var rndY = Math.random();

	var posX = thisComp.width * rndX;
	var posY = thisComp.height * rndY;
	
	p = [posX, posY];
	
	var sample = circleLayer.sampleImage(p, [0.5, 0.5]);
	sampleAlpha = sample[3];
	
	if(sampleAlpha>0.2)
	{
		break;
	}

	i++;
	seed++;
}

p;

 

 

Any clearifications is very appreciated.

 

- Jakob

Mylenium
Legend
October 25, 2023

Again, I think changing the seed inside the loop probably causes mayhem. Even just incrementing it by 1 may produce insanely large numbers and exhaust the internal cycles. Also a thought that occured to me after my first reply: A one pixel hit area may be to small and you may need an additional loop to progressively refine the check - test a 50 x 50 area first and then go smaller iteratively until you find the exact hit point. Point being that never finding anything may also simply exhaust all cycles.

 

Mylenium 

Inspiring
October 25, 2023

Thank you for answering, but I don't think you're right about any of that.

The sampleImage seems to work when tested with same random values and return 1 in the alpha as it should. Even with a one pixel hit area.

The layer that is being targeted is taking up more than half of the space in the comp and is easially hit. Again, I tested it with the exact random point, and it is a hit.

Mylenium
Legend
October 25, 2023

That's probably not going to work conceptually as you are re-seeding the random function inside the main loop. That way you may never actually get a hit because in your case you're actually changing it whenever there would be a hit so it moves away to the next sample. It would probably work better if you separated the functions and controlled the main loop with break and continue statements based on whether the hit is true or false.

 

Mylenium

Inspiring
October 25, 2023

Thanks for the reply. But actually, I do take that into account by adding 1 to the seed for every recursion.

p = findPointOnLayer(targetLayer, functionSeed+1);

It's a good idea to try a while loop instead, but I still don't see why the recursion call doesn't work.