|
|
|
|
|
|
| |
| |
|
|
|
|
| |
| |
|
|
I'm having a subtle problem that I can't pin down, when trying to use
logical-OR statements inside of #case directives. I'm using the strcmp()
function to compare various strings, plus OR blocks separating those strcmp()
comparisons inside of each #case. Posting my problematic scene code isn't
practical here (it involves lots of image_maps), but I came up with a simplified
test. I'm hoping to glean some insights into these interactions, from more
astute newsgroup observers ;-)
There are four things involved: strings, #switch/#case, the strcmp() function,
and OR.
Here's the test code, before I go into the details. Note that IMG_TYPE and AA
exactly match. The problem is that #switch is falling through to the #else
clause, when it should not do so (because IMG_TYPE and AA *are* the same.) If
the #case clause is successful, you'll see a GREEN box; otherwise, a
crosshatched box. Comment-out the two OR lines for a successful test.
--------------------
#version 3.71; // or 3.7
global_settings{assumed_gamma 1.0 max_trace_level 5}
default{finish{ambient 0 emission 1 diffuse 0}}
camera {
perspective
location <.5, .5, -1.5>
look_at <.5, .5, 0>
}
#declare IMG_TYPE = "jpg"
#local AA = "jpg"
#local BB = "png"
#local CC = "tiff"
box{0,<1,1,0>
no_shadow
pigment{
#switch(1000)
#case(
// INDIVIDUALLY, these all work the way they are supposed to-- but not
// all three at once. The OR's are causing some kind of problem, and
// the result always fall through to the #else clause.
(strcmp(IMG_TYPE,AA) + 1000)
| (strcmp(IMG_TYPE,BB) + 1000)
| (strcmp(IMG_TYPE,CC) + 1000)
)
srgb <0,1,0> // GREEN square
#debug "\nAt least ONE of the #case clauses is valid.\n\n\n\n"
#break
#else
// A cross-hatch warning image...
average
pigment_map{
[1 gradient x+y
frequency 6
color_map{
[.25 srgb <1,0,0>]
[.25 srgb 0]
}
]
[1 gradient x-y
frequency 6
color_map{
[.25 srgb <1,0,0>]
[.25 srgb 0]
}
]
}
#debug "\nNO #case clause is valid.\n\n"
#end // of #switch
} // end of pigment
}
-----------------------
I assume that a #case clause can USE logical operators like ORs??
What DOES work is to *remove* all of the OR blocks--using just ONE
strcmp() + 1000 in the #case (any one of the three). That results in correct
#switch behavior (either a 'go' of 'no go'.) That's not what I want, of course,
as I need all three in the #case statement. But is it possible that OR is not
the correct logical operator to use? One *guess* I have is that #case is
'reading' the strcmp()-plus-OR blocks left to right-- and finally comes to
strcmp(IMG_TYPE,CC) + 1000, the result of which does NOT 'match'
#switch(1000) ... possibly causing the fall-through to the #else clause(?)
My understanding of #switch is that ANY value can be used; it doesn't
specifically need just TRUE/FALSE of 1/0, just so long as a particular #case
result matches it. But I don't really know its hidden operation. BTW, I didn't
use 'TRUE' in the #switch() because, when strcmp() finds two strings that
*match*, its numerical output is zero-- which should be a logical 'false' in a
TRUE/FALSE clause, not 'true.' (AFAIU!)
Perhaps I shouldn't be using strcmp() at all. It *is* a rather complex beast--
its numerical output depends on where the various strings fall into the 'ASCII
collating sequence.' (I had to re-read the docs to try and understand this,
along with running some experiments.) My use of +1000 in the #switch clause
(and in the #case arguments) was to try and avoid such problems, as 1000 is way
outside of the ASCII numbering sequence. But no matter *what* numerical value I
use-- while also using the ORs-- the #else clause is always invoked.
And in my real scene, I'm finding that the OR clauses *sometimes* need the added
parentheses around the various strcmp() + 1000 statements -- but that
seems to work inconsistently as well :-/
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
I've only briefly looked this over, but it seems to me that you've misunderstood
how the switch-case/range-break-end block works.
You define #switch (trigger) - which uses a variable value "trigger" for the
rest of the case/range block to operate on.
Then every case () or range () directive is set up to operate on a specific
value of "trigger" or range of "trigger" values.
#break directives end each sub-block.
Then there's a catch-all else, then the end.
So,
#declare Clock = clock;
#switch (Clock)
#case (0.1)
#debug "The clock is at 0.1 \n"
#break
#case (0.2)
#debug "The clock is at 0.2 \n"
#break
#case (0.3)
#debug "The clock is at 0.3 \n"
#break
#case (0.4)
#debug "The clock is at 0.4 \n"
#break
#case (0.5)
#debug "The clock is at 0.5 \n"
#break
#else
#debug "The clock is over 0.5... \n"
#end
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Bald Eagle" <cre### [at] netscapenet> wrote:
> I've only briefly looked this over, but it seems to me that you've
> misunderstood how the switch-case/range-break-end block works.
>
> You define #switch (trigger) - which uses a variable value "trigger" for the
> rest of the case/range block to operate on.
Right; I used 1000 as the value of the 'trigger.'
>
> Then every case () or range () directive is set up to operate on a specific
> value of "trigger" or range of "trigger" values.
Yep. In my example-- and using only ONE comparison in the #case statement (no
ORs)-- #case((strcmp(IMG_TYPE,AA) + 1000)) is the 'correct' match for the
trigger... because strcmp(...) returns the number zero in this comparison,
and 0 + 1000 = 1000. Voila! That's a successful result (or so it seems!)
Alternately, strcmp{IMG_TYPE,BB) returns a numerical value of -6 (BB is
actually the string "png", not "jpg"-- and they are separated in the 'ASCII
numerical sequence' by -6 values or places or whatever.) So -6 + 1000 = 994,
which doesn't match #switch(1000)-- thus it falls through to the #else clause,
as it should.
The problem seems to be with my use of ORs in the #case; they seem to be
screwing up the results somehow. The *successful* (strcmp(IMG_TYPE,AA) + 1000))
comparison value is being ignored or overridden, or something!
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Kenneth" <kdw### [at] gmailcom> wrote:
> The problem seems to be with my use of ORs in the #case; they seem to be
> screwing up the results somehow. The *successful* (strcmp(IMG_TYPE,AA) + 1000))
> comparison value is being ignored or overridden, or something!
Right - I think that you can't use case() like that.
I think the Boolean comparison might yield a 0 or a 1, thus nothing ever returns
1000.
Maybe you ought to do a regular
#if (comparison1 | comparison2 | comparison3)
#declare Trigger = 1000;
#end
Then proceed as you're doing.
Or whatever else that leads you to recoding...
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Bald Eagle" <cre### [at] netscapenet> wrote:
> "Kenneth" <kdw### [at] gmailcom> wrote:
>
> > The problem seems to be with my use of ORs in the #case; they seem to be
> > screwing up the results somehow. The *successful* (strcmp(IMG_TYPE,AA) + 1000))
> > comparison value is being ignored or overridden, or something!
>
> Right - I think that you can't use case() like that.
>
> I think the Boolean comparison might yield a 0 or a 1, thus nothing
> ever returns 1000.
Well, both of these seem to work correctly (when not using the troublesome ORs,
that is)...
#switch(0)
#case(strcmp(IMG_TYPE,AA))
#switch(1000)
#case((strcmp(IMG_TYPE,AA) + 1000)
-- which in itself is actually kind of surprising, as I assumed #switch(0) would
be the equivalent of a 'false' statement Boolean-wise or in a TRUE/FALSE
comparison. That's why I didn't use #switch(TRUE)-- also because, with *that*,
the overal results--when USING the ORs--were screwy in a different way!
>
> Maybe you ought to do a regular
> #if (comparison1 | comparison2 | comparison3)
> #declare Trigger = 1000;
> #end
>
..... or just separate the various comparisons into individual #cases. I was
trying to avoid such stuff, simply because it didn't look... compact and elegant
;-)
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
By the way...
Add these three #debug statements to my code example, right before the final
closing curly bracket. They return messages about the numerical 'differences'
(in the 'ASCII numbering sequence') between IMG_TYPE and AA,BB,CC.
#debug concat("\n","numerical value of strcmp(IMG_TYPE,AA) is
",str(strcmp(IMG_TYPE,AA),0,5),"\n\n")
#debug concat("\n","numerical value of strcmp(IMG_TYPE,BB) is
",str(strcmp(IMG_TYPE,BB),0,5),"\n\n")
#debug concat("\n","numerical value of strcmp(IMG_TYPE,CC) is
",str(strcmp(IMG_TYPE,CC),0,5),"\n\n")
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
"Kenneth" <kdw### [at] gmailcom> wrote:
> ...That's why I didn't use #switch(TRUE)-- also because, with *that*,
> the overal results--when USING the ORs--were screwy in a different way!
>
An interesting example of that:
In my code, change...
#switch(1000)
#case((strcmp(IMG_TYPE,AA) + 1000)
| (strcmp(IMG_TYPE,BB) + 1000)
| (strcmp(IMG_TYPE,CC) + 1000)
)
to...
#switch(true)
#case(
// no (strcmp(IMG_TYPE,AA), which is the only 'correct' match
(strcmp(IMG_TYPE,BB))
| (strcmp(IMG_TYPE,CC))
)
This still produces a 'true' result (the GREEN box), when neither of the #case
comparisons actually 'match'. BUT... it occurs to me that a matching 'true'
value could be ANY number (positive or negative!), just so long as it's not a
zero-- which would be a 'false' result.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
You're ---- thinking about #switch and #case() in an --- odd way.
I see where it's going wrong, and this will give you an idea of why:
#switch(true)
#case(1)
rgb <0, 0, 0.2>
#break
#case(
// no (strcmp(IMG_TYPE,AA), which is the only 'correct' match
(strcmp(IMG_TYPE,BB))
| (strcmp(IMG_TYPE,CC))
)
#switch(true) is a very strange usage, and I'm sure clipka could give some
source-code explanation of why it works the way it does.
But basically, as I suspected, it just selects the FIRST #case() regardless of
what it is.
In fact, check out:
#switch(strcmp(IMG_TYPE,BB) | strcmp(IMG_TYPE,CC) )
#case(-10)
rgb <1, 1, 0>
#break
#case(-6)
rgb <1, 1, 1>
#break
#case(1)
rgb <0, 0, 0.2>
#break
#case(1000)
It selects the blue pigment, which corresponds to 1.
So, I think you need to do something along the lines of
#declare IMG_TYPE = (some string operator on your filename)
#if IMG_TYPE = "jpg" #local AA = 1; #end
#if IMG_TYPE = "png" #local AA = 2; #end
#if IMG_TYPE = "tiff" #local AA = 3; #end
#select (AA)
.....
OR, since if any one of the cases you want to select for is going to yield a
value of zero for strcmp(),
#declare Pig = strcmp(IMG_TYPE,AA) * strcmp(IMG_TYPE,BB) * strcmp(IMG_TYPE,CC);
and then #select (Pig)
(that works for me)
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
Am 07.11.2017 um 20:32 schrieb Kenneth:
> #switch(1000)
> #case(
> // INDIVIDUALLY, these all work the way they are supposed to-- but not
> // all three at once. The OR's are causing some kind of problem, and
> // the result always fall through to the #else clause.
> (strcmp(IMG_TYPE,AA) + 1000)
> | (strcmp(IMG_TYPE,BB) + 1000)
> | (strcmp(IMG_TYPE,CC) + 1000)
> )
Ah... yes... no, don't do that.
The `#switch`/`#case` construct is designed to be used as follows:
// (A)
#switch(VARIABLE)
#case(CONST1)
// go here if VARIABLE = CONST1
#break
#case(CONST2)
// go here if VARIABLE = CONST2
#break
...
#end
It so happens that the `#case` values /can/ be other variables (and of
course the `#switch` value /can/ be a constant), allowing for a hack to
co-opt the statement as a replacement for pathologic `#if... #else #if
... #end #end` nesting:
// (B)
#switch(true)
#case(CONDITION1)
// go here if CONDITION1 is true
#break
#case(CONDITION2)
// otherwise go here if CONDITION2 is true
#break
...
#end
If the conditions are string equality tests (`strcmp(...)=0`), the
following similar construct is also possible:
// (C)
#switch(0)
#case(strcmp(STRING,CONST1))
// go here if STRING = CONST1
#break
#case(strcmp(STRING,CONST2))
// otherwise go here if STRING = CONST2
#break
...
#end
Note however that (B) and (C) *do not mix* nicely -- you have to decide
whether you want your `#case` expressions to be logical tests (allowing
for logical OR, AND etc.) or `strcmp()` results. You can't just try to
mix them (unless you know exactly what you're doing).
Also, there's a much easier way to achieve a logical OR in any `#switch`
construct: Just place multiple `#case` statements without a `#break` in
between, like so:
#switch(0)
#case(strcmp(STRING,CONST1A))
#case(strcmp(STRING,CONST1B))
// go here if STRING = CONST1A or CONST1B
#break
#case(strcmp(STRING,CONST2A))
#case(strcmp(STRING,CONST2B))
// otherwise go here if STRING = CONST2A or CONST2B
#break
Finally, note that as of v3.7, (B) and (C) can be rewritten as:
// (B)
#if(CONDITION1)
// go here if CONDITION1 is true
#elseif(CONDITION2)
// otherwise go here if CONDITION2 is true
...
#end
// (C)
#if(STRING = CONST1)
// go here if STRING = CONST1
#elseif(STRING = CONST2)
// otherwise go here if STRING = CONST2
...
#end
> Perhaps I shouldn't be using strcmp() at all. It *is* a rather complex beast--
Indeed (though with the `+1000` term you're overcomplicating things).
As of v3.7, the various comparison operators (`=`, `<` etc.) are a much
better choice in most cases, now that they also support strings.
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
| |
|
|
clipka <ano### [at] anonymousorg> wrote:
> Also, there's a much easier way to achieve a logical OR in any `#switch`
> construct: Just place multiple `#case` statements without a `#break` in
> between, like so:
>
> #switch(0)
> #case(strcmp(STRING,CONST1A))
> #case(strcmp(STRING,CONST1B))
> // go here if STRING = CONST1A or CONST1B
> #break
> #case(strcmp(STRING,CONST2A))
> #case(strcmp(STRING,CONST2B))
> // otherwise go here if STRING = CONST2A or CONST2B
> #break
Yes, I had considered mentioning this possibility (I've discovered it
accidentally by failing to include the #break(s) :O, so I'm glad you provided
this example.
Thanks for all of the other examples - useful stuff and a very good supplement
to the official docs :)
Post a reply to this message
|
|
| |
| |
|
|
|
|
| |
|
|