Creating a simple triangulation (using C#)

This is a very simple example illustrating how to wrap these APIs in a C# console application to create a Vulcan triangulation.

To avoid BadImageFormatException exceptions - the .Net project must have platform target set to x64.

The Vulcan API DLLs should exist in same directory as your application.

//////////////////////////////////////////////////////////////////////////////
//
// Name        : mtkExportedApi_ReadWrite_dotnet.cs
// Description : A basic example of using the mtkExportedApi with C#
//
//////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;

namespace Vulcan00tWriter
{
  class Program
  {
    // Import C Functions required
    [DllImport("mtkExportedApi_ReadWrite_Init.dll", EntryPoint = "MTK_API_InitExtend", CharSet = CharSet.None)]
    private static extern int MTK_API_InitExtend();
    [DllImport("mtkExportedApi_ReadWrite.dll", EntryPoint = "MTK_API_Terminate", CharSet = CharSet.None)]
    private static extern void MTK_API_Terminate();
    [DllImport("mtkExportedApi_ReadWrite.dll", EntryPoint = "MTK_SetVulcanEnvironmentVariable", CharSet = CharSet.None)]
    private static extern int MTK_SetVulcanEnvironmentVariable(string vulcan);
    [DllImport("mtkExportedApi_ReadWrite.dll", EntryPoint = "MTK_Triangulation_New", CharSet = CharSet.None)]
    private static extern IntPtr MTK_Triangulation_New();
    [DllImport("mtkExportedApi_ReadWrite.dll", EntryPoint = "MTK_Triangulation_Save", CharSet = CharSet.None)]
    private static extern int MTK_Triangulation_Save(IntPtr triang, string name);
    [DllImport("mtkExportedApi_ReadWrite.dll", EntryPoint = "MTK_Triangulation_Close", CharSet = CharSet.None)]
    private static extern int MTK_Triangulation_Close(IntPtr triang);
    [DllImport("mtkExportedApi_ReadWrite.dll", EntryPoint = "MTK_Triangulation_IsValid", CharSet = CharSet.None)]
    private static extern int MTK_Triangulation_IsValid(IntPtr triang);
    [DllImport("mtkExportedApi_ReadWrite.dll", EntryPoint = "MTK_Triangulation_AddTriangle", CharSet = CharSet.None)]
    private static extern int MTK_Triangulation_AddTriangle(IntPtr triang, ref int a, ref int b, ref int c);
    [DllImport("mtkExportedApi_ReadWrite.dll", EntryPoint = "MTK_Triangulation_AddPoint", CharSet = CharSet.None)]
    private static extern int MTK_Triangulation_AddPoint(IntPtr triang, ref double x, ref double y, ref double z);

    static void Main(string[] args)
    {
      var vulcanPath = "";
      while(!Directory.Exists(vulcanPath))
      {
        Console.WriteLine("Please input your Vulcan install path:\n");
        vulcanPath = Console.ReadLine();
      }

      var savePath = "";
      while(string.IsNullOrEmpty(savePath) || File.Exists(savePath))
      {
        Console.WriteLine("Enter path to save 00t file:\n");
        savePath = Console.ReadLine();
        savePath = Path.GetFullPath(savePath);
        if(File.Exists(savePath))
          Console.WriteLine($"{savePath} already exists. Try a different file name.");
      }

      // Initialise the library and check licence
      if (InitVulcan(vulcanPath))
      {
        // Build the triangulation
        BuildDemoTriangulation(savePath);
      }
      // Clean up
      MTK_API_Terminate();
      Console.WriteLine("Done");
      Console.WriteLine("Press any key to exit...");
      Console.ReadLine();
    }


    static void BuildDemoTriangulation(string path)
    {
      double edge_size = 5;
      List<Vector3D> points = new List<Vector3D>();
      List<TripleIndex> faces = new List<TripleIndex>();

      // Create a tetrahedron
      points.Add(new Vector3D(-edge_size, -edge_size, -edge_size));
      points.Add(new Vector3D(-edge_size, edge_size, edge_size));
      points.Add(new Vector3D(edge_size, -edge_size, edge_size));
      points.Add(new Vector3D(edge_size, edge_size, -edge_size));

      faces.Add(new TripleIndex(0, 1, 2));
      faces.Add(new TripleIndex(0, 2, 3));
      faces.Add(new TripleIndex(0, 1, 3));
      faces.Add(new TripleIndex(1, 2, 3));

      IntPtr triang = MTK_Triangulation_New();
      if(triang == IntPtr.Zero)
      {
        Console.WriteLine("Failed to create new triangulation in memory.");
        return;
      }

      Console.WriteLine("Writing points");
      points.ForEach(pt => MTK_Triangulation_AddPoint(triang, ref pt.X, ref pt.Y, ref pt.Z));

      Console.WriteLine("Writing faces");
      faces.ForEach(face => MTK_Triangulation_AddTriangle(triang, ref face.A, ref face.B, ref face.C));

      Console.WriteLine($"Saving path {path}");
      if(MTK_Triangulation_Save(triang, path) != 0)
      {
        Console.WriteLine($"Error occured saving {path}");
      }

      Console.WriteLine("Removing reference to object");
      MTK_Triangulation_Close(triang);
    }

    static bool InitVulcan(string path)
    {
      if (MTK_SetVulcanEnvironmentVariable(path) == 0)
      {
        if (MTK_API_InitExtend() == 0)
        {
          Console.WriteLine("Library initialised");
          return true;
        } else
        {
          Console.WriteLine("Failed to initialise with Extend license");
        }
      } else
      {
        Console.WriteLine("Failed to set Vulcan Environment Variable");
      }
      return false;
    }

    public struct Vector3D
    {
      public double X, Y, Z;
      public Vector3D(double x, double y, double z)
      {
        X = x; Y = y; Z = z;
      }
    }

    public struct TripleIndex
    {
      public int A, B, C;
      public TripleIndex(int a, int b, int c)
      {
        A = a; B = b; C = c;
      }
    }
  }
}