воскресенье, 17 января 2016 г.

Revit. Ленивые вычисления

          На форуме Dynamobim.ru есть интересная тема , почему то мои советы сводятся что я все решения свожу к многосложным задачам и что все дураки кроме меня. Хотя такого не ставлю ни в коем случае. Если есть задача то у ее есть решение и оно не всегда простое. И так суть вопроса.
          Допустим нам нужно генерировать некоторые вещи (длина, высота, ширина, число и тд) случайным образом. Как вариант раскидать в хаотичном порядке панели на фасаде здания. Или как у автора темы генерировать длину стен случайным образом. Но я решил показать на примере фасадных панелей которые лучше выполнить не стенами а обобщенными моделями в данной задаче.


          Если мы собрались решать такого рода задачи то в том же Dynamo у нас нету огромного количества алгоритмов. Их придется писать самим под конкретные задачи. Я покажу пример решения средствами IronPython и Python.
          Для генерации случайных чисел воспользуемся библиотекой random, вот список методов которые можно вызывать из этой библиотеки для переменной random:
random.seed([X], version=2) - инициализация генератора случайных чисел. Если X не указан, используется системное время.
random.getstate() - внутреннее состояние генератора.
random.setstate(state) - восстанавливает внутреннее состояние генератора. Параметр state должен быть получен функцией getstate().
random.getrandbits(N) - возвращает N случайных бит.
random.randrange(start, stop, step) - возвращает случайно выбранное число из последовательности.
random.randint(A, B) - случайное целое число N, A ≤ N ≤ B.
random.choice(sequence) - случайный элемент непустой последовательности.
random.shuffle(sequence, [rand]) - перемешивает последовательность (изменяется сама последовательность). Поэтому функция не работает для неизменяемых объектов.
random.sample(population, k) - список длиной k из последовательности population.
random.random() - случайное число от 0 до 1.
random.uniform(A, B) - случайное число с плавающей точкой, A ≤ N ≤ B (или B ≤ N ≤ A).
random.triangular(low, high, mode) - случайное число с плавающей точкой, low ≤ N ≤ high. Mode - распределение.
random.betavariate(alpha, beta) - бета-распределение. alpha>0, beta>0. Возвращает от 0 до 1.
random.expovariate(lambd) - экспоненциальное распределение. lambd равен 1/среднее желаемое. Lambd должен быть отличным от нуля. Возвращаемые значения от 0 до плюс бесконечности, если lambd положительно, и от минус бесконечности до 0, если lambd отрицательный.
random.gammavariate(alpha, beta) - гамма-распределение. Условия на параметры alpha>0 и beta>0.
random.gauss(значение, стандартное отклонение) - распределение Гаусса.
random.lognormvariate(mu, sigma) - логарифм нормального распределения. Если взять натуральный логарифм этого распределения, то вы получите нормальное распределение со средним mu и стандартным отклонением sigma. mu может иметь любое значение, и sigma должна быть больше нуля.
random.normalvariate(mu, sigma) - нормальное распределение. mu - среднее значение, sigma - стандартное отклонение.
random.vonmisesvariate(mu, kappa) - mu - средний угол, выраженный в радианах от 0 до 2π, и kappa - параметр концентрации, который должен быть больше или равен нулю. Если каппа равна нулю, это распределение сводится к случайному углу в диапазоне от 0 до 2π.
random.paretovariate(alpha) - распределение Парето.

Для решение данной задачи воспользуемся методом random.randrange.

в начале кода нужно прописать импортированную библиотеку:

import random

Далее зададимся некой длинной стены и введем переменную которая за это отвечает:

Length=20000

Для получения сгенерированных чисел длин отдельных панелей объявим пустой список:

List=list()

Теперь начинается самое интересное , нам нужно получать некий ряд чисел и заносить их в пустой список, для этого начнем цикл в определенной области чисел для определенной функции:

for b in range(0,100):

тут я задал область от 0 до 100 , то есть мы будем генерировать  максимально 100 панелей на длине фасада в 20000 мм.
Внутри цикла зададимся функцией генерации и объявим нам нужную переменную с нужным методом генерации:

a=random.randrange(500,3000,100)

Тут минимальный размер панелей задан 500 а максимальный 3000, кратность генерации 100.
Теперь нам числа которые генерирует цикл нужно куда то занести, если не вносить то они генерируются в оперативную память, внесем эти числа в ранее объявленный пустой список:

List.append(a)

Но у нас есть задача чтобы у нас генерировалось столько панелей что бы их общая длина не вышла за пределы стены в 20000 мм.Ка мы это решим ? для этого воспользуемся булевыми операторами и введем некое условие , что если сумма всех чисел вылезет за пределы некого значения то мы должны остановить цикл и внести последнее значение как остаток от разности того что мы успели сгенерировать и общей длины:

if sum(List)>17000:
        List.append(Length-sum(List))
        break

          В данном случае у нас максимальная длина панели 3000, значит если общая длина вылезет за значение 20000-3000=17000 то нам нужно внести в список последнее значение как остаток и закончить цикл командой break
         В итоге мы получим код примерно такого исполнения :

 или так:



            Как видно все время меняется общее число панелей в области максимальной длины и меняется сама начинка области.
            Но нам этого мало ! мы ведь с вами инженеры и понимаем что нам нужно генерировать не только по одному ряду данные панели , но еще и по высоте стены , то есть выполнять многоуровневые циклы. 
            Для это введем новый цикл , который просто добавит нам еще дополнительно 5 рядов раскладки панелей:

for c in range (0,5):

           И выполнив табуляцию  всех строчек кода до этого мы получим следующий код и его результат:


или кто использует Visual Studio:



           Не правда ли лаконичность кода поражает ? и ничего сложного нету , все довольно логично и код читаемый. Совет не пытайтесь кодить на обум методом тыка, пишите его и потом читайте с учетом всех операндов.
           
            Ну это была только математика. А как перенести все элементы списков в нужные параметры объектов Revit   используя нехитрые возможности API  думаю уже ни для кого не секрет. Тем более я уже описывал как это делать ранее и есть много информации в свободном доступе. И если все сделать правильно и хоть чуточку приложить умственных усилий мы получим следующее:
 Если немного побаловаться с цветом то можно и так :

             Область применения таких алгоритмов бесконечна , раскладка панелей фасадов, раскладка каменной кладки, блоков ФБС и тд и тп. Как логичное продолжение этой темы и ленивых вычислений может служить спецификация раскроя арматуры, листа и тд . Но это уже вопрос оптимизации. Тут так же можно решить обратную задачу , допустим у поставщика есть на складе много не кондиции , можно используя определенный сортамент составить некий продукт.
             P.S. Один в поле воин ! :)
            


11 комментариев:

  1. dynamobim.ru затролели

    ОтветитьУдалить
  2. Этот комментарий был удален автором.

    ОтветитьУдалить
  3. Автор фееричен! Михаил, раз уж вы написали столько букв, объясните, что мешает в Dynamo использовать функционал встроенной math библиотеки, как впрочем и подключить модуль random? http://i.piccy.info/i9/2baeda215684ef3c10b9b5dd36265f5c/1453108705/111734/993547/2016_01_18_11_08_35.png

    ОтветитьУдалить
    Ответы
    1. Тоесть для этой задачи нужно подключить библиотеку math ? И где я сказал что в Dynamo нельзя написать данный влгоритм ? Напишите строчку конкретную с такой фразой.

      Удалить
  4. 1. Тоесть для этой задачи нужно подключить библиотеку math ?
    Именно
    2. И где я сказал что в Dynamo нельзя написать данный влгоритм ? Напишите строчку конкретную с такой фразой.
    "Если мы собрались решать такого рода задачи то в том же Dynamo у нас нету огромного количества алгоритмов. Их придется писать самим под конкретные задачи."

    ОтветитьУдалить
    Ответы
    1. 1. Чушь, я без ее сделал, если я ее использую то покажите где и разберитесь с арифметикой и динамической библиотекой mathmodule.so которую мы вызываем прописывая import math http://pythonworld.ru/moduli/modul-math.html
      2. "Нету готовых алгоритмов" и "нельзя написать" код это разные вещи.
      P.S.Столько с Лабановым спорили по этому поводу и в итоге пишите ахинею....... Касательно модуля math (который я так и не понял к чему приплели) является статическим модулем и он вызывается и в Dynamo если он поддерживает IronPython. Когда вы пишите (врете)про то чего нету в статье , это выглядит очень глупо.

      Удалить
  5. 1. Миша, спасибо за твой совет, в свою очередь могу порекомендовать тебе разобраться с основами программирования.

    Опять же, в Dynamo класс задач, которые ты описал решается с помощью стандартной математической .Net библиотеки либо с помощью подключаемой посредством скрипта на IRonPython библиотеки random. То что ты решил без math похвально.
    2. "в том же Dynamo у нас нету огромного количества алгоритмов."
    Миша, передергиванием фактов не стоит скрывать свое дилетанство.

    P.S. Ну, во первых с ЛОбановым вы не спорили, это было скорее похоже на попытки школьника (то есть тебя) самоутвердиться. В общем, не известно, что вы, Михаил, представляете из себя как инженер, но судя по тому что вы пишите - в программировании вы дилетант, к тому же несколько воинственный дилетант)
    И да, эти убогие попытки повышения градуса дискуссии: "ахинея", "приплели", "врете" - согласен, выглядят очень глупо. Все таки троль с тебя Миша тоже никакой)

    ОтветитьУдалить
    Ответы
    1. 1. Да ради бога ,только причем тут math к статье ?
      "что мешает в Dynamo использовать функционал встроенной math библиотеки" - фраза была к чему тогда ?
      С такой логикой можно перечислить все встроенные библиотеки и модули....

      2. Передергиванием не занимаюсь и специально написал нейтрально, что бы понаблюдать как у людей проявляется "синдром утенка".

      3. "Опять же, в Dynamo класс задач, которые ты описал решается с помощью стандартной математической .Net библиотеки либо с помощью подключаемой посредством скрипта на IRonPython библиотеки random. То что ты решил без math похвально."

      Мне не лень вас опять огорчить, подобный класс задач решается не библиотеками. Мы говорим про "Ленивые алгоритмы" и в более сложных генераторах нужно использовать в том же Python специальную функцию yield:
      http://itman.in/python-yield/
      Найти косинус или синус или число Пи это не "подобный класс задач"

      P.S. За неправильную фамилию прошу прощения , иностранец я. А вообще за вами интересно наблюдать , не именно за вами , а и за многими вашими коллегами. Как сказал один хороший специалист (не дословно) "этот BIM курятник давно пора было ........" без слез на щеках смотреть уже нельзя.

      Удалить
  6. Разрешите пять копеек.
    Недавно на хабре вышла прекрасная статья о языках программирования: http://habrahabr.ru/company/yandex/blog/272759/?utm_campaign=email_digest&utm_source=email_habrahabr&utm_medium=email_week_20160119&utm_content=link2post
    -
    Так вот лектор вскользь проходит по питону, говорит что он рано или поздно помрет, но при этом очень лестно говорит что питон - лучший язык для ПРОТОТИПОВ.
    -
    Так вот на мой взгляд инженерам и архитекторам как раз и не хватает возможности видеть в реальном режиме что происходит с их моделью....
    -
    Вот я вижу сетку фасада и понимаю что это фасад... Вижу соотношение, вижу пропорции... И могу менять - добиваясь лучшего результата...
    -
    А что я вижу когда получаю массив чисел из питона? -ответ ничего.. Динама как раз является зародышем для графичного программирования.. и не нужно ее использовать для проектирования космического корабля... Вот и весь спор... Кесарю - кесарево.

    ОтветитьУдалить
  7. Дима геометрические примитивы видеть во время исполнения кода здорова спору нет ! но у инженеров иные проблемы и они уже знают что должны получить , это просто математика. По моему я иного никогда не говорил.

    ОтветитьУдалить
  8. И если честно Python не особо катит инженерам , всех кого я знаю из науки фортранщики а всех кто решает вопросы автоматизации Lisp а я решил экспериментировать с Python. И если честно вопрос оптимизации скорости вычислений у меня уже стоит ребром ......Python очень медленный для инженерных расчетов.

    ОтветитьУдалить

Поиск по этому блогу