Work with Mechanical Layers and Layer Groups (Part 1 of 2)

Dmytro Kabenok

May 27, 2021

Overview

Mechanical SDK is pre-configured to create objects on specific layers. Regardless of what layer is set as current, Mechanical SDK creates objects only on the predefined layer. If the layer doesn't exist, it is automatically created. These mechanical layers have predefined settings such as layer color, lineweight, etc. which are taken from a set of pre-configured settings that are referred to as layer definitions.

You can create multiple sets of mechanical layers. Each set is called a layer group. With mechanical layer groups, you can:

  • Move or copy objects from one layer group to another.
  • Work globally with individual layers that are part of a layer group. For example, you can change the lineweight regardless of the layer group on which you created it.
  • Set a color for the layer group, then override the color of individual layers by the layer group color.
  • Lock and freeze layer groups to simplify design work.

There are three files in which the required classes and functions are declared:

  • AmiLayer.h
  • AmiLayerCfg.h
  • AmiLayObjCfg.h

These files belong to the McadApi module and are available in the public Include directory.

Examples of Working with Layers

You can create any of the following mechanical layers: AM_0, AM_1, AM_2, AM_3, AM_4, AM_5, AM_6, AM_7, AM_8, AM_9, AM_10, AM_11, AM_12, AM_0N, AM_1N, AM_2N, AM_3N, AM_4N, AM_5N, AM_6N, AM_7N, AM_8N, AM_9N, AM_10N, AM_11N, AM_12N, AM_CL, AM_PAREF, AM_BOR, AM_VIEWS, AM_INV, AM_TR, AM_HID, AM_VIS, AM_PARDIM, AM_REFDIM.

These layers contain a preconfigured set of parameters and are created based on those parameters. Use a name from the list to create a mechanical layer, otherwise a regular layer is created.

To create a new mechanical layer, use the following code example:

// Note: The next block of code requires additional inclusion of "AmiLayer.h"

OdDbDatabase* pDb = ... // get a pointer to the current database

OdString layerName = L"AM_11"; // layer name from the list above to create
OdString layerGroup; // group name can be empty, in this case no group is
                     // created. If you want to create a layer in a specific
                     // group, then specify the name of the group

AmiStatus status = amiCreateLayer(layerName, layerGroup, pDb);
if (status.success())
{
  ... // The layer is successfully created
}
else
{
  ... // The layer can not be created. Perhaps it already exists or input
      // parameters are not set correctly
}

To import a layer configuration from a file, use the following code example:

// Note: The next block of code requires additional inclusion of "AmiLayer.h"

OdDbDatabase* pDb = ... // get a pointer to the current database

bool bReplace = true; // for a complete copy of mechanical layer settings
                      // if set as false, only part of settings will be copied
OdString dwgName = ... // set file path with file name for settings import

AmiStatus status = amiImportLayCfg(pDb, dwgName, bReplace);
if (status.success())
{
  ... // Settings successfully imported
}
else
{
  ... // Failure during import
}

To reset all settings related to mechanical layers to factory defaults, use the following code example:

//Note: The next block of code requires additional inclusion of "AmiLayer.h"

OdDbDatabase* pDb = ... // get a pointer to the current database

AmiStatus status = amiSetLayCfgDefault(pDb);
if (status.success())
{
  ... // Settings successfully restored to defaults
}
else
{ 
  ... // Failure during settings reset
}

You can get an array of all mechanical layers for the specified standard by using the following code example:

// Note: The next block of code requires additional inclusion of "AmiLayer.h" and
//       "AcmStandardManager.h"

OdDbDatabase* pDb = ... // get a pointer to the current database

// get the current std ID
OdDbObjectId stdId;
if (getAcmStdMgr()->getCurrent(stdId, pDb) != Acm::eOk)
  return;

OdArray<AmiLayerCfg*> arLayCfg;
AmiStatus status = amiGetAllLayers(arLayCfg, stdId);
if (status.success())
{
  // Perform some actions with the array. For example you can loop through all
  // elements of the array and set the same lineweight value. In this case don't
  // forget to add the "AmiLayerCfg.h" inclusion

  for (OdUInt16 i = 0; i < arLayCfg.length(); ++i)
  {
    AmiLayerCfg* pLayerCfg = arLayCfg[i];
    if (pLayerCfg)
      pLayerCfg->setLineweight(OdDb::kLnWt005);
  }
}
else
{
  ... // Failure during execution
}

// Don't forget to clear the memory because the ‘new’ operator is used to create
// each element in the array

for (OdUInt16 i = 0; i < arLayCfg.length(); ++i)
  delete arLayCfg[i];

To change the values for only one mechanical layer, it is not necessary to get the entire array and look for a specific object in it. You can do it using the example code below:

// Note: The next block of code requires additional inclusion of "AmiLayer.h",
//       "AcmStandardManager.h" and "AmiLayerCfg.h"

OdDbDatabase* pDb = ... // get a pointer to the current database

// get the current std ID
OdDbObjectId stdId;
if (getAcmStdMgr()->getCurrent(stdId, pDb) != Acm::eOk)
  return;

OdString layerName = ... // set the layer name from the previously mentioned
                         // list of names for the amiCreateLayer() function
AmiLayerCfg* layerProp = NULL;

AmiStatus status = amiGetLayerProperty(layerName, layerProp, stdId);
if (status.success())
{
  layerProp->setInvisible(true);
}
else
{
  ... // Failure during execution. Perhaps the input parameters are incorrect
}

// Don't forget to clear the memory because the ‘new’ operator was used for
// object creation

if (layerProp)
  delete layerProp;

To get an array of all mechanical layer objects for the specified standard, use the following code example:

// Note: The next block of code requires additional inclusion of "AmiLayer.h" and
//       "AcmStandardManager.h"

OdDbDatabase* pDb = ... // get a pointer to the current database

// get the current std ID for amiGetAllLayerObjs
OdDbObjectId stdId;
if (getAcmStdMgr()->getCurrent(stdId, pDb) != Acm::eOk)
  return;

OdArray<AmiLayObjCfg*> arLayObjCfg;
AmiStatus status = amiGetAllLayerObjs(arLayObjCfg, stdId);
if (status.success())
{
  // Perform an action with the array. For example you can loop through all
  // elements of the array and set the same line weight value. In this case
  // don't forget to add the "AmiLayObjCfg.h" inclusion

  for (OdUInt16 i = 0; i < arLayObjCfg.length(); ++i)
  {
    AmiLayObjCfg* pLayObjCfg = arLayObjCfg[i];
    if (pLayObjCfg)
      pLayObjCfg->setLineweight(OdDb::kLnWt005);
  }
}
else
{
  ... // Failure during execution
}

// Don't forget to clear the memory because the ‘new’ operator is used to create
// each element in the array

for (OdUInt16 i = 0; i < arLayObjCfg.length(); ++i)
  delete arLayObjCfg[i];

To change the values for only one mechanical layer object (just like in the example with a mechanical layer), it is not necessary to get the entire array and look for a specific object in it. You can get the object you are looking for using a special key. All available keys are listed below:

BHNV, BHNVS, BOR2, BOR3, BOR5, CAL2, CAL3, CAL5, CAL7, CENN, CENW, CLIN, CON1, CON2, CON3, CON4, DETA, DIAG, DILI, DIMP, DIMR, FEMN, FEMPN, FEMSP, FEMST, FEMVN, FEMVT, HATC, HIDN, HIDW, HLIN, HOCN, HOCW, INFO, LEAD, N_BHNV, N_CON1, N_CON2, N_CON3, N_CON4, N_CENN, N_CENW, N_DILI, N_HATC, N_HIDN, N_HIDW, N_LEAD, N_NGIP, N_PHAN, N_TCON, N_THLI, N_TLEN, N_VPLI, NGIP, PAL2, PAL3, PAL5, PHAN, POSN, RCGN, RCGW, BRK, SECT, SYB3, MSYM, TCON, THLI, TIT2, TIT3, TIT5, TLEN, TRAIL, TRLI, TXT1, TXT2, TXT3, TXT5, TXT7, VIEW, VEDH, VEDV, VPLI, ZIZA, SPLI.

// Note: The next block of code requires additional inclusion of "AmiLayer.h",
//       "AcmStandardManager.h" and "AmiLayObjCfg.h"

OdDbDatabase* pDb = ... // get a pointer to the current database

// get the current std ID
OdDbObjectId stdId;
if (getAcmStdMgr()->getCurrent(stdId, pDb) != Acm::eOk)
  return;

OdString objKey = ... // set a key of the mechanical layer object from the list above
AmiLayObjCfg* objProp = NULL;

AmiStatus status = amiGetLayerObjProperty(objKey, objProp, stdId);
if (status.success())
{
  OdCmColor color;
  color.setColorIndex(3);
  objProp->setTrueColor(color);
}
else
{
  ... // Failure during execution. Perhaps the input parameters are incorrect
}

// Don't forget to clear the memory because the ‘new’ operator was used for
// object creation

if (objProp)
  delete objProp;