You,
gentle reader,
are reading this documentation off of CPAN.
I know this because this paragraph does not show up in the final .pm files that are installed on a user's computer.
The documentation that you see may have a few subtle differences from the documentation that you would view on your computer using podview or perldoc.
If you have any concerns regarding documentation skew,
be sure to check the documentation on your local machine.

This module provides a number of PDL-threaded functions and bindings for use with the Prima toolkit. Many of the functions are PDL bindings for the standard Prima drawing functions. Others are useful functions for color manipulation, or getting data into a form that PDL knows how to handle. I generally divide the subroutines of this module into two categories: methods and functions. The methods are subroutines that operate on a Prima widget; the functions are subroutines that act on or return piddles.

Most of the methods given here are PDLified versions of the Prima drawing API functions, which are documented under Prima::Drawable. In general, where the Prima API uses singular nouns, I here use plural nouns. A few of the methods are only available in this module, mostly added to accomodate the needs of PDL::Graphics::Prima, the plotting library built on these bindings.

This bindings can be applied to any object whose class is derived from Prima::Drawable, including displayed widgets and abstract canvases such as Prima::PS::Drawable. If you create your own derived canvas, these methods should Just Work. (I wish I could take credit for this, but it's really due to the fact that Prima's internals are very well engineered.)

The Prima image coordinate origin is located in lower left corner, which is where you would expect to find it when creating plots. However, it is different from the way that many graphics libraries do their coordinates.

If you want PDL to thread over line patterns, but you want to use the standard Prima line patterns, you'll need to convert them line patterns to a piddle. This works very simply like this:

my $patterns = piddle_of_patterns_for(lp::Solid, lp::Dash);

This creates a piddle with the two patterns so that you could have PDL thread over them.

You can also create your own line pattern piddles by hand. I recommend you use byte array, since otherwise it will be converted to byte arrays for you. The first element of a row in your byte array specifies the number of pixels to be "on", the second specifies the number to be "off", the third specifies the number to be "on" again, the fourth "off", the fifth "on", etc. If that doesn't make sense, hopefully a couple of examples will help clarify.

This example creates the equivalent of lp::Dash:

my $dash_pattern = byte (9, 3);

This example creates a piddle with four line types: lp::Solid, lp::Dash, lp::ShortDash, and lp::DashDot:

When you create a byte piddle, all of the patterns must have the same number of bytes in their specification. Of course, different patterns have different lengths, so in that case simply pad the shorter specifications with zeroes.

THIS FUNCTION IS DEPRECATED AND NOW DIES IF YOU TRY TO USE IT. Performing the same PDL drawing operation on different widgets via PDL threading makes atomic behavior very difficult, so this functionality has been removed. If you think you'd like this behavior back, please let me know.

The methods described below are a bit unusual for PDL functions. First, they are not actually PDL functions at all but are methods for Prima::Drawable objects. Second, their signatures will look a bit funny. Don't worry too much about that, though, because they will resemble normal signatures close enough that you should be able to understand them, I hope.

The arcs go from the start_angles to the end_angles along the ellipses centered at the xs and ys, with the specified x- and y-diameters. The angles are measured in degrees, not radians. The difference between this command and "chords" or "sectors" is that arcs does not connect the dangling ends.

The chord starts at start_angle and runs to end_angle along the ellipse centered at x, y, with their specified diameters x_diameter, y_diameter. Unlike "arcs" or "sectors", it connects the ends of the arc with a straight line. The angles are measured in degrees, not radians.

Chords are partial elipses that run from start_angle to end_angle along the ellipse centered at x, y, each with their specified diameters. The ends are connected with a line and the interior is filled. Use this to draw the open-mouth part of a smiley face.

NOTE: there is no underscore between fill and poly, which is different from the other fill methods!

This is useful for drawing arbitrary filled shapes and for visualizing integrals. Splines would be the better choice if you want to draw curves, but a PDL interface to splines is not (yet) implemented.

Unlike most of the other methods, this one actually makes a half-hearted effort to process bad values. In addition to the IEEE bad values of nan and inf, PDL has support for bad values. Unlike in pdl_polys, pdl_fillpolys will simply skip any point that is marked as bad, but drawing the rest of the polygon. In other words, it reduces the degree of your polygon by one. If you sent it four points and one of them was bad, you would get a triangle instead of a quadralaters.

Infinities are also handled, though not perfectly. There are a few situations where pdl_polys will correctly draw what you mean but pdl_fillpolys will not.

Because this skips bad data altogether, if you have too much bad data (i.e. fewer than three good points), the routine will simply not draw anything. I'm debating if this should croak, or at least give a warning. (Of course, a warning to STDOUT is rather silly for a GUI toolkit.)

More specifically, this draws an arc from start_angle to end_angle along the ellipse centered at x, y, with specified x- and y-diameters. Like "fill_chords", this command connects the end points of the arc, but unlike "fill_chords", it does so by drawing two lines, both of which also connect to the ellipse's center. This results in shapes that look like pie pieces or pie remnants, depending of whether you're a glass-half-full or glass-half-empty sort of person.

NOTE THIS MAY NOT WORK ON MACS! There seems to be a bug in either Prima or in Mac's X-windows library that prevents this function from doing its job as described. That means that flood filling is not cross-platform, at least not at the moment. This notice will be removed from the latest version of this documentation as soon as the item is addressed, and it may be that your version of Prima has a work-around for this problem. At any rate, it only effects Mac users.

Note that fill_color is probably not what you think it is. The color of the final fill is determined by your colors property. What, then, does fill_color specify? It indicates how Prima is supposed to perform the fill. If singleborder is zero, then fill_color is the color of the boundary to which Prima is to fill. In other words, if you had a bunch of intersecting lines that were all red and you wanted the interior of those intersecting lines to be blue, you would say something like

$widget->pdl_flood_fills($x, $y, cl::Red, 0, colors => cl::Blue);

On the other hand, if singleborder is 1, then the value of fill_color tells Prima to replace every contiguous pixel of colorfill_color with the new color specified by colors (or the current color, if no colors piddle is given).

If you put that snippet of code in the example from the synopsis, you should see a number of narrow rectangles intersecting circles, with the interior of both shapes filled. Resizing the window will lead to randomly changed positions for those space-ship looking things.

In contrast to polylines, which are supposed to be connected, these lines are meant to be independent. Also note that this method does make an effort to handle bad values, both the IEEE sort (nan, inf) and the official PDL bad values. See pdl_polylines for a discussion of what might constitute proper bad value handling.

This method goes to great lengths to Do What You Mean, which is actually harder than you might have expected. This is the backbone for the Lines plot type of PDL::Graphics::Prima, so it needs to be able to handle all manner of strange input. Here is what happens when you specify strange values:

If an x value is infinite (but the paired y value is not), a horizontal line is drawn from the previous x/y pair out to the edge of a widget; another line is drawn from the edge to the next x/y pair. The behavior for an infinite y value is similar, except that the line is drawn vertically.

For example, the three points (0, 1), (1, 1), (2, inf), (3, 1), (4, 1) would be rendered as a line from (0, 1) to (1, 1), then a vertical line straight up from (1, 1) to the upper edge of the widget or clipping rectangle, then a vertical line straight down to (3, 1) from the upper edge of the widget or clipping rectangle, then a horizontal line from (3, 1) to (4, 1).

If x or y is a large value (say, both x and y are 5e27 when the rest of your numbers are of the order of 100), it will not be possible to actually show a renderin of a line to that point. However, it is possible to correctly render the slope of that point out to the edge of the clipping rectangle. Thus the slope of the line from within-clip points to large values is faithfully rendered.

Here's an example of how to plot data using pdl_polylines (though you'd do better to use PDL::Graphics::Prima to create plots):

More specifically, this draws an arc from start_angle to end_angle along the ellipse centered at x, y, with specified x- and y-diameters. Like "fill_chords", this command connects the end points of the arc, but unlike "fill_chords", it does so by drawing two lines, both of which also connect to the ellipse's center. This results in shapes that look like pie pieces or pie remnants, depending of whether you're a glass-half-full or glass-half-empty sort of person.

Through various combinations of N_points, filled, and skip, you can generate many different regular symbols, including dashes, stars, asterisks, triangles, and diamonds. You can also specify each symbol's size and orientation. The size is the radius of a circle that would circumscribe the shape. The orientation is... well... just keep reading.

This will draw a circle with a radius of the given size. The circle will be filled or not based on the value passed for filled, but the orientation and skip parameters are ignored. This is almost redundant compared with the ellipse functions, except that this arrangement makes it very easy to thead over filled/not-filled, and you cannot specify an eccentricity for your points using pdl_symbols.

This will draw a line centered at (x, y) and with a length of 2*size. The orientation is measured in degrees, starting from horizontal, with increasing angles rotating the line counter-clockwise. The value for skip is ignored.

This is particulary useful for visualizing slope-fields (although calculating the angles for the slope field is surprisingly tricky).

This will draw a shape related to a regular polygon with the specified number of sides. Precisely what kind of polygon it draws is based on the value of skip. For example, a five-sided polygon with a skip of one would give you a pentagon:

A skip of zero is a special case, and means draw lines to each point from the center. In other words, create an asterisk:

second point
third /
point `. /
`. /
`./_______ first
.'\ point
.' \
.' \
fourth \
point
fifth point
skip = 0

In summary, a skip of zero gives you an N-asterisk. A skip of one gives you a regular polygon. A skip of two gives you a star. And so forth. Higher values of skip are allowed; they simply add to the winding behavior.

Specifying the orientation changes the position of the first point and, therefore, all subsequent points. A positive orientation rotates the first point counter-clockwise by the specified number of degrees. Obviously, due to the symmetry of the shapes, rotations of 360 / N_points look identical to not performing any rotation.

For all nonzero values of skip, specifying a fill will end up with a filled shape instead of a line drawing.

By default, filled stars and other symbols with odd numbers of points have a hole in their middle. However, Prima provides a means for indicating that you want such shapes filled; that is the fillWinding property. As with almost all graphical properties, you can specify the fillWinding property for each symbol by specifying the fillWindings piddle.

This example creates a table of shapes. It uses an argument from the command line to determine the line width.

This means that you tried to draw on something that is not a Prima::Drawable object, or a class derived from it. I don't know enough about the Prima internals to know if that has any hope of working, but why do it in the first place?

Those well versed in PDL::PP might ask how I manage to produce pdlified methods that take variable numbers of arguments. That is a long story, and it is told in the volumes of comments in pdlprima.pd. Give it a read if you want to know what goes on behind the scenes.

Bad values are handled decently in "polylines" and "fillpolys", but not for the other functions. Bad x/y values should be skipped for almost all the drawing primitives, but what about bad colors for valid coordinates? I could not draw the primitive, defer to the widget's default color, or use the value associated with the singular key (i.e. color). But I haven't decided which of these is best.

Another interface between PDL and Prima is <PDL::PrimaImage>. I am indebted to Dmitry for that module because it gave me a working template for this module, including a working Makefile.PL. Thanks Dmitry!