Renga BIM APIs

    Hello! In this article, I will talk about the Renga BIM system API. You can read about the system here , here you can also request a version for non-commercial use. In short, Renga is a three-dimensional computer-aided design system in architecture and construction. In it, the designer / architect / constructor works with the information model of the building, receives associative drawings, specifications, in general, creates the project.



    Why do I need a CAD system API


    At first, as usual, a little water.

    The development of extensions for CAD systems is quite common, because in any design there are various areas, sections and standards for design documentation that require different highly specialized functionality. In addition, there are tasks of integration with programs for calculation, visualization, workflow and many others. The solution is to create plug-ins that extend the functionality of the system.

    Simple extension example


    Let's go through the basic steps to create an extension. You will need VisualStudio and the certainty that you know C ++ (the Renga has a C ++ API now, but in the future we will switch to COM, we will support .Net extensions).

    So, in steps:

    1. Download the SDK from here , unpack it in a convenient place.
    2. Create a simple dll with default settings, call MyPlugin.
    3. In the additional inclusion folders and additional lib folders, add the path to RengaSDK, add RengaApi.lib and RengaBase.lib to the included libraries.
    4. Now write a minimal implementation. In essence, the C ++ extension to Renga is a regular dll library with an export function that returns a pointer to the IPlugin interface. Therefore, all we need to do is:

      a) Create a class inherited from this interface. We implement both the start and stop interface methods in the class; these methods will be called after loading and before unloading, respectively. We leave the implementation empty for now.

      b) Implement an export function that returns a pointer to the IPlugin interface. You can use the EXPORT_PLUGIN macro to do this.
    5. Create an extension description file named MyPlugin.rnedesc with the following text:

      MyPlugin1.0Vendor nameCopyright text1.2MyPlugin.dll
    6. In order for the extension to appear in Renga in the Renga installation folder in the Plugins folder, create the MyPlugin folder, in which we put our dll and description file.

    If everything is done correctly, then when Renga starts, in the settings dialog in the “Extensions” section, our extension will appear, which does nothing.

    Let's make him calculate the amount of brick needed to build walls in a building. Take the rate of consumption - 400 pieces per cubic meter, taking into account the seams.

    1. First, create a button in the main application panel. Let's do it right in the initialize method

    bool MyPlugin::initialize(const wchar_t * pluginPath)
    {
      auto countBricksAction = rengaapi::UIControls::createAction();
      countBricksAction.setToolTip(rengabase::String(L"Рассчитать количество кирпичей в стенах"));
      auto primaryPanelExtension = rengaapi::UIControls::createToolPanelExtension();
      primaryPanelExtension.addToolButton(countBricksAction);
      return true;
    }

    2. Next, we implement the button click handler, create the class CountBricksHandler, the descendant of the rengaapi :: IInvokable interface. Create it in the MyPlugin class and set it as the button handler.

    
    //CountBricksHandler.h
    #pragma once
    #include 
    class CountBricksHandler : public rengaapi::IInvokable
    {
    public:
      void invoke();
    };
    //CountBricksHandler.cpp
    #include "stdafx.h"
    #include "CountBricksHandler.h"
    void CountBricksHandler::invoke()
    {}
    

    3. Declare the m_countBricksHandler field in the private section of the MyPlugin class, set it as the handler for countBricksAction.

    
    auto countBricksAction = rengaapi::UIControls::createAction();
      countBricksAction.setToolTip(rengabase::String(L"Count bricks in walls"));
      countBricksAction.setTriggerHandler(&m_countBricksHandler);
    

    4. Now it remains to implement the calculation of the number of bricks in the walls. Let's create a simple class - a calculator, which will calculate the volume of the “Brick” material used in the walls, and give out the amount depending on the transmitted consumption rate. We call the calculation in the Invoke method of the button handler.

    
    //BricksCounter.h
    #pragma once
    namespace rengaapi
    {
      class Wall;
    }
    class BricksCounter
    {
    public:
      BricksCounter(int consumptionRatePerM3);
      int calculateBricks();
    private:
      double calculateBricksVolume();
      double calculateBricksVolumeInSingleWall(rengaapi::Wall* pWall);
      int calculateBricksCountInVolume(double bricksVolume);
    private:
      int m_consumptionRatePerM3;
    };
    

    
    //BricksCounter.cpp
    #include "stdafx.h"
    #include "BricksCounter.h"
    #include 
    #include 
    #include 
    #include 
    const wchar_t* c_briksMaterialName = L"Кирпич";
    BricksCounter::BricksCounter(int consumptionRatePerM3)
      : m_consumptionRatePerM3(consumptionRatePerM3)
    {
    }
    int BricksCounter::calculateBricks()
    {
      double bricksVolume = calculateBricksVolume();
      int bricksNumber = calculateBricksInVolume(bricksVolume);
      return bricksNumber;
    }
    double BricksCounter::calculateBricksVolume()
    {
      double result = 0.0;
      assert(rengaapi::Project::hasProject());
      auto allObjects = rengaapi::Project::model().objects();
      for (auto objectIt = allObjects.begin(); objectIt != allObjects.end(); ++objectIt)
      {
        if ((*objectIt)->type() == rengaapi::ModelObjectTypes::WallType)
        {
          rengaapi::Wall* pWall = dynamic_cast(*objectIt);
          assert(pWall != nullptr);
          result += calculateBricksVolumeInSingleWall(pWall);
        }
      }
      return result;
    }
    double BricksCounter::calculateBricksVolumeInSingleWall(rengaapi::Wall * pWall)
    {
      auto materialId = pWall->material();
      rengaapi::LayeredMaterial wallMaterial;
      rengaapi::Materials::layeredMaterial(materialId, wallMaterial);
      auto materialLayers = wallMaterial.layers();
      auto layerQuantityCollection = pWall->quantities().materialQuantities();
      double bricksVolume = 0.0;
      for (size_t i = 0; i < materialLayers.size(); ++i)
      {
        if (materialLayers.get(i).material().name_() == rengabase::String(c_briksMaterialName))
        {
          auto oVolumeMeasure = layerQuantityCollection.get(i).netVolume();
          if (oVolumeMeasure.hasValue())
          {
            bricksVolume += oVolumeMeasure.getValue()->inMeters3();
          }
        }
      }
      return bricksVolume;
    }
    int BricksCounter::calculateBricksInVolume(double bricksVolume)
    {
      return static_cast(bricksVolume * m_consumptionRatePerM3);
    }
    

    
    // CountBricksHandler.cpp
    #include "stdafx.h"
    #include "CountBricksHandler.h"
    #include "BricksCounter.h"
    #include 
    #include 
    const int c_bricksConsumptionRatePerM3 = 400;
    void CountBricksHandler::invoke()
    {
      if (!rengaapi::Project::hasProject())
      {
        rengaapi::Message::showMessageBox(rengaapi::Message::Info,
          rengabase::String(L"Сообщение MyPlugin"),
          rengabase::String(L"Проект отсутствует. Невозможно подсчитать поличество кирпича."));
      }
      else
      {
        BricksCounter counter(c_bricksConsumptionRatePerM3);
        int bricksCount = counter.calculateBricks();
        std::wstring message = std::wstring(L"Количество кирпича в стенах, шт: ") + std::to_wstring(bricksCount);
        rengaapi::Message::showMessageBox(rengaapi::Message::Info,
          rengabase::String(L"Сообщение MyPlugin"),
          rengabase::String(message.data()));
      }
    }
    

    The full extension code is here



    More about Renga extensions


    In principle, everything to start working with the Renga API is in the SDK (http://rengabim.com/sdk/), there are also examples of all the main features.

    Also, as examples, we developed an extension for viewing the model in the form of a hierarchical structure (tree) and an extension for filtering model objects according to various criteria. These extensions are available both in assembled form and in the form of source code, you can use it as an example or modify it to taste. In addition, third-party developers created extensions for 3D rendering and for export to 3D PDF. Look for these and new extensions here .

    What API allows


    The Renga API now allows you to:

    • Export a 3D representation of objects in the form of a polygonal mesh (mesh representation), divided into groups so that, for example, it is possible to distinguish the facade of the wall from the end.
    • Add controls to the Renga user interface (well, and respond to them, of course).
    • Get the parameters and calculated characteristics of three-dimensional objects of the model (volumes, areas, sizes, etc.).
    • Create custom properties, assign them to model objects, change the value.
    • Manage visibility and highlight model objects.

    That's all for today, we will be happy to answer your questions. Write under Renga, generate ideas, develop with us!

    Eugene Tian, ​​Lead Programmer, Renga Software.

    Also popular now: