Array-like access to Spline


Why it is introduced

   This patch was proposed by the Ingo in post posted on news.povray.org. The main idea is to allow asking about dimension_size of spline as well as for time parameter and vector result at control points. So the syntax with below patch can be now:

SPLINE_USAGE:
  SPLINE_EVALUATION | SPLINE_MEASUREMENT | SPLINE_ENTRY

SPLINE_EVALUATION:
  #declare Spline_Value = MySpline(Val);
  #declare Spline_Value = MySpline(Val, SPLINE_TYPE);

SPLINE_MEASUREMENT:
  #declare Number_Of_Entries = dimension_size( MySpline );

SPLINE_ENTRY:
  #declare Float_Time_Parameter = MySpline[ Counter ][ 0 ];
  #declare Vector_Value_Of_Entry = MySpline[ Counter ][ 1 ];

How it is implemented

   All I need was to recognize some additional tokens and adjust number of terms returned in express.cpp file. First I turned on functionality of returning values for entries. There is function Parse_Spline_Call responsible for returning values when spline identifier is found in expression. There is only one expectation (LEFT_PAREN_TOKEN) in this function so I have to introduce whole expectation block. Validation for array subscript was copied from parsing 'real' array entry.

void Parse_Spline_Call(EXPRESS Express, int *Terms)
{
    SPLINE *spline = (SPLINE*)(Token.Data);
    DBL Val;
    int j,k;

    EXPECT
        CASE (LEFT_PAREN_TOKEN)
            Val=Parse_Float();
            Get_Token();

            if(Token.Token_Id == COMMA_TOKEN)
                {
                    /*If there is a second parameter, make a copy of the spline
                    with a new type and evaluate that.*/
                    spline = Copy_Spline(spline);
                    Get_Token();
                    switch(Token.Token_Id)
                    {
                        case LINEAR_SPLINE_TOKEN:
                            spline->Type = LINEAR_SPLINE;
                            break;
                        case QUADRATIC_SPLINE_TOKEN:
                            spline->Type = QUADRATIC_SPLINE;
                            break;
                        case CUBIC_SPLINE_TOKEN:
                            spline->Type = CATMULL_ROM_SPLINE;
                            break;
                        case NATURAL_SPLINE_TOKEN:
                            spline->Type = NATURAL_SPLINE;
                            break;
                        default:
                            Error("linear_spline, quadratic_spline, natural_spline, or cubic_spline expected.");
                            break;
                    }
                    GET(RIGHT_PAREN_TOKEN);
                    Get_Spline_Val(spline, Val, Express, Terms);
                    Destroy_Spline(spline);
                    spline = NULL;
                }
            else
                {
                    UNGET
                    GET(RIGHT_PAREN_TOKEN);
                    Get_Spline_Val(spline, Val, Express, Terms);
                }
            EXIT
        END_CASE
        CASE (LEFT_SQUARE_TOKEN)
            Val=Parse_Float();
            k=(int)(1.0e-08+Val);
            if ((k < 0) || (Val < -1.0e-08))
            {
                Error("Negative subscript");
            }
            if (k >= spline->Number_Of_Entries)
            {
                Error("Spline-Array subscript out of range");
            }
            GET(RIGHT_SQUARE_TOKEN);
            GET(LEFT_SQUARE_TOKEN);
            if ((int)Parse_Float())
            {
                *Terms = spline->Terms;
                for(j=0; j<spline->Terms; j++)
                {
                    Express[j]=spline->SplineEntries[k].vec[j];
                } 
            }
            else
            {
                *Terms = 1;
                Express[0]=spline->SplineEntries[k].par;
            }
            GET(RIGHT_SQUARE_TOKEN);
            EXIT
        END_CASE
        OTHERWISE
           Expectation_Error ("( or [");
        END_CASE
    END_EXPECT

}

   The second part was asking about number of entries via dimension_size. This keyword is handled in Parse_Num_Factor function so again I added some additional tokens recognition:

void Parse_Num_Factor (EXPRESS Express,int *Terms)
{
  int i = 0;
  DBL Val,Val2;
  VECTOR Vect,Vect2,Vect3;
  OBJECT *Object;  
  TRANSFORM Trans;
  TURB Turb;
  UCS2 *Local_String, *Local_String2;
  char *Local_C_String;
  POV_ISTREAM *f;
  POV_ARRAY *a;
  int Old_Ok=Ok_To_Declare;
  DBL greater_val, less_val, equal_val ;
  SPLINE *spline;

  Ok_To_Declare=true;

  EXPECT
    CASE (FLOAT_FUNCT_TOKEN)
       /* All of these functions return a DBL result */
       switch(Token.Function_Id)
         {
          case ABS_TOKEN:
          :
          :
          :
          break;

          case DIMENSION_SIZE_TOKEN:
            GET(LEFT_PAREN_TOKEN)

            EXPECT
              CASE(ARRAY_ID_TOKEN)
                Parse_Comma();
                a = (POV_ARRAY *)(*(Token.DataPtr));
                i = (int)Parse_Float()-1.0;
                if ((i < 0) || (i > a->Dims))
                  Val = 0.0;
                else
                  Val = a->Sizes[i];
                EXIT
              END_CASE
              CASE(SPLINE_ID_TOKEN)
                spline = (SPLINE*)(Token.Data); 
                Val = spline->Number_Of_Entries;
                EXIT
              END_CASE
              OTHERWISE
                Expectation_Error ("spline or array");
              END_CASE
            END_EXPECT

            GET(RIGHT_PAREN_TOKEN)
            break;

         }
       :
       :
}

Notes

   This patch was designed only for reading values. Returned vector should be adjusted with correct number of components according to components of spline.


Contact

This is an unofficial addition to POV-Ray. Do not ask the POV-Team for help with this. Feel free to send all opinions, suggestions, corrections and thanks :-) connected with this site to me
Copyright 2002 by Wlodzimierz ABX Skiba

Valid HTML 4.01!   Valid CSS!   Bobby WorldWide Approved AAA
If a thing is worth doing, it is worth doing well.