Reading a block model

Download raw version here.

//////////////////////////////////////////////////////////////////////////////
//
// Name        : VulcanSDK_blockmodel_example.cpp
// Description : A basic example of using the Vulcan SDK with block models
//
// Maptek Pty Ltd, 2020
//
//////////////////////////////////////////////////////////////////////////////

#include <stdio.h>

#include "mtkExportedApi_ReadWrite.h"

int RunBlockModelExample(char* filename)
{
   int status, i;

   MTK_BlockModel *bmodel;
   double model_x0, model_y0, model_z0, model_x1, model_y1, model_z1;
   double match_x0, match_y0, match_z0, match_x1, match_y1, match_z1;

   long long numBlocks;
   int numBlockVariables;
   char* variableName;
   bool foundNumericUserVariable;
   double variableValue, defaultValue, summedValue;
   

   printf("Initialising API using Maptek Extend licence...");
   // Setup environment variable 'VULCAN' for this process to a 
   // Vulcan installation directory for dependencies and licencing. 
   MTK_SetVulcanEnvironmentVariable("C:/Program Files/Maptek/Vulcan 12.0.3");
   // Initialise library using client-side Maptek Extend licence
   if (MTK_API_InitExtend())
   {
      HandleError();
      return 1;
   }
   printf("done\n");

   printf("Opening block model %s...", filename);
   bmodel = MTK_BlockModel_Open(filename, 0);
   if (!bmodel)
   {
      HandleError();
      return 1;
   }
   printf("done\n");

   status = MTK_BlockModel_GetModelExtent(
               bmodel,
               &model_x0, &model_y0, &model_z0,
               &model_x1, &model_y1, &model_z1
            );
   if (status)
   {
      HandleError();
      return 1;
   }
   printf("BlockModel extents: %.2f %.2f %.2f, %.2f %.2f %.2f\n",
          model_x0, model_y0, model_z0, model_x1, model_y1, model_z1);

   numBlocks = MTK_BlockModel_NBlocks(bmodel);
   if (numBlocks == -1)
   {
      HandleError();
      return 1;
   }
   printf("Number of blocks in model: %lld\n", numBlocks);

   // This code creates a block 'match'. A block match is a subset of the
   //    block model and can be created in various ways. In this case it is
   //    being created by shrinking the extents.
   // Once a match is created, navigation calls such as NextBlock work
   //    within the match, not the entire model.
   printf("Creating match for a central portion of the block model...");
   match_x0 = model_x0 + ((model_x1 - model_x0) / 3);
   match_x1 = model_x1 - ((model_x1 - model_x0) / 3);
   match_y0 = model_y0 + ((model_y1 - model_y0) / 3);
   match_y1 = model_y1 - ((model_y1 - model_y0) / 3);
   match_z0 = model_z0 + ((model_z1 - model_z0) / 3);
   match_z1 = model_z1 - ((model_z1 - model_z0) / 3);
   status = MTK_BlockModel_SetMatchExtent(
               bmodel,
               match_x0, match_y0, match_z0,
               match_x1, match_y1, match_z1
            );
   if (status)
   {
      HandleError();
      return 1;
   }
   printf("done\n");
   printf("BlockMatch extents: %.2f %.2f %.2f, %.2f %.2f %.2f\n",
          match_x0, match_y0, match_z0, match_x1, match_y1, match_z1);

   // This code finds a numeric variable that we can use later
   printf("Searching for a numeric user variable...");
   numBlockVariables = MTK_BlockModel_NVariables(bmodel);
   if (numBlockVariables == -1)
   {
      HandleError();
      return 1;
   }
   foundNumericUserVariable = false;
   variableName = (char*)malloc(sizeof(char) * 256);
   for (i = 0; i < numBlockVariables; ++i)
   {
      status = MTK_BlockModel_GetVariableName(bmodel, i, variableName);
      if (status)
      {
         HandleError();
         return 1;
      }

      status = MTK_BlockModel_IsNumber(bmodel, variableName);
      if (status == -1)
      {
         HandleError();
         return 1;
      }

      if (status == 1)
      {
         foundNumericUserVariable = true;
         break;
      }
   }
   if (!foundNumericUserVariable)
   {
      printf("not found, so using volume\n");
      sprintf(variableName, "volume");
   }
   else
   {
      printf("found %s\n", variableName);
   }

   // This code iterates through blocks in the match, retrieving the values of
   //    the specified variable and summing them if they are not equal to
   //    their default value
   printf("Summing %s in block model match "
          "(ignoring default values)... ", variableName);
   summedValue = 0;

   status = MTK_BlockModel_GetDefaultNumber(
               bmodel, variableName, &defaultValue
            );
   if (status)
   {
      HandleError();
      return 1;
   }

   status = MTK_BlockModel_FirstBlock(bmodel);
   if (status)
   {
      HandleError();
      return 1;
   }

   numBlocks = 0;
   do
   {
      numBlocks = numBlocks + 1;
      status = MTK_BlockModel_GetNumber(
                  bmodel, variableName, &variableValue
               );
      if (status)
      {
         HandleError();
         return 1;
      }

      if (variableValue != defaultValue)
      {
         summedValue += variableValue;
      }

      status = MTK_BlockModel_NextBlock(bmodel);
      if (status)
      {
         HandleError();
         return 1;
      }

      status = MTK_BlockModel_IsEof(bmodel);
   } while (status == 0);
   if (status == -1)
   {
      HandleError();
      return 1;
   }
   printf("%.2f\n", summedValue);

   printf("Number of blocks in match: %lld\n", numBlocks);

   free(variableName);

   if (MTK_BlockModel_Close(bmodel))
   {
      HandleError();
      return 1;
   }
   MTK_API_Terminate();
   return 0;
}

static void HandleError()
{
   char error[MTK_BUFFER_SIZE];
   MTK_API_GetError(error);
   printf("%s\n", error);
   MTK_API_Terminate();
}