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 ];
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;
}
:
:
}
This patch was designed only for reading values. Returned vector should be adjusted with correct number of components according to components of spline.