用等长元素边界的随机空间算法

Eir*_*rik 8 c# algorithm geometry

我是一名建筑系学生,试图用蚱蜢中的C#解决C#的空间问题.

我想要创造的空间是机场的展览空间.空间将由相似长度的元素组成.我们的想法是将它们与铰链连接,从而允许它们根据使用的元素数量创建不同布局和大小的空间.

插图

从图中可以看出,我希望空间以一个远离起点的开口元素长度结束.

我的第一次尝试是根据所需的段(墙)数量创建等边三角形.简而言之,从起点开始,创建三角形,然后将形成外边框的三角形边添加到点列表中.此点列表将返回到Grasshopper应用程序,该应用程序在点之间绘制线条.有一点是我从最后三角形的AC侧或BC侧随机创建了下一个三角形.

以下是创建空间的示例(适用于12 - 8 - 14 - 20个元素):

各种生成的形状

以下是创建这些点列表的源代码:

private void RunScript(double radius, int walls, ref object A)
{

  //
  List<Point3d> pointList = new List<Point3d>();
  List<Point3d> lastList = new List<Point3d>();

  bool alternate = true;
  bool swapped = false;
  Random turn = new Random();

  // set up the first part of the triangle
  Point3d point1 = new Point3d(0, 0, 0);
  Point3d point2 = new Point3d(0, radius, 0);
  pointList.Add(point1);
  pointList.Add(point2);
  Point3d calcPoint;

  for(int i = 0; i < walls - 1; i++) // walls - 1, is because I need one less triangle to get to the amount of walls
  {
    // use the method to create two similar circles and return the intersection point
    // in order to create an equilateral triangle
    calcPoint = FindCircleIntersections(point1.X, point1.Y, point2.X, point2.Y, radius, alternate);

    // random generator: will decide if the new triangle should be created from side BC or AC
    bool rotate = turn.Next(2) != 0;
    Print("\n" + rotate);

    // set the 2nd and 3rd point as 1st and 2nd - depending on random generator.
    if(rotate)
    {
      point1 = point2;
      if(swapped == true)
        swapped = false;
      else
        swapped = true;
    }

    // if the direction is swapped, the next point created will not be a part of the outer border
    if(swapped)
      lastList.Add(calcPoint);
    else
      pointList.Add(calcPoint);

    point2 = calcPoint;

    // swap direction of intersection
    if(rotate)
    {
      if(alternate)
        alternate = false;
      else
        alternate = true;
    }

  }

  lastList.Reverse();

  foreach (Point3d value in lastList)
  {
    pointList.Add(value);
  }

  A = pointList;

}



// Find the points where the two circles intersect.
private Point3d FindCircleIntersections(
  double cx0, double cy0, double cx1, double cy1, double rad, bool alternate)
{
  // Find the distance between the centers.
  double dx = cx0 - cx1;
  double dy = cy0 - cy1;
  double dist = Math.Sqrt(dx * dx + dy * dy);


  // Find a and h.
  double a = (rad * rad - rad * rad + dist * dist) / (2 * dist);
  double h = Math.Sqrt(rad * rad - a * a);

  // Find P2.
  double cx2 = cx0 + a * (cx1 - cx0) / dist;
  double cy2 = cy0 + a * (cy1 - cy0) / dist;

  // Get the points P3.
  if(alternate)
    return new Point3d((double) (cx2 + h * (cy1 - cy0) / dist), (double) (cy2 - h * (cx1 - cx0) / dist), 0);
  else
    return new Point3d((double) (cx2 - h * (cy1 - cy0) / dist), (double) (cy2 + h * (cx1 - cx0) / dist), 0);
}
Run Code Online (Sandbox Code Playgroud)

我想做的是改变这些形状的创造,使它们不仅是走廊,而且类似于我最初的草图.我想要一个算法来获取段(数字和长度)的输入,然后提出可以用这么多段创建的不同空间布局.我想因为镶嵌,必须用三角形,正方形或六边形创建空间?你认为我应该研究这个"最大区域"算法:在stackoverflow上覆盖一个半径相等的圆圈的任意区域吗?

我非常感谢这个算法的任何帮助.干杯,Eirik

小智 1

如果您只对生成要外部评估的实例(而不是所有此类实例)的程序感兴趣,则可以“夸大”您的曲线。例如,在第二张图像的 14 段实例中,有一个地方曲线向内并折回 - 因此您的点列表中有一个点重复。对于这样的曲线,您可以切除两个(相同)点(A 和 B)之间的所有内容,以及周围的点之一(A 或 B),并且您回收了一些点来扩展曲线 - 可能会导致非走廊结构。不过,您可能需要施展一些魔法来确保它是一条“闭合”曲线,但请交替购买,在曲线的前部和后部添加线段。

另一个机会:如果您可以识别曲线的内部(并且有相关的算法),那么在两条线段相对于曲线形成凹角的任何地方,您都可以将其吹出以形成非走廊区域。例如,上面 14 段曲线的第二和第三段可能会向左吹出。

连续将这两种方法应用于类似走廊的曲线应该会生成许多您正在寻找的形状。祝你好运!