Conditional Directives

### 6.2.6 Conditional Directives

POV-Ray allows a variety of language directives to implement conditional parsing of various sections of your scene file. This is especially useful in describing the motion for animations but it has other uses as well. Also available is a `#while` loop directive. You may nest conditional directives 200 levels deep.

#### 6.2.6.1 The #if...#else...#end Directives

The simplest conditional directive is a traditional `#if` directive. It is of the form...

    IF_DIRECTIVE:
        #if ( Cond ) TOKENS... [#else TOKENS...] #end

The TOKENS are any number of POV-Ray keyword, identifiers, or punctuation and `(` Cond `)` is a float expression that is interpreted as a boolean value. The parentheses are required. The `#end` directive is required. A value of 0.0 is false and any non-zero value is true.

Note: extremely small values of about 1e-10 are considered zero in case of round off errors.

If Cond is true, the first group of tokens is parsed normally and the second set is skipped. If false, the first set is skipped and the second set is parsed. For example:

     #declare Which=1;
     #if (Which)
       box { 0, 1 }
     #else
       sphere { 0, 1 }
     #end

The box is parsed and the sphere is skipped. Changing the value of `Which` to `0` means the box is skipped and the sphere is used. The `#else` directive and second token group is optional. For example:

     #declare Which=1;
     #if (Which)
       box { 0, 1 }
     #end

Changing the value of `Which` to `0` means the box is removed.

At the beginning of the chapter "Language Directives" it was stated that "These directives can appear in almost any place in the scene file....". The following is an example where it will not work, it will confuse the parser:

       #if( #if(yes) yes #end ) #end

#### 6.2.6.2 The #ifdef and #ifndef Directives

The `#ifdef` and `#ifndef` directive are similar to the `#if` directive however they are used to determine if an identifier has been previously declared.

    IFDEF_DIRECTIVE:
        #ifdef ( IDENTIFIER ) TOKENS... [#else TOKENS...] #end
    IFNDEF_DIRECTIVE:
        #ifndef ( IDENTIFIER ) TOKENS... [#else TOKENS...] #end

If the IDENTIFIER exists then the first group of tokens is parsed normally and the second set is skipped. If false, the first set is skipped and the second set is parsed. This is especially useful for replacing an undefined item with a default. For example:

      #ifdef (User_Thing)
      // This section is parsed if the
      // identifier "User_Thing" was
      // previously declared
      object{User_Thing} // invoke identifier
     #else
      // This section is parsed if the
      // identifier "User_Thing" was not
      // previously declared
      box{<0,0,0>,<1,1,1>} // use a default
     #end
      // End of conditional part

The `#ifndef` directive works the opposite. The first group is parsed if the identifier is not defined. As with the `#if` directive, the `#else` clause is optional and the `#end` directive is required.

The `#ifdef` and `#ifndef` directives can be used to determine whether a specific element of an array has been assigned.

     #declare MyArray=array[10]
     //#declare MyArray[0]=7;
     #ifdef(MyArray[0])
        #debug "first element is assigned\n"
     #else
        #debug "first element is not assigned\n"
     #end

#### 6.2.6.3 The #switch, #case, #range and #break Directives

A more powerful conditional is the `#switch` directive. The syntax is as follows...

    SWITCH_DIRECTIVE:
       #switch ( Switch_Value ) SWITCH_CLAUSE... [#else TOKENS...] #end
    SWITCH_CLAUSE:
       #case( Case_Value ) TOKENS... [#break] |
       #range( Low_Value , High_Value ) TOKENS... [#break]

The TOKENS are any number of POV-Ray keyword, identifiers, or punctuation and `(` Switch_Value `)` is a float expression. The parentheses are required. The `#end` directive is required. The SWITCH_CLAUSE comes in two varieties. In the `#case` variety, the float Switch_Value is compared to the float Case_Value. If they are equal, the condition is true.

Note: that values whose difference is less than 1e-10 are considered equal in case of round off errors.

In the `#range` variety, Low_Value and High_Value are floats separated by a comma and enclosed in parentheses. If Low_Value <= Switch_Value and Switch_Value<=High_Value then the condition is true.

In either variety, if the clause's condition is true, that clause's tokens are parsed normally and parsing continues until a `#break`, `#else` or `#end` directive is reached. If the condition is false, POV-Ray skips until another `#case` or `#range` is found.

There may be any number of `#case` or `#range` clauses in any order you want. If a clause evaluates true but no `#break` is specified, the parsing will fall through to the next `#case` or `#range` and that clause conditional is evaluated. Hitting `#break` while parsing a successful section causes an immediate jump to the `#end` without processing subsequent sections, even if a subsequent condition would also have been satisfied.

An optional `#else` clause may be the last clause. It is only executed if the clause before it was a false clause.

Here is an example:

     #switch (VALUE)
      #case (TEST_1)
       // This section is parsed if VALUE=TEST_1
      #break //First case ends
      #case (TEST_2)
       // This section is parsed if VALUE=TEST_2
      #break //Second case ends
      #range (LOW_1,HIGH_1)
       // This section is parsed if (VALUE>=LOW_1)&(VALUE<=HIGH_1)
      #break //Third case ends
      #range (LOW_2,HIGH_2)
       // This section is parsed if (VALUE>=LOW_2)&(VALUE<=HIGH_2)
      #break //Fourth case ends
      #else
       // This section is parsed if no other case or
       // range is true.
     #end // End of conditional part

#### 6.2.6.4 The #while...#end Directive

The `#while` directive is a looping feature that makes it easy to place multiple objects in a pattern or other uses.

    WHILE_DIRECTIVE:
        #while ( Cond ) TOKENS... #end

The TOKENS are any number of POV-Ray keyword, identifiers, or punctuation marks which are the body of the loop. The `#while` directive is followed by a float expression that evaluates to a boolean value. A value of 0.0 is false and any non-zero value is true.

Note: extremely small values of about 1e-10 are considered zero in case of round off errors.

The parentheses around the expression are required. If the condition is true parsing continues normally until an `#end` directive is reached. At the end, POV-Ray loops back to the `#while` directive and the condition is re-evaluated. Looping continues until the condition fails. When it fails, parsing continues after the `#end` directive.

Note: it is possible for the condition to fail the first time and the loop is totally skipped. It is up to the user to insure that something inside the loop changes so that it eventually terminates.

Here is a properly constructed loop example:

     #declare Count=0;
     #while (Count < 5)
      object { MyObject translate x*3*Count }
      #declare Count=Count+1;
     #end

This example places five copies of `MyObject` in a row spaced three units apart in the x-direction.