Difference between revisions of "Category talk:LSL Vector"
(5 intermediate revisions by 2 users not shown) | |||
Line 41: | Line 41: | ||
===Useful Snippets=== | ===Useful Snippets=== | ||
The IsVector function fails for vectors whose z element is negative, at least under Mono. (It also does not work on other grids because the cast to vector and back to string eliminates negative zero there.) | The IsVector function fails for vectors whose z element is negative, at least under Mono. (It also does not work on other grids because the cast to vector and back to string eliminates negative zero there.)<br> | ||
'''Edit:''' It does work, see Correction below... | |||
I tried the following: | I tried the following: | ||
Line 77: | Line 78: | ||
With this function, the above tests work. It tests for number of elements and then lets the compiler decide what it accepts as vector. Only for ZERO_VECTOR, special treatment is necessary. Therefore, it checks that only zeros and decimal points are in the remaining string. The compiler itself accepts missing ">" and it would also accept more than 3 elements - that's why the function checks the number of elements before. | With this function, the above tests work. It tests for number of elements and then lets the compiler decide what it accepts as vector. Only for ZERO_VECTOR, special treatment is necessary. Therefore, it checks that only zeros and decimal points are in the remaining string. The compiler itself accepts missing ">" and it would also accept more than 3 elements - that's why the function checks the number of elements before. | ||
It's probably not the most efficient way to do it and also accepts more than is actually valid (esp. for ZERO_VECTOR), but it does accept all valid | It's probably not the most efficient way to do it and also accepts more than is actually valid (esp. for ZERO_VECTOR), but it does accept all valid vectors (I hope ^^). Discussion and improvements are welcome. For IsRotation, the implementation would be almost the same, except checking for 4 elements instead of 3. | ||
[[User:Shuichi Shinji|Shuichi Shinji]] 01:13, 31 March 2014 (PDT) | [[User:Shuichi Shinji|Shuichi Shinji]] 01:13, 31 March 2014 (PDT) | ||
:It's going to give false positives on things with multiple periods. And it doesn't handle zero vectors expressed in hex or scientific notation. I applaud your efforts thus far. -- '''[[User:Strife_Onizuka|Strife]]''' <sup><small>([[User talk:Strife_Onizuka|talk]]|[[Special:Contributions/Strife_Onizuka|contribs]])</small></sup> 13:16, 31 March 2014 (PDT) | |||
<lsl> | |||
llOwnerSay( "IsVector(<.,.,.>) -> 0: " + (string)IsVector( "<.,.,.>" ) );//BTW: breaks LSL Editor | |||
llOwnerSay( "IsVector(<.......,0,0>) -> 0: " + (string)IsVector( "<.......,0,0>" ) );//BTW: breaks LSL Editor | |||
llOwnerSay( "IsVector(<0x0.0,0x0p+1,-0x0p-1>) -> 1: " + (string)IsVector( "<0x0.0,0x0.p+1,-0x0.p-1>" ) ); | |||
llOwnerSay( "IsVector(<0.0e1,0.0e+1,-0.0e-1>) -> 1: " + (string)IsVector( "<0.0e1,0.0e+1,-0.0e-1>" ) ); | |||
</lsl> | |||
::Right. I don't know how bad false positives are; the other 2 could be solved by adding 1,x,e,p to the split list, but also adding more false positives, which is not nice. But just adding a "-" to the split list in the original implementation would solve that it's not working for negative z's yet. Of course, it would also add some false positives, such as "1.2--3", but so it already did with "1.2 3" (spaces inside the number) - maybe one line from my proposal could be added so that it properly checks non-ZERO_VECTORs, at least. -- [[User:Shuichi Shinji|Shuichi Shinji]] 08:30, 4 April 2014 (PDT) | |||
<lsl> | |||
integer IsVector(string s) | |||
{ | |||
list split = llParseString2List(s, [" ", "-"], ["<", ">", ","]); | |||
if(llGetListLength(split) != 7)//we must check the list length, or the next test won't work properly. | |||
return FALSE; | |||
if((vector)s != ZERO_VECTOR)//parsing error or real ZERO_VECTOR lead to ZERO_VECTOR | |||
return TRUE; | |||
return !((string)((vector)s) == (string)((vector)((string)llListInsertList(split, ["-"], 5)))); | |||
//it works by trying to flip the sign on the Z element of the vector, | |||
//if it works or breaks the vector then the values won't match. | |||
//if the vector was already broken then the sign flip will have no affect and the values will match | |||
//we cast back to string so we can catch negative zero which allows for support of ZERO_VECTOR | |||
} | |||
</lsl> | |||
---- | |||
====Correction==== | |||
Ok, your function '''does''' work for negative z's, I must have made a mistake when I first checked it - sorry for the confusion. However, I have a few improvements: | |||
* don't filter out spaces during the split, because e.g. " < 1 , 2 , 3 > " is not a valid vector (the leading spaces are the problem): <lsl>list split = llParseString2List( s, [], ["<", ">", ","] );</lsl> | |||
* for rotations, don't add the "-" for the s member, but for z (I had problems with s) | |||
With these, the following checks all work (in SL; LSLeditor interprets it a bit differently in some cases): | |||
<lsl> | |||
llOwnerSay( "IsVector(<0.47,0.149, 1.001>) -> 1: " + (string)IsVector( "<0.47,0.149, 1.001>" ) ); | |||
llOwnerSay( "IsVector(<0.47,0.149, 1.001,3>) -> 0: " + (string)IsVector( "<0.47,0.149, 1.001,3>" ) ); | |||
llOwnerSay( "IsVector(<0.47,0.149,-1.001>) -> 1: " + (string)IsVector( "<0.47,0.149,-1.001>" ) ); | |||
llOwnerSay( "IsVector(<0.47,0.149,+1.001>) -> 1: " + (string)IsVector( "<0.47,0.149,+1.001>" ) ); | |||
llOwnerSay( "IsVector(< 0.47, 0.149, -1.001 >) -> 1: " + (string)IsVector( "< 0.47, 0.149, -1.001 >" ) ); | |||
llOwnerSay( "IsVector( < 0.47, 0.149, -1.001 > ) -> 0: " + (string)IsVector( " < 0.47, 0.149, -1.001 > " ) ); | |||
llOwnerSay( "IsVector(<0.47,0.1A9,-1.001>) -> 0: " + (string)IsVector( "<0.47,0.1A9,-1.001>" ) ); | |||
llOwnerSay( "IsVector(<0.47,0.149,;-1.001>) -> 0: " + (string)IsVector( "<0.47,;0.149,-1.001>" ) ); | |||
llOwnerSay( "IsVector(<0.47,0.149,-1.001) -> 0: " + (string)IsVector( "<0.47,0.149,-1.001" ) ); | |||
llOwnerSay( "IsVector(<0,0.000,0>) -> 1: " + (string)IsVector( "<0,0.000,0>" ) ); | |||
llOwnerSay( "IsVector(<0,0.000,0,0>) -> 0: " + (string)IsVector( "<0,0.000,0,0>" ) ); | |||
llOwnerSay( "IsVector(<+0,-0.000,-0>) -> 1: " + (string)IsVector( "<+0,-0.000,-0>" ) ); | |||
llOwnerSay( "IsVector(<0x0.0,0x0p+1,-0x0p-1>) -> 1: " + (string)IsVector( "<0x0.0,0x0.p+1,-0x0.p-1>" ) ); | |||
llOwnerSay( "IsVector(<0.0e1,0.0e+1,-0.0e-1>) -> 1: " + (string)IsVector( "<0.0e1,0.0e+1,-0.0e-1>" ) ); | |||
llOwnerSay( "IsRotation(<0.47,0.149,-1.001>) -> 0: " + (string)IsRotation( "<0.47,0.149,-1.001>" ) ); | |||
llOwnerSay( "IsRotation(<0.47,0.149,-1.001,3>) -> 1: " + (string)IsRotation( "<0.47,0.149,-1.001,3>" ) ); | |||
llOwnerSay( "IsRotation(<0.47,0.149,+1.001,3>) -> 1: " + (string)IsRotation( "<0.47,0.149,+1.001,3>" ) ); | |||
llOwnerSay( "IsRotation(< 0.47, 0.149, 0.99,3 >) -> 1: " + (string)IsRotation( "< 0.47, 0.149, 0.99,3 >" ) ); | |||
llOwnerSay( "IsRotation( < 0.47, 0.149, 0.99,3 > ) -> 0: " + (string)IsRotation( " < 0.47, 0.149, 0.99,3 > " ) ); | |||
llOwnerSay( "IsRotation(<0.47,0.1A9,-1.001,3>) -> 0: " + (string)IsRotation( "<0.47,0.1A9,-1.001,3>" ) ); | |||
llOwnerSay( "IsRotation(<0.47,0.149,-1.001,;3>) -> 0: " + (string)IsRotation( "<0.47,;0.149,-1.001,3>" ) ); | |||
llOwnerSay( "IsRotation(<0.47,0.149,-1.001,3) -> 0: " + (string)IsRotation( "<0.47,0.149,-1.001,3" ) ); | |||
llOwnerSay( "IsRotation(<0,0.000,0>) -> 0: " + (string)IsRotation( "<0,0.000,0>" ) ); | |||
llOwnerSay( "IsRotation(<0,0.000,0,0>) -> 1: " + (string)IsRotation( "<0,0.000,0,0>" ) ); | |||
llOwnerSay( "IsRotation(<+0,-0.000,-0,-0>) -> 1: " + (string)IsRotation( "<+0,-0.000,-0,-0>" ) ); | |||
</lsl> | |||
'''Not relevant for SL, just a remark:''' For grids where the "-" approach does not work because negative zeros are filtered out during the casts, the following slightly less elegant works instead: | |||
<lsl> | |||
// vector | |||
if ( (vector)((string)llListReplaceList( split, [1], 5, 5 )) == ZERO_VECTOR ) return FALSE; // parsing error in x or y | |||
return ((vector)((string)llListReplaceList( split, [1], 3, 3 )) != ZERO_VECTOR); // parsing error in z | |||
// rotation | |||
if ( (rotation)((string)llListReplaceList( split, [2], 7, 7 )) == ZERO_ROTATION ) return FALSE; // parsing error in x, y or z | |||
return ((rotation)((string)llListReplaceList( split, [1], 5, 5 )) != ZERO_ROTATION); // parsing error in s | |||
</lsl> | |||
[[User:Shuichi Shinji|Shuichi Shinji]] 01:20, 10 April 2014 (PDT) |
Latest revision as of 00:20, 10 April 2014
<lsl> //******************************* //IMPOSSIBLE TO GET A ZERO_VECTOR //*******************************
vector c = <0.0, 0.0, 0.1>;
default {
touch_start(integer total_number) { c -= <0.0, 0.0, 0.025>; llSay(0, (string)c); if (c == ZERO_VECTOR) llSay(0, "ZERO_VECTOR"); // never c is a ZERO_VECTOR }
} </lsl> <lsl> //********************** //IN THIS WAY IT RUNS... //**********************
vector c = <0.0, 0.0, 0.1>;
default {
touch_start(integer total_number) { c -= <0.0, 0.0, 0.025>; llSay(0, (string)c); if ((string)c == "<0.00000, 0.00000, 0.00000>") llSay(0, "ZERO_VECTOR"); }
} </lsl> —The preceding unsigned comment was added on 06:29, 29 April 2012 by Zohan Galewind
The above is caused by how floating point math works. 0.1 does not fall on an exact boundary as a float, nor does 0.025. Furthermore the rounding on the two values do not exactly line up, so (4 * 0.025) != 0.1. This is not a bug but a caveat of using floating point math. -- Strife (talk|contribs) 11:00, 29 April 2012 (PDT)
Useful Snippets
The IsVector function fails for vectors whose z element is negative, at least under Mono. (It also does not work on other grids because the cast to vector and back to string eliminates negative zero there.)
Edit: It does work, see Correction below...
I tried the following:
<lsl> // After the "->" is the expected result (for the proposed new function), after the ":" the actual one llOwnerSay( "IsVector(<0.47,0.149, 1.001>) -> 1: " + (string)IsVector( "<0.47,0.149, 1.001>" ) ); llOwnerSay( "IsVector(<0.47,0.149, 1.001,3>) -> 0: " + (string)IsVector( "<0.47,0.149, 1.001,3>" ) ); llOwnerSay( "IsVector(<0.47,0.149,-1.001>) -> 1: " + (string)IsVector( "<0.47,0.149,-1.001>" ) ); llOwnerSay( "IsVector(<0.47,0.149,+1.001>) -> 1: " + (string)IsVector( "<0.47,0.149,+1.001>" ) ); llOwnerSay( "IsVector( < 0.47, 0.149, -1.001 > ) -> 0: " + (string)IsVector( " < 0.47, 0.149, -1.001 > " ) ); llOwnerSay( "IsVector(<0.47,0.1A9,-1.001>) -> 0: " + (string)IsVector( "<0.47,0.1A9,-1.001>" ) ); llOwnerSay( "IsVector(<0.47,;0.149,-1.001>) -> 0: " + (string)IsVector( "<0.47,;0.149,-1.001>" ) ); llOwnerSay( "IsVector(<0.47,0.149,-1.001) -> 1: " + (string)IsVector( "<0.47,0.149,-1.001" ) ); llOwnerSay( "IsVector(<0,0.000,0>) -> 1: " + (string)IsVector( "<0,0.000,0>" ) ); llOwnerSay( "IsVector(<0,0.000,0,0>) -> 0: " + (string)IsVector( "<0,0.000,0,0>" ) ); llOwnerSay( "IsVector(<+0,-0.000,-0>) -> 1: " + (string)IsVector( "<+0,-0.000,-0>" ) ); </lsl>
I propose the following change:
<lsl> // Returns whether the given string contains a vector. // Accepts what the compiler accepts and checks ZERO_VECTOR separately. integer IsVector ( string s ) {
list split = llParseString2List( s, ["<", ">", ",", " ", "-", "+"], [] ); // not allowed to be inside numbers if ( llGetListLength( split ) != 3 ) return FALSE; // must be 3 elements if ( (vector)s != ZERO_VECTOR ) return TRUE; // parsing error or real ZERO_VECTOR lead to ZERO_VECTOR split = llParseString2List( (string)split, ["0", "."], [] ); return (split == []);
} </lsl>
With this function, the above tests work. It tests for number of elements and then lets the compiler decide what it accepts as vector. Only for ZERO_VECTOR, special treatment is necessary. Therefore, it checks that only zeros and decimal points are in the remaining string. The compiler itself accepts missing ">" and it would also accept more than 3 elements - that's why the function checks the number of elements before.
It's probably not the most efficient way to do it and also accepts more than is actually valid (esp. for ZERO_VECTOR), but it does accept all valid vectors (I hope ^^). Discussion and improvements are welcome. For IsRotation, the implementation would be almost the same, except checking for 4 elements instead of 3.
Shuichi Shinji 01:13, 31 March 2014 (PDT)
- It's going to give false positives on things with multiple periods. And it doesn't handle zero vectors expressed in hex or scientific notation. I applaud your efforts thus far. -- Strife (talk|contribs) 13:16, 31 March 2014 (PDT)
<lsl> llOwnerSay( "IsVector(<.,.,.>) -> 0: " + (string)IsVector( "<.,.,.>" ) );//BTW: breaks LSL Editor llOwnerSay( "IsVector(<.......,0,0>) -> 0: " + (string)IsVector( "<.......,0,0>" ) );//BTW: breaks LSL Editor llOwnerSay( "IsVector(<0x0.0,0x0p+1,-0x0p-1>) -> 1: " + (string)IsVector( "<0x0.0,0x0.p+1,-0x0.p-1>" ) ); llOwnerSay( "IsVector(<0.0e1,0.0e+1,-0.0e-1>) -> 1: " + (string)IsVector( "<0.0e1,0.0e+1,-0.0e-1>" ) ); </lsl>
- Right. I don't know how bad false positives are; the other 2 could be solved by adding 1,x,e,p to the split list, but also adding more false positives, which is not nice. But just adding a "-" to the split list in the original implementation would solve that it's not working for negative z's yet. Of course, it would also add some false positives, such as "1.2--3", but so it already did with "1.2 3" (spaces inside the number) - maybe one line from my proposal could be added so that it properly checks non-ZERO_VECTORs, at least. -- Shuichi Shinji 08:30, 4 April 2014 (PDT)
<lsl> integer IsVector(string s) {
list split = llParseString2List(s, [" ", "-"], ["<", ">", ","]); if(llGetListLength(split) != 7)//we must check the list length, or the next test won't work properly. return FALSE; if((vector)s != ZERO_VECTOR)//parsing error or real ZERO_VECTOR lead to ZERO_VECTOR return TRUE; return !((string)((vector)s) == (string)((vector)((string)llListInsertList(split, ["-"], 5)))); //it works by trying to flip the sign on the Z element of the vector, //if it works or breaks the vector then the values won't match. //if the vector was already broken then the sign flip will have no affect and the values will match //we cast back to string so we can catch negative zero which allows for support of ZERO_VECTOR
} </lsl>
Correction
Ok, your function does work for negative z's, I must have made a mistake when I first checked it - sorry for the confusion. However, I have a few improvements:
- don't filter out spaces during the split, because e.g. " < 1 , 2 , 3 > " is not a valid vector (the leading spaces are the problem): <lsl>list split = llParseString2List( s, [], ["<", ">", ","] );</lsl>
- for rotations, don't add the "-" for the s member, but for z (I had problems with s)
With these, the following checks all work (in SL; LSLeditor interprets it a bit differently in some cases):
<lsl> llOwnerSay( "IsVector(<0.47,0.149, 1.001>) -> 1: " + (string)IsVector( "<0.47,0.149, 1.001>" ) ); llOwnerSay( "IsVector(<0.47,0.149, 1.001,3>) -> 0: " + (string)IsVector( "<0.47,0.149, 1.001,3>" ) ); llOwnerSay( "IsVector(<0.47,0.149,-1.001>) -> 1: " + (string)IsVector( "<0.47,0.149,-1.001>" ) ); llOwnerSay( "IsVector(<0.47,0.149,+1.001>) -> 1: " + (string)IsVector( "<0.47,0.149,+1.001>" ) ); llOwnerSay( "IsVector(< 0.47, 0.149, -1.001 >) -> 1: " + (string)IsVector( "< 0.47, 0.149, -1.001 >" ) ); llOwnerSay( "IsVector( < 0.47, 0.149, -1.001 > ) -> 0: " + (string)IsVector( " < 0.47, 0.149, -1.001 > " ) ); llOwnerSay( "IsVector(<0.47,0.1A9,-1.001>) -> 0: " + (string)IsVector( "<0.47,0.1A9,-1.001>" ) ); llOwnerSay( "IsVector(<0.47,0.149,;-1.001>) -> 0: " + (string)IsVector( "<0.47,;0.149,-1.001>" ) ); llOwnerSay( "IsVector(<0.47,0.149,-1.001) -> 0: " + (string)IsVector( "<0.47,0.149,-1.001" ) ); llOwnerSay( "IsVector(<0,0.000,0>) -> 1: " + (string)IsVector( "<0,0.000,0>" ) ); llOwnerSay( "IsVector(<0,0.000,0,0>) -> 0: " + (string)IsVector( "<0,0.000,0,0>" ) ); llOwnerSay( "IsVector(<+0,-0.000,-0>) -> 1: " + (string)IsVector( "<+0,-0.000,-0>" ) ); llOwnerSay( "IsVector(<0x0.0,0x0p+1,-0x0p-1>) -> 1: " + (string)IsVector( "<0x0.0,0x0.p+1,-0x0.p-1>" ) ); llOwnerSay( "IsVector(<0.0e1,0.0e+1,-0.0e-1>) -> 1: " + (string)IsVector( "<0.0e1,0.0e+1,-0.0e-1>" ) ); llOwnerSay( "IsRotation(<0.47,0.149,-1.001>) -> 0: " + (string)IsRotation( "<0.47,0.149,-1.001>" ) ); llOwnerSay( "IsRotation(<0.47,0.149,-1.001,3>) -> 1: " + (string)IsRotation( "<0.47,0.149,-1.001,3>" ) ); llOwnerSay( "IsRotation(<0.47,0.149,+1.001,3>) -> 1: " + (string)IsRotation( "<0.47,0.149,+1.001,3>" ) ); llOwnerSay( "IsRotation(< 0.47, 0.149, 0.99,3 >) -> 1: " + (string)IsRotation( "< 0.47, 0.149, 0.99,3 >" ) ); llOwnerSay( "IsRotation( < 0.47, 0.149, 0.99,3 > ) -> 0: " + (string)IsRotation( " < 0.47, 0.149, 0.99,3 > " ) ); llOwnerSay( "IsRotation(<0.47,0.1A9,-1.001,3>) -> 0: " + (string)IsRotation( "<0.47,0.1A9,-1.001,3>" ) ); llOwnerSay( "IsRotation(<0.47,0.149,-1.001,;3>) -> 0: " + (string)IsRotation( "<0.47,;0.149,-1.001,3>" ) ); llOwnerSay( "IsRotation(<0.47,0.149,-1.001,3) -> 0: " + (string)IsRotation( "<0.47,0.149,-1.001,3" ) ); llOwnerSay( "IsRotation(<0,0.000,0>) -> 0: " + (string)IsRotation( "<0,0.000,0>" ) ); llOwnerSay( "IsRotation(<0,0.000,0,0>) -> 1: " + (string)IsRotation( "<0,0.000,0,0>" ) ); llOwnerSay( "IsRotation(<+0,-0.000,-0,-0>) -> 1: " + (string)IsRotation( "<+0,-0.000,-0,-0>" ) ); </lsl>
Not relevant for SL, just a remark: For grids where the "-" approach does not work because negative zeros are filtered out during the casts, the following slightly less elegant works instead:
<lsl> // vector if ( (vector)((string)llListReplaceList( split, [1], 5, 5 )) == ZERO_VECTOR ) return FALSE; // parsing error in x or y return ((vector)((string)llListReplaceList( split, [1], 3, 3 )) != ZERO_VECTOR); // parsing error in z // rotation if ( (rotation)((string)llListReplaceList( split, [2], 7, 7 )) == ZERO_ROTATION ) return FALSE; // parsing error in x, y or z return ((rotation)((string)llListReplaceList( split, [1], 5, 5 )) != ZERO_ROTATION); // parsing error in s </lsl>
Shuichi Shinji 01:20, 10 April 2014 (PDT)