Показаны сообщения с ярлыком вырвимозг. Показать все сообщения
Показаны сообщения с ярлыком вырвимозг. Показать все сообщения

пятница, 7 сентября 2018 г.

[AutoLISP] - Куда уходит память?

При разработке приложения на AutoLISP столкнулся с утечкой памяти. На тестах под нагрузкой сжиралась вся оперативная память (всего - 16 Гб).
Запуск сборщика мусора не помог, все переменные проекта проверил, всё в порядке.
При отладке выявил, что виновником утечки памяти является функция 
vlax-ename->vla-object

После безуспешных попыток найти решение помог уже не раз выручавший меня способ: последовательное чтение списка всех функций. 
В книге "Autolisp и Visual Lisp в среде AutoCAD" есть очень удобное приложение - в одну таблицу собраны все функции и методы, сначала пробежался по ней, но безуспешно. Пошёл шерстить всю книгу и нашёл метод получения vla-объекта по хэндлу примитива HandleToObject. 

Ну а дальше дело техники - забираем хэндл из DXF-данных примитива и по нему получаем vla-object:

(defun kha_vlax-ename->vla-object (e doc)
  (vla-HandleToObject doc (cdr (assoc 5 (entget e)))))

Удачи!

воскресенье, 5 ноября 2017 г.

[Revit API] - Маркировка взрыв-схемы

В Revit очень неудобно маркировать элементы, смещённые функцией "Переместить элементы" или "Displace Elements". В этом видео я покажу как решить эту проблему с помощью Revit API

Этот урок я делал с помощью макросов в Revit  и так случилось, что я прибил файл rvt и у меня не осталось исходников. Поэтому смотрим то, что записано:



Удачи!

пятница, 11 декабря 2015 г.

[Revit API] - Как получить линии из условного обозначения отверстия (продолжение)

Всё-таки нашёл решение с получением линий из семейства категории "Типовые аннотации". Как и обещал, пишу продолжение.

Google не помог, в руководстве пользователя тоже ничего не смог обнаружить.
На этот раз выручил сайт revitapisearch.com. Этот сайт - последний рубеж в моих изысканиях.
Если что-то совсем не выходит или нужно окончательно убедиться в том, что невозможно сделать через Revit API - захожу туда, нажимаю на кнопку "Members" и забиваю в поиске на страничке слова по смыслу.
Довольно-таки муторное занятие:


И далее F3, F3, F3 по всей простыне.
На 118-м найденном слове наткнулся на метод:


Ага, на этот раз охота оказалась удачной.

Строку из предыдущего сообщения

GeometryElement geometryElement = element.get_Geometry(geomOption);

заменяю на

FamilyInstance fi = (FamilyInstance)element;
GeometryElement geometryElement = fi.GetOriginalGeometry(geomOption);

Код скомпилировался и даже сработал, но в итоге я получил какую-то козявку в базовой точке проекта:


Видимо OriginalGeometry - это описание геометрии внутри семейства.

В объекте типа FamilyInstance есть метод GetTransform(). 
Смотрю что есть интересного в линии:

Добавляю строчку с трансформацией линии:

if (l != null)
{
    l = (Line)l.CreateTransformed(fi.GetTransform());
    lines.Add(l);
}

В итоге получаю список линий, с изменённым положением и отмасштабированных таким же образом, как и семейства аннотаций:
Удачи! 

четверг, 3 декабря 2015 г.

[Revit API] - Как получить линии из условного обозначения отверстия

На прошлой неделе Хасан Мамаев задал вопрос:
Я пытаюсь получить геометрию нескольких экземпляров одного плоского семейства таким кодом:
i.GetInstanceGeometry()
но выдаёт ошибку: AttributeError: 'FamilyInstance' object has no attribute 'GetInstanceGeometry'
Объекты, из которых нужно вытянуть линии - условное отображение отверстий:

Сегодня появилось время, пытаюсь разобраться.

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

После изысканий разработал такой код:

private List<Line> GetLines(Element element)
{

    List<Line> lines = new List<Line>();

    Autodesk.Revit.DB.Options geomOption = element.Document.Application.Create.NewGeometryOptions();

            if (null != geomOption)
            {
                geomOption.View = element.Document.ActiveView;               
            }

    GeometryElement geometryElement = element.get_Geometry(geomOption);

    foreach (GeometryInstance gi in geometryElement)
    {
        foreach (GeometryObject go in gi.GetInstanceGeometry())
        {
            Line l = go as Line;

            if (l != null)
            {
                lines.Add(l);
            }
        }
    }

    return lines;

}

Этот код заработал для элементов типа Элементы узлов. 
Для Типовых аннотаций не работает. Если найду решение, то сделаю продолжение.

Удачи!

воскресенье, 1 ноября 2015 г.

[Revit API] - Запись данных в ключевую спецификацию

Не так давно я писал о способе создания пользовательской таблицы.
Задумался о том, как же теперь наполнить её через API.
Оказалось что здесь всё прозрачно и методы работы описаны в документации:

//Code Region: Inserting a row
public void CreateSubtitle(ViewSchedule schedule)
{
    TableData colTableData = schedule.GetTableData();

    TableSectionData tsd = colTableData.GetSectionData(SectionType.Header);
    tsd.InsertRow(tsd.FirstRowNumber + 1);
    tsd.SetCellText(tsd.FirstRowNumber + 1, tsd.FirstColumnNumber, "Schedule of column top and base levels with offsets");
}

Получаю объект TableSectionData, далее создаются строчки, столбцы, пишутся/читаются данные
из ячеек, задаю форматирование.
Можно сделать таблицу с расширенными возможностями форматирования, записывать туда данные. То что возможности есть - хорошо, при необходимости применю, на некоторое время даже забыл
про эту тему.

До сегодняшнего дня был ещё один интересный нерешённый вопрос: как заполнять программным способом ключевую спецификацию? В первый раз он возник месяцев восемь назад,
как ни бился над ним - не нашёл подхода.

Видимо эта задачка крутилась в мозгу в фоновом режиме и однажды во время прогулки внезапно пришла мысль, зацепка.

Обратите внимание на строчку:
TableSectionData tsd = colTableData.GetSectionData(SectionType.Header);

Тэкс, Header, Header. Если есть Header, может есть и сама таблица?

Набираю SectionType и Iintellisense предложил первой строчкой интересный вариант: 


Пишу код как в справке, заменил Header на Body.
Строки данных добавляются/удаляются методами InsertRow и RemoveRow. Уже хорошо.
А вот с записью данных возникла проблема. На методе  SetCellText возникает ошибка, записать текст не удаётся таким же образом как это делается в заголовке таблицы.

Всё, приехали? Как бы не так!

Выручил Revit Lookup: 
выбрал спецификацию, покопался в данных, но не нашёл ничего, что могло бы помочь в записи данных.


Делал несколько подходов, в последний из них забыл выбрать спецификацию в диспетчере проектов и получил совершенно другую картинку:


Что случилось? А случилось вот что: при снятом выделении вида в диспетчере проектов в Revit Lookup попадают все элементы текущего вида. То есть каждая строчка ключевой спецификации - это объект класса Element. Его нет в модели и у него нет категории. 
Зато есть параметры, соответствующие полям спецификации.

Через FilteredElementCollector получаем элементы ключевой спецификации, перебираем их и задаём нужные значения.

Пример кода:

    private void WriteToKeySchedule(View view)
    {
   // Получение элементов вида
   FilteredElementCollector collector = new FilteredElementCollector(view.Document, view.Id);
  
        // Для примера взят параметр "Комментарии", который есть у большинства элементов
        // перед запуском примера добавьте его в ключевую спецификацию
            string s = "test";
            foreach (Element element in collector)
            {
                element.LookupParameter("Комментарии").Set(s);
            }        
    }

Поля спецификации заполнены:

Далее дело техники - прикрутить модуль связи с Exel/CSV/XML... да с чем угодно, всё зависит от конкретных задач, и писать данные в ключевые спецификации

Сделал минимальный тестовый проект: скачать.
Для запуска макроса нужно перейти в диспетчер макросов, выбрать макрос и запустить его.

Удачи!

воскресенье, 18 октября 2015 г.

[Revit] - Семейства категории "Каркас несущий" и границы помещений.

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

Первым делом пошёл в гуглить. Тишина. В том числе и на зарубежных форумах. Ну или я не спец по поиску. Нашёл только аналогичный вопрос в группе ВКонтакте.

Здесь я написал порядок поиска решения вопроса, но получилось нудно и очень много букв, я их безжалостно вытер, оставил только про гугл.

После некоторых изысканий вывел такой алгоритм:

1. Создаём семейство категории "Перекрытия".  Как это обычно делается в Revit - создаётся оно не очевидным путём: 
     - создаём модель в контексте категории "Перекрытия"
     - создаём произвольное выдавливание
     - создаём из него группу
     - не выходя из режима редактирования модели в контексте 
        R -> Сохранить как... -> Библиотека -> Группа 
      
После сохранения получаем загружаемое семейство категории "Перекрытия" (далее Граница помещения - перекрытия.rfa). 

2. Редактируем семейство , задаём в нём опорные плоскости и параметры для управления длиной/шириной/высотой, задаём параметры L, B, H как параметры экземпляра.

UPD: Семейство нужно сделать общим


3. Вставляем семейство Граница помещения - перекрытия.rfa в Балка.rfa, задаём нужные параметры L, B, H. (я связал их с параметрами семейства Балка.rfa - Длина, b, h)



4. Вставляем семейство Балка.rfa в проект и любуемся результатом:

Если семейство Балка.rfa уже было загружено в проект, то границы помещения могут не обновиться сразу же. Для этого достаточно переместить балку в любом направлении и вернуть обратно. Также не забываем включить расчёт объёмов помещений.

Ещё я прокинул параметр "Граница помещения" семейства Граница помещения - перекрытия.rfa в семейство Балка.rfa, чтобы можно было управлять границей помещения для каждого элемента в проекте таким же образом, как это делается для стандартных элементов - таких как стены, перекрытия или крыши.

На следующий день выяснилось, что проектировщики выполнили с помощью семейств на основе "Каркас несущий" железобетонное сборное здание и архитекторы не могут размещать помещения в своём проекте.

Для стен принцип такой же. Только чтобы всё было по фен-шую сделал новое семейство границы помещения на основе "Стены" и вставил его в семейства сборных стеновых панелей.


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

По идее можно выполнить семейство произвольной формы для вырезания из объёма помещения.

UPD: здесь можно посмотреть ещё приёмы работы с панелями в сборных зданиях