Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Drawing star shapes with variable parameters

Tags:

java

shapes

swing

I have task to write program allowing users to draw stars, which can differ in size and amount of arms. When I was dealing with basic stars I was doing it with GeneralPath and tables of points :

     int xPoints[] = { 55, 67, 109, 73, 83, 55, 27, 37, 1, 43 };
     int yPoints[] = { 0, 36, 36, 54, 96, 72, 96, 54, 36, 36 };
     Graphics2D g2d = ( Graphics2D ) g;
     GeneralPath star = new GeneralPath();
     star.moveTo( xPoints[ 0 ], yPoints[ 0 ] );
     for ( int k = 1; k < xPoints.length; k++ )
     star.lineTo( xPoints[ k ], yPoints[ k ] );
     star.closePath();
     g2d.fill( star );

What method should I choose for drawing stars with variable inner and outer radius, as well as different amount of arms ? This is what I should obtain :

alt text http://img228.imageshack.us/img228/6427/lab6c.jpg

like image 655
sasklacz Avatar asked Apr 25 '10 21:04

sasklacz


2 Answers

Having n arms means you end up with 2n vertices, the even ones are on the outer circle, and the odd ones on the inner circle. Viewed from the center, the vertices are at evenly spaced angles (the angle is 2*PI/2*n = Pi/n). On an unit circle (r=1), the x,y coordinates of the points i=0..n is cos(x),sin(x). Multiply those coordinates with the respective radius (rOuter or rInner, depending of whether i is odd or even), and add that vector to the center of the star to get the coordinates for each vertex in the star path.

Here's the function to create a star shape with given number of arms, center coordinate and outer, inner radius:

public static Shape createStar(int arms, Point center, double rOuter, double rInner) {
    double angle = Math.PI / arms;

    GeneralPath path = new GeneralPath();

    for (int i = 0; i < 2 * arms; i++) {
        double r = (i & 1) == 0 ? rOuter : rInner;
        Point2D.Double p = new Point2D.Double(
            center.x + Math.cos(i * angle) * r, 
            center.y + Math.sin(i * angle) * r);
        if (i == 0) {
            path.moveTo(p.getX(), p.getY());
        }
        else {
            path.lineTo(p.getX(), p.getY());
        }
    }
    path.closePath();
    return path;
}
like image 200
Peter Walser Avatar answered Oct 05 '22 23:10

Peter Walser


I think you should use the same classes (GeneralPath), but here you should focus on how to compute the vertex coordinates.

The first thing that comes to my mind is positioning 2N points on a circle of radius R1, centered at (0,0). Then, "strech" every odd vertex by multiplying its vector by c. The constant c should be equal to R2/R1 (i.e. the proportion of inner and outer radiuses).

But maybe there is a simpler solution...

like image 25
Eyal Schneider Avatar answered Oct 06 '22 00:10

Eyal Schneider