алгоритм для случайного пространства, ограниченного элементами равной длины - PullRequest
8 голосов
/ 11 декабря 2010

Я студент архитектуры, пытающийся решить пространственную проблему с C # в Grasshopper для Rhino.

Пространство, которое я пытаюсь создать, - это выставочное пространство в аэропорту. Пространство будет состоять из элементов одинаковой длины. Идея состоит в том, чтобы соединить их шарниром и тем самым позволить им создавать пространства разной планировки и размера в зависимости от того, сколько элементов используется.

illustration

Как вы можете видеть из иллюстрации, я бы хотел, чтобы пространство заканчивалось открытием элемента на расстоянии от начальной точки.

Моей первой попыткой было создание равносторонних треугольников в зависимости от количества необходимых сегментов (стенок). Короче говоря, из начальной точки создаются треугольники, а затем стороны треугольника, которые формируют внешнюю границу, добавляются в список точек. Этот список точек возвращается в приложение Grasshopper, которое рисует линии между точками. Небольшой момент в том, что я сделал случайным образом создание следующего треугольника со стороны AC или BC из последнего треугольника.

Вот пример созданных пробелов (для 12 - 8 - 14 - 20 элементов):

various generated shapes

Вот исходный код, который создает эти списки точек:

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);
}

Что я хотел бы сделать, так это изменить создание этих фигур так, чтобы они были не только коридорами, но и напоминали мои первоначальные наброски. Я хотел бы, чтобы алгоритм взял ввод сегментов (число и длина), а затем предложил различные макеты пространства, которые можно создать с этим количеством сегментов. Я думаю, из-за тесселяции пространство должно было бы быть создано с помощью треугольников, квадратов или шестиугольников? Как вы думаете, мне следует изучить алгоритм «максимальной площади»: Покрытие произвольной области кружками равного радиуса здесь в stackoverflow ?

Буду очень признателен за любую помощь по этому алгоритму. Ура, Эйрик

1 Ответ

1 голос
/ 12 декабря 2010

Если вы просто заинтересованы в программе для генерации экземпляров, которые будут оцениваться извне (и не всех таких экземпляров), вы можете «накачать» свою кривую. Например, в 14-сегментном экземпляре на втором изображении есть место, где кривая идет внутрь и удваивается назад, поэтому в вашем списке точек повторяется одна точка. Для кривых, подобных этой, вы можете вырезать все между двумя (одинаковыми) точками (A и B), а также одной из окружающих точек (A или B), и вы восстановили некоторые точки, чтобы расширить свою кривую - возможно, в результате не коридорная структура. Возможно, вам придётся поработать над магией, чтобы убедиться, что это «замкнутая» кривая, однако, покупайте попеременно, добавляя сегменты к передней и задней части кривой.

Еще одна возможность: если вы можете идентифицировать внутреннюю часть кривой (и для этого есть алгоритмы), то в любом месте, где два сегмента образуют вогнутый угол относительно вашей кривой, вы можете выдуть ее, чтобы сделать область без коридора. Например. второй и третий сегменты вашей 14-сегментной кривой выше могут быть сдвинуты влево.

Последовательное применение этих двух методов к кривой, подобной коридору, должно создать множество искомых фигур. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...