Is this code correct ?

Discussion in 'C Programming' started by johnnash, Feb 28, 2008.

  1. johnnash

    johnnash Guest

    In my project I need to shoot rays from the source.I know you cannot
    follow all the rays from the source as you can actually shoot rays at
    infinite angles,therefore my plan is to launch rays from the
    trasmitter in all directions spaced eg. x degrees or something. This
    is the logic I have used for a C program -

    consider the source to be centre of the unit sphere.

    0<=theta<=180(zenith)
    0<=phi<=360 (azimuth)

    Then run a for loop like this -

    for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
    degree difference or there will be infinite rays */
    for( phi = 0; phi <=360; phi = phi + 5 )
    {
    /*Calculate the cartesian coordinates of a point p(a struct) on
    sphere*/
    P.x = r*sin(theta)*cos(phi);

    P.y = r * sin(theta) *sin(phi);

    P.z = r * cos(theta);

    direction[index] = VectorSubtract(P, Center_of_Sphere);

    VectorNormalize(direction[index]);

    /*direction is just a list that will store ray directions */
    johnnash, Feb 28, 2008
    #1
    1. Advertising

  2. johnnash

    Eric Sosman Guest

    johnnash wrote:
    > In my project I need to shoot rays from the source.I know you cannot
    > follow all the rays from the source as you can actually shoot rays at
    > infinite angles,therefore my plan is to launch rays from the
    > trasmitter in all directions spaced eg. x degrees or something. This
    > is the logic I have used for a C program -
    >
    > consider the source to be centre of the unit sphere.
    >
    > 0<=theta<=180(zenith)
    > 0<=phi<=360 (azimuth)
    >
    > Then run a for loop like this -
    >
    > for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
    > degree difference or there will be infinite rays */
    > for( phi = 0; phi <=360; phi = phi + 5 )
    > {
    > /*Calculate the cartesian coordinates of a point p(a struct) on
    > sphere*/
    > P.x = r*sin(theta)*cos(phi);
    >
    > P.y = r * sin(theta) *sin(phi);
    >
    > P.z = r * cos(theta);
    >
    > direction[index] = VectorSubtract(P, Center_of_Sphere);
    >
    > VectorNormalize(direction[index]);
    >
    > /*direction is just a list that will store ray directions */


    What's your question?

    Your outline looks all right, but there are a few
    points worth mentioning:

    1) C's trigonometric functions work in radians, not
    in degrees, so the code as written will not give the
    results you presumably expect. Multiply each argument
    by pi/180 before passing it to sin() or cos().

    2) Your phi steps from 0 degrees up to and including
    360 degrees. Since 0 and 360 are the same angle, each
    zenith has one ray that's shot twice.

    3) It is not good to worry too much about efficiency,
    but some features of your code are so inefficient that
    I can't resist pointing them out. In the inner loop you
    evaluate sin(theta) twice and cos(theta) once -- but
    theta remains unchanged while phi steps all around the
    circle, so you get the same pair of answers over and over
    again. Instead, consider calculating the functions of
    theta once before entering the phi loop:

    for (theta = 0; theta <= 180; theta += 5) {
    double sint = sin(pi / 180 * theta);
    double cost = cos(pi / 180 * theta);
    for (phi = 0; phi < 360; phi += 5) {
    P.x = r * sint * cos(pi / 180 * phi);
    P.y = r * sint * sin(pi / 180 * phi);
    P.z = r * cost;
    ...

    3b) To avoid even more function evaluations, consider
    interchanging the theta and phi loops and pre-calculating
    sin(pi / 180 * phi) and cos(pi / 180 * phi) instead. (In
    the inner theta loop, you would of course call sin() only
    once.)

    4) Since you say you're using a unit sphere, I imagine
    that r == 1 -- in which case, why bother multiplying by it?

    --
    Eric Sosman, Feb 28, 2008
    #2
    1. Advertising

  3. johnnash

    johnnash Guest

    On Feb 28, 11:55 pm, Eric Sosman <> wrote:
    > johnnash wrote:
    > > In my project I need to shoot rays from the source.I know you cannot
    > > follow all the rays from the source as you can actually shoot rays at
    > > infinite angles,therefore my plan is to launch rays from the
    > > trasmitter in all directions spaced eg. x degrees or something. This
    > > is the logic I have used for a C program -

    >
    > > consider the source to be centre of the unit sphere.

    >
    > > 0<=theta<=180(zenith)
    > > 0<=phi<=360 (azimuth)

    >
    > > Then run a for loop like this -

    >
    > > for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
    > > degree difference or there will be infinite rays */
    > > for( phi = 0; phi <=360; phi = phi + 5 )
    > > {
    > > /*Calculate the cartesian coordinates of a point p(a struct) on
    > > sphere*/
    > > P.x = r*sin(theta)*cos(phi);

    >
    > > P.y = r * sin(theta) *sin(phi);

    >
    > > P.z = r * cos(theta);

    >
    > > direction[index] = VectorSubtract(P, Center_of_Sphere);

    >
    > > VectorNormalize(direction[index]);

    >
    > > /*direction is just a list that will store ray directions */

    >
    > What's your question?
    >
    > Your outline looks all right, but there are a few
    > points worth mentioning:
    >
    > 1) C's trigonometric functions work in radians, not
    > in degrees, so the code as written will not give the
    > results you presumably expect. Multiply each argument
    > by pi/180 before passing it to sin() or cos().
    >
    > 2) Your phi steps from 0 degrees up to and including
    > 360 degrees. Since 0 and 360 are the same angle, each
    > zenith has one ray that's shot twice.
    >
    > 3) It is not good to worry too much about efficiency,
    > but some features of your code are so inefficient that
    > I can't resist pointing them out. In the inner loop you
    > evaluate sin(theta) twice and cos(theta) once -- but
    > theta remains unchanged while phi steps all around the
    > circle, so you get the same pair of answers over and over
    > again. Instead, consider calculating the functions of
    > theta once before entering the phi loop:
    >
    > for (theta = 0; theta <= 180; theta += 5) {
    > double sint = sin(pi / 180 * theta);
    > double cost = cos(pi / 180 * theta);
    > for (phi = 0; phi < 360; phi += 5) {
    > P.x = r * sint * cos(pi / 180 * phi);
    > P.y = r * sint * sin(pi / 180 * phi);
    > P.z = r * cost;
    > ...
    >
    > 3b) To avoid even more function evaluations, consider
    > interchanging the theta and phi loops and pre-calculating
    > sin(pi / 180 * phi) and cos(pi / 180 * phi) instead. (In
    > the inner theta loop, you would of course call sin() only
    > once.)
    >
    > 4) Since you say you're using a unit sphere, I imagine
    > that r == 1 -- in which case, why bother multiplying by it?
    >
    > --
    >


    Thank you very much. However I did not understand the 2nd point.
    johnnash, Feb 28, 2008
    #3
  4. johnnash

    Micah Cowan Guest

    johnnash wrote:
    > On Feb 28, 11:55 pm, Eric Sosman <> wrote:
    >> johnnash wrote:
    >>> for( phi = 0; phi <=360; phi = phi + 5 )


    >> 2) Your phi steps from 0 degrees up to and including
    >> 360 degrees. Since 0 and 360 are the same angle, each
    >> zenith has one ray that's shot twice.


    > Thank you very much. However I did not understand the 2nd point.


    There are 360 degrees to a circle. 0 through 360 is 361. Shooting at phi
    == 0 and again at phi == 360 is exactly the same as shooting at phi == 0
    twice.

    You want that for statement to begin like:
    for (phi = 0; phi < 360; phi += 5)
    ^^^
    rather than with <=.

    --
    Micah J. Cowan
    Programmer, musician, typesetting enthusiast, gamer...
    http://micah.cowan.name/
    Micah Cowan, Feb 28, 2008
    #4
  5. johnnash

    Coos Haak Guest

    Op Thu, 28 Feb 2008 10:31:20 -0800 (PST) schreef johnnash:

    > In my project I need to shoot rays from the source.I know you cannot
    > follow all the rays from the source as you can actually shoot rays at
    > infinite angles,therefore my plan is to launch rays from the
    > trasmitter in all directions spaced eg. x degrees or something. This
    > is the logic I have used for a C program -
    >
    > consider the source to be centre of the unit sphere.
    >
    > 0<=theta<=180(zenith)

    0<=theta<=90 is enough.
    --
    Coos
    Coos Haak, Feb 28, 2008
    #5
  6. johnnash

    Thad Smith Guest

    johnnash wrote:
    > In my project I need to shoot rays from the source.I know you cannot
    > follow all the rays from the source as you can actually shoot rays at
    > infinite angles,therefore my plan is to launch rays from the
    > trasmitter in all directions spaced eg. x degrees or something. This
    > is the logic I have used for a C program -
    >
    > consider the source to be centre of the unit sphere.
    >
    > 0<=theta<=180(zenith)
    > 0<=phi<=360 (azimuth)
    >
    > Then run a for loop like this -
    >
    > for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
    > degree difference or there will be infinite rays */
    > for( phi = 0; phi <=360; phi = phi + 5 )
    > {
    > /*Calculate the cartesian coordinates of a point p(a struct) on
    > sphere*/


    Be aware that the distribution you get with this approach will not be
    uniform. You will have a hot spot at 90 degrees zenith darkening as your
    angle approaches 0 and 180 degrees.

    I am not a graphics programmer, but I think to get a uniform distribution,
    you should aim each vector at an equal-size portion of a sphere at a given
    distance. You could do this, for each zenith angle, by going around a
    circle on a unit sphere at equal spacing.

    --
    Thad
    Thad Smith, Feb 29, 2008
    #6
  7. johnnash <> writes:
    > In my project I need to shoot rays from the source.I know you cannot
    > follow all the rays from the source as you can actually shoot rays at
    > infinite angles,therefore my plan is to launch rays from the
    > trasmitter in all directions spaced eg. x degrees or something. This
    > is the logic I have used for a C program -
    >
    > consider the source to be centre of the unit sphere.
    >
    > 0<=theta<=180(zenith)
    > 0<=phi<=360 (azimuth)
    >
    > Then run a for loop like this -
    >
    > for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
    > degree difference or there will be infinite rays */
    > for( phi = 0; phi <=360; phi = phi + 5 )
    > {

    [snip]

    Your rays are spaced much more tightly near the poles than near the
    equator. If your sphere were the surface of the Earth, then on the
    equator you'd have one ray about every 550 kilometers. On the circle
    5 degrees from either pole, your rays are less than 50 kilometers
    apart. And at the pole itself, you have 72 rays at the same spot.

    Computing N points on a sphere that are perfectly equally placed is
    tricky, and likely impossible for most values of N. But you can vary
    the number of points on each parallel of latitude should give you
    decent results.

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 29, 2008
    #7
  8. johnnash

    Ernie Wright Guest

    Thad Smith wrote:

    > johnnash wrote:
    >
    >> In my project I need to shoot rays from the source. [...]
    >>
    >> consider the source to be centre of the unit sphere.
    >>
    >> 0<=theta<=180(zenith)
    >> 0<=phi<=360 (azimuth)
    >>
    >> Then run a for loop like this -
    >>
    >> for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
    >> degree difference or there will be infinite rays */
    >> for( phi = 0; phi <=360; phi = phi + 5 )

    >
    > Be aware that the distribution you get with this approach will not be
    > uniform. You will have a hot spot at 90 degrees zenith darkening as
    > your angle approaches 0 and 180 degrees.
    >
    > I am not a graphics programmer, but I think to get a uniform
    > distribution, you should aim each vector at an equal-size portion of a
    > sphere at a given distance. You could do this, for each zenith angle,
    > by going around a circle on a unit sphere at equal spacing.


    There are a number of ways to approach this. One would be to scale the
    steps in phi by the sine of theta,

    for ( phi = 0; phi < 360; phi += 5.0 / sin( theta )) ...

    The poles, where theta = 0 or 180, are treated as a special case, since
    there's no need to test different increments of phi.

    A better way would be to use the vertex coordinates of a spherical
    tessellation. The icosahedron is a roughly spherical shape made of 12
    equally spaced vertices and 20 equilateral triangles. You can use the
    3D cartesian coordinates of the vertices directly as a uniform sample of
    the unit sphere. For a higher sampling rate, subdivide each triangle.

    The OP desperately needs to acquaint himself with the fundamentals of
    3D graphics. Basic raytracing in particular is well understood, well
    documented, and thoroughly covered in any good first-semester college
    course on 3D. The textbooks used in those courses would be a *much*
    better source of information than c.l.c.

    - Ernie http://home.comcast.net/~erniew
    Ernie Wright, Feb 29, 2008
    #8
  9. johnnash

    johnnash Guest

    On Feb 29, 10:29 am, Thad Smith <> wrote:
    > johnnash wrote:
    > > In my project I need to shootraysfrom the source.I know you cannot
    > > follow all theraysfrom the source as you can actually shootraysat
    > > infinite angles,therefore my plan is to launchraysfrom the
    > > trasmitter in all directions spaced eg. x degrees or something. This
    > > is the logic I have used for a C program -

    >
    > > consider the source to be centre of the unit sphere.

    >
    > > 0<=theta<=180(zenith)
    > > 0<=phi<=360 (azimuth)

    >
    > > Then run a for loop like this -

    >
    > > for( theta = 0 ; theta <=180; theta = theta + 5 ) /* taking some 5
    > > degree difference or there will be infiniterays*/
    > > for( phi = 0; phi <=360; phi = phi + 5 )
    > > {
    > > /*Calculate the cartesian coordinates of a point p(a struct) on
    > > sphere*/

    >
    > Be aware that the distribution you get with this approach will not be
    > uniform. You will have a hot spot at 90 degrees zenith darkening as your
    > angle approaches 0 and 180 degrees.
    >
    > I am not a graphics programmer, but I think to get a uniform distribution,
    > you should aim each vector at an equal-size portion of a sphere at a given
    > distance. You could do this, for each zenith angle, by going around a
    > circle on a unit sphere at equal spacing.
    >
    > --
    > Thad


    I thought what would actually happen over here is that I would get a
    thicker density of rays near the poles as opposed to when zenith
    becomes 90
    johnnash, Mar 5, 2008
    #9
  10. johnnash

    johnnash Guest


    > There are a number of ways to approach this. One would be to scale the
    > steps in phi by the sine of theta,
    >
    > for ( phi = 0; phi < 360; phi += 5.0 / sin( theta )) ...
    >
    > The poles, where theta = 0 or 180, are treated as a special case, since
    > there's no need to test different increments of phi.
    >


    why increment phi in steps of sin(theta) ?? if we do this, then when
    zenith is 90, the rays will far apart whereas near the poles, they
    would be bundled closely and there will be a very thick density.
    johnnash, Mar 5, 2008
    #10
  11. johnnash

    Ernie Wright Guest

    johnnash wrote:

    >>There are a number of ways to approach this. One would be to scale the
    >>steps in phi by the sine of theta,
    >>
    >> for ( phi = 0; phi < 360; phi += 5.0 / sin( theta )) ...
    >>
    >>The poles, where theta = 0 or 180, are treated as a special case, since
    >>there's no need to test different increments of phi.

    >
    > why increment phi in steps of sin(theta) ?? if we do this, then when
    > zenith is 90, the rays will far apart whereas near the poles, they
    > would be bundled closely and there will be a very thick density.


    It depends on how you define your angles. If sine doesn't work, you can
    use cosine (which is actually more common).

    - Ernie http://home.comcast.net/~erniew
    Ernie Wright, Mar 5, 2008
    #11
  12. johnnash

    johnnash Guest

    On Mar 5, 7:09 pm, Ernie Wright <> wrote:
    > johnnash wrote:
    > >>There are a number of ways to approach this. One would be to scale the
    > >>steps in phi by the sine of theta,

    >
    > >> for ( phi = 0; phi < 360; phi += 5.0 / sin( theta )) ...

    >
    > >>The poles, where theta = 0 or 180, are treated as a special case, since
    > >>there's no need to test different increments of phi.

    >
    > > why increment phi in steps of sin(theta) ?? if we do this, then when
    > > zenith is 90, the rays will far apart whereas near the poles, they
    > > would be bundled closely and there will be a very thick density.

    >
    > It depends on how you define your angles. If sine doesn't work, you can
    > use cosine (which is actually more common).
    >
    > - Ernie http://home.comcast.net/~erniew


    ok i think i understood. may be what you are trying to say is that the
    rays tend to bundled along the poles(i.e. theta = 0 and 180) so what
    we do is we increment phi by greater values near pole. because when
    theta is closer to zero or 180, the sine value will be very low
    resulting in a very high value of 5 / sin(theta) ?? but at theta = 90
    which represents the equatior, increment is only 5 degree..
    johnnash, Mar 5, 2008
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. joon
    Replies:
    1
    Views:
    511
    Roedy Green
    Jul 8, 2003
  2. Dan

    correct or not correct?

    Dan, Oct 2, 2003, in forum: HTML
    Replies:
    7
    Views:
    433
  3. J.Ram
    Replies:
    7
    Views:
    640
  4. Dhananjay
    Replies:
    0
    Views:
    731
    Dhananjay
    Mar 26, 2009
  5. froil
    Replies:
    12
    Views:
    304
    Gunnar Hjalmarsson
    Mar 2, 2006
Loading...

Share This Page