2010-04-25 4 views
6

J'ai la tâche d'écrire un programme permettant aux utilisateurs de dessiner des étoiles, qui peuvent différer en taille et en quantité de bras. Quand je traitais avec des étoiles de base que je le faisais avec GeneralPath et tables de points:Dessiner des formes d'étoile avec des paramètres variables

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

Quelle méthode choisir pour dessiner étoiles avec un rayon intérieur et extérieur variable ainsi que différentes quantités d'armes? Voilà ce que je dois obtenir:

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

Répondre

19

Avoir bras n signifie que vous retrouvez avec 2n sommets, les même les sont sur le cercle extérieur, et les étranges sur le cercle intérieur. Vu du centre, les sommets sont à angles égaux (l'angle est 2 * PI/2 * n = Pi/n). Sur un cercle unitaire (r = 1), les coordonnées x, y des points i = 0..n sont cos (x), sin (x). Multipliez ces coordonnées par le rayon respectif (rOuter ou rInner, selon que i est impair ou pair), et ajoutez ce vecteur au centre de l'étoile pour obtenir les coordonnées de chaque sommet dans le chemin des étoiles.

Voilà la fonction de créer une forme d'étoile avec un nombre donné de bras, le centre de coordonnées et externe, le rayon interne:

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; 
} 
3

Je pense que vous devriez utiliser les mêmes classes (GeneralPath), mais ici vous devriez vous concentrer sur la façon de calculer les coordonnées des sommets.

La première chose qui me vient à l'esprit est de positionner 2N points sur un cercle de rayon R1, centré en (0,0). Ensuite, "strech" chaque sommet impair en multipliant son vecteur par c. La constante c doit être égale à R2/R1 (c'est-à-dire la proportion des rayons interne et externe).

Mais peut-être il y a une solution plus simple ...

2

Voici un example de trouver des points également espacés sur un circle qui peut aider. Il suffit de faire le nombre de points, n, un paramètre dans le constructeur.

private int n; 
... 
public CircleTest(int n) { 
    ... 
    this.n = n; 
} 
... 
for (int i = 0; i < n; i++) { 
    double t = 2 * Math.PI * i/n; 
    ... 
} 
Questions connexes