POV-Ray : Newsgroups : povray.documentation.inbuilt : SOR documentation Server Time
15 Sep 2025 08:10:52 EDT (-0400)
  SOR documentation (Message 25 to 34 of 34)  
<<< Previous 10 Messages Goto Initial 10 Messages
From: William F Pokorny
Subject: Re: SOR documentation
Date: 9 Sep 2025 07:33:42
Message: <68c01096$1@news.povray.org>
On 9/8/25 11:10, William F Pokorny wrote:
> Thinking aloud, it might be possible to allow x<0 control points - ONLY 
> - where both on curve points and off curve control points are forced to 
> be always ascending (>= previous) in y. This, probably, would cover the 
> 'useful' x<0 control point cases while preventing the curve from 
> crossing into -x?  I'll try to play with this thought some more when I 
> again have time - need to run.

I spent some time on this idea and, on seeing some issues where entire 
segments would just blink out of existence, I went back to trying more 
parser legal point sets and found similar weirdness. :-(

There exists internal cylinder bounding of segments intended to reduce 
the number of calls to the solvers. My guess is that code isn't 
completely solid, but who knows.

Attached an image where the top row uses the currently legal point set of:

     <+1.5,-0.01> // C0
     <+0.4, 0.0>  // P1
     <+0.3, 0.5>  // P2
     <+0.4, 0.9>  // P3
     <+1.5,+0.91> // C4

and the shape breaks apart(a)(b). In the bottom row I changed that last 
control point to:

    <+1.5,+0.901> // C4

and the entire top segment drops out.

So yep...

Bill P.

(a) Curve going negative can already happen without negative control 
points.

(b) In yuqk the parts of the sor there all look good. In v3.8 beta 2, 
the results for top segment are noisy; Likely solver differences.


Post a reply to this message


Attachments:
Download 'sor_oddness.png' (22 KB)

Preview of image 'sor_oddness.png'
sor_oddness.png


 

From: William F Pokorny
Subject: Re: SOR documentation
Date: 9 Sep 2025 07:45:00
Message: <68c0133c$1@news.povray.org>
On 9/8/25 14:06, Bald Eagle wrote:
>> (*) I tried inverting all the on curve points and this does NOT work as
>> I incorrectly remembered for some recent sor{} post - that must be a
>> lathe{} only thing.
...> Right, because sor is an implicit interpolation, and lathe is a 
parametric
> interpolation.

Unsure. With the lathe the reason to flip the point set order is to flip 
the normals (and perhaps too textures on parts of the resulting shape). Ref:

https://news.povray.org/povray.binaries.images/thread/%3C5745b756%241@news.povray.org%3E/

I see no reason this couldn't be true for the sor too - even if all that 
happens internally is normalizing the decreasing point during parsing 
and setting a flag to flip the normals.

That said. When I relaxed the parser's sanity checking so I could try 
and render the reversed point set I got no sor result. Given other 
discoveries this morning this might also be related to segments simply 
dropping out due how the internal cylinder bounding is being done. I 
don't know. I don't know. I don't know.

Bill P.


Post a reply to this message

From: Bald Eagle
Subject: Re: SOR documentation
Date: 9 Sep 2025 09:05:00
Message: <web.68c025a1251da1bc646727bb25979125@news.povray.org>
William F Pokorny <ano### [at] anonymousorg> wrote:
> On 9/8/25 14:06, Bald Eagle wrote:
> >> (*) I tried inverting all the on curve points and this does NOT work as
> >> I incorrectly remembered for some recent sor{} post - that must be a
> >> lathe{} only thing.
> ...> Right, because sor is an implicit interpolation, and lathe is a
> parametric
> > interpolation.
>
> Unsure. With the lathe the reason to flip the point set order is to flip
> the normals (and perhaps too textures on parts of the resulting shape). Ref:
>
>
https://news.povray.org/povray.binaries.images/thread/%3C5745b756%241@news.povray.org%3E/

Yes, but this is not what I'm talking about.
I'm not trying to reverse the order of the entire point set, (which _ought_ to
be a valid point set for the sor - I think it's just "lazily" coded to check in
one direction - I think it could easily check for points going sequentially in
either direction)  I'm just trying to use ANY value for either the first or last
control point to change the tangent direction at the endpoints.

> I see no reason this couldn't be true for the sor too - even if all that
> happens internally is normalizing the decreasing point during parsing
> and setting a flag to flip the normals.

Yes, but even if we still just had the current sor monotonically increasing in
y, we could just switch texture and interior_texture to achieve the same result.
But I agree that given your point, sor could really use a much more in-depth
investigation and possible/probable recoding.

With regard to the abs() implementation, that was only to be applied to the r
result of the sor, so that anything that crossed the rotation axis would be a
valid control point.  I just didn't see why a mirror-image control point would
be invalid.

> That said. When I relaxed the parser's sanity checking so I could try
> and render the reversed point set I got no sor result. Given other
> discoveries this morning this might also be related to segments simply
> dropping out due how the internal cylinder bounding is being done.

I skimmed over the internal bounding part, but can try to devote some more time
to verifying what it does and how.

One thing that I noticed with going over the source code several different
objects is that we have a repetition of spline code - why don't we have all the
splines in one place and use them as the basis for all the various objects that
use them?

Simplifying things like that would make sure that the splines are consistent
between the various objects, and potentially open up the ability to use
user-defined spline interpolations for defining the outline of the objects.

- BW


Post a reply to this message

From: Bald Eagle
Subject: Re: SOR documentation
Date: 9 Sep 2025 13:40:00
Message: <web.68c065bf251da1bc646727bb25979125@news.povray.org>
William F Pokorny <ano### [at] anonymousorg> wrote:

>      <+1.5,+0.91> // C4
>
> and the shape breaks apart(a)(b). In the bottom row I changed that last
> control point to:
>
>     <+1.5,+0.901> // C4
>
> and the entire top segment drops out.

Looking at the code, I'd say that either it's the solver or the EPSILON value -
or both.  That's definitely a weird result, and you have an excellent sense for
employing good incidental test cases.
I'd say that this is the kind of thing where more extensive diagramming of the
actual control points and cubic spline would be helpful, and maybe have a grid
of sor {} objects with varying control points.

I have a bit of trouble putting all of the pieces in sor.cpp together to see how
all of the data flows in order to make the actual sor on-screen.  If you could
explain that briefly, that would be a huge help in my ongoing investigations and
debugging.

Do you see anywhere that the code would simply not render the surface?  Any way
to indicate to the user that it does such a thing?

> (b) In yuqk the parts of the sor there all look good. In v3.8 beta 2,
> the results for top segment are noisy; Likely solver differences.

In the source:
Where is "Number" defined?
Where is EPSILON defined?

Some things I've noticed and am confused by:

In void Sor::Compute_Sor(Vector2d *P, RenderStatistics& stats) [Line 960]

starting at line 1003, we have:
    for (i = 0; i < Number; i++)
    {
        if ((fabs(P[i+2][Y] - P[i][Y]) < EPSILON) ||
            (fabs(P[i+3][Y] - P[i+1][Y]) < EPSILON))
        {
            throw POV_EXCEPTION_STRING("Incorrect point in surface of
revolution.");
        }

which is the only check that throws that error, and because it uses fabs (),
that doesn't actually check for the control points doubling back on themselves,
it seems like that's a check to make sure the tangent doesn't have a slope of
zero.

Now, moving down to line 1078, we have:
        while (n--)
        {
            if ((r[n] >= y[0]) && (r[n] <= y[1]))
            {
                x[n] = sqrt(r[n] * (r[n] * (r[n] * A + B) + C) + D);
            }
        }

and I'm confused as to why r is getting compared to the y value and not the x
value.  It seems that the radius ought to be compared to the control point x
values - unless I'm missing something.

Also, as far as I'm aware, the Catmull-Rom spline doesn't have as well-defined a
control polygon as a Bezier spline does, and so I'm wondering if there needs to
be a better bounding estimate for the min and max values.

So something that's been bouncing around the ole' noggin but I haven't yet
articulated is:
If we interpolate a spline with entirely valid control points, but the
interpolated part winds up crossing the rotation axis - what happens?


Post a reply to this message

From: Bald Eagle
Subject: Re: SOR documentation
Date: 9 Sep 2025 15:50:00
Message: <web.68c08422251da1bcfceb8cd325979125@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:

> Now, moving down to line 1078, we have:
>         while (n--)
>         {
>             if ((r[n] >= y[0]) && (r[n] <= y[1]))
>             {
>                 x[n] = sqrt(r[n] * (r[n] * (r[n] * A + B) + C) + D);
>             }
>         }
>
> and I'm confused as to why r is getting compared to the y value and not the x
> value.  It seems that the radius ought to be compared to the control point x
> values - unless I'm missing something.

This is because good ole' Dieter likes to mix and match labels between the
comments and the code.
r here is the array of roots found by the polynomial solver, not the radius of
the sor at that height (which is x).  So we're just checking to make sure we're
testing between the roots.  Still need to see why the roots bracket a spline
segment . . .

- BW


Post a reply to this message

From: Bald Eagle
Subject: Re: SOR documentation
Date: 10 Sep 2025 09:30:00
Message: <web.68c17cd1251da1bcbe3debd925979125@news.povray.org>
William F Pokorny <ano### [at] anonymousorg> wrote:
.... how the internal cylinder bounding is being done. I

Check out Fig. 5, pg 11
https://www.cemyuksel.com/research/catmullrom_param/catmullrom_cad.pdf

We might have better luck if we changed how the bounding is done.
It also shows how I can create a set of control points where the curve
overshoots the control point polygon, and so I can use that to have the
interpolated curve cross over the rotation axis to see what happens.

I'll make a speculative prediction and say that the algorithm will try to take
the sqrt of that negative radius and fail - either throwing an error, or just
blanking out that portion of the curve - or the whole segment.

I'll probably have to convert most of the solver code to SDL and then use what I
get out of that to start to answer some other questions.

- BW


Post a reply to this message

From: William F Pokorny
Subject: Re: SOR documentation
Date: 10 Sep 2025 11:16:51
Message: <68c19663$1@news.povray.org>
On 9/10/25 09:27, Bald Eagle wrote:
> I'll make a speculative prediction and say that the algorithm will try to take
> the sqrt of that negative radius and fail - either throwing an error, or just
> blanking out that portion of the curve - or the whole segment.

Thanks for reference! :-)

If you're referring to the sqrt I think you are, you've guessed 
correctly! :-) I have a potential fix for it. The sqrt(-) along with 
some fine detail in how std::min(), std::max() work when passed a -nan 
value as the first argument vs the second argument cause the segment 
blink out issue. Only limited testing thus far. Maybe I'll get to more 
tonight.

I see some other not really wrong, but not optimal stuff happening too 
with the cylinder segment bounding in y. Sort of as if it was written to 
support on curve points in ascending or descending order less any 
optimization for the y coordinates (The cylinders get taller and taller 
as you have more segments instead of aligning with each of the segments 
in y).

Bill P.


Post a reply to this message

From: William F Pokorny
Subject: Re: SOR documentation
Date: 11 Sep 2025 05:58:33
Message: <68c29d49$1@news.povray.org>
On 9/10/25 11:16, William F Pokorny wrote:
> If you're referring to the sqrt I think you are, you've guessed 
> correctly! 🙂 I have a potential fix for it. The sqrt(-) along with some 
> fine detail in how std::min(), std::max() work when passed a -nan value 
> as the first argument vs the second argument cause the segment blink out 
> issue. Only limited testing thus far. Maybe I'll get to more tonight.

Attached an image of some more testing. It includes the fix for the 
segment blink out issue & that fix looks good thus far. For testing I 
disabled all the point list sanity checking to see what works and not.

---

Not going to go through the image in detail, but in answer to your 
question about on curve points going negative it looks like a no go 
without a deep dive and probable re-work of the current code.

For reasons I don't understand, when I allow on curve points to go 
negative the camera ray direction affects results. This shown in the 
fourth row where the sor slowly disappears then reappears as rotated 
about x.

---

The descending in y on curve points doesn't work at all.

---

Allowing the first and last control points to go negative is fine and I 
plan to add that relaxing to the blank out fix for yuqk's next release.

---

You had mentioned not being able to flip the two control points in y. 
Where everything I'd tried to that point seemed to work. You also 
mentioned this bit of code in sor.cpp :

if ((fabs(P[i+2][Y] - P[i][Y]) < gkMinIsectDepthReturned) ||
     (fabs(P[i+3][Y] - P[i+1][Y]) < gkMinIsectDepthReturned))
{
throw POV_EXCEPTION_STRING("Incorrect point in surface of revolution.");
}

I'm finding it is this run time check which sometimes doesn't allow 
control points flipping in y. For yuqk what will be in the next release 
is some added error text when that check trips so it is easier to 
understand what is wrong.

Error! Problem point in sor segment 0 point set.
fabs(P[2][Y] - P[0][Y] || fabs(P[3][Y] - P[1][Y])
fabs(0.5 - 0.5 || fabs(0.9 - 0) < 4.44089e-08

The center images in the bottom two rows(*) of the attached image trip 
this check and error. So, that code is catching some 'particular' cases 
where given the control point locations relative to other on curve 
points doesn't render correctly.

(*) Those rows are start the control points at one extreme and slowly 
flip them to the opposite extreme in y moving left to right in the lower 
two rows.

---

So with the segment blink out fix, it does look like more could be 
allowed as valid point sets for the sor & yuqk will adopt those 
relaxations. The shapes with negative control points do break up more 
often, but as we found this can happen today with certain point lists.

(I've not really looked at intersections and differences as yet)

Bill P.

Aside: Somewhere I should mentioned too that that blink out fix corrects 
the blink out, but in certain cases it also slightly corrects bounding 
cylinders where due how min/max work there was no blink out. In other 
words some fringe fixes/differences might appear too due the blink out fix.


Post a reply to this message


Attachments:
Download 'sor_testing.png' (114 KB)

Preview of image 'sor_testing.png'
sor_testing.png


 

From: Bald Eagle
Subject: Re: SOR documentation
Date: 11 Sep 2025 10:40:00
Message: <web.68c2de77251da1bcf34d8a9e25979125@news.povray.org>
William F Pokorny <ano### [at] anonymousorg> wrote:

> Attached an image of some more testing. It includes the fix for the
> segment blink out issue & that fix looks good thus far.

So what did you do?

in line 1082
x[n] = sqrt(r[n] * (r[n] * (r[n] * A + B) + C) + D);

I'd suggest changing that something like

x[n] = sqrt( fabs(r[n] * (r[n] * (r[n] * A + B) + C) + D) );


> Not going to go through the image in detail, but in answer to your
> question about on curve points going negative it looks like a no go
> without a deep dive and probable re-work of the current code.

I'd suggest the above, if you haven't already done that.

Also, it may have something to do with calculating the intersections.

There's a check on Radius2 that I saw, so see what happens when you change:

Lines 1110-1111
Radius1 = xmin;
Radius2 = xmax;

to use fabs()

> For reasons I don't understand, when I allow on curve points to go
> negative the camera ray direction affects results. This shown in the
> fourth row where the sor slowly disappears then reappears as rotated
> about x.


> The descending in y on curve points doesn't work at all.

Not surprising - all the checks for the control point order need to be
rewritten.


> You had mentioned not being able to flip the two control points in y.
> Where everything I'd tried to that point seemed to work.

I'll have to do some more experimenting when I get the chance.

> You also
> mentioned this bit of code in sor.cpp :
>
> if ((fabs(P[i+2][Y] - P[i][Y]) < gkMinIsectDepthReturned) ||
>      (fabs(P[i+3][Y] - P[i+1][Y]) < gkMinIsectDepthReturned))
> {
> throw POV_EXCEPTION_STRING("Incorrect point in surface of revolution.");
> }
>
> I'm finding it is this run time check which sometimes doesn't allow
> control points flipping in y.

That def seems to be related to what you're seeing in those last 2 rows - since
the cp's are nearly coincident in y.


> The shapes with negative control points do break up more
> often, but as we found this can happen today with certain point lists.

Do you think as a quick fix, we could just add -ymin to all the values to
translate everything into the first quadrant, starting at y=0, and then
translate everything back after the math gets done?

Very nice that some of this is getting worked out after 30 years.  :)

- BW


Post a reply to this message

From: William F Pokorny
Subject: Re: SOR documentation
Date: 11 Sep 2025 22:27:06
Message: <68c384fa$1@news.povray.org>
On 9/11/25 10:36, Bald Eagle wrote:
>> Attached an image of some more testing. It includes the fix for the
>> segment blink out issue & that fix looks good thus far.
> So what did you do?

The current fix is:

     if ((r[n] >= y[0]) && (r[n] <= y[1]))
     {
//      x[n] = sqrt(r[n] * (r[n] * (r[n] * A + B) + C) + D);
         double tmpVal = (r[n] * (r[n] * (r[n] * A + B) + C) + D);
         if (tmpVal>=0.0)
             x[n] = sqrt(tmpVal);
         else
         {
             tmpVal = std::abs(tmpVal);
             x[n] = sqrt(tmpVal);
             x[n] *= -1.0;
         }
     }

As for the bounding suggestion, I don't know. Of note is that the 
Radius1 value is never used that I see.

Something I did try was faking a user bounding radius multiplier option. 
In some configurations where only a subset of the on curve points were 
negative in x. It often helped with apparent clipping - but there always 
remained some issue with the the ray directions relative to the overall 
sor - where all or part of sor 'segment(s)' would drop away (this an 
issue apart from the entire-segment blink out issue up top).

My wild guess. There are internally calculated A,B,C,D values used for 
the quadratic eqn solved while setting the two bounding radii values. 
Those calculated values involve the x values as given for the sor point 
set. Maybe something could go 'more right' there when negative values 
are present - I don't know.

Bill P.


Post a reply to this message

<<< Previous 10 Messages Goto Initial 10 Messages

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