Geometric

From Second Life Wiki
Jump to navigation Jump to search

I tried to minimize the script function names to be easily readable. All the geometric function names start with a g.

Here is the legend:

Shorthand Name Description
X Point vector defining a point in space
L Line A line has an origin and a direction
R Ray A ray is like a line, except it is more distinct as it can define wether it points forward or back
P Plane A two dimensional doubly ruled surface of infinite size
S Sphere A sphere is defined by origin and radius
d Distance Defines that a distance should be returned
n Nearest Calculate nearest
p Project Calculates projection
x Intersection Calculates intersection
Z Float Represents that a float is returned
V Vector Represents that a vector is returned


Original

<lsl>//===================================================// // Geometric Library 1.0 // // "May 4 2008", "2:24:30" // // Copyright (C) 2008, Nexii Malthus (cc-by) // // http://creativecommons.org/licenses/by/3.0/ // //===================================================//

vector CP(vector A,vector B){

   return A % B;}

vector Project3D(vector A,vector B){

   vector proj;
   proj.x = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.x;
   proj.y = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.y;
   proj.z = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.z;
   return proj;}

// POINT float gXXdZ(vector A,vector B){

   // Distance P2P.
   return llVecDist(A,B);}

vector gXXdV(vector A,vector B){

   // Vector to move from P2P.
   return A-B;}

// LINE vector gLXdV(vector O,vector D,vector A){

   // Calculates the vector from a point to the closest point on a line
   return (O-A)-((O-A)*D)*D;}

float gLXdZ(vector O,vector D,vector A){

   // Calculates distance of this vector, but faster on it's own
   return llSqrt(CP((A-O),D)*CP((A-O),D));}

vector gLLdV(vector O1,vector D1,vector O2,vector D2){

   // Shortest vector of two lines
   return Project3D( (O2-O1), CP(D1,D2) );}

float gLLdZ(vector O1,vector D1,vector O2,vector D2){

   // Returns the distance between two lines
   vector A = CP(D1,D2);float B = llVecMag(A);A = <A.x/B,A.y/B,A.z/B>;
   return (O2-O1) * A;}

vector gLLnX(vector O1,vector D1,vector O2,vector D2){

   // Closest point of two lines
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   return O1 + D1*t;}

vector X1;vector X2;vector V1;float Z1;

gLLnnXX(vector O1,vector D1,vector O2,vector D2){

   // Two closest points of two lines
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);}

gLLnnXXVZ(vector O1,vector D1,vector O2,vector D2){

   // Computes two closest points of two lines, vector and distance
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;
   
   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );
   
   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;
   
   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);
   V1 = CP(nD1,nD2);
   Z1 = llVecMag(V1);}

// PLANE float gPXdZ(vector Pn,float Pd,vector A){

   // Finds distance of a point from a plane
   return A * Pn + Pd;}

vector gPXdV(vector Pn,float Pd,vector A){

   // Finds vector that points from point to nearest on plane
   return -(Pn * A + Pd)*Pn;}

vector gPXnX(vector Pn,float Pd,vector A){

   // Finds closest point on plane given point
   return A - (Pn * A + Pd) * Pn;}

float gPRxZ(vector Pn,float Pd,vector O,vector D){

   // Finds distance to intersection of plane along ray
   return -( ( (Pn*D)+(Pn*O) ) / (Pn*D) );}
   //return -( (Pn*D)/(Pn*O+Pd) );}

vector gPRdV(vector Pn,float Pd,vector O,vector D){

   // Finds distance vector along a ray to a plane
   return D * gPRxZ(Pn,Pd,O,D);}
   //return -( (Pn*D)/(Pn*O+Pd) )*D;}

vector gPRxX(vector Pn,float Pd,vector O,vector D){

   // Finds intersection point along a ray to a plane
   return O + gPRdV(Pn,Pd,O,D);}

vector gPLxX(vector Pn,float Pd,vector O,vector D){

   // Finds interesection point of a line and a plane
   return O -( (Pn*D)/(Pn*O+Pd) )*D;}

vector oO;vector oD;

gPPxL(vector Pn,float Pd,vector Qn,float Qd){

   // Finds line of intersection of two planes
   oD = CP(Pn,Qn)/llVecMag(CP(Pn,Qn));
   vector Cross = CP(CP(Pn,Qn),Pn);
   vector Bleh = (-Pd*Pn);
   oO = Bleh - (Qn*Cross)/(Qn*Bleh+Qd)*Cross/llVecMag(Cross);}

float gRXpZ(vector O,vector D,vector A){

   // Finds projected distance of a point along a ray
   return (A-O)*D;}

gPRpR(vector Pn,float Pd,vector O,vector D){

   // Projects a ray onto a plane
   oO = O - (Pn * O + Pd) * Pn;
   vector t = llVecNorm( D - Project3D(D,Pn) );t = <1.0/t.x,1.0/t.y,1.0/t.z>;
   oD = CP(Pn,t);}

// SPHERE vector gSRxX(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return ZERO_VECTOR;
   
   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);
   
   float disc = b * b - 4 * a * c;
   
   if(disc < 0) return ZERO_VECTOR;
   
   float distSqrt = llSqrt(disc);
   float q;
   
   if(b < 0)
       q = (-b - distSqrt)/2.0;
   else 
       q = (-b + distSqrt)/2.0;
   
   float t0 = q / a;
   float t1 = c / q;
   
   if(t0 > t1){
       float temp = t0;
       t0 = t1;
       t1 = temp;
   }
   
   if(t1 < 0) return ZERO_VECTOR;
   
   if(t0 < 0)
       t = t1;
   else
       t = t0;
   
   return Ro + (t * Rd);

}

integer gSRx(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return FALSE;
   
   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);
   
   float disc = b * b - 4 * a * c;
   
   if(disc < 0) return FALSE;
   return TRUE;

}

// Other vector pN;float pD; gTiP(vector p1,vector p2,vector p3){

   // Turns three vector points in space into a plane
   pN = llVecNorm( CP((p2-p1),(p3-p1)) );
   pD = -p1*pN;}

integer gTXcC(vector p1,vector p2,vector p3,vector x){

   // Can be used to check wether a point is inside a triangle
   gTiP(p1,p2,p3);
   vector Vn;vector En;
       Vn = p1 - x;
       En = CP((p2-p1),pN);
   if( ((p1-x)*CP(p2-p1,pN) >= 0)&&((p2-x)*CP(p3-p2,pN) >= 0)&&((p3-x)*CP(p1-p3,pN) >= 0) ) return TRUE;
   return FALSE;}

integer gTVXcC(vector p1,vector p2,vector p3,vector v,vector x){

   if( ((p1-x)*CP(p2-p1,v) >= 0)&&((p2-x)*CP(p3-p2,v) >= 0)&&((p3-x)*CP(p1-p3,v) >= 0) ) return TRUE;
   return FALSE;}

integer gTRcC(vector p1,vector p2,vector p3,vector O,vector D){

   return gTVXcC(p1,p2,p3,O,D);}

vector gRZiX(vector O,vector D,float z){

   return O+z*D;}

default{state_entry(){}}

</lsl>

Optimized ESL

<lsl>//===================================================// // Geometric Library 1.0 Optimized ESL Build 1 // // "May 4 2008", "14:19:37" // // Copyright (C) 2008, Nexii Malthus (cc-by) // // Copyright (C) 2008, Strife Onizuka (cc-by) // // http://creativecommons.org/licenses/by/3.0/ // //===================================================//

  1. define CP(A, B) ((A) % (B))
  2. ifndef CP

vector CP(vector A,vector B){

   return A % B;}
  1. endif
  1. if 0

vector Project3D(vector A,vector B){

   vector proj;
   proj.x = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.x;
   proj.y = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.y;
   proj.z = ( (A*B) / (B.x*B.x + B.y*B.y + B.z*B.z) ) * B.z;
   return proj;}
  1. else

vector Project3D(vector A,vector B){

   return B * ((A*B) / (B*B));}
  1. endif

// POINT

  1. define gXXdZ llVecDist
  2. ifndef gXXdZ

float gXXdZ(vector A,vector B){

   // Distance P2P.
   return llVecDist(A,B);}
  1. endif
  1. define gXXdV(A,B) ((A) - (B))
  2. ifndef gXXdV

vector gXXdV(vector A,vector B){

   // Vector to move from P2P.
   return A-B;}
  1. endif

// LINE

  1. if 0

vector gLXdV(vector O,vector D,vector A){

   // Calculates the vector from a point to the closest point on a line
   return (O-A)-((O-A)*D)*D;}
  1. else

vector gLXdV(vector O,vector D,vector A){

   // Calculates the vector from a point to the closest point on a line
   vector t = (O-A);
   return t - (t*D)*D;}
  1. endif
  1. define gLXdZ(O, D, A) llVecMag(CP((A-O),D))
  2. ifndef gLXdZ

float gLXdZ(vector O,vector D,vector A){

   // Calculates distance of this vector, but faster on it's own
   return llVecMag(CP((A-O),D));}
  1. endif
  1. define gLLdV(O, D, A) Project3D( (O2-O1), CP(D1,D2) )
  2. ifndef gLLdV

vector gLLdV(vector O1,vector D1,vector O2,vector D2){

   // Shortest vector of two lines
   return Project3D( (O2-O1), CP(D1,D2) );}
  1. endif
  1. define gLLdZ(O1, D1, O2, D2) ((O2-O1) * llVecNorm(CP(D1,D2)))
  2. ifndef gLLdZ

float gLLdZ(vector O1,vector D1,vector O2,vector D2){

   // Returns the distance between two lines
   vector A = CP(D1,D2);float B = llVecMag(A);A = <A.x/B,A.y/B,A.z/B>;
   return (O2-O1) * A;}
  1. endif
  1. if 0

vector gLLnX(vector O1,vector D1,vector O2,vector D2){

   // Closest point of two lines
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;

   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );

   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;

   return O1 + D1*t;}
  1. else

vector gLLnX(vector O1,vector D1,vector O2,vector D2){

   // Closest point of two lines
   vector t = <O2*D1, O1*D2, O2*D2>;
   
   return O1 + D1 * (( t.z * ((O1*D1)-t.x) - t.x * (t.y-t.z) ) / ( t.x*t.y - (D1*D1)*t.z ));}
  1. endif

vector X1;vector X2;vector V1;float Z1;

  1. if 0

gLLnnXX(vector O1,vector D1,vector O2,vector D2){

   // Two closest points of two lines
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;

   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );

   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;

   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);}
  1. else

gLLnnXX(vector O1,vector D1,vector O2,vector D2){

   // Two closest points of two lines
   #define a (O1*D1)
   #define c (D1*D1)
   #define d (O2*D1)
   #define e (O1*D2)
   #define f (O2*D2)
   vector nD1 = < c, e, 0.0>;
   vector nD2 = < d, f, 0.0>;
   #undef c
   #undef d
   #undef e
   #undef f
   #define c nD1.x
   #define d nD2.x
   #define e nD1.y
   #define f nD2.y
   X2 = (X1 = (O1 + D1 * (( d*(a-d) - d*(e-f) ) / ( d*e - c*f )))) + CP(nD1,nD2);}
   #undef a
   #undef c
   #undef d
   #undef e
   #undef f
  1. endif
  1. if 0

gLLnnXXVZ(vector O1,vector D1,vector O2,vector D2){

   // Computes two closest points of two lines, vector and distance
   vector nO1 = < O1*D1, O1*D2, 0>;
   vector nO2 = < O2*D1, O2*D2, 0>;
   vector nD1 = < D1*D1, O1*D2, 0>;
   vector nD2 = < O2*D1, O2*D2, 0>;

   float t = ( nD2.x*nD1.y - nD1.x*nD2.y );

   t = ( nD2.y*(nO1.x-nO2.x) - nD2.x*(nO1.y-nO2.y) ) / t;

   X1 = O1 + D1*t;
   X2 = X1 + CP(nD1,nD2);
   V1 = CP(nD1,nD2);
   Z1 = llVecMag(V1);}
  1. else

gLLnnXXVZ(vector O1,vector D1,vector O2,vector D2){

   // Computes two closest points of two lines, vector and distance
   #define a (O1*D1)
   #define c (D1*D1)
   #define d (O2*D1)
   #define e (O1*D2)
   #define f (O2*D2)
   vector nD1 = < c, e, 0.0>;
   vector nD2 = < d, f, 0.0>;
   #undef c
   #undef d
   #undef e
   #undef f
   #define c nD1.x
   #define d nD2.x
   #define e nD1.y
   #define f nD2.y
   X2 = (X1 = (O1 + D1 * (( f * (a-d) - d * (e-f) ) / ( d*e - c*f )))) + (V1 = (CP(nD1,nD2)));
   Z1 = llVecMag(V1);}
   #undef a
   #undef c
   #undef d
   #undef e
   #undef f
  1. endif

// PLANE

  1. define gPXdZ(Pn, Pd, A) ((A) * (Pn) + (Pd))
  2. ifndef gPXdZ

float gPXdZ(vector Pn,float Pd,vector A){

   // Finds distance of a point from a plane
   return A * Pn + Pd;}
  1. endif

vector gPXdV(vector Pn,float Pd,vector A){

   // Finds vector that points from point to nearest on plane
   return -(Pn * A + Pd)*Pn;}

vector gPXnX(vector Pn,float Pd,vector A){

   // Finds closest point on plane given point
   return A - (Pn * A + Pd) * Pn;}
  1. if 0

float gPRxZ(vector Pn,float Pd,vector O,vector D){

   // Finds distance to intersection of plane along ray
   return -( ( (Pn*D)+(Pn*O) ) / (Pn*D) );}
   //return -( (Pn*D)/(Pn*O+Pd) );}
  1. else

float gPRxZ(vector Pn,float Pd,vector O,vector D){

   // Finds distance to intersection of plane along ray
   float a = (Pn*D);
   return -( ( a+(Pn*O) ) / a );}
   //return -( (Pn*D)/(Pn*O+Pd) );}
  1. endif

vector gPRdV(vector Pn,float Pd,vector O,vector D){

   // Finds distance vector along a ray to a plane
   return D * gPRxZ(Pn,Pd,O,D);}
   //return -( (Pn*D)/(Pn*O+Pd) )*D;}

vector gPRxX(vector Pn,float Pd,vector O,vector D){

   // Finds intersection point along a ray to a plane
   return O + gPRdV(Pn,Pd,O,D);}

vector gPLxX(vector Pn,float Pd,vector O,vector D){

   // Finds interesection point of a line and a plane
   return O -( (Pn*D)/(Pn*O+Pd) )*D;}

vector oO;vector oD;

  1. if 0

gPPxL(vector Pn,float Pd,vector Qn,float Qd){

   // Finds line of intersection of two planes
   oD = CP(Pn,Qn)/llVecMag(CP(Pn,Qn));
   vector Cross = CP(CP(Pn,Qn),Pn);
   vector Bleh = (-Pd*Pn);
   oO = Bleh - (Qn*Cross)/(Qn*Bleh+Qd)*Cross/llVecMag(Cross);}
  1. else

gPPxL(vector Pn,float Pd,vector Qn,float Qd){

   // Finds line of intersection of two planes
   vector a = CP(Pn,Qn);
   oD = llVecNorm(a);
   vector Cross = CP(a,Pn);
   vector Bleh = (-Pd*Pn);
   oO = Bleh - (Qn*Cross)/(Qn*Bleh+Qd)*llVecNorm(Cross);}
  1. endif
  1. define gRXpZ(O, D, A) (A-O)*D
  2. ifndef gRXpZ

float gRXpZ(vector O,vector D,vector A){

   // Finds projected distance of a point along a ray
   return (A-O)*D;}
  1. endif
  1. if 0

gPRpR(vector Pn,float Pd,vector O,vector D){

   // Projects a ray onto a plane
   oO = O - (Pn * O + Pd) * Pn;
   vector t = llVecNorm( D - Project3D(D,Pn) );t = <1.0/t.x,1.0/t.y,1.0/t.z>;
   oD = CP(Pn,t);}
  1. else

gPRpR(vector Pn,float Pd,vector O,vector D){

   // Projects a ray onto a plane
   oO = O - (Pn * O + Pd) * Pn;
   O = llVecNorm( D - Project3D(D,Pn) );
   oD = CP(Pn, (<1.0/O.x,1.0/O.y,1.0/O.z>));}
  1. endif

// SPHERE

  1. if 0

vector gSRxX(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return ZERO_VECTOR;

   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);

   float disc = b * b - 4 * a * c;

   if(disc < 0) return ZERO_VECTOR;

   float distSqrt = llSqrt(disc);
   float q;

   if(b < 0)
       q = (-b - distSqrt)/2.0;
   else 
       q = (-b + distSqrt)/2.0;

   float t0 = q / a;
   float t1 = c / q;

   if(t0 > t1){
       float temp = t0;
       t0 = t1;
       t1 = temp;
   }

   if(t1 < 0) return ZERO_VECTOR;

   if(t0 < 0)
       t = t1;
   else
       t = t0;

   return Ro + (t * Rd);

}

  1. else

vector gSRxX(vector Sp, float Sr, vector Ro, vector Rd){

   if(Rd)
   {
       Ro -= Sp;
       //vector RayOrg = llDetectedPos(x) - llGetPos();
       float a = Rd * Rd;
       float b = 2 * Rd * Ro;
       float c = (Ro * Ro)  - (Sr * Sr);
    
       float disc = b * b - 4 * a * c;
    
       if(disc >= 0)
       {
           float q = ((llSqrt(disc) * ~((b > 0) * -2)) - b) / 2.0;
           if(q)//avoid a divide by zero!
           {
               float t0 = q / a;
               float t1 = c / q;
            
               if(((t0 < t1) || (t1 < 0)) && (t0 >= 0))
                   return Ro + (t0 * Rd);
               if(t1 >= 0)
                   return Ro + (t1 * Rd);
           }
       }
   }
   return ZERO_VECTOR;

}

  1. endif
  1. if 0

integer gSRx(vector Sp, float Sr, vector Ro, vector Rd){

   float t;Ro = Ro - Sp;
   //vector RayOrg = llDetectedPos(x) - llGetPos();
   if(Rd == ZERO_VECTOR) return FALSE;

   float a = Rd * Rd;
   float b = 2 * Rd * Ro;
   float c = (Ro * Ro)  - (Sr * Sr);

   float disc = b * b - 4 * a * c;

   if(disc < 0) return FALSE;
   return TRUE;

}

  1. else

integer gSRx(vector Sp, float Sr, vector Ro, vector Rd){

   if(Rd)
   {
       Ro -= Sp;
       //vector RayOrg = llDetectedPos(x) - llGetPos();
       float a = Rd * Rd;
       float b = 2 * Rd * Ro;
       float c = (Ro * Ro)  - (Sr * Sr);
       return (b * b - 4 * a * c) >= 0;
   }
   return FALSE;

}

  1. endif

// Other vector pN;float pD;

  1. if 0

gTiP(vector p1,vector p2,vector p3){

   pN = llVecNorm( CP((p2-p1),(p3-p1)) );
   pD = -p1*pN;}
  1. else

gTiP(vector p1,vector p2,vector p3){

   pD = -p1*(pN = llVecNorm( CP((p2-p1),(p3-p1)) ));}
  1. endif
  1. if 0

integer gTXcC(vector p1,vector p2,vector p3,vector x){

   gTiP(p1,p2,p3);
   vector Vn;vector En;
       Vn = p1 - x;
       En = CP((p2-p1),pN);
   if( ((p1-x)*CP(p2-p1,pN) >= 0)&&((p2-x)*CP(p3-p2,pN) >= 0)&&((p3-x)*CP(p1-p3,pN) >= 0) ) return TRUE;
   return FALSE;}
  1. else

integer gTXcC(vector p1,vector p2,vector p3,vector x){

   gTiP(p1,p2,p3);
   vector Vn = p1 - x;
   vector En = CP((p2-p1),pN);
   return( ((p1-x)*CP(p2-p1,pN) >= 0) && ((p2-x)*CP(p3-p2,pN) >= 0) && ((p3-x)*CP(p1-p3,pN) >= 0) );}
  1. endif
  1. if 0

integer gTVXcC(vector p1,vector p2,vector p3,vector v,vector x){

   if( ((p1-x)*CP(p2-p1,v) >= 0)&&((p2-x)*CP(p3-p2,v) >= 0)&&((p3-x)*CP(p1-p3,v) >= 0) ) return TRUE;
   return FALSE;}
  1. else

integer gTVXcC(vector p1,vector p2,vector p3,vector v,vector x){

   return ( ((p1-x)*CP(p2-p1,v) >= 0)&&((p2-x)*CP(p3-p2,v) >= 0)&&((p3-x)*CP(p1-p3,v) >= 0) );}
  1. endif
  1. define gTRcC gTVXcC
  2. ifndef gTRcC

integer gTRcC(vector p1,vector p2,vector p3,vector O,vector D){

   return gTVXcC(p1,p2,p3,O,D);}
  1. endif
  1. define gRZiX(O, D, z) ((O)+(D)*(z))
  2. ifndef gRZiX

vector gRZiX(vector O,vector D,float z){

   return O+z*D;}
  1. endif</lsl>