• Global community
• Language:
• Deutsch
• English
• Español
• Français
• Português
• 日本語コミュニティ
Dedicated community for Japanese speakers
• 한국 커뮤니티
Dedicated community for Korean speakers
Exit
• Recursive expression with sampleimage

# Recursive expression with sampleimage

Engaged ,
Oct 25, 2023 Oct 25, 2023

Copied

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

TOPICS
Expressions

Views

515

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
8 Replies 8
LEGEND ,
Oct 25, 2023 Oct 25, 2023

Copied

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

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Engaged ,
Oct 25, 2023 Oct 25, 2023

Copied

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.

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Engaged ,
Oct 25, 2023 Oct 25, 2023

Copied

I have just tried to do this with a while loop. Which may be a simpler way to do it. But the problem seems to be the same. It will go into an endless loop, freezing 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;``````

While the below does not go into endless loop but obvoiusly doesn't do anything but to leave the loop.

``````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 = 1;

seed++;
}

p;``````

There must be somthing wrong with the sampleImage output. Although, I have tested it and it does return 1 as it should?

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Community Expert ,
Oct 25, 2023 Oct 25, 2023

Copied

Depending on what your objective is, I'd be tempted to do something like this, ditching sampleImage and recursion:

``````circle = thisComp.layer("circle");
seedRandom(index,true);
a = random(Math.PI*2);
x = r*Math.sin(a);
y = r*Math.cos(a);
circle.position + [x,y]``````

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Engaged ,
Oct 26, 2023 Oct 26, 2023

Copied

Thanks Dan. You're right. That would be a better way. I should have explained more carefully. The circle layer is simply a test. The real project will have a more complicated shape.

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
LEGEND ,
Oct 25, 2023 Oct 25, 2023

Copied

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

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Engaged ,
Oct 25, 2023 Oct 25, 2023

Copied

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.

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Engaged ,
Oct 26, 2023 Oct 26, 2023

Copied

LATEST

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