Jump to content

Drawing Triangles, Pentagons, Stars, etc. Plugin: 2007-02-09


Recommended Posts

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:

VariousShapes-1.gif

If you like it, you can download the precompiled effect here: BoltBait's Plugin Pack

    PolygonUI.jpg

Visit this site to see step-by-step instructions how to actually use the script: http://boltbait.googlepages.com/shapes

Here is the updated Codelab script: (For you script writers... it is one of the weirdest scripts you'll ever see. Why? Because the rendering loop doesn't seem to do anything!):

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 are some examples of stars you can create:

VariousStars1.gif

Now I want to see what you can do with it!

Source Code

    Since you asked, here is the VS2005 souce code: PolygonSRC.zip (Ignore the fact that I misspelled the project name. :D )
    This should serve as a good example of how to use GDI+ drawing commands on the canvas.
    This should also serve as a good example of how to use this template.

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

Link to post
Share on other sites

Hi

I have got an error line 43:

 ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; 

PrimaryColor isn't recognize (paint 2.72!)

I change it to

ColorBgra PrimaryColor = (ColorBgra) 0;

for the tests.

Try this code to have stars:

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 = 0;        // degrees to rotate the shape (0-359), default 0, slider 
   double angfact = 2;          // angle factor to draw crossing lines, default 1, slider 

   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) 0; 

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

   // Find the first vertex 
   angle = Math.PI * ((th ) + rotation) / 180.0; 
   X1 = (r * Math.Cos(angle*angfact)) + CenterX; 
   Y1 = (r * Math.Sin(angle*angfact)) + CenterY; 

   for (int P = 0; P<=verticies; P++) 
   { 
       // Find next end point (X2,Y2) 
       angle = Math.PI * ((th * P) + rotation) / 180.0; 
       X2 = (r * Math.Cos(angle*angfact)) + CenterX; 
       Y2 = (r * Math.Sin(angle*angfact)) + CenterY; 

       // Draw line from (X1,Y1) to (X2,Y2) 
       DrawLine((int)X1,(int)Y1,(int)X2,(int)Y2, dst, PrimaryColor, selectionRegion); 

       // Get ready for the next line 
       X1 = X2; 
       Y1 = Y2; 
   } 
} 

void DrawLine(int x1, int y1, int x2, int y2, Surface dst, ColorBgra LineColor, PdnRegion selectionRegion) 
{ 
  int i; 
  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; 
        } 
     } 
  } 
} 

Link to post
Share on other sites
Hi

I have got an error line 43:

 ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.PrimaryColor; 

PrimaryColor isn't recognize (paint 2.72!)

I change it to

ColorBgra PrimaryColor = (ColorBgra) 0;

for the tests.

That's correct. Primary color is a 3.0 thing.

For 2.72, change the line to:

ColorBgra PrimaryColor = (ColorBgra)EnvironmentParameters.ForeColor;

Hey! Nice idea for creating stars. I noticed some problems with your code--it doesn't work when you choose a figure with an even number of sides and for some reason, the lines don't come out solid. I'm going to steal that idea and put it on my page. (Well, I won't steal it, per se--I'll credit you.)

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

Link to post
Share on other sites

OK, so, taking Madjik's idea (then fixing it)...

Here is the updated 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     { 
       for (int x = rect.Left; 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    { 
    // 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   { 
     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      { 
        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 are some examples of stars you can create:

VariousStars1.gif

Now, who will put a UI on this?

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

Link to post
Share on other sites
  • 3 weeks later...

Madjik, you could put a dropdown box with the options "star" and "poligon". It's kinda stupid to have a 1-255 slider instead if sometimes nothing appears or appears a star or appears a poligon.

A brush width slider would also be nice.

sig6rj3.png
Link to post
Share on other sites

@ Trickman:

I asked for help for GUI : result near none !

I tried to adapt sources, I found standard GUI with one, two or three sliders. That's what I used for Polygones. I could give my source as well if you want to adapt it, I will look forward to see what you'll change to make it "less stupid" !

@ boilbait:

Thanks for your answer!

Link to post
Share on other sites

Some more explanation about "starisation" with the Polygone Effect:

Let's start with a simple one : Vertice = 7 / Stars = 1.

star1.png

When drawing the polygone the line simply goes from point 0 (not shown, sorry) to point 1 to point 2 etc...

If then we change stars to 2:

star2.png

The line will skip one point. The line goes from point 0 to point 2 to point 4 etc...

Then we have crossing lines that are drawing a star.

If then we change stars to 3:

star3.png

The line will skip two points. The line goes from point 0 to point 3 to point 6 etc...

Then the star looks fine.

If then we change stars to 4:

star4.png

The line will skip three points. The line goes from point 0 to point 4 to point 1 etc...

Then the star looks exactly as the previous one (stars=3) but it is drawn the other way.

If then we change stars to 5 then the star should look as stars=2 but it is drawn the other way.

If then we change stars to 6 then the star should look as stars=1 but it is drawn the other way.

And finaly if we set stars to 7 then all lines are going from point 0 to point 0 so we have a spot.

To have some kind of stickers you should draw a star with a lot of vertices like this example (vertice=29 stars=9)

With the magic wand select outside the star and invert the selection by Ctrl+I then use the gradient effect to fill it.

star29.png

Link to post
Share on other sites
  • 1 month later...

Yes but when people think "Curves" w.r.t. image editing software, they think of this: http://www.getpaint.net/doc/3.0/en/Curves.html . Maybe replace the word "curves" with "shapes."

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to post
Share on other sites

MadJik, could you send me the source code to the Polygon effect? I would like to look at it.

Also, I've been thinking a lot about effect submenus. I think that anything that creates something new (like drawing shapes) should be in a submenu called "Render".

Here is how I group the effects that I have written:

http://boltbait.googlepages.com/

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...