// COM version of the TMSH2D01 test case (mesh of a simple square).
//

#include "stdafx.h"
#include "..\common\fe_defs.h"


/**
   Very simple C++ program to mesh a square with triangles or quadrangles.
   Uses CM2 TriaMesh and CM2 QuadMesh through the COM interface.
   */

int main(int argc, char* argv[])
{

   wchar_t     msg1[256] = L"";           // For error messages.

   if (FAILED(CoInitialize(NULL)))
   {
      cout << "Initialization COM failed.\n";
      return 0;
   }

   try
   {
      IDoubleMatPtr                       pPos (__uuidof(DoubleMat));
      IUIntVecPtr                         pIndices (__uuidof(UIntVec));
      IUIntMatPtr                         pConnectB (__uuidof(UIntMat));
      IUIntMatPtr                         pConnectM (__uuidof(UIntMat));
      meshtools::IMeshToolsPtr            pMT (__uuidof(meshtools::MeshTools));
      meshtools1D::IMeshTools1DPtr        pMT1D (__uuidof(meshtools1D::MeshTools1D));
      triamesh::ImesherPtr                pT3M (__uuidof(triamesh::mesher));   
      quadmesh::ImesherPtr                pQ4M (__uuidof(quadmesh::mesher)); 
      triamesh::Idata_typePtr             pT3D (__uuidof(triamesh::data_type));
      quadmesh::Idata_typePtr             pQ4D (__uuidof(quadmesh::data_type));

      // Registration of the DLLs.
      pT3M->registration ("Licensed to DEMO.", "FC5B65DEDF55");
      pQ4M->registration ("Licensed to DEMO.", "7FA4A61046AA");

      // Construct the four vertices of the square.
      pPos->push_back2 ( 0.0, 0.0);
      pPos->push_back2 (10.0, 0.0);
      pPos->push_back2 (10.0, 10.0);
      pPos->push_back2 ( 0.0, 10.0);

      // Mesh the four segments (10 elements on each segment).
      pMT1D->mesh_straight1 (pPos, 0, 1, 10, pIndices);  pIndices->pop_back();
      pMT1D->mesh_straight1 (pPos, 1, 2, 10, pIndices);  pIndices->pop_back();
      pMT1D->mesh_straight1 (pPos, 2, 3, 10, pIndices);  pIndices->pop_back();
      pMT1D->mesh_straight1 (pPos, 3, 0, 10, pIndices);
      pMT1D->indices_to_connectE2 (pIndices, pConnectB);

      // Do the triangle mesh.
      pT3D->put_pos (pPos);
      pT3D->put_connectB (pConnectB);
      pT3M->run (pT3D);
      if (pT3D->error_code != 0)       // Catch errors.
      {
         BSTR  bstr1 = 0;
         pT3D->get_msg1 (&bstr1);
         if (bstr1) ::wcsncpy (msg1, bstr1, 255);
         ::SysFreeString (bstr1);
         throw "CM2 Exception";   
      }
      pT3D->get_pos (&pPos);
      pT3D->get_connectM (&pConnectM);
      pT3D->print_info();

      // MEDIT output of the triangle mesh
      pMT->medit_output ("T3.mesh", pPos, pConnectM, (element_type)CM2_FACET3);


      // Do the quadrangle mesh.
      pQ4D->put_pos (pPos);
      pQ4D->put_connectB (pConnectB);
      pQ4M->run (pQ4D);
      if (pQ4D->error_code != 0)       // Catch errors.
      {
         BSTR  bstr1 = 0;
         pQ4D->get_msg1 (&bstr1);
         if (bstr1) ::wcsncpy (msg1, bstr1, 255);
         ::SysFreeString (bstr1);
         throw "CM2 Exception";   
      }
      pQ4D->get_pos (&pPos);
      pQ4D->get_connectM (&pConnectM);
      pQ4D->print_info();

      // MEDIT output of the quadrangle mesh
      pMT->medit_output ("Q4.mesh", pPos, pConnectM, (element_type)CM2_FACEQ4);
   }

   catch (const _com_error& err)    // For COM errors.
   {
      std::cout << err.ErrorMessage() << endl;
   }

   catch( const char* str )         // For CM2 errors.
   {
      std::wcout << str << ": " << msg1 << endl;
   }

   CoUninitialize();

   return 0;
}
