POV-Ray : Newsgroups : povray.newusers : help with macro Server Time
25 Nov 2024 05:29:12 EST (-0500)
  help with macro (Message 1 to 7 of 7)  
From: mine
Subject: help with macro
Date: 15 May 2006 09:00:01
Message: <web.44687a797f9206dfa533cc200@news.povray.org>
I've made a basic macro (with the help of a tutorial)that randomly places
objects (in this case spheres) in a given space. The trouble is the
tutorial didn't tell me how to stop the spheres from touching. Can anyone
help? I've included the macro below.

#declare floater = sphere{<0,.5,0>, 1}
#declare thingy_red = <1,0,0>;
#declare floater_count = 20;
#declare Locations = seed(1);
#while (floater_count > 0)
  #declare x_loc = rand(Locations)*7-1;
  #declare y_loc = rand(Locations)*7-1;
  #declare z_loc = rand(Locations)*7-1;
object{floater
      pigment{color thingy_red}
      translate <x_loc,y_loc,z_loc>
      }
  #declare floater_count = floater_count - 1;
#end


Post a reply to this message

From: Chris B
Subject: Re: help with macro
Date: 15 May 2006 09:33:31
Message: <4468832b$1@news.povray.org>
"mine" <nomail@nomail> wrote in message 
news:web.44687a797f9206dfa533cc200@news.povray.org...
> I've made a basic macro (with the help of a tutorial)that randomly places
> objects (in this case spheres) in a given space. The trouble is the
> tutorial didn't tell me how to stop the spheres from touching. Can anyone
> help? I've included the macro below.
>
> #declare floater = sphere{<0,.5,0>, 1}
> #declare thingy_red = <1,0,0>;
> #declare floater_count = 20;
> #declare Locations = seed(1);
> #while (floater_count > 0)
>  #declare x_loc = rand(Locations)*7-1;
>  #declare y_loc = rand(Locations)*7-1;
>  #declare z_loc = rand(Locations)*7-1;
> object{floater
>      pigment{color thingy_red}
>      translate <x_loc,y_loc,z_loc>
>      }
>  #declare floater_count = floater_count - 1;
> #end
>
>

Hi,

You can declare an array of size 'floater_count', then each time round the 
current loop, do another loop to test whether the position of the centre of 
the sphere is closer than the diameter of floater to any of the existing 
positions (see the vlength() function, which you can use on the difference 
between each pair of positions).

Then you can put the 'object' statement plus the line where you decrement 
'floater_count' inside an #if clause along with a new line to add the new 
position into the array.

If you're likely to want to increase float_count to where you get close to 
the limit where you can't find enough positions, then you should also add a 
way of breaking out of your existing loop to avoid that you loop 
indefinitely.

I didn't post code because it sounds like you're trying to work stuff out 
for yourself, but if you want the answer, just say.

Regards,
Chris B.


Post a reply to this message

From: Warp
Subject: Re: help with macro
Date: 15 May 2006 09:42:50
Message: <4468855a@news.povray.org>
mine <nomail@nomail> wrote:
> I've made a basic macro (with the help of a tutorial)that randomly places
> objects (in this case spheres) in a given space. The trouble is the
> tutorial didn't tell me how to stop the spheres from touching. Can anyone
> help?

  This is not the fastest possible algorithm for a large number of
spheres, but it gets the job done. Note that it can end in an infinite
loop if the defined box runs out of space for any more spheres.

camera { location -z*25 look_at 0 angle 35 }
light_source { <100, 200, -300>, 1 }
light_source { <-200, 100, -100>, <.5,.3,.1> }

#declare Objects = 300;
#declare MinCoords = <-5, -5, -5>;
#declare MaxCoords = <5, 5, 5>;
#declare SphereDiameter = 1;
#declare S = seed(0);

#declare Centers = array[Objects];
#declare CoordInd = 0;
#while(CoordInd < Objects)
  #declare CoordOk = false;
  #while(!CoordOk)
    #declare Coord =
      MinCoords+(MaxCoords-MinCoords)*<rand(S), rand(S), rand(S)>;
    #declare CoordOk = true;
    #declare Ind = CoordInd-1;
    #while(Ind >= 0)
      #if(vlength(Centers[Ind]-Coord) < SphereDiameter)
        #declare CoordOk = false;
        #declare Ind = -1;
      #end
      #declare Ind = Ind-1;
    #end // #while(Ind >= 0)
  #end // #while(!CoordOk)
  #declare Centers[CoordInd] = Coord;
  #declare CoordInd = CoordInd+1;
#end // #while(CoordInd < Objects)

#declare Ind = 0;
#while(Ind < Objects)
  sphere
  { Centers[Ind], SphereDiameter/2
    pigment { rgb x }
    finish { specular .5 }
  }
  #declare Ind = Ind+1;
#end


-- 
                                                          - Warp


Post a reply to this message

From: mine
Subject: Re: help with macro
Date: 15 May 2006 12:35:01
Message: <web.4468ad3d4767bb90a533cc200@news.povray.org>
"Chris B" <c_b### [at] btconnectcomnospam> wrote:
> "mine" <nomail@nomail> wrote in message
> news:web.44687a797f9206dfa533cc200@news.povray.org...
> > I've made a basic macro (with the help of a tutorial)that randomly places
> > objects (in this case spheres) in a given space. The trouble is the
> > tutorial didn't tell me how to stop the spheres from touching. Can anyone
> > help? I've included the macro below.
> >
> > #declare floater = sphere{<0,.5,0>, 1}
> > #declare thingy_red = <1,0,0>;
> > #declare floater_count = 20;
> > #declare Locations = seed(1);
> > #while (floater_count > 0)
> >  #declare x_loc = rand(Locations)*7-1;
> >  #declare y_loc = rand(Locations)*7-1;
> >  #declare z_loc = rand(Locations)*7-1;
> > object{floater
> >      pigment{color thingy_red}
> >      translate <x_loc,y_loc,z_loc>
> >      }
> >  #declare floater_count = floater_count - 1;
> > #end
> >
> >
>
> Hi,
>
> You can declare an array of size 'floater_count', then each time round the
> current loop, do another loop to test whether the position of the centre of
> the sphere is closer than the diameter of floater to any of the existing
> positions (see the vlength() function, which you can use on the difference
> between each pair of positions).
>
> Then you can put the 'object' statement plus the line where you decrement
> 'floater_count' inside an #if clause along with a new line to add the new
> position into the array.
>
> If you're likely to want to increase float_count to where you get close to
> the limit where you can't find enough positions, then you should also add a
> way of breaking out of your existing loop to avoid that you loop
> indefinitely.
>
> I didn't post code because it sounds like you're trying to work stuff out
> for yourself, but if you want the answer, just say.
>
> Regards,
> Chris B.

hi Chris B.
I tried figure it out but kept on getting lost. You better just give me the
answer. I sort of understand what I was trying to do but I have no idea how
to do it. Thanks for helping.


Post a reply to this message

From: Chris B
Subject: Re: help with macro
Date: 15 May 2006 14:12:37
Message: <4468c495$1@news.povray.org>
"mine" <nomail@nomail> wrote in message 
news:web.4468ad3d4767bb90a533cc200@news.povray.org...
> "Chris B" <c_b### [at] btconnectcomnospam> wrote:
>> "mine" <nomail@nomail> wrote in message
>> news:web.44687a797f9206dfa533cc200@news.povray.org...
>> > I've made a basic macro (with the help of a tutorial)that randomly 
>> > places
>> > objects (in this case spheres) in a given space. The trouble is the
>> > tutorial didn't tell me how to stop the spheres from touching. Can 
>> > anyone
>> > help? I've included the macro below.
>> >
>> ... snip ...
>>
>> Hi,
>>
>> You can declare an array of size 'floater_count', then each time round 
>> the
>> current loop, do another loop to test whether the position of the centre 
>> of
>> the sphere is closer than the diameter of floater to any of the existing
>> positions (see the vlength() function, which you can use on the 
>> difference
>> between each pair of positions).
>>
>> Then you can put the 'object' statement plus the line where you decrement
>> 'floater_count' inside an #if clause along with a new line to add the new
>> position into the array.
>>
>> If you're likely to want to increase float_count to where you get close 
>> to
>> the limit where you can't find enough positions, then you should also add 
>> a
>> way of breaking out of your existing loop to avoid that you loop
>> indefinitely.
>>
>> I didn't post code because it sounds like you're trying to work stuff out
>> for yourself, but if you want the answer, just say.
>>
>> Regards,
>> Chris B.
>
> hi Chris B.
> I tried figure it out but kept on getting lost. You better just give me 
> the
> answer. I sort of understand what I was trying to do but I have no idea 
> how
> to do it. Thanks for helping.
>
>

Hi,

I see Warp has posted a perfectly good solution, that does the same thing in 
a slightly different sequence. It collects the set of points into an array 
in the first loop, then draws the objects using those points in a second 
loop.

Here's the approach I described using the code you posted as a starting 
point (I'd recommend you use uppercase letters to start each variable name 
as that helps avoid conflicts with any stuff added to future versions of 
POV-Ray). I also added the LoopLimit stuff that both Warp and I mentioned 
earlier to avoid infinite loops (so you probably want to set the 
Floater_count back to 20).


camera {location <0, 0, -10> look_at  <3,3,0>}
light_source { <0, 50, -400> color 1}

#declare ObjectRadius = 1;

#declare Floater = sphere{<0,.5,0>, ObjectRadius}
#declare Thingy_red = <1,0,0>;
#declare Floater_count = 200;
#declare Locations = seed(1);

#declare Positions = array[Floater_count];
#declare FloaterQuantity = Floater_count;
#declare LoopLimit = 1000;
#declare CollisionCounter = 0;

#while (Floater_count > 0 & CollisionCounter < LoopLimit)
  #declare x_loc = rand(Locations)*7-1;
  #declare y_loc = rand(Locations)*7-1;
  #declare z_loc = rand(Locations)*7-1;
  #declare I = FloaterQuantity - 1;
  #declare TooClose = 0;
  #while(I>Floater_count-1)
    #if (vlength(<x_loc,y_loc,z_loc>-Positions[I])<ObjectRadius*2)
      #declare TooClose = 1;
    #end
    #declare I = I - 1;
  #end
  #if (TooClose)
    #declare CollisionCounter = CollisionCounter + 1;
  #else
    #declare CollisionCounter = 0;
    object{Floater
      pigment{color Thingy_red}
      translate <x_loc,y_loc,z_loc>
    }
    #declare Floater_count = Floater_count - 1;
    #declare Positions[Floater_count] = <x_loc,y_loc,z_loc>;
  #end
#end

#if (CollisionCounter >= LoopLimit)
  #debug "\n\nWARNING: Loop Limit Exceeded\n\n\n"
#end
.

Regards,
Chris B.


Post a reply to this message

From: mine
Subject: Re: help with macro
Date: 15 May 2006 21:20:00
Message: <web.446927cc4767bb909c81dded0@news.povray.org>
"Chris B" <c_b### [at] btconnectcomnospam> wrote:
> "mine" <nomail@nomail> wrote in message
> news:web.4468ad3d4767bb90a533cc200@news.povray.org...
> > "Chris B" <c_b### [at] btconnectcomnospam> wrote:
> >> "mine" <nomail@nomail> wrote in message
> >> news:web.44687a797f9206dfa533cc200@news.povray.org...
> >> > I've made a basic macro (with the help of a tutorial)that randomly
> >> > places
> >> > objects (in this case spheres) in a given space. The trouble is the
> >> > tutorial didn't tell me how to stop the spheres from touching. Can
> >> > anyone
> >> > help? I've included the macro below.
> >> >
> >> ... snip ...
> >>
> >> Hi,
> >>
> >> You can declare an array of size 'floater_count', then each time round
> >> the
> >> current loop, do another loop to test whether the position of the centre
> >> of
> >> the sphere is closer than the diameter of floater to any of the existing
> >> positions (see the vlength() function, which you can use on the
> >> difference
> >> between each pair of positions).
> >>
> >> Then you can put the 'object' statement plus the line where you decrement
> >> 'floater_count' inside an #if clause along with a new line to add the new
> >> position into the array.
> >>
> >> If you're likely to want to increase float_count to where you get close
> >> to
> >> the limit where you can't find enough positions, then you should also add
> >> a
> >> way of breaking out of your existing loop to avoid that you loop
> >> indefinitely.
> >>
> >> I didn't post code because it sounds like you're trying to work stuff out
> >> for yourself, but if you want the answer, just say.
> >>
> >> Regards,
> >> Chris B.
> >
> > hi Chris B.
> > I tried figure it out but kept on getting lost. You better just give me
> > the
> > answer. I sort of understand what I was trying to do but I have no idea
> > how
> > to do it. Thanks for helping.
> >
> >
>
> Hi,
>
> I see Warp has posted a perfectly good solution, that does the same thing in
> a slightly different sequence. It collects the set of points into an array
> in the first loop, then draws the objects using those points in a second
> loop.
>
> Here's the approach I described using the code you posted as a starting
> point (I'd recommend you use uppercase letters to start each variable name
> as that helps avoid conflicts with any stuff added to future versions of
> POV-Ray). I also added the LoopLimit stuff that both Warp and I mentioned
> earlier to avoid infinite loops (so you probably want to set the
> Floater_count back to 20).
>
>
> camera {location <0, 0, -10> look_at  <3,3,0>}
> light_source { <0, 50, -400> color 1}
>
> #declare ObjectRadius = 1;
>
> #declare Floater = sphere{<0,.5,0>, ObjectRadius}
> #declare Thingy_red = <1,0,0>;
> #declare Floater_count = 200;
> #declare Locations = seed(1);
>
> #declare Positions = array[Floater_count];
> #declare FloaterQuantity = Floater_count;
> #declare LoopLimit = 1000;
> #declare CollisionCounter = 0;
>
> #while (Floater_count > 0 & CollisionCounter < LoopLimit)
>   #declare x_loc = rand(Locations)*7-1;
>   #declare y_loc = rand(Locations)*7-1;
>   #declare z_loc = rand(Locations)*7-1;
>   #declare I = FloaterQuantity - 1;
>   #declare TooClose = 0;
>   #while(I>Floater_count-1)
>     #if (vlength(<x_loc,y_loc,z_loc>-Positions[I])<ObjectRadius*2)
>       #declare TooClose = 1;
>     #end
>     #declare I = I - 1;
>   #end
>   #if (TooClose)
>     #declare CollisionCounter = CollisionCounter + 1;
>   #else
>     #declare CollisionCounter = 0;
>     object{Floater
>       pigment{color Thingy_red}
>       translate <x_loc,y_loc,z_loc>
>     }
>     #declare Floater_count = Floater_count - 1;
>     #declare Positions[Floater_count] = <x_loc,y_loc,z_loc>;
>   #end
> #end
>
> #if (CollisionCounter >= LoopLimit)
>   #debug "nnWARNING: Loop Limit Exceedednnn"
> #end
> .
>
> Regards,
> Chris B.

Thanks both for the help.

Chris B.
I never would have got that. This is the first time I've used these
#declare, #if, #while, etc. stuff. I really know hardly anything about this
macro stuff so I had trouble understanding what you where telling me to do.
Once I play around with this code I'm sure I'll have at least a bit easier
time of things. What's really needed is a series of good tutorials,
especially for new users of pov-ray, as the whole macro thing is very hard
to learn and understand. I'm sure with time I'll be fine.


Post a reply to this message

From: Chris B
Subject: Re: help with macro
Date: 21 May 2006 10:55:51
Message: <44707f77@news.povray.org>
>What's really needed is a series of good tutorials,
> especially for new users of pov-ray, as the whole macro thing is very hard
> to learn and understand. I'm sure with time I'll be fine.
>

There's one here http://www.hoboes.com/html/NetLife/POV/Scripting/#macros
that covers declarations, while loops and macros.

Regards
Chris B.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.