BoltBait's Pages - Shapes

Sarcasm, just one of the services I offer.

 

Paint.NET Standard Shape Filter

I needed to draw a pentagon, but Paint.NET didn't have a tool to do that.  I don't have a way to create tools, so I did the next best thing--I wrote a Codelab script.

Here are some examples of what you can create with this filter:

The filter takes 3 input variables: (1) Number of sides, (2) Rotation Angle, and (3) Radius.

It always draws the shape using the Primary Color as defined in the Colors docker window.

 

The Idea

I figured that the math would be fairly easy to determine the coordinates of the verticies.  If I use the polar system, I can define the first point to be at 0 degrees (theta) and a specified radius (r).  From that, the next point will be at the same radius and at X degrees (where X = 360 degrees / number of sides).  The rest of the points follow from there.

It is easy to add the rotation angle before converting from polar to Cartesian.

By the way, we convert from polar to Cartesian by using the following formula (in C#):

        angle = Math.PI * ((th * P) + rotation) / 180.0;
        X = (r * Math.Cos(angle)) + CenterX;
        Y = (r * Math.Sin(angle)) + CenterY;

Where th (theta) is the angle in degrees, r is the radius, P is the point number, rotation is the degrees to rotate the diagram, CenterX & CenterY define the center point of the object.  This gives you the coordinates (x,y) of the desired point (P).

Once you find the two end points, it is accademic to draw a line between the two points.  Repeat this for the requested number of sides.

 

Stars

User Madjik on the Paint.NET forum suggested that the code be modified to draw stars as well as standard shapes.  Wow, what a great idea!  I modified the code and added the stars variable.  Setting this to 1 will create the normal standard shape.  Setting it higher than 1 (2, for example) will draw stars.  The upper limit of the stars variable is just below one half the number of verticies.  The updated codelab script is available below.

Here are some examples of stars you can create:

 

The Problem

The real problem with this effect (and why its so slow) is that drawing shapes is really the job of a tool, not an effect.  The way I am rendering the shape does not lend itself well to an Effect plugin.  But, hopefully, you will find this useful... even as slow as it is.

 

The Effect DLL

You can download the precompiled DLL here:  Polygon.dll

Just drop this file in your \program files\Paint.NET\effects directory and you should be all set.

 

Instructions for Use

The best way to use this is to follow these steps:

1) Choose your Primary Color in the color docker window for the outline color that you wish to draw.  For my examples above, I chose White.

2) Use the Circle Selection tool to select the general size of your shape.  Make sure to hold down the Shift Key so that the circle selection is constrained to a true circle.

3) Run the effect.

4) Adjust the input variables for your desired shape.  All of my samples above have been rotated to some degree.

 

Source Code

Here is the Codelab script:

void Render(Surface dst, Surface src, Rectangle rect) 
{ 
 int rpercent = 95; // percent of radius (1-100), default 100, slider 
 int verticies = 5; // number of points (3-10?), default 5, slider 
 int rotation = 15; // degrees to rotate the shape (0-359), default 0, slider 
 int stars = 1; // 1=normal, 2=stars (integer, range 1 to less than verticies/2) 

 PdnRegion selectionRegion = EnvironmentParameters.GetSelection(src.Bounds); 
 Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt(); 

 // Because I have to reset the destination every time 
 // this is reeeeeaaaaallllly slow 
 for(int y = rect.Top; y < rect.Bottom; y++) 
 { 
 for (int x = rect.Left; x < rect.Right; x++) 
 { 
 if (selectionRegion.IsVisible(x, y)) 
 { 
 dst[x,y] = src[x,y]; 
 } 
 } 
 } 

 // If this was a tool, this is where the starting nub is located 
 long CenterX = (long)(((selection.Right - selection.Left) / 2)+selection.Left); 
 long CenterY = (long)(((selection.Bottom - selection.Top) / 2)+selection.Top); 

 // calculate actual radius 
 // If this was a tool, you should calculate this from the second nub location 
 double r = (double)(Math.Min(CenterX-selection.Left,CenterY-selection.Top)/100.0*rpercent); 

 ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; // for 2.72 use .ForeColor; 

 ColorBgra CurrentPixel; 
 double th = 360.0/verticies; 
 double X1 = 0, Y1 = 0, X2 = 0, Y2 = 0; 
 double angle = 0; 

 for (int P = 0; P<=verticies; P++) 
 { 
 // Find the starting point (X1,Y1) 
 angle = Math.PI * ((th * P) + rotation) / 180.0; 
 X1 = (r * Math.Cos(angle)) + CenterX; 
 Y1 = (r * Math.Sin(angle)) + CenterY; 
 // Find next end point (X2,Y2) 
 angle = Math.PI * ((th * (P+stars)) + rotation) / 180.0; 
 X2 = (r * Math.Cos(angle)) + CenterX; 
 Y2 = (r * Math.Sin(angle)) + CenterY; 
 // Draw line from (X1,Y1) to (X2,Y2) 
 DrawLine((int)X1,(int)Y1,(int)X2,(int)Y2, dst, PrimaryColor, selectionRegion); 
 } 
} 

void DrawLine(int x1, int y1, int x2, int y2, Surface dst, ColorBgra LineColor, PdnRegion selectionRegion) 
{ 
 int i,gd,gm; 
 double roundx,roundy,xi,yi,dx,dy,x,y,l; 

 dx=x2-x1; 
 dy=y2-y1; 

 if(Math.Abs(dx)>Math.Abs(dy)) 
 { 
 l=dx; 
 } 
 else 
 { 
 l=dy; 
 } 

 if (l<0) 
 { 
 DrawLine(x2,y2,x1,y1,dst,LineColor,selectionRegion); 
 } 
 else 
 { 
 xi=dx/l; 
 yi=dy/l; 

 x=x1; 
 y=y1; 

 if (selectionRegion.IsVisible((int)x, (int)y)) 
 { 
 dst[(int)x, (int)y] = LineColor; 
 } 

 for(i=1;i<=l;i++) 
 { 
 x=x+xi; 
 y=y+yi; 

 roundx=x+0.5; 
 roundy=y+0.5; 
 if (selectionRegion.IsVisible((int)roundx, (int)roundy)) 
 { 
 dst[(int)roundx, (int)roundy] = LineColor; 
 } 
 } 
 } 
}

 

Here is the VS2005 source code:  PolygonSRC.zip

Just unzip this into your My Documents/Visual Studio 2005/Projects directory and open the solution file.

 

Here is an example of using this plugin to make a shiny sticker:

 

Final Thoughts

This would work MUCH better as a tool than an effect DLL.  I have sent the code to Rick to see if he wants to include a Draw Standard Shape tool in 3.0+.  He let me know that 3.0 is locked down, but he will look at this for a future release.

 

Tuesday, February 6, 2006