Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages | Examples

examples/modelassemble.cpp

/*******************************************************************************
  Copyright (c) 2002-2004 J. P. Abelanet/Basis Software.
  All Rights Reserved.

  -> THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF BASIS SOFTWARE. <-

  FILE
    modelassemble.cpp
    
  DESCRIPTION
    Sample code for assembling curved-surface models into larger models.
  
  PARAMETERS
    returns:
      0 - no errors occurred
     -1 - unknown error occurred
      1 - read failed
      2 - write failed
      3 - model assembly failed
      5 - error occurred while deleting the database

  REVISIONS
    03/28/03 - J. P. - Modified to return error code if DATABASE_Delete failed
    12/16/04 - J. P. - Modified to use EntityList class

  AUTHOR
    J. P. Abelanet - 12/17/02
*******************************************************************************/

/* system includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

/* library includes */
#include <geom/Database.h>
#include <geom/Entity.h>
#include <geom/EntityList.h>
#include <geom/NativeFileWriter.h>
#include <nmb/Edge.h>
#include <nmb/Model.h>
#include <nmb/NativeTopologyReader.h>
#include <nmb/Vertex.h>
#include <nmb/nmbcrvassemble.h>
#include <nmb/nmbcrvintegrity.h>
#include <nmb/nmbtopology.h>
#include <vmath/Base.h>
#include <vmath/Error.h>
#include <vmath/memory.h>
#include <vmath/polynomial.h>
#include <vmath/tolerance.h>

/* local declarations */
#define CHECK_INTEGRITY         TRUE


static Boolean SummarizeModel (const Model *model, const Int32 Index)
/*==============================================================================
  ABSTRACT
    This routine summarizes the contents of a model.
  
  PARAMETERS
    model  IN
      model to use
    
    Index  IN
      Identifier to use for this model
      
    returns:
      TRUE if no errors occurred
  
  REVISIONS
    12/03/03 - J. P. - Modified to summarize vertices as well
    
  AUTHOR
    J. P. Abelanet - 12/20/02
==============================================================================*/
{
  Edge  **Edges;
  Vertex        **Vertices;
  Int32         i, NumFaces, NumEdges, NumVertices;
  Int32         NumWireEdges, NumLaminaEdges, NumManifoldEdges, NumNonmanifoldEdges;
  Int32         NumWireVertices, NumLaminaVertices, NumManifoldVertices, NumNonmanifoldVertices;
  char          TopolTypeString[80];
  char          TopolType, EdgeTopolType, VertexTopolType;
  
  NMBT_Model_Inquire_Faces (model, NULL, &NumFaces);
  NMBT_Model_Inquire_Edges (model, &Edges, &NumEdges);
  NMBT_Model_Inquire_Vertices (model, &Vertices, &NumVertices);

  fprintf (stdout, "==> New Model #%ld <==\n", Index);
  fprintf (stdout, "Number of faces\t\t:  %12ld\n", NumFaces);
  fprintf (stdout, "Number of edges\t\t:  %12ld\n", NumEdges);
  fprintf (stdout, "Number of vertices\t:  %12ld\n", NumVertices);
  NMBT_Model_Inquire_TopologicalType (model, &TopolType);
  switch (TopolType) {
    case NMBT_MODEL_TOPOL_TYPE_WIRE:
      sprintf (TopolTypeString, "wire");
      break;
    case NMBT_MODEL_TOPOL_TYPE_SHEET:
      sprintf (TopolTypeString, "sheet");
      break;
    case NMBT_MODEL_TOPOL_TYPE_MANIFOLD:
      sprintf (TopolTypeString, "manifold");
      break;
    case NMBT_MODEL_TOPOL_TYPE_NONMANIFOLD:
      sprintf (TopolTypeString, "non-manifold");
      break;
  }
  fprintf (stdout, "Topological type\t:  %s\n", TopolTypeString);

  NumWireEdges = NumLaminaEdges = NumManifoldEdges = NumNonmanifoldEdges = 0;
  for (i = 0; i < NumEdges; i++) {
    NMBT_Edge_Inquire_TopologicalType (Edges[i], &EdgeTopolType);
    switch (EdgeTopolType) {
      case NMBT_TOPOL_TYPE_WIRE:
        NumWireEdges++;
        break;
      case NMBT_TOPOL_TYPE_LAMINA:
        NumLaminaEdges++;
        break;
      case NMBT_TOPOL_TYPE_MANIFOLD:
        NumManifoldEdges++;
        break;
      case NMBT_TOPOL_TYPE_NONMANIFOLD:
        NumNonmanifoldEdges++;
        break;
    }
  }
  MEM_ArrayFree ((void**)&Edges);
  if (NumWireEdges)
    fprintf (stdout, "  # of wire edges\t:  %12ld\n", NumWireEdges);
  if (NumLaminaEdges)
    fprintf (stdout, "  # of lamina edges\t:  %12ld\n", NumLaminaEdges);
  if (NumManifoldEdges)
    fprintf (stdout, "  # of manifold edges\t:  %12ld\n", NumManifoldEdges);
  if (NumNonmanifoldEdges)
    fprintf (stdout, "  # of non-man edges\t:  %12ld\n", NumNonmanifoldEdges);

  NumWireVertices = NumLaminaVertices = NumManifoldVertices = NumNonmanifoldVertices = 0;
  for (i = 0; i < NumVertices; i++) {
    NMBT_Vertex_Inquire_TopologicalType (Vertices[i], &VertexTopolType);
    switch (VertexTopolType) {
      case NMBT_TOPOL_TYPE_WIRE:
        NumWireVertices++;
        break;
      case NMBT_TOPOL_TYPE_LAMINA:
        NumLaminaVertices++;
        break;
      case NMBT_TOPOL_TYPE_MANIFOLD:
        NumManifoldVertices++;
        break;
      case NMBT_TOPOL_TYPE_NONMANIFOLD:
        NumNonmanifoldVertices++;
        break;
    }
  }
  MEM_ArrayFree ((void**)&Vertices);
  if (NumWireVertices)
    fprintf (stdout, "  # of wire vertices\t:  %12ld\n", NumWireVertices);
  if (NumLaminaVertices)
    fprintf (stdout, "  # of lamina vertices\t:  %12ld\n", NumLaminaVertices);
  if (NumManifoldVertices)
    fprintf (stdout, "  # of manifold vertices:  %12ld\n", NumManifoldVertices);
  if (NumNonmanifoldVertices)
    fprintf (stdout, "  # of non-man vertices\t:  %12ld\n", NumNonmanifoldVertices);

  return (TRUE);
} /* SummarizeModel */


static Boolean AssembleModels (Database *const Geom, const Real64 EdgeTolerance)
/*==============================================================================
  ABSTRACT
    This routine assembles all the curved-surface MODELS in a database.
  
  PARAMETERS
    Geom  INOUT
      Database to use
    
    EdgeTolerance  IN
      Allowable gap between faces
        
    returns:
      TRUE if no errors occurred
  
  REVISIONS
    03/10/03 - J. P. - Added explicit casts
    10/24/03 - J. P. - Modified to delete unused support geometry
    10/27/03 - J. P. - Modified to perform error checking more gracefully
    11/07/03 - J. P. - Fixed memory leaks in case of assembly failure
    01/21/04 - J. P. - Fixed memory leak in case of first integrity check failure
    05/25/04 - J. P. - Adding casts to error code for printing
      
  AUTHOR
    J. P. Abelanet - 12/20/02
==============================================================================*/
{
  EntityList    Models, Assemblies, UnusedGeometry;
  Entity        *DependentChild;
  Int32         i;
  ERR_type      LocalError, Error = ERR_no_errors;
  
  /* Find all the models */
  Geom->Inquire_Entities (ENT_class_curved_model,
      &Models);

  /* Summarize the contents of each MODEL */
  for (i = 0; i < Models.numEntities; i++) {
#if CHECK_INTEGRITY
    if ((LocalError = NMBCI_Model_Check_Integrity ((Model*)Models.entityList[i])) != ERR_no_errors)
      Error = LocalError;
#endif /* CHECK_INTEGRITY */
    SummarizeModel ((Model*)Models.entityList[i], i);
  }
  
  /* If an error occurred, abort */
  if (Error != ERR_no_errors)
    return (Error == ERR_no_errors);

  /* Assemble the models */
  if ((LocalError = NMBCASS_Model_Assemble (&Models, EdgeTolerance,
           FALSE, TRUE, &Assemblies, &UnusedGeometry)) != ERR_no_errors) {
    fprintf (stderr, "WARNING:  NMBCASS_Model_Assemble:  Failure assembling models (error #%ld)...\n", (Int32)LocalError);
    Error = LocalError;
  }

  if (UnusedGeometry.numEntities > 0) {
    Int32       NumDeleted = 0;
  
    /* Delete the unused curves */
    for (i = 0; i < UnusedGeometry.numEntities; i++)
      if (UnusedGeometry.entityList[i]->Inquire_Deletable (&DependentChild)) {
        NumDeleted++;
        UnusedGeometry.entityList[i]->Delete ();
      }
    
    if (NumDeleted > 0)
      printf ("NOTE:  Deleted %ld unused support curves...\n", NumDeleted);
  }
  
  /* Summarize the contents of each MODEL */
  for (i = 0; i < Assemblies.numEntities; i++) {
#if CHECK_INTEGRITY
    if ((LocalError = NMBCI_Model_Check_Integrity ((Model*)Assemblies.entityList[i])) != ERR_no_errors)
      Error = LocalError;
#endif /* CHECK_INTEGRITY */
    SummarizeModel ((Model*)Assemblies.entityList[i], i);
  }

  /* Add the new assemblies to the database */
  if ((LocalError = Geom->Attach_Entities (&Assemblies)) != ERR_no_errors) {
    fprintf (stderr, "WARNING:  Database::Attach_Entities:  Failure attaching models (error #%ld)...\n", (Int32)LocalError);
    Error = LocalError;
  }

  return (Error == ERR_no_errors);
} /* AssembleModels */


int main (int argc, char **argv)
{
  Database      *DB = NULL;
  Real64        EdgeTolerance = TOL_GetSamePointTol ();
  Real64        secs;
  Int32         i, ci, cf;
  char          FileName[256] = "";
  char          NMBFileName[] = "modelassemble.out.nmb";
  Int32         ErrorCode = 0;
  
  /* Check for command line args */
  for (i = 1; i < argc; i++)
    if (strcmp (argv[i], "-h") == 0) {
      printf ("Usage:  %s [-t xx.xx] [filename]\n", argv[0]);
      return (0);
    } else if (strcmp (argv[i], "-t") == 0)
      EdgeTolerance = atof (argv[++i]);
    else if (i == (argc - 1))
      strcpy (FileName, argv[i]);
    
  /* Create an empty database */
  if (!(DB = new Database ()))
    return (-1);

  /* Read the file */
  if (strlen (FileName) == 0)
    strcpy (FileName, "../data/faceface.test.nmb");
  printf ("Reading %s...\n", FileName);
  ci = clock();
  if (NativeTopologyReader::Read (FileName, DB) != ERR_no_errors)
    return (1);
  printf ("Finished reading file...\n");
  cf = clock();
  secs = (Real64)(cf - ci)/(Real64)CLOCKS_PER_SEC;
  fprintf (stdout, "Elapsed CPU Time (secs) = %.2f\n", secs);
  
  printf ("Assembling models...\n");
  ci = cf;
  if (!AssembleModels (DB, EdgeTolerance))
    ErrorCode = 3;
  printf ("Finished assembling models...\n");
  cf = clock();
  secs = (Real64)(cf - ci)/(Real64)CLOCKS_PER_SEC;
  fprintf (stdout, "Elapsed CPU Time (secs) = %.2f\n", secs);

  /* Write the new models to file */
  printf ("Writing database to %s...\n", NMBFileName);
  ci = cf;
  if (NativeFileWriter::Write (NMBFileName, DB) == ERR_no_errors)
    printf ("Write succeeded...\n");
  else {
    printf ("Write failed...\n");
    ErrorCode = 2;
  }
  cf = clock();
  secs = (Real64)(cf - ci)/(Real64)CLOCKS_PER_SEC;
  fprintf (stdout, "Elapsed CPU Time (secs) = %.2f\n", secs);
  
  /* Destroy the database and its contents */
  printf ("Destroying database and its contents...\n");
  ci = cf;
  if (DB->Delete () != ERR_no_errors)
    ErrorCode = 5;
  printf ("Finished destroying database and its contents...\n");
  cf = clock();
  secs = (Real64)(cf - ci)/(Real64)CLOCKS_PER_SEC;
  fprintf (stdout, "Elapsed CPU Time (secs) = %.2f\n", secs);
  
  /* This is only being called to free state memory used by the polynomial
     routines in order that memory checking routines acknowledge that no
     memory is in use on exit */
  POLY_FreeSystem ();
  
  return (ErrorCode);
}

Copyright © 1993-2004 Basis Software
All rights reserved.
Generated on Mon Jan 3 14:51:46 2005 for GE by doxygen 1.4.0