4

私は一種の挑戦を自分自身に課し、それを理解するために助けを求めることができると思いました. Java Graphics を使用して、特定の点に稲妻が当たっているように見えるものを描画したいと考えています。

今、私はこれを持っているだけで、安価な「稲妻」をランダムな方向に発射します。

lightning[0] = new Point(370,130); //This is a given start point.

// Start in a random direction, each line segment has a length of 25
double theta = rand.nextDouble()*2*Math.PI;
int X = (int)(25*Math.cos(theta));
int Y = (int)(25*Math.sin(theta));

//Populate the array with more points
for (int i = 1 ; i < lightning.length ; i++)
{
  lightning[i] = new Point(X + lightning[i-1].x, Y + lightning[i-1].y);

  boolean plusminus = rand.nextBoolean();
  if (plusminus) theta = theta + rand.nextDouble()*(Math.PI/2);
  else theta = theta - rand.nextDouble()*(Math.PI/2);

  X = (int)(25*Math.cos(theta));
  Y = (int)(25*Math.sin(theta));
}

// Draw lines connecting each point
canvas.setColor(Color.WHITE);
for (int i = 1 ; i < lightning.length ; i++)
{
  int Xbegin = lightning[i-1].x;
  int Xend = lightning[i].x;
  int Ybegin = lightning[i-1].y;
  int Yend = lightning[i].y;

  canvas.drawLine(Xbegin, Ybegin, Xend, Yend);

  //if (Xend != Xbegin) theta = Math.atan((Yend - Ybegin)/(Xend - Xbegin));

  // Restrict the angle to 90 degrees in either direction
  boolean plusminus = rand.nextBoolean();
  if (plusminus) theta = theta + rand.nextDouble()*(Math.PI/2);
  else theta = theta - rand.nextDouble()*(Math.PI/2);

  // 50/50 chance of creating a half-length off-shoot branch on the end
  if (rand.nextBoolean())
  {
    int Xoff = (int)(Xend+(12*Math.cos(theta)));
    int Yoff = (int)(Yend+(12*Math.sin(theta)));

    canvas.drawLine(Xend, Yend, Xoff, Yoff);
  }
}

この効果を作成する同様の方法を考えようとしていますが、配列の最後のポイントを事前に定義して、稲妻が特定のポイントを「打つ」ことができるようにします。つまり、ランダムな方法で Point 配列にデータを入力したいのですが、それでも最終的な 1 つの点に収束します。

体重を計りたい人はいますか?

4

2 に答える 2

4

これはかなりシンプルで、正確で、エレガントなアプローチだと思います。分割統治戦略を採用しています。2 つの値のみから開始します。

  • 出発地点
  • 終点

中点を計算します。その中間点をオフセットしますvariance(長さを基準にして計算できます)。オフセットは、始点と終点を結ぶベクトルに垂直であることが理想的ですが、ボルトが実際の稲妻のようにほぼ垂直に移動する限り、オフセットを水平にすることでコストを抑えることができます。(start, offset_mid) と (offset_mid, end) の両方について上記の手順を繰り返しますが、今回はより小さな数値を使用してvariance. これは、分散のしきい値または線分の長さのしきい値に達したときに終了できる再帰的アプローチです。再帰が巻き戻されると、すべてのコネクタ セグメントを描画できます。アイデアは、最大の分散がボルトの中心で発生し (開始から終了までの距離が最も長い場合)、再帰呼び出しごとにポイント間の距離が縮小し、分散も縮小するというものです。このようにして、ボルトのグローバル分散は、ローカル分散よりもはるかに大きくなります (実際の稲妻のように)。

これは、このアルゴリズムで同じ事前定義されたポイントから生成された 3 つの異なるボルトのイメージです。これらのポイントはたまたま (250,100) と (500,800) です。任意の方向 (「ほぼ垂直」だけでなく) に移動するボルトが必要な場合は、ボルトの移動角度に基づいて X と Y の両方をシフトして、ポイント シフト コードをさらに複雑にする必要があります。

雷

このアプローチの Java コードを次に示します。ArrayList分割統治アプローチでは、最終的にいくつの要素が含まれるかが事前にわからないため、を使用しました。

// play with these values to fine-tune the appearance of your bolt
private static final double VAR_FACTOR = 0.40;
private static final double VAR_DECREASE = 0.55;
private static final int MIN_LENGTH = 50;

public static ArrayList<Point> buildBolt(Point start, Point end) {
    ArrayList<Point> bolt = new ArrayList<Point>();
    double dx = start.getX() - end.getX();
    double dy = start.getY() - end.getY();
    double length = Math.sqrt(dx*dx + dy*dy);
    double variance = length * VAR_FACTOR;
    bolt.add(start);
    buildBolt(start, end, bolt, variance);
    return bolt;
}

private static void buildBolt(Point start, Point end,
                              List<Point> bolt, double variance) {
    double dx = start.getX() - end.getX();
    double dy = start.getY() - end.getY();
    double length = Math.sqrt(dx*dx + dy*dy);
    if (length > MIN_LENGTH) {        
        int varX = (int) ((Math.random() * variance * 2) - variance);
        int midX = (start.x + end.x)/2 + varX;
        int midY = (start.y + end.y)/2;
        Point mid = new Point(midX, midY);
        buildBolt(start, mid, bolt, variance * VAR_DECREASE);
        buildBolt(mid, end, bolt, variance * VAR_DECREASE);
    } else {
        bolt.add(end);
    }
    return;      
}
于 2012-12-05T18:58:02.960 に答える
1

Without any graphics experience, I have this advice: it's going to be hard to pick a specific point, then try to reach it in a "random" way. Instead, I'd recommend creating a straight line from the origin to destination, then randomly bending parts of it. You could make several passes, bending smaller and smaller segments down to a certain limit to get the desired look. Again, I'm saying this without any knowledge of the graphics API.

于 2012-12-05T18:52:02.740 に答える