2016-11-17 1 views
-1

У меня возникли проблемы с выяснением трех вещей. (Создано с помощью панели чертежа: http://www.buildingjavaprograms.com/DrawingPanel.java)Java: рисование звезды и точек подключения с панелью чертежа

Проблема №1: Нанесение многоугольника таким образом, чтобы он был центрирован и не криво. Это незаметно, когда нарисовано больше очков.

Проблема №2: Соединение всех точек звезды вместе, так что это гигантский круг (пунктир). Я не понимаю, почему это происходит, если, возможно, метод не самый лучший.

Проблема №3: ​​При рисовании с небольшим количеством точек я замечаю, что она не нарисовала точку правильно, и она выглядит как квадрат.

Я очень благодарен за помощь!

import java.awt.*; 

public class StarSampler { 

     public static void main(String[] args) 
     { 
      DrawingPanel panel = new DrawingPanel(500, 500); 
      Graphics2D g = panel.getGraphics(); 
      g.setColor(Color.BLUE); 

      fillStar(g, 250, 250, 150, 5, 1); 
     } 

     public static void fillStar(Graphics2D g, int ctrX, int ctrY, int radius, int nPoints, double spikiness) 
     { 
      double xDouble[] = new double[2*nPoints]; 
      double yDouble[] = new double[2*nPoints]; 
      int xPoint[] = new int[100]; 
      int yPoint[] = new int[100]; 

      for (int i = 0; i < 2*nPoints; i++) 
      { 
      double iRadius = (i % 2 == 0) ? radius : (radius * spikiness); 
      double angle = (i * 720.0)/(2*nPoints); 

      xDouble[i] = ctrX + iRadius * Math.cos(Math.toRadians(angle)); 
      yDouble[i] = ctrY + iRadius * Math.sin(Math.toRadians(angle)); 

      for (int j = 0; j < nPoints; j++) // Casts for ints and doubles 
      { 
       xPoint[j] = (int) xDouble[j]; 
       yPoint[j] = (int) yDouble[j]; 
      } 
      } 

      g.fillPolygon(xPoint, yPoint, nPoints); // Creates polygon 
      // Polygon gets drawn crookedly 
      g.drawPolyline(xPoint, yPoint, nPoints); // Draws lines to connect points 
      // Two lines go straight to (0,0) when nPonts*2 and nothing without *2? 
     } 
} 

Мой выход:

Wrong Output

Моя цель выхода (без меченых точек, две звезды только для примера):

Correct Output

ответ

2

Вопросы с вашим кодом имеют логического характера или из-за неаккуратного стиля кодирования:

for (int j = 0; j < nPoints; j++) // Casts for ints and doubles 
     { 
      xPoint[j] = (int) xDouble[j]; 
      yPoint[j] = (int) yDouble[j]; 
     } 

Этот фрагмент кода должен преобразовывать все части многоугольника в целые числа. У этой части кода есть несколько вопросов:

  1. Он не охватывает все пункты. Цикл создает в общей сложности 2 * nPoints точек, но только половина из них преобразуется. Здесь пропадают спайки от
  2. Зачем это во внутреннем цикле? Это не должно выполняться в цикле, который генерирует значения. Это просто огромное количество избыточных копий и бросков.
  3. Зачем хранить два отдельных массива? Просто преобразуйте их непосредственно в создание. Поскольку никакое значение не будет повторно использовано, нет смысла поддерживать ценность с полной точностью в любом случае.

Круг 360 градусов, а не 720. Этот код:

double angle = (i * 720.0)/(2*nPoints); 

будет изменять угол между созданными точками. Это означает, что вы либо генерируете только половину спайков, если число равно, либо генерируете много пересекающихся линий (тоже не выглядит плохо, но не то, что вы хотите, я думаю).

Единичный круг (относящийся к части тригометрии) определен таким образом, что (1, 0) является точкой с углом 0 ° к центру. Здесь также будет создан ваш первый всплеск. Просто выровняйте угол 90 ° для поворота круга на 90 ° против часовой стрелки.

Это рабочее решение на основе вашего кода. Основной метод только содержит код для управления простого тестирования UI-:

import javax.swing.*; 
import java.awt.*; 
import java.awt.image.BufferedImage; 

public class StarSampler 
{ 
    private static final int WIDTH = 500, 
           HEIGHT = 500, 
           RADIUS = 200; 

    private static final double SPIKINESS = 0.5; 

    public static void main(String[] args) 
    { 
     BufferedImage bi = new BufferedImage(500, 500, BufferedImage.TYPE_4BYTE_ABGR); 
     updateImage(5, bi); 

     JFrame frame = new JFrame("Some Test"); 
     frame.setLayout(new BorderLayout()); 

     frame.add(new JLabel(new ImageIcon(bi)), BorderLayout.CENTER); 

     //menu to update number of spikes 
     JPanel sub = new JPanel(); 
     sub.setLayout(new BoxLayout(sub, BoxLayout.X_AXIS)); 
     sub.add(new JLabel("Spikes: ")); 
     JSpinner spikeSpinner = new JSpinner(new SpinnerNumberModel(5, 1, 500, 1)); 
     spikeSpinner.addChangeListener(e -> { 
      updateImage((Integer) spikeSpinner.getModel().getValue(), bi); 
      SwingUtilities.invokeLater(()->frame.repaint()); 
     }); 
     sub.add(spikeSpinner); 
     frame.add(sub, BorderLayout.SOUTH); 

     frame.pack(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    private static void updateImage(int nSpikes, BufferedImage bi) 
    { 
     int ctrX = WIDTH/2, ctrY = HEIGHT/2; 

     int nPoints = nSpikes * 2 + 1; 

     int xPoint[] = new int[nPoints]; 
     int yPoint[] = new int[nPoints]; 

     //generate star 
     for (int i = 0; i < nPoints; i++) 
     { 
      double iRadius = (i % 2 == 0) ? RADIUS : (RADIUS * SPIKINESS); 
      double angle = (i * 360.0)/(2*nSpikes); 

      xPoint[i] = (int) (ctrX + iRadius * Math.cos(Math.toRadians(angle - 90))); 
      yPoint[i] = (int) (ctrY + iRadius * Math.sin(Math.toRadians(angle - 90))); 
     } 

     //paint the star 
     Graphics2D g2 = (Graphics2D) bi.getGraphics(); 
     g2.setColor(Color.blue); 
     g2.fillRect(0, 0, WIDTH, HEIGHT); 
     g2.setStroke(new BasicStroke(4.f)); 
     g2.setColor(Color.yellow); 
     g2.drawPolyline(xPoint, yPoint, nPoints); 

     //insert control lines 
     g2.setStroke(new BasicStroke(1.f)); 
     g2.setColor(Color.black); 
     for(int i = 0; i < nSpikes * 2; i++) 
      g2.drawLine(ctrX, ctrY, xPoint[i], yPoint[i]); 

     int w1 = RADIUS, 
       w2 = (int) (RADIUS * SPIKINESS); 
     g2.drawOval(ctrX - w1, ctrY - w1, w1 * 2, w1 * 2); 
     g2.drawOval(ctrX - w2, ctrY - w2, w2 * 2, w2 * 2); 
    } 
} 
+0

Это мой плохим, я с помощью панель рисования (http://www.buildingjavaprograms.com/DrawingPanel.java) не JPanel. Но я действительно ценю код, и я пытаюсь понять логику, которую вы реализовали. – Aramza

+0

@Aramza UI-компоненты не имеют особого значения. Метод 'updateImage' содержит всю логику рисования звезды, а' main'-method обрабатывает только пользовательский интерфейс и его создание. «BufferedImage» -параметр 'updateImage'-Method может быть легко заменен на« Graphics »-Object. Фактически этот параметр используется точно один раз; для извлечения упомянутого «графического объекта» ... – Paul

Смежные вопросы