Path stroke with multiple colors?
-
I've programatically built up a Path object. This part works perfect. Now I want to add a vertical "threshold". So say my path goes from Y=0 to Y=100. The "threshold" may be at Y=50 or whatever. I want the path Y <= 50 to be blue and the path Y > 50 to be green or whatever. So, right now, I'm using a LinearGradientBrush (oriented vertical and calculate the transition point and do something like 0 color1 0.5 color1 0.5 color2 1 color2 By having the two stops at 0.5, you get the hard color transition which is what I'm looking for. Now the problem :)... Depending on where the threshold line is, the LinearGradientBrush gets round off errors and sometimes the color break is 1 line too high, sometimes 1 line too low. What I mean is, my control is 27 pixels high, so the threshold line is at y=14. So theoretically, color1 should always be above the line and color2 below, but sometimes it shifts up due to the round off errors. Any other way to do this that'll yield better results?
-
I've programatically built up a Path object. This part works perfect. Now I want to add a vertical "threshold". So say my path goes from Y=0 to Y=100. The "threshold" may be at Y=50 or whatever. I want the path Y <= 50 to be blue and the path Y > 50 to be green or whatever. So, right now, I'm using a LinearGradientBrush (oriented vertical and calculate the transition point and do something like 0 color1 0.5 color1 0.5 color2 1 color2 By having the two stops at 0.5, you get the hard color transition which is what I'm looking for. Now the problem :)... Depending on where the threshold line is, the LinearGradientBrush gets round off errors and sometimes the color break is 1 line too high, sometimes 1 line too low. What I mean is, my control is 27 pixels high, so the threshold line is at y=14. So theoretically, color1 should always be above the line and color2 below, but sometimes it shifts up due to the round off errors. Any other way to do this that'll yield better results?
That's an interesting problem which takes me back to when I was at Adobe implementing the PostScript code for printing the very complex gradients that Illustrator 5.0 enabled. It might be helpful if you could post a link to a graphic, or two. Knowing what type of elements you used to build the Path would also be useful: arc ? bezier ? I wonder if your use-cases are approaching the limits of what can be resolved in terms of color-shift on the screen ? One idea/guess: what if you built a Graphics Region of only "line-to's" ("flattening" arcs or beziers into line segments), and then rendered the Path by enumerating the Region ? Well, does sound far-fetched and what about impact on performance, but no harm done trying to think-outside-the-box, here.
«OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. » Alan Kay's clarification on what he meant by the term "Object" in "Object-Oriented Programming."
-
That's an interesting problem which takes me back to when I was at Adobe implementing the PostScript code for printing the very complex gradients that Illustrator 5.0 enabled. It might be helpful if you could post a link to a graphic, or two. Knowing what type of elements you used to build the Path would also be useful: arc ? bezier ? I wonder if your use-cases are approaching the limits of what can be resolved in terms of color-shift on the screen ? One idea/guess: what if you built a Graphics Region of only "line-to's" ("flattening" arcs or beziers into line segments), and then rendered the Path by enumerating the Region ? Well, does sound far-fetched and what about impact on performance, but no harm done trying to think-outside-the-box, here.
«OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. » Alan Kay's clarification on what he meant by the term "Object" in "Object-Oriented Programming."
Here is perhaps a simple example. I might be getting thrown off by the gradient behavior. If you print screen and zoom in with Paint (or some program that doesn't muck with the pixels as you zoom), you'll see the gradient isn't doing a clean break. Even though if you punch the numbers into Calc, they looks correct to me.
-
That's an interesting problem which takes me back to when I was at Adobe implementing the PostScript code for printing the very complex gradients that Illustrator 5.0 enabled. It might be helpful if you could post a link to a graphic, or two. Knowing what type of elements you used to build the Path would also be useful: arc ? bezier ? I wonder if your use-cases are approaching the limits of what can be resolved in terms of color-shift on the screen ? One idea/guess: what if you built a Graphics Region of only "line-to's" ("flattening" arcs or beziers into line segments), and then rendered the Path by enumerating the Region ? Well, does sound far-fetched and what about impact on performance, but no harm done trying to think-outside-the-box, here.
«OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. » Alan Kay's clarification on what he meant by the term "Object" in "Object-Oriented Programming."
Jesus... why is everything like pulling teeth? So I tried going down a different path (no pun intended) and decided to split the path along the threshold line. That way I wouldn't have to deal with the gradient rounding errors. So, I find some code to split the path (combining the geometry with an exclusion rectangle) and I tweak it to split it how I want it. Then I notice that the half that has the last point auto closes to the first point!! Are you serious? What good is that? I find a post about somebody else complaining about it **5 YEARS** ago on the MSDN forums and the MSDN guys respond saying they "know about it, but oh well, that's how it works..." :mad: :mad: :mad:
-
Here is perhaps a simple example. I might be getting thrown off by the gradient behavior. If you print screen and zoom in with Paint (or some program that doesn't muck with the pixels as you zoom), you'll see the gradient isn't doing a clean break. Even though if you punch the numbers into Calc, they looks correct to me.
Sorry, SledgeHammer, I think my post was way off-target in terms of really understanding what you are doing. I certainly do have a deep experience in "gradient fills," and some form of awkward out-of-kilter color transitions (banding) resulting from "impedance mismatch" between bitmap resolution and rendering-device resolution and type is certainly a typical problem. I spent months while at Adobe (in the late Neolithic era) doing systematic research on creating optimized PostScript code that took into account device characteristics (from 300 dpi laser-printers, to 2400 dpi photo-typesetters, to inkjets, etc.) in deciding how to render gradients in color separations, as well as mono-color. So, please forget my whacko idea about using 'Regions: I focused on "Path" in terms of how you might be "stroking it" rather than "filling it."
«OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. » Alan Kay's clarification on what he meant by the term "Object" in "Object-Oriented Programming."
-
Sorry, SledgeHammer, I think my post was way off-target in terms of really understanding what you are doing. I certainly do have a deep experience in "gradient fills," and some form of awkward out-of-kilter color transitions (banding) resulting from "impedance mismatch" between bitmap resolution and rendering-device resolution and type is certainly a typical problem. I spent months while at Adobe (in the late Neolithic era) doing systematic research on creating optimized PostScript code that took into account device characteristics (from 300 dpi laser-printers, to 2400 dpi photo-typesetters, to inkjets, etc.) in deciding how to render gradients in color separations, as well as mono-color. So, please forget my whacko idea about using 'Regions: I focused on "Path" in terms of how you might be "stroking it" rather than "filling it."
«OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. » Alan Kay's clarification on what he meant by the term "Object" in "Object-Oriented Programming."
It is a stroked line. Think of a stock chart for example. Typically, its a line graph where the above last close is stroked green and the below last close is stroked red. The last close line is typically a 1 pixel horizontal line. So, its very important asthetically for red pixels not to "bleed" over into the part of the chart thats above the last close line and for green pixels not to "bleed" over into the part of the chart thats below the last close line. So... I'm trying to implement something similiar. Paths don't natively support that kind of stroking, so the WPF "trick" is to use a vertical LinearGradientBrush and do a hard color change over at the correct Y position to match up with the horizontal line. Unfortunately, the LinearGradientBrush works on a 0.0 to 1.0 coordinate system where as a line placed on a grid is going to work on a 0.0 to 26.0 coordinate system (control is 27 pixels high). I kind of gave up on splitting the path as that has the same issue as the LinearGradientBrush and introduces the whole problem of having to write my own split algorithm. So it seems like the real problem is I'm not "rounding / fudging" the LinearGradientBrush in the same way that a 1 pixel horizontal line is going to get rounded / fudged on to the grid. Think about it, if I have a 27 pixel high control, there is certainly a center horizontal line at y=14 and you are left with 13 pixels on either side. HOWEVER, mathamatically speaking, that point is at 13.5. Since my control is 27 pixels high, I think the y position needs to be rounded to .5's to match up the gradient break with the line break. Haven't quite matched the WPF fudging though :(.
-
It is a stroked line. Think of a stock chart for example. Typically, its a line graph where the above last close is stroked green and the below last close is stroked red. The last close line is typically a 1 pixel horizontal line. So, its very important asthetically for red pixels not to "bleed" over into the part of the chart thats above the last close line and for green pixels not to "bleed" over into the part of the chart thats below the last close line. So... I'm trying to implement something similiar. Paths don't natively support that kind of stroking, so the WPF "trick" is to use a vertical LinearGradientBrush and do a hard color change over at the correct Y position to match up with the horizontal line. Unfortunately, the LinearGradientBrush works on a 0.0 to 1.0 coordinate system where as a line placed on a grid is going to work on a 0.0 to 26.0 coordinate system (control is 27 pixels high). I kind of gave up on splitting the path as that has the same issue as the LinearGradientBrush and introduces the whole problem of having to write my own split algorithm. So it seems like the real problem is I'm not "rounding / fudging" the LinearGradientBrush in the same way that a 1 pixel horizontal line is going to get rounded / fudged on to the grid. Think about it, if I have a 27 pixel high control, there is certainly a center horizontal line at y=14 and you are left with 13 pixels on either side. HOWEVER, mathamatically speaking, that point is at 13.5. Since my control is 27 pixels high, I think the y position needs to be rounded to .5's to match up the gradient break with the line break. Haven't quite matched the WPF fudging though :(.
Okay, well I understood your question more than I thought I did :) Given the presence of a "last close" line in some color other than red or green, and assuming there's always at least one pixel of "open space" both below and above the integer value of the height of the close line: I'd simply draw the red line up to close line height minus one, and draw the green line beginning vertically at close line height plus one. So I'd be validating the last vertical position of the red line, and the first vertical position of the green line and "doing the right thing." I'd also draw the close line last ... as an overlay ... to hide any mistakes that were made. Am I on your frequency yet ?
«OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. » Alan Kay's clarification on what he meant by the term "Object" in "Object-Oriented Programming."