Bool.dll Library Logo

 

Sample Code

Overview

The sample code below illustrates the use of the BoolDll library. It performs one of the following boolean operations (OR, DIFF, XOR, AND) on two polygons and writes the results to a DXF file.

Program Flow

The basic calls for using the boolean are listed below:

Reserve License
Get Handle
Set Boolean Parameters
Execute Boolean Operation
Write the DXF
Free Output
Return Handle
Release License

Header


#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <booldll.h>
#include <unistd.h>

#define Grid        0.001
#define COPYRIGHTYR "2009"
#define COMPANYINFO "Artwork Conversion Software, Inc.\n\
417 Ingalls Street, Santa Cruz, CA 95060\n\
Tel: 831 426 8183 Web http://www.artwork.com"

void RunBoolean(FILE * strm, int handle, int opcode, int vnum, int *v1, int *v2);

Static Variables


// the output DXF file name will depend on the operation performed
static char *fname[] = {
(char*)"or.dxf", (char*)"diff.dxf", (char*)"xor.dxf", (char*)"and.dxf"
};

// these are the vertices for the first polygon. The second polygon  
// will be created by shifting these vertices
static int poly_template[] = {
20000, 30000, 50000, 30000, 50000, 10000, 90000, 10000, 
90000, 40000, 60000, 70000, 20000, 70000, 20000, 30000
};


Main Program Loop


int main (int argc, const char** argv)
{  
  fprintf(stderr, "\n%s\n", BoolDllGetVersion());
  fprintf(stderr, "(C) %s %s\n\n\n", COPYRIGHTYR, COMPANYINFO);
  
  // we define the four operation codes; one of these will be passed to the 
  // boolean library when the boolean is executed.

  int opcode = UNION_OPCODE;
  if(argc > 1){
    if(strcasecmp(argv[1], "or") == 0)
      opcode = UNION_OPCODE;
    else if(strcasecmp(argv[1], "diff") == 0)
      opcode = DIFFERENCE_OPCODE;
    else if(strcasecmp(argv[1], "xor") == 0)
      opcode = XOR_OPCODE;
    else if(strcasecmp(argv[1], "and") == 0)
      opcode = INTERSECTION_OPCODE;
    else{
      fprintf(stderr, "USAGE: %s [ or | diff | xor | and ]\n\n", argv[0]);
      return 0;
    }
  }

// The working directory is where we will store any temporary files to disk 
// and also where we look for the input file and write any output files and log files.

char workingdir[256];
  getcwd(workingdir, sizeof(workingdir));

 

Reserve the License(s)


The very first call should be to reserve a license -- otherwise subsequent calls will fail due to the lack of a license to execute. If you are going to run multiple threads of booldll, you must reserve all of the licenses in advance. After reserving the license, get the handle for the booldll thread.

 
 //Reserve 1 BoolDll license
  if(BoolDllReserveLicenses(workingdir, 1))
    fprintf(stderr, "Failed to reserve BoolDll license\n\n");
  else{
    //Get 1 BoolDll handle
    int BHandle = BoolDllInit_MT();
    
    if(BHandle < 0)
      fprintf(stderr, "Failed to get BoolDll handle\n\n");
    else{


Create the Two Input Polygons


We have to get our polygon data set up. In this simple example we simply read the template we set up in the static data section for the first polygon and shift it slightly to create the second polygon. Of course, in a real application the polygon vertices would come from some external source.

 //Create boolean's polygon input (derived from poly_template)
      int vnum = 8;
      int poly_original[16];
      int poly_shifted[16];
      for(int i = 0; i < vnum*2; i++){
        poly_original[i] = poly_template[i];
        poly_shifted[i] = poly_template[i]+10000;
      }


 

Set Boolean Parameters


Before calling the boolean operation, we first must define the various parameters that control the boolean. You will notice that since we are not illustrating the use of the sizing operation we have commented out the parameter settting calls related to sizing.

      //Set Boolean clip mode to auto (optimal horizontal stripes)
      BoolClip_Init_MT(1, 100, BOOL_CLIP_MODE_AUTO, BHandle);
      //Set Boolean output polygon's maximum vertex count to 16384
      BoolSet_Maxpts_MT(16384, BHandle);
      //Redirect Boolean log to /dev/null
      BoolSetLogFileParm_MT(REMLOGFILENAME_PARM, "/dev/null", BHandle);
      //Set Sizing Mode (NO_SIZING, STD_SIZING, INCR_SIZING, NON_ISOTR_SIZING)
      SizingMode_MT(NO_SIZING, BHandle);
      /*
      //If sizing is standard or incremental set sizing value
      BoolSetDoubleParm_MT(SIZING_PARM, 5000.0, BHandle);

      //If sizing is non-isotropic
      BoolSetNonIsotrSzParms_MT(4500.0, 5500.0, BHandle);

      //If sizing mode is incremental or non-isotropic
      //Set Corner Mode (RIGHT_ANGLE_CORNER, THREE_POINT_CORNER, FIVE_POINT_CORNER)
      RoundCorners_MT(RIGHT_ANGLE_CORNER, BHandle);
      */
 

Execute the Boolean


Now that both input polygons have been created and the booldll parameters have been set, we can call the main function of booldll and get back a unionized (or other operation) polygon.

 //Run Boolean
        RunBoolean(out, BHandle, opcode, vnum, poly_original, poly_shifted);


 

Create the DXF File


To create a valid DXF file we first must write the file header. Once that is complete we can write the two input polygons and the resulting booleanized polygon as entities, then a short section to end the DXF file and close it.

fprintf(stderr, "Creating output file: %s\n\n", fname[opcode-1]);
      
      //Create the output DXF file
      FILE * out = fopen(fname[opcode-1], "w+");
      if(!out)
        fprintf(stderr, "Failed to create output file\n\n");
      else{
        //Write DXF file header
        fprintf(out, "  0\nSECTION\n  2\nTABLES\n  0\nTABLE\n  2\nLAYER\n 70\n     3\n");
        fprintf(out, "  0\nLAYER\n  2\nINPUT1\n 70\n     0\n 62\n     1\n  6\nCONTINUOUS\n");
        fprintf(out, "  0\nLAYER\n  2\nINPUT2\n 70\n     0\n 62\n     2\n  6\nCONTINUOUS\n");
        fprintf(out, "  0\nLAYER\n  2\nOUTPUT\n 70\n     0\n 62\n     3\n  6\nCONTINUOUS\n");
        fprintf(out, "  0\nENDTAB\n  0\nENDSEC\n      0\nSECTION\n  2\nENTITIES\n");
        
        //Write original poly to DXF as a zero width closed polyline
        fprintf(out, "  0\nPOLYLINE\n  8\nINPUT1\n 66\n     1\n 10\n0.0\n 20\n0.0\n");
        for(int j = 0; j < vnum*2; j+=2){
          fprintf(out, "  0\nVERTEX\n  8\nINPUT1\n 10\n%g\n 20\n%g\n", 
                  ((double)poly_original[j])*Grid, ((double)poly_original[j+1])*Grid);
        }
        fprintf(out, "  0\nSEQEND\n  8\nINPUT1\n");
    
        //Write the shifted polygon to DXF
        fprintf(out, "  0\nPOLYLINE\n  8\nINPUT2\n 66\n     1\n 10\n0.0\n 20\n0.0\n");
        for(int j = 0; j < vnum*2; j+=2){
          fprintf(out, "  0\nVERTEX\n  8\nINPUT2\n 10\n%g\n 20\n%g\n", 
                  ((double)poly_shifted[j])*Grid, ((double)poly_shifted[j+1])*Grid);
        }
        fprintf(out, "  0\nSEQEND\n  8\nINPUT2\n");

        //Write Boolean output polygon(s) to DXF
        for(int i = 0; i < opnum; i++){
         fprintf(strm, "  0\nPOLYLINE\n  8\nOUTPUT\n 66\n     1\n 10\n0.0\n 20\n0.0\n");
         for(int j = 0; j < ovnum[i]*2; j+=2){
           fprintf(strm, "  0\nVERTEX\n  8\nOUTPUT\n 10\n%g\n 20\n%g\n", 
                ((double)overt[i][j])*Grid, ((double)overt[i][j+1])*Grid);
        }
        fprintf(strm, "  0\nSEQEND\n  8\nOUTPUT\n");

        //Write end of DXF file
        fprintf(out, "  0\nENDSEC\n  0\nEOF\n");
        
        //Close DXF file
        fclose(out);
        out = NULL;

 

Free Output


Now we release memory used by the boolean operation.

 //Cleanup Boolean output
  BoolRelease_memory(overt, ovnum, opnum);

 

Return the Handle


 //Return BoolDll handle
      if(BoolDllClose_MT(BHandle))
        fprintf(stderr, "Failed to return BoolDll handle\n\n");


 

Release the License


}
    
    //Release all reserved BoolDll licenses
    BoolDllReleaseLicenses();
}
  
  return 0;
}



 

RunBoolean


void RunBoolean(FILE * strm, int handle, int opcode, int vnum, int *v1, int *v2)
{
  int ** overt = NULL;
  int * ovnum = NULL;
  int opnum = 0;
  
  //Booleanize input polygons
  int ret = Boolean_MT(&overt, &ovnum, &opnum, &v1, &vnum, 1, &v2, &vnum, 1, opcode, handle);  
  if(ret)
    fprintf(stderr, "Boolean Error (opcode %d): %d\n\n", opcode, ret);
  else{
    }
  }