当前位置 : 主页 > 手机开发 > 无线 >

创建一个随机移动到定义的端点的Java Point数组

来源:互联网 收集:自由互联 发布时间:2021-06-10
我发出了一些挑战,并认为我可以站出来寻求帮助.我想用 java Graphics绘制一些看起来像闪电一样的东西. 现在我只是拥有这个,它在随机方向射出廉价的“闪电”,我不在乎它最终到底在哪
我发出了一些挑战,并认为我可以站出来寻求帮助.我想用 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数组,但仍然会收敛于最后一个点.

有人在乎称重吗?

我认为这是一种相当简单,准确和优雅的方法.它采用分而治之的策略.仅从2个值开始:

>起点
>终点

计算中点.将中点偏移一些值方差(可以相对于长度计算).理想情况下,偏移应该是连接起点和终点的矢量的法线,但是只要你的螺栓大部分垂直移动,就像真正的闪电一样,你可以通过使这个偏移水平来便宜.对于(start,offset_mid)和(offset_mid,end)重复上述过程,但这次使用较小的数字进行方差.这是递归方法,其可以在达到阈值方差或阈值线段长度时终止.当递归展开时,您可以绘制所有连接器段.这个想法是最大的方差发生在螺栓的中心(当开始到结束的距离最长时),并且每次递归调用时,点之间的距离会缩小,方差也会缩小.这样,螺栓的全局方差将远大于任何局部方差(如真正的闪电).

这是使用该算法从相同的预定点生成的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;      
}
网友评论