Демонстрационная программа по расчету массы стен по их объему, умноженному на заданную плотность

Скачайте здесь и сохраните на своем компьютере файл программы.
При помощи кнопки 1 на панели LABPP_Calc для Revit откройте диалог выбора файла на компьютере.
Найдите текстовый файл с расширением cpp, в котором записана программа и нажмите "Ок".
На экране появится диалог 2.
В поле 3 введите плотность.
В поле 4 выберите букву, которая соответствует расчетному полю калькулятора, в которое вы хотите чтобы записался результат.
Нажмите "Расчет" (5).
Программа выберет в проекте элементы, у которых имеется материал, содержащий слово "Бетон".
Выведет их последовательно на панель сообщений из программ в калькуляторе с указанием объема и массы, полученной умножением объема на заданную плотность.
Суммарный объем запишется в поле A, а суммарная масса - в поле, которое вы выбрали в пункте 4.
Вот полный текст этого программного файла.
//*********************************************************************************
// LABPP Calc weight by density and volume with dialog and insert to calulator.cpp
// LABPP C++ for Revit
// Jurii@Tsepov.com
//*********************************************************************************
// Дескрипторы объектов - это целые числа, которые присваиваются каждому создаваемому объекту
int iDialog;
int iButton_Calculate;
int iTextEdit;
int iLabel1, iLabel2;
int iPopUp;
int main()
{
object("create", "ts_dialog", iDialog); // Создать объект ts_dialog и получить его дескриптор в переменную iDialog
ts_dialog(iDialog, "init_dialog", "palette", 0, 0, 200, 400); // инициализировать ts_dialog как немодальный (плавающий) диалог Revit
ts_dialog(iDialog, "settitle", "Мой диалог LABPP в Revit"); // задать заголовок окна
ts_dialog(iDialog, "SetClientWH", 300, 150); // задать размеры окна
ts_dialog(iDialog, "set_as_main_panel"); // установить этот диалог как главный - когда он закроется, все остальные окна тоже закроются
object("create", "ts_dialogcontrol", iLabel1); // Создать элемент текст на панели диалога
ts_dialogcontrol(iLabel1, "init_control", "LeftText", iDialog, 10, 10, 170, 24); // инициализация как текст, выравненный по левой стороне
ts_dialogcontrol(iLabel1, "SetText", "Расчетная плотность"); // задать текст
object("create", "ts_dialogcontrol", iTextEdit); // Создать поле для ввода текста
ts_dialogcontrol(iTextEdit, "init_control", "TextEdit", iDialog, 190, 10, 80, 24); // инициализация как текстового редактора, положение x,y и ширина и высота
ts_dialogcontrol(iTextEdit, "settooltip", "Плотность материала"); // задать всплывающий текст (при наведении мыши)
ts_dialogcontrol(iTextEdit, "SetText", "2,2"); // предустановить текст
object("create", "ts_dialogcontrol", iLabel2); // Создать текст 2
ts_dialogcontrol(iLabel2, "init_control", "LeftText", iDialog, 10, 35, 170, 24);
ts_dialogcontrol(iLabel2, "SetText", "Результат записать в поле");
object("create", "ts_dialogcontrol", iPopUp); // Создать popup элемент диалога (ниспадающий список)
ts_dialogcontrol(iPopUp, "init_control", "PopUp", iDialog, 190, 35, 80, 25); // инициализировать как popup, задать положение x,y и ширину и высоту
ts_dialogcontrol(iPopUp, "AppendItem"); // добавить пустой пункт
ts_dialogcontrol(iPopUp, "SetItemText", 1,"B"); // задать текст для пункта 1
ts_dialogcontrol(iPopUp, "AppendItem");
ts_dialogcontrol(iPopUp, "SetItemText", 2, "C");
ts_dialogcontrol(iPopUp, "AppendItem");
ts_dialogcontrol(iPopUp, "SetItemText", 3, "D");
ts_dialogcontrol(iPopUp, "SelectItem", 1); // сделать выбранным первый элемент ("B")
object("create", "ts_dialogcontrol", iButton_Calculate, "iButton_Calculate"); // Создать кнопку
ts_dialogcontrol(iButton_Calculate, "init_control", "button", iDialog, 190, 75, 80, 24); // инициализировать кнопку, задать положение x,y и ширину и высоту
ts_dialogcontrol(iButton_Calculate, "eventreaction", "Event_ButtonClicked", "Event_ButtonClicked_DCName"); // задать обработчик событий (тип "Event_ButtonClicked" и имя функции "Event_ButtonClicked_DCName")
ts_dialogcontrol(iButton_Calculate, "settext", "Расчет"); // задать надпись на кнопке
bool bres;
ts_dialog(iDialog, "invoke", bres); // запустить диалог
}
// Обработчик события нажатия (Event Handler) для кнопки
// когда кнопка нажата, эта функция выполняется
// здесь iDescr - это дескриптор нажатой кнопки (iButtonCalculate в этом примере)
// и sDescr - текстовое имя элемента ("iButtonCalculate" в этом примере);
int Event_ButtonClicked_DCName(int iDescr, string sDescr)
{
// в конструкциях if скобки { и } обязательны
if (sDescr == "iButton_Calculate")
{
Do_iButton_Calculate();
}
}
// функция, которая выполняется когда нажата кнопка iButton_Calculate
int Do_iButton_Calculate()
{
string s;
ts_dialogcontrol(iTextEdit, "gettext", s); // Получить текст из iTextEdit - плотность как текст, содержащий число с плавающей точкой
strreplaceall(s, ",", "."); // Если пользователь ввел "," мы заменяем его на "."
double density = atof(s); // конвертируем текст в число с плавающей точкой
// загрузить элементы из проекта Revit во внутренний список № 1 с фильтром:
// любые элементы ("OST_Zombie"), MainFilter = 0,
// параметр с генезисом "EP" (вкладка Common параметров на панели LABPP BIM Master) "ZFromProject0" должен быть >= 0 И
// параметр с генезисом "UPt" (уровень типа элемента TypeProps на панели LABPP BIM Master) "Имя типа" должен содержать "бетон"
// "_CONTAINS" - если есть знак подчеркивания, то при сравнении не учитывается регистр текста (все равно если "бетон", "Бетон" или "БЕТОН")
rvt_request("load_elements_list", 1, "OST_Zombie", "MainFilter", 0,
"(","EP","ZFromProject0",">=",0,")", "AND",
"(","UPt", "Имя типа", "_CONTAINS", "бетон",")"
);
rvt_request("get_loaded_elements_list_count", 1); // запрос сколько элементов загружено в список 1
int icount = rvt_getnumvalue(); // поместить результат запроса в переменную icount
// объявить и присвоить первичные значения требуемым переменным
string selement_name = "";
double dvolume = 0;
double dvolumeall = 0;
double dmassa = 0;
double dmassaall = 0;
int i;
// напечатать в окре сообщений программ
// ---------------
// Элементы 10 шт
//----------------
cout << "\r\n---------------" << "\r\nЭлементы " << itoa(icount) << "шт\r\n---------------";
// Расчетный цикл
for (i = 0; i < icount; i++)
{
rvt_request("set_current_element_from_list", 1, i); // установить элемент i из списка № 1 как текущий для работы с ним
rvt_request("get_element_value", "EP", "element_name"); // запросить имя элемента (параметр с генезисом "EP" - Common в LABPP BIM Master
selement_name = rvt_getstrvalue(); // поместить результат запроса в переменную selement_name
rvt_request("get_element_value", "UP", "Объем"); // запросить значение параметра UP/Объем (генезис "UP" - значит переменная уровня экземпляра элемента, вкладка ElemProps в LABPP_BIM_Master.
dvolume = tsround(rvt_getnumvalue(),4); // получить результат запроса и округлить до 4-х знаков после запятой
dmassa = dvolume * density; // расчитать массу умножением объема на плотность
dmassaall += dmassa; // суммировать массу
// напечатать строку отчета
cout << "\r\n" << itoa(i+1) << "). "<< selement_name << ": объем= " << dvolume << " масса при плотности " << s << "=" << dmassa;
dvolumeall += dvolume; // суммировать объем
}
// печатать итоговую строку
cout << "\r\n" << "Суммарный объем элементов= " << dvolumeall << " суммарная масса при плотности " << s << "=" << dmassaall;
// поместить в поле "A" LABPP_Calc суммарное значение объема и комментарий
rvt_request("calc_field", "set", "a", 0, ftoa(tsround(dvolumeall,4)), "Объем элементов");
string fieldletter2;
ts_dialogcontrol(iPopUp, "GetText", fieldletter2); // получить из элемента popup имя поля, куда записать массу ("B", "C" or "D")
rvt_request("calc_field", "set", fieldletter2, 0, ftoa(tsround(dmassaall,4)), "Масса при плотности "+s); // поместить в поле LABPP_Calc итоговую массу и комментарий
}
На самом деле LABPP C++ для Revit скрывает и делает за вас множество технологических операций.
Поэтому вам остается только понять его простые конструкции и использовать в своих целях.
Разберем по порядку текст программы.
В начале программы идет объявление переменных.
Если они объявляются вне функций, то они будут доступны в любой функции и подпрограмме.
В программе обязательно должна быть функция
int main()
{
}
Ее тело выполняется в первую очередь.
Если вы не программист, то просто пишите так как как здесь и не думайте.
Функции и процедуры пишутся после так же как main, например функция, которая на входе получает строку в переменной s, строку в переменной sres и целое число в переменной i, а возвращает число и... строку в переменную sres:
int my_function(string s, string & sres, int i)
{
sres = s + itoa(i);
return 11;
}
В так выглядит программа с этой функцией.
int main()
{
int a, res;
string strres;
a = 1;
strres = "строка";
res = my_function("строка", strres, a); // в res запишется 11, а strres будет "строка 1"
}
int my_function(string s, string & sres, int i)
{
sres = s + " " + itoa(i);
return 11;
}
Символ "&" означает, что sres в подпрограмме - это ссылка на входящую переменную указанную в аргументе и изменение sres будет отражаться на содержимом аргумента, т.е. strres.
Мы объявили переменную iDialog (могли бы назвать иначе или объявить несколько для разных объектов диалогов).
int iDialog;
...
int main()
{
Создаем объект диалога и получаем его дескриптор в эту переменную iDialog.
object("create", "ts_dialog", iDialog); // Создать объект ts_dialog и получить его дескриптор в переменную iDialog
...
При обращении к функции ts_dialog мы указываем дескриптор нужного диалога, который, хранится в переменной iDialog, поэтому программа понимает
у какого диалога мы хотим задать заголовок.
ts_dialog(iDialog, "settitle", "Мой диалог LABPP в Revit"); // задать заголовок окна
...
}
Итак, в самом начале мы объявляем переменные для хранения так называемых дескрипторов объектов.
Окно диалога, текст в окне диалога, поле для ввода текста и кнопки - это все объекты, обращение к которым делается с использованием их дескриптора.
// Дескрипторы объектов - это целые числа, которые присваиваются каждому создаваемому объекту
int iDialog; // дестриптор диалога
int iButton_Calculate; // дескриптор кнопки
int iTextEdit; // дескриптор поля редактирования текста
int iLabel1, iLabel2; // дескрипторы текста
int iPopUp; // дескриптор ниспадающего списка
Дальше начинается главная функция main() от { до }
int main()
{
создаем окно диалога и настраиваем:
object("create", "ts_dialog", iDialog); // Создать объект ts_dialog и получить его дескриптор в переменную iDialog
ts_dialog(iDialog, "init_dialog", "palette", 0, 0, 200, 400); // инициализировать ts_dialog как немодальный (плавающий) диалог Revit
ts_dialog(iDialog, "settitle", "Мой диалог LABPP в Revit"); // задать заголовок окна

ts_dialog(iDialog, "SetClientWH", 300, 150); // задать размеры окна
ts_dialog(iDialog, "set_as_main_panel"); // установить этот диалог как главный - когда он закроется, все остальные окна тоже закроются

object("create", "ts_dialogcontrol", iLabel1); // Создать элемент текст на панели диалога
ts_dialogcontrol(iLabel1, "init_control", "LeftText", iDialog, 10, 10, 170, 24); // инициализация как текст, выравненный по левой стороне
ts_dialogcontrol(iLabel1, "SetText", "Расчетная плотность"); // задать текст

object("create", "ts_dialogcontrol", iTextEdit); // Создать поле для ввода текста
ts_dialogcontrol(iTextEdit, "init_control", "TextEdit", iDialog, 190, 10, 80, 24); // инициализация как текстового редактора, положение x,y и ширина и высота
ts_dialogcontrol(iTextEdit, "settooltip", "Плотность материала"); // задать всплывающий текст (при наведении мыши)
ts_dialogcontrol(iTextEdit, "SetText", "2,2"); // предустановить текст

object("create", "ts_dialogcontrol", iLabel2); // Создать текст 2
ts_dialogcontrol(iLabel2, "init_control", "LeftText", iDialog, 10, 35, 170, 24);
ts_dialogcontrol(iLabel2, "SetText", "Результат записать в поле");

object("create", "ts_dialogcontrol", iPopUp); // Создать popup элемент диалога (ниспадающий список)
ts_dialogcontrol(iPopUp, "init_control", "PopUp", iDialog, 190, 35, 80, 25); // инициализировать как popup, задать положение x,y и ширину и высоту
ts_dialogcontrol(iPopUp, "AppendItem"); // добавить пустой пункт
ts_dialogcontrol(iPopUp, "SetItemText", 1,"B"); // задать текст для пункта 1
ts_dialogcontrol(iPopUp, "AppendItem");
ts_dialogcontrol(iPopUp, "SetItemText", 2, "C");
ts_dialogcontrol(iPopUp, "AppendItem");
ts_dialogcontrol(iPopUp, "SetItemText", 3, "D");

ts_dialogcontrol(iPopUp, "SelectItem", 1); // сделать выбранным первый элемент ("B")

object("create", "ts_dialogcontrol", iButton_Calculate, "iButton_Calculate"); // Создать кнопку
ts_dialogcontrol(iButton_Calculate, "init_control", "button", iDialog, 190, 75, 80, 24); // инициализировать кнопку, задать положение x,y и ширину и высоту
ts_dialogcontrol(iButton_Calculate, "eventreaction", "Event_ButtonClicked", "Event_ButtonClicked_DCName"); // ** задать обработчик событий (тип "Event_ButtonClicked" и имя функции "Event_ButtonClicked_DCName")
ts_dialogcontrol(iButton_Calculate, "settext", "Расчет"); // задать надпись на кнопке
bool bres;
ts_dialog(iDialog, "invoke", bres); // запустить диалог

На этом выполнение главной процедуры программы заказчивается.
Не экране остается диалог, который все события обрабатывает самостоятельно.
}
Когда пользователь нажимает кнопку "Расчет" программа выполняет эту процедуру, потому, для этой кнопки она указана как обработчик событий
для нажатия (см. выше п. **)
Внутри нее проверяется какая кнопка обратилась к этому обработчику.
И если это кнопка с именем "iButton_Calculate", то запускается функция Do_iButton_Calculate().
// Обработчик события нажатия (Event Handler) для кнопки
// когда кнопка нажата, эта функция выполняется
// здесь iDescr - это дескриптор нажатой кнопки (iButtonCalculate в этом примере)
// и sDescr - текстовое имя элемента ("iButtonCalculate" в этом примере);
int Event_ButtonClicked_DCName(int iDescr, string sDescr)
{
// в конструкциях if скобки { и } обязательны
if (sDescr == "iButton_Calculate")
{
Do_iButton_Calculate();
}
}
// функция, которая выполняется когда нажата кнопка iButton_Calculate
int Do_iButton_Calculate()
{
string s;
ts_dialogcontrol(iTextEdit, "gettext", s); // Получить текст из iTextEdit - плотность как текст, содержащий число с плавающей точкой
strreplaceall(s, ",", "."); // Если пользователь ввел "," мы заменяем его на "."
double density = atof(s); // конвертируем текст в число с плавающей точкой
В LABPP C++ для Revit имеется 10 встроенных списков элементов (количество списков увеличивается командой при необходимости).
Отбирать элементы в этот список можно либо прямым указанием в вызове функции, либо заранее создать таблицу строк фильтров.
Возможно неограниченное количество скобок, команды "И" и "ИЛИ", указание различных функций и параметров элементов.
LABPP для Revit использует понятие Генезис для разделения параметров на категории чтобы избежать путанницы.
Какие параметры использовать в фильтрах вы можете понять запустив LABPP BIM Master.
На вкладке Common (общие) расположены параметры с генезисом "ЕP". На вкладке "ElemProps" (параметры на уровне экземпляра элемента) - генезис "UP". На вкладке "TypeProps" (параметры на уровне типа) - генезис "EPt". На вкладке BuiltInPars (встроенные параметры) - "UPb", и на вкладке "QTY" (quantity, количественные) - генезис "Q".
Команды для сравнения параметров разнообразны. От простого сравнения значений, до попадания в диапазон и наличия текстового шаблона Regex.

// загрузить элементы из проекта Revit во внутренний список № 1 с фильтром:
// любые элементы ("OST_Zombie"), MainFilter = 0,
// параметр с генезисом "EP" (вкладка Common параметров на панели LABPP BIM Master) "ZFromProject0" должен быть >= 0 И
// параметр с генезисом "UPt" (уровень типа элемента TypeProps на панели LABPP BIM Master) "Имя типа" должен содержать "бетон"
// "_CONTAINS" - если есть знак подчеркивания, то при сравнении не учитывается регистр текста (все равно если "бетон", "Бетон" или "БЕТОН")
rvt_request("load_elements_list", 1, "OST_Zombie", "MainFilter", 0,
"(","EP","ZFromProject0",">=",0,")", "AND",
"(","UPt", "Имя типа", "_CONTAINS", "бетон",")"
);
rvt_request("get_loaded_elements_list_count", 1); // запрос сколько элементов загружено в список 1
int icount = rvt_getnumvalue(); // поместить результат запроса в переменную icount
// объявить и присвоить первичные значения требуемым переменным
string selement_name = "";
double dvolume = 0;
double dvolumeall = 0;
double dmassa = 0;
double dmassaall = 0;
int i;
// напечатать в окре сообщений программ
// ---------------
// Элементы 10 шт
//----------------
cout << "\r\n---------------" << "\r\nЭлементы " << itoa(icount) << "шт\r\n---------------";
// Расчетный цикл
for (i = 0; i < icount; i++)
{
rvt_request("set_current_element_from_list", 1, i); // установить элемент i из списка № 1 как текущий для работы с ним
rvt_request("get_element_value", "EP", "element_name"); // запросить имя элемента (параметр с генезисом "EP" - Common в LABPP BIM Master
selement_name = rvt_getstrvalue(); // поместить результат запроса в переменную selement_name
rvt_request("get_element_value", "UP", "Объем"); // запросить значение параметра UP/Объем (генезис "UP" - значит переменная уровня экземпляра элемента, вкладка ElemProps в LABPP_BIM_Master.
dvolume = tsround(rvt_getnumvalue(),4); // получить результат запроса и округлить до 4-х знаков после запятой
dmassa = dvolume * density; // расчитать массу умножением объема на плотность
dmassaall += dmassa; // суммировать массу
// напечатать строку отчета
cout << "\r\n" << itoa(i+1) << "). "<< selement_name << ": объем= " << dvolume << " масса при плотности " << s << "=" << dmassa;
dvolumeall += dvolume; // суммировать объем
}
// печатать итоговую строку
cout << "\r\n" << "Суммарный объем элементов= " << dvolumeall << " суммарная масса при плотности " << s << "=" << dmassaall;
// поместить в поле "A" LABPP_Calc суммарное значение объема и комментарий
rvt_request("calc_field", "set", "a", 0, ftoa(tsround(dvolumeall,4)), "Объем элементов");
string fieldletter2;
ts_dialogcontrol(iPopUp, "GetText", fieldletter2); // получить из элемента popup имя поля, куда записать массу ("B", "C" or "D")
rvt_request("calc_field", "set", fieldletter2, 0, ftoa(tsround(dmassaall,4)), "Масса при плотности "+s); // поместить в поле LABPP_Calc итоговую массу и комментарий
}