POV-Ray : Newsgroups : povray.advanced-users : testing if a provided string matches strings in array Server Time
29 Jun 2024 02:00:53 EDT (-0400)
  testing if a provided string matches strings in array (Message 1 to 5 of 5)  
From: Kene
Subject: testing if a provided string matches strings in array
Date: 30 Sep 2009 04:25:00
Message: <web.4ac31453c0c633cf772dd76f0@news.povray.org>
I have been trying to build a macro that will help place a povray object using a
relative coordinate system. My idea is to support 3 types of objects namely
Cylinder, box and sphere. Each of these will use 3 arrays. 1 to save the
objects, 2 to save their current coordinates and 3 to save an id. Each object
has a specified format and a predictable number of vectors. Using their id in
the id array the macro should be able to determine the coordinates for each
object from the corresponding Coordinates and Objects arrays.

I have implemented this for the cylinder object i.e. creation of the cylinder
and capturing the object, coordinates and id. I plan next to have a micro that
can locate and place the cylinder in the scene and another micro that can locate
it and put it in reference to another object in the scene.

My problem is that I cannot seem to wrap my mind around testing for the cylinder
id in the Cylinder_Id array. Can somebody help me out here? I have included the
code so far. Any help will be appreciated.

Kene

----------------------
#include "colors.inc"
#include "arrays.inc"

/*+++++++++++++++ Fundamental declarations ++++++++++++++*/
#declare Floor_Surface = 0;

/*+++++++++++++++ Capturing Cylinders +++++++++++++++*/
#declare Cylinder_Loc = 7; //parameters for cylinder location properties
#declare Cylinder_Loc_I = 0; //count for adding cylinder location parameters
#declare Cylinder_Num = 1; //count for incrementing stored cylinder index
#declare Cylinder_Num_I = 0; //count for incrementing stored cylinder index
#declare Cylinder_Id = 1; //count for incrementing stored cylinder index
#declare Cylinder_Id_I = 0; //count for incrementing stored cylinder index
#declare Cylinder_Objects = array[ Cylinder_Num ] //holding cylinder objects
#declare Cylinder_Objects_Loc = array[ Cylinder_Loc ] //holding properties
#declare Cylinder_Objects_Id = array[ Cylinder_Id ] //holding id

//saving cylinder object
#macro Cylinder_Num_Incr()
  #declare Cylinder_Num_I = Cylinder_Num_I + 1;
#end

#macro Save_Cylinder( Object )
  #declare Cylinder_Objects[ Cylinder_Num_I ] = Object;
  Cylinder_Num_Incr()
  #declare Cylinder_Num = Cylinder_Num + Cylinder_Num_I;
  Resize_Array( Cylinder_Objects, Cylinder_Num )
#end

//saving cylinder location
#macro Cylinder_Loc_Incr()
  #declare Cylinder_Loc_I = Cylinder_Loc_I + 1;
#end

#macro Save_Cylinder_Loc( X1, Y1, Z1, X2, Y2, Z2, Radius )
  #declare Cylinder_Objects_Loc[ Cylinder_Loc_I ] = X1;
  Cylinder_Loc_Incr()
  #declare Cylinder_Objects_Loc[ Cylinder_Loc_I ] = Y1;
  Cylinder_Loc_Incr()
  #declare Cylinder_Objects_Loc[ Cylinder_Loc_I ] = Z1;
  Cylinder_Loc_Incr()
  #declare Cylinder_Objects_Loc[ Cylinder_Loc_I ] = X2;
  Cylinder_Loc_Incr()
  #declare Cylinder_Objects_Loc[ Cylinder_Loc_I ] = Y2;
  Cylinder_Loc_Incr()
  #declare Cylinder_Objects_Loc[ Cylinder_Loc_I ] = Z2;
  Cylinder_Loc_Incr()
  #declare Cylinder_Objects_Loc[ Cylinder_Loc_I ] = Radius;
  Cylinder_Loc_Incr()
  #declare Cylinder_Loc = Cylinder_Loc + Cylinder_Loc_I;
  Resize_Array( Cylinder_Objects_Loc, Cylinder_Loc )
#end

//saving cylinder id
#macro Cylinder_Id_Incr()
  #declare Cylinder_Id_I = Cylinder_Id_I + 1;
#end

#macro Save_Cylinder_Id( Object_Name )
  #declare Cylinder_Objects_Id[ Cylinder_Id_I ] = "Object_Name";
  Cylinder_Id_Incr()
/*  #declare Cylinder_Objects_Id[ Cylinder_Id_I ] = "Object_Description";
  Cylinder_Id_Incr()*/
  #declare Cylinder_Id = Cylinder_Id + Cylinder_Id_I;
  Resize_Array( Cylinder_Objects_Id, Cylinder_Id )
#end

/*+++++++++++++++ building a Cylinder ++++++++++++++++*/
#macro Make_Cylinder( Name, Radius, Height )
  #local Base_PointX = 0;                //x value at base of cylinder
  #local Base_PointY = Floor_Surface;    //y value at base of cylinder
  #local Base_PointZ = 0;                //z value at base of cylinder
  #local Cap_PointX = 0;                 //x value at top of cylinder
  #local Cap_PointY = Base_PointY + Height; //y value at top of cylinder
  #local Cap_PointZ = 0;                 //z value at top of cylinder
  #local Cylinder_Radius = Radius;       //radius of cylinder
  #local Base_Point = <Base_PointX, Base_PointY, Base_PointZ>;
  #local Cap_Point = <Cap_PointX, Cap_PointY, Cap_PointZ>;
  #local Cylinder_Obj = cylinder{ Base_Point, Cap_Point, Cylinder_Radius }
  Save_Cylinder( Cylinder_Obj ) //save object without any texture
  Save_Cylinder_Loc( Base_PointX, Base_PointY, Base_PointZ, Cap_PointX,
Cap_PointY, Cap_PointZ, Cylinder_Radius ) //Cylinder always needs 7 parameters
  Save_Cylinder_Id( Name ) //ID for recognizing this cylinder for recollection
#end

/*+++++++++++++++ Manupulating a Cylinder ++++++++++++++++
CAN'T FIGURE THIS FOR NOW*/
#macro Put_Cylinder( Name, XPos, YPos, ZPos )
  #local Count = 0;
  #while ( Count < Cylinder_Id )
    #if( strcmp( Cylinder_Objects_Id[ Count ], Name)=0)
      #debug Cylinder_Objects_Id[ Count ]
    #else
      #debug Cylinder_Objects_Id[ Count ]
    #end
    #declare Count = Count + 1;
  #end
#end

/*++++++++++++++++++++Start test commands+++++++++++++++++++*/
light_source{ <-20, 400, -20> color White }
camera{ location <20, 20, -30> look_at 0 }
plane{ y, 0 pigment{ color Yellow }}


Make_Cylinder( "FirstCyl", 5, 10 ) // create first cylinder
Make_Cylinder( "SecondCyl", 10, 6 ) // create second cylinder... testing
Put_Cylinder( "FirstCyl", 0, 0, 0 ) //put cylinder in scene without reference


Post a reply to this message

From: Chris B
Subject: Re: testing if a provided string matches strings in array
Date: 30 Sep 2009 06:06:57
Message: <4ac32dc1@news.povray.org>
"Kene" <nomail@nomail> wrote in message 
news:web.4ac31453c0c633cf772dd76f0@news.povray.org...
>I have been trying to build a macro that will help place a povray object 
>using a
> relative coordinate system.
> ...
> My problem is that I cannot seem to wrap my mind around testing for the 
> cylinder
> id in the Cylinder_Id array. Can somebody help me out here?
>

Hi Kene,

The error you get in the message stream at the moment is "Attempt to access 
uninitialized array element". This is because your Save_Cylinder_Id macro 
adds to the size of the array after adding the last element, so there's 
always an empty array element at the end of the array. You can avoid testing 
the last element by using:

  #while ( Count < Cylinder_Id-Cylinder_Id_I)


It also adds "Object_Name" inside quotes to the array, which adds that 
string to the array, not the contents of the identifier Object_Name. This 
means your test for the actual object name is never successful. So you'd 
need:

  #declare Cylinder_Objects_Id[ Cylinder_Id_I ] = Object_Name;


But I have a more general concern that you're making life far more 
complicated for yourself than it needs to be. If you were working in a 
computer language with a full trace and debug toolset then indexing problems 
like this would be easy enough to trace through, but you don't have anything 
more powerful than the #debug statement to get you through this in POV-Ray. 
I'd recommend using more of the powerful features of POV-Ray SDL to vastly 
simplifying what you've got before going any further.

Anywhere you've got a macro for 1 or 2 lines of code I'd recommend 
eliminating it.

There's no need to keep so many different indices. You can store 3D vectors 
inside arrays and you can have multi-dimensional arrays, so you can store a 
start vector and an end vector in the same array:

#declare Cylinder_Locations = array [5][2];
#declare Cylinder_Locations[0][0] = <1,2,3>;
#declare Cylinder_Locations[0][1] = <4,5,6>;

This means you only need one index for all the cylinder arrays.

You can still access individual vector components e.g.
Cylinder_Locations[0,1].y
gives you the value '5'

So the whole Save_Cylinder_Loc macro comes down to 2 lines, at which point 
I'd scrap the macro altogether and simply inline the code.

It seems excessive to keep resizing the array (a relatively expensive 
option) each time you add an element. I don't think empty arrays take up 
much memory in POV-Ray, so you could declare your arrays with sufficient 
elements at the start and cut down on render times and on the amount of code 
you need to debug.

When using debug I'd recommend using it with the 'concat' function to help 
make messages stand out better in the message stream. Eg:

      #debug concat("Match: ",Cylinder_Objects_Id[ Count ],"\n")
      #debug concat("No Match: ",Cylinder_Objects_Id[ Count ],"\n")

I can offer more advice if you'd like, but it already sounds like I'm 
banging on a bit. :-)

Regards,
Chris B.


Post a reply to this message

From: Kene
Subject: Re: testing if a provided string matches strings in array
Date: 30 Sep 2009 07:25:01
Message: <web.4ac33fedf217dc18772dd76f0@news.povray.org>
> It also adds "Object_Name" inside quotes to the array, which adds that
> string to the array, not the contents of the identifier Object_Name. This
> means your test for the actual object name is never successful. So you'd
> need:
>
>   #declare Cylinder_Objects_Id[ Cylinder_Id_I ] = Object_Name;
>
>

I tried this but kept getting errors. But I will try it again

> But I have a more general concern that you're making life far more
> complicated for yourself than it needs to be. If you were working in a
> computer language with a full trace and debug toolset then indexing problems
> like this would be easy enough to trace through, but you don't have anything
> more powerful than the #debug statement to get you through this in POV-Ray.
> I'd recommend using more of the powerful features of POV-Ray SDL to vastly
> simplifying what you've got before going any further.

Yes I totally agree. I have a tight schedule but really could not help diving
in. I know there are terribly mistakes as I have not used POV consistently over
the years... but so long as I was stumbling along... I will try to calm down a
bit. Your comments are invaluable though. I was really getting drowned.

>
> Anywhere you've got a macro for 1 or 2 lines of code I'd recommend
> eliminating it.
>
> There's no need to keep so many different indices. You can store 3D vectors
> inside arrays and you can have multi-dimensional arrays, so you can store a
> start vector and an end vector in the same array:
>
> #declare Cylinder_Locations = array [5][2];
> #declare Cylinder_Locations[0][0] = <1,2,3>;
> #declare Cylinder_Locations[0][1] = <4,5,6>;
>
> This means you only need one index for all the cylinder arrays.
>
> You can still access individual vector components e.g.
> Cylinder_Locations[0,1].y
> gives you the value '5'
>
> So the whole Save_Cylinder_Loc macro comes down to 2 lines, at which point
> I'd scrap the macro altogether and simply inline the code.
>

This would be beautiful!

> It seems excessive to keep resizing the array (a relatively expensive
> option) each time you add an element. I don't think empty arrays take up
> much memory in POV-Ray, so you could declare your arrays with sufficient
> elements at the start and cut down on render times and on the amount of code
> you need to debug.
>

Sigh!

> When using debug I'd recommend using it with the 'concat' function to help
> make messages stand out better in the message stream. Eg:
>
>       #debug concat("Match: ",Cylinder_Objects_Id[ Count ],"\n")
>       #debug concat("No Match: ",Cylinder_Objects_Id[ Count ],"\n")
>

Thanks


Post a reply to this message

From: Chris B
Subject: Re: testing if a provided string matches strings in array
Date: 30 Sep 2009 07:41:27
Message: <4ac343e7@news.povray.org>
"Chris B" <nom### [at] nomailcom> wrote in message 
news:4ac32dc1@news.povray.org...
> But I have a more general concern that you're making life far more 
> complicated for yourself than it needs to be..........

I couldn't resist the temptation to fiddle with the code a little. The code 
below does the same thing in a way that I think is far simpler, using a 
single array index for the different arrays. I've split out the Location and 
Radius arrays so that locations can be stored as 2x3D vectors in a 2D array.

Doing this makes the macros you had so simple (2 or 3 lines each) that I've 
combined them into a single macro. I added a Type parameter to illustrate 
how you might be able to make this quite generic, potentially avoiding 
having to have separate macros for different shapes. You may find this 
approach useful when moving on to less primitive object types.

Regards,
Chris B.

#include "colors.inc"

/*+++++++++++++++ Fundamental declarations ++++++++++++++*/
#declare Floor_Surface = 0;

/*+++++++++++++++ Capturing Cylinders +++++++++++++++*/
#declare Component_ArraySize = 2000;
#declare Component_Index = -1;
#declare Component_Objects      = array[Component_ArraySize]    // Cylinder 
objects
#declare Component_Objects_Loc  = array[Component_ArraySize][2] // Locations
#declare Component_Objects_Rad  = array[Component_ArraySize]    // Radii
#declare Component_Objects_Id   = array[Component_ArraySize]    // Id
#declare Component_Objects_Type = array[Component_ArraySize]    // Type

// Save object
#macro Save_Object (Name, Type, Obj, Start, End, Radius)
  #declare Component_Index = Component_Index+1;
  #declare Component_Objects[Component_Index] = Obj;
  #declare Component_Objects_Loc[Component_Index][0] = Start;
  #if (strcmp(Type,"Cylinder")=0 | strcmp(Type,"Cone")=0)
    #declare Component_Objects_Loc[Component_Index][1] = End;
  #end
  #declare Component_Objects_Rad[Component_Index]    = Radius;
  #declare Component_Objects_Id[Component_Index] = Name;
  #declare Component_Objects_Type[Component_Index] = Type;
#end

/*+++++++++++++++ building a Cylinder ++++++++++++++++*/
#macro Make_Cylinder( Name, Radius, Height )
  #local Base_PointX = 0;                //x value at base of cylinder
  #local Base_PointY = Floor_Surface;    //y value at base of cylinder
  #local Base_PointZ = 0;                //z value at base of cylinder
  #local Cap_PointX = 0;                 //x value at top of cylinder
  #local Cap_PointY = Base_PointY + Height; //y value at top of cylinder
  #local Cap_PointZ = 0;                 //z value at top of cylinder
  #local Component_Radius = Radius;       //radius of cylinder
  #local Base_Point = <Base_PointX, Base_PointY, Base_PointZ>;
  #local Cap_Point = <Cap_PointX, Cap_PointY, Cap_PointZ>;
  #local Component_Obj = cylinder{ Base_Point, Cap_Point, Component_Radius }

  Save_Object(Name, "Cylinder", Component_Obj, Base_Point, Cap_Point, 
Radius)
#end

/*+++++++++++++++ Manupulating a Cylinder ++++++++++++++++*/
#macro Put_Cylinder( Name, XPos, YPos, ZPos )
  #local Count = 0;
  #while ( Count < Component_Index)
    #if( strcmp( Component_Objects_Id[ Count ], Name)=0)
      Component_Objects[Count]
      #debug concat("Match: ",Component_Objects_Id[ Count ],"\n")
    #else
      #debug concat("No Match: ",Component_Objects_Id[ Count ],"\n")
    #end
    #declare Count = Count + 1;
  #end
#end

/*++++++++++++++++++++Start test commands+++++++++++++++++++*/
light_source{ <-20, 400, -20> color White }
camera{ location <20, 20, -30> look_at 0 }
plane{ y, 0 pigment{ color Yellow }}


Make_Cylinder( "FirstCyl", 5, 10 ) // create first cylinder
Make_Cylinder( "SecondCyl", 10, 6 ) // create second cylinder... testing
Put_Cylinder( "FirstCyl", 0, 0, 0 ) //put cylinder in scene without 
reference


Post a reply to this message

From: Kene
Subject: Re: testing if a provided string matches strings in array
Date: 30 Sep 2009 09:00:01
Message: <web.4ac3552cf217dc18772dd76f0@news.povray.org>
"Chris B" <nom### [at] nomailcom> wrote:
> "Chris B" <nom### [at] nomailcom> wrote in message
> news:4ac32dc1@news.povray.org...
> > But I have a more general concern that you're making life far more
> > complicated for yourself than it needs to be..........
>
> I couldn't resist the temptation to fiddle with the code a little. The code
> below does the same thing in a way that I think is far simpler, using a
> single array index for the different arrays. I've split out the Location and
> Radius arrays so that locations can be stored as 2x3D vectors in a 2D array.
>

Needless to say Chris... I have no words to express my gratitude. You've set me
up really sweetly! If only I could buy you pizza or something...


Post a reply to this message

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