2016-11-17 9 views
-1

私は3つのことを考え出すのに問題があります。 (図面パネルで作成:http://www.buildingjavaprograms.com/DrawingPanel.javaJava:図面を描くことで星を描くとポイントを結ぶ

問題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

(ラベル付きの点がなければ、ちょうど例えば2つ星)私の目標出力:

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. なぜ2つの別々のアレイを保つのですか?作成時に直接変換してください。値が再利用されることはないので、とにかく完全な精度で値を保持することには意味がありません。

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

    が作成点間の角度を変化させる:

円は360度ではなく720本のコードです。これは、数が偶数であれば、スパイクの半分だけを生成するか、多くの交差線を生成することを意味します(どちらも悪くはありませんが、あなたが望むものではありません)。

単位円(trignometry-partに関連)は、(1,0)が中心に対して0°の角度を持つ点であるように定義されます。これは、最初のスパイクが作成される場所です。角度の90°を減算するだけで、円を反時計回りに90°回転させることができます。

ここにあなたのコードに基づいて動作する解決策があります。これが私の悪い、私は描画パネル(http://www.buildingjavaprograms.com/DrawingPanel.java)ではないのJPanelを使用していている

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

:メイン・メソッドは、単純なテスト-UIを管理するためのコードを保持しています。しかし、私はコードを本当に感謝し、あなたが実装したロジックを理解しようとしています。 – Aramza

+0

@Aramza UIコンポーネントはまったく問題ではありません。 'updateImage'メソッドにはスターをペイントするすべてのロジックが含まれていますが、' main'メソッドはUIとその作成だけを処理します。 'updateImage'メソッドの' BufferedImage'パラメータは 'Graphics'オブジェクトで簡単に置き換えることができます。実際、このパラメータは正確に1回だけ使用されます。前記 'Graphics'-Objectを検索する – Paul

関連する問題