/*******************************************************************************
*                                                                       
*N  {geom_buffer.c}  -- demonstrates buffer generating.
*   
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*P  Purpose:
*    This sample C program demonstrates how to generate buffer for point, line and 
*    polygon shapes. It also demostrate the usage of  SE_shape_difference().
*  
*    The result buffer shapes will be store on your SDE server. You can use other
*    ESRI products,such as ArcGIS Desktop, to view the results.
*    
*   Sample cases:
*   
*   1. Generating buffer for following point shapes:
*   (1): Single point...
*   (2): Multipoint. resulting in a multi-parts polygon...
*   (3): Multipoint. resulting in a single part polygon...
*   
*   2.Generating buffer for following line shapes:
*   
*   (1): Single part line; resulting in a simple polygon:
*   (2): Single part line;resulting in a polygon with a hole
*   (3): multi-part,non-intersecting line; resulting in a multi-part polygon...
*   (4): multi-part,non-intersecting line;resulting in a single part polygon:
*   (5): Multi-part line intersecting at one common point...

*   3.Generating buffer for following polygon shapes:
*   (1): Simple polygon(a circle)
*   (2): Simple polygon with hole,buffersize<hole_radius
*   (3): Simple polygon with hole,buffersize>hole_radius
*   (4): Five parts polygon that generates a polygon buffer with multiple parts
*   (5): Five parts polygon that generates a polygon buffer with a single part
*   
*   
*E                                                                 
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* How to compile:: 
*	 Please refer section "Build C Samples" in the SDE sample
*
*E
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Usage:
*     geom_buffer {server} {instance} {database} {user} {password} {result_tablename}  
*
*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*X  Legalese:
*
* Copyright � 2007 ESRI
*
* All rights reserved under the copyright laws of the United States and 
* applicable international laws, treaties, and conventions.
*
* You may freely redistribute and use this sample code, with or without 
* modification, provided you include the original copyright notice and use 
* restrictions.  
*
* Disclaimer:  THE SAMPLE CODE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED 
* WARRANTIES, INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ESRI OR 
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
* OR BUSINESS INTERRUPTION) SUSTAINED BY YOU OR A THIRD PARTY, HOWEVER CAUSED 
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 
* TORT ARISING IN ANY WAY OUT OF THE USE OF THIS SAMPLE CODE, EVEN IF ADVISED 
* OF THE POSSIBILITY OF SUCH DAMAGE.
* 
* For additional information, contact:
* Environmental Systems Research Institute, Inc.
* Attn: Contracts and Legal Services Department
* 380 New York Street
* Redlands, California, 92373
* USA
* 
* email: contracts@esri.com
*
*E
****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include "sdetype.h"
#include "sdeerno.h"

/* Function macros */
#define check_rc_return_on_failure(c,s,rc,f) \
	{if(rc!= SE_SUCCESS) {check_rc_(c,s,rc,f,__LINE__,__FILE__);return rc; }}

/*****************************/
/* Local Function Prototypes */
/****************************/
void check_rc_(SE_CONNECTION Connection, SE_STREAM Stream, LONG rc, 
				 char *comment, LONG line_no, char* file_name) ;
static LONG S_create_layer (SE_CONNECTION connection, CHAR *table,CHAR *keyword,LONG precision);
static LONG S_point_cases(SE_CONNECTION connection,const CHAR* table);
static LONG S_line_cases(SE_CONNECTION connection,const CHAR* table);
static LONG S_polygon_cases(SE_CONNECTION connection,const CHAR* table);

LONG  main(int argc, char *argv[]){
	CHAR   			*server, 
       	       		*user, 
					*passwd, 
					*database,
					*instance,
					*rslt_layer_name;
	SE_CONNECTION 	conn;
	SE_ERROR 		error;
	LONG			result;
	BOOL			all_step_passed=TRUE;

	if(argc<7){
		printf("usage: %s <server> <instance> <database> <user> <passwd> <result_layer>",argv[0]);
		exit(1);
	}

	server=argv[1];
	instance=argv[2];
	database=argv[3];
	user=argv[4];
	passwd=argv[5];
	rslt_layer_name=argv[6];
	
	printf("\nConnecting to SDE server %s:%s as %s\n",server,instance,user);
	result = SE_connection_create( server, instance, database, user, passwd, &error, &conn );
	check_rc_return_on_failure(conn,NULL,result,"SE_connection_create");
	printf("\t---Connected");

	/*Create a layer to store results*/
	printf("\n\nCreating a layer to store results......\n");
	result=S_create_layer (conn,rslt_layer_name,"DEFAULTS",64);
	if(result!=SE_SUCCESS)
		return result;
	else
		printf("\tLayer %s created.\n",rslt_layer_name);

	/*point shapes*/
	printf("\n\n***************************************************************************\n");
	printf("* Generating buffer for point shapes......                                *\n");
	printf("***************************************************************************\n");
	result=S_point_cases(conn,rslt_layer_name);
	if(result!=SE_SUCCESS)
		return result;

	/* line shapes */
	printf("\n\n***************************************************************************\n");
	printf("* Generating buffer for line shapes......                                 *\n");
	printf("***************************************************************************\n");
	result=S_line_cases(conn,rslt_layer_name);
	if(result!=SE_SUCCESS)
		return result;

	/* polygon shapes */
	printf("\n\n***************************************************************************\n");
	printf("* Generating buffer for polygon shapes......                              *\n");
	printf("***************************************************************************\n");
	result=S_polygon_cases(conn,rslt_layer_name);
	if(result!=SE_SUCCESS)
		return result;

	SE_connection_free(conn);
	
}


/***********************************************************************
*
*N  {S_point_cases}  -  Point case samples.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*P  Purpose:
*     This function demostrate buffers for point shapes
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*A  Parameters:
*     <connection>  ==  (SE_CONNECTION) The connection handle.
*     <reftable  >  ==  (CHAR*) the result layer name
*E
***********************************************************************/
static LONG S_point_cases(SE_CONNECTION connection,const CHAR* reftable)
{
	SE_STREAM       stream;
	LONG            result,i;
	SHORT           number_of_columns;
	CHAR            **base_columns;
	SE_LAYERINFO    layer;
	SE_COORDREF     coordref;
	SE_SHAPE        shape,buffshape;
	CHAR			casename[32];
	SHORT           casename_ind, buffshape_ind;
    SE_POINT		shape_points[128];
	int				num_of_points;
	FLOAT			distance; 
	BOOL			identical=TRUE, allpassed=TRUE;

	//init columns names for insert
	number_of_columns = 2;
	base_columns = (CHAR **) malloc (number_of_columns * sizeof(CHAR *));
	for(i=0;i<number_of_columns;i++)
		base_columns[i]=(CHAR *) malloc (SE_MAX_COLUMN_LEN);

	strcpy(	base_columns[0],"CASENAME");
	strcpy(	base_columns[1],"SHAPE");

	//prepare shape objects
	result = SE_layerinfo_create (NULL,&layer);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_create");
	result = SE_coordref_create (&coordref);
	check_rc_return_on_failure (connection,NULL,result,"SE_coordref_create");
	result = SE_layer_get_info (connection,reftable,base_columns[1],layer);
	check_rc_return_on_failure (connection,NULL,result,"SE_layer_get_info");
	result = SE_layerinfo_get_coordref (layer,coordref);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_get_coordref");
	result = SE_shape_create (coordref,&shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_create");
	result = SE_shape_create (coordref,&buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_create");

	/*prepare an insert stream to insert results*/
	result = SE_stream_create (connection,&stream);
	check_rc_return_on_failure (connection,NULL,result,"SE_stream_create");

	result = SE_stream_insert_table (stream,reftable,number_of_columns,
								   (const CHAR **)base_columns);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_insert_table");
	result = SE_stream_bind_input_column (stream,1,casename,&casename_ind);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_bind_input_column");
	result = SE_stream_bind_input_column (stream,2,buffshape,&buffshape_ind);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_bind_input_column");
	casename_ind  = SE_IS_NOT_NULL_VALUE;
	buffshape_ind = SE_IS_NOT_NULL_VALUE;

	
	/*Point Case: single point*/
	printf("PT1: Single point...\n");
    num_of_points = 1;
    shape_points[0].x = 500.0; shape_points[0].y = 500.0;
    result = SE_shape_generate_point(num_of_points, shape_points, 
                NULL, NULL, shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_point");
	//generate the buffer
	distance=50.0;	
	strcpy(casename,"PT1");
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	/*Point Case: multipoint*/
	num_of_points=4;
    shape_points[0].x =1000.0; shape_points[0].y = 1000.0;
    shape_points[1].x =2000.0; shape_points[1].y = 1000.0;
    shape_points[2].x =2000.0; shape_points[2].y = 3000.0;
    shape_points[3].x =1000.0; shape_points[3].y = 3000.0;
    result = SE_shape_generate_point(num_of_points, shape_points, 
                NULL, NULL, shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_point");
	
	printf("PT2: Multipoint. resulting in a multi-parts polygon...\n");
	//generate the buffer
	distance=50.0;	
	strcpy(casename,"PT2");
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	printf("PT3: Multipoint. resulting in a single part polygon...\n");
	//generate the buffer
	distance=1500.0;
	strcpy(casename,"PT3");
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	//free resources
	result = SE_stream_free(stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_free");
	SE_shape_free(shape);
	SE_shape_free(buffshape);
	SE_layerinfo_free(layer);
	SE_coordref_free(coordref);
	for(i=0;i<number_of_columns;i++)
		free(base_columns[i]);
	free(base_columns);

	return(SE_SUCCESS);
}

/***********************************************************************
*
*N  {S_line_cases}  -  Line case samples.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*P  Purpose:
*     This function demostrate buffers for line shapes
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*A  Parameters:
*     <connection>  ==  (SE_CONNECTION) The connection handle.
*     <reftable  >  ==  (CHAR*) the result layer name
*E
***********************************************************************/
static LONG S_line_cases(SE_CONNECTION connection,const CHAR* reftable)
{
	SE_STREAM       stream;
	LONG            result,i;
	SHORT           number_of_columns;
	CHAR            **base_columns;
	SE_LAYERINFO    layer;
	SE_COORDREF     coordref;
	SE_SHAPE        shape,buffshape;
	CHAR			casename[32];
	SHORT           casename_ind,buffshape_ind;
    SE_POINT		shape_points[128];
	int				num_of_points,num_of_parts, part_offsets[10];
	FLOAT			distance; 
	BOOL			identical=TRUE, allpassed=TRUE;

	//init columns names for insert
	number_of_columns = 2;
	base_columns = (CHAR **) malloc (number_of_columns * sizeof(CHAR *));
	for(i=0;i<number_of_columns;i++)
		base_columns[i]=(CHAR *) malloc (SE_MAX_COLUMN_LEN);

	strcpy(	base_columns[0],"CASENAME");
	strcpy(	base_columns[1],"SHAPE");

	/*prepare shape objects....*/
	result = SE_layerinfo_create (NULL,&layer);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_create");
	result = SE_coordref_create (&coordref);
	check_rc_return_on_failure (connection,NULL,result,"SE_coordref_create");
	result = SE_layer_get_info (connection,reftable,base_columns[1],layer);
	check_rc_return_on_failure (connection,NULL,result,"SE_layer_get_info");
	result = SE_layerinfo_get_coordref (layer,coordref);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_get_coordref");
	result = SE_shape_create (coordref,&shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_create");
	result = SE_shape_create (coordref,&buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_create");

	/*prepare an insert stream*/
	result = SE_stream_create (connection,&stream);
	check_rc_return_on_failure (connection,NULL,result,"SE_stream_create");

	result = SE_stream_insert_table (stream,reftable,number_of_columns,
								   (const CHAR **)base_columns);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_insert_table");
	result = SE_stream_bind_input_column (stream,1,casename,&casename_ind);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_bind_input_column");
	result = SE_stream_bind_input_column (stream,2,buffshape,&buffshape_ind);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_bind_input_column");

	casename_ind  = SE_IS_NOT_NULL_VALUE;
	buffshape_ind = SE_IS_NOT_NULL_VALUE;

	/* single part line cases*/
    num_of_points = 7;
	num_of_parts  = 1;
	part_offsets[0] = 0;
    shape_points[0].x = 1000.0; shape_points[0].y = 1000.0;
    shape_points[1].x = 3000.0; shape_points[1].y = 1000.0;
    shape_points[2].x = 4000.0; shape_points[2].y = 2000.0;
    shape_points[3].x = 3000.0; shape_points[3].y = 3000.0;
    shape_points[4].x = 2000.0; shape_points[4].y = 2000.0;
    shape_points[5].x = 1000.0; shape_points[5].y = 3000.0;
    shape_points[6].x = 1300.0; shape_points[6].y = 1000.0;
    result = SE_shape_generate_line(num_of_points, num_of_parts,
                part_offsets, shape_points, NULL, NULL, shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_line");

	//Single part line shape resulting in a simple polygon
	printf("LN1: Single part line; resulting in a simple polygon:\n");
	//generate the buffer
	strcpy(casename,"LN1");
	distance=50.0;
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	//Single part line shape resulting in a polygon with a hole
	printf("LN2: Single part line;resulting in a polygon with a hole\n");
	//generate the buffer
	strcpy(casename,"LN2");
	distance=150.0;
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	//multi-part, non-intersecting line shape; 
    num_of_points = 8;
	num_of_parts  = 4;
	part_offsets[0] = 0;
	part_offsets[1] = 2;
	part_offsets[2] = 4;
	part_offsets[3] = 6;
    shape_points[0].x = 1000.0; shape_points[0].y = 1000.0;
    shape_points[1].x = 4000.0; shape_points[1].y = 1000.0;
    shape_points[2].x = 1000.0; shape_points[2].y = 2000.0;
    shape_points[3].x = 1000.0; shape_points[3].y = 4000.0;
    shape_points[4].x = 4000.0; shape_points[4].y = 2000.0;
    shape_points[5].x = 4000.0; shape_points[5].y = 4000.0;
    shape_points[6].x = 1000.0; shape_points[6].y = 5000.0;
    shape_points[7].x = 4000.0; shape_points[7].y = 5000.0;
    result = SE_shape_generate_line(num_of_points, num_of_parts,
                part_offsets, shape_points, NULL, NULL, shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_line");

	//multi-part, non-intersecting line shape; resulting in a multi-part polygon
	printf("LN3: multi-part,non-intersecting line; resulting in a multi-part polygon...\n");
	//generate the buffer
	strcpy(casename,"LN3");
	distance=50.0;
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	
	//multi-part, non-intersecting line shape;resulting in a single part polygon
	printf("LN4: multi-part,non-intersecting line;resulting in a single part polygon:\n");
	//generate the buffer
	strcpy(casename,"LN4");
	distance=2000.0;
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");
	
	//Two part, multi-part line intersecting at one common point
	printf("LN5: Multi-part line intersecting at one common point...\n");
    num_of_points = 6;
	num_of_parts  = 2;
	part_offsets[0] = 0;
	part_offsets[1] = 3;
    shape_points[0].x = 1000.0; shape_points[0].y = 1000.0;
    shape_points[1].x = 2000.0; shape_points[1].y = 2000.0;
    shape_points[2].x = 3000.0; shape_points[2].y = 3000.0;
    shape_points[3].x = 1000.0; shape_points[3].y = 3000.0;
    shape_points[4].x = 2000.0; shape_points[4].y = 2000.0;
    shape_points[5].x = 3000.0; shape_points[5].y = 1000.0;
    result = SE_shape_generate_line(num_of_points, num_of_parts,
                part_offsets, shape_points, NULL, NULL, shape);
	strcpy(casename,"LN5");
	//generate the buffer
	distance=50.0;
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	//free resources
	result = SE_stream_free(stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_free");
	SE_shape_free(shape);
	SE_shape_free(buffshape);
	SE_layerinfo_free(layer);
	SE_coordref_free(coordref);
	for(i=0;i<number_of_columns;i++)
		free(base_columns[i]);
	free(base_columns);

	return(SE_SUCCESS);
}


/***********************************************************************
*
*N  {S_polygon_cases}  -  polygon case samples.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*P  Purpose:
*     This function demostrate buffers for polygon shapes
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*A  Parameters:
*     <connection>  ==  (SE_CONNECTION) The connection handle.
*     <reftable  >  ==  (CHAR*) the result layer name
*E
***********************************************************************/
static LONG S_polygon_cases(SE_CONNECTION connection,const CHAR* reftable)
{
	SE_STREAM       stream;
	LONG            result,i;
	SHORT           number_of_columns;
	CHAR            **base_columns;
	SE_LAYERINFO    layer;
	SE_COORDREF     coordref;
	SE_SHAPE        shape,buffshape,tmpshp1,tmpshp2;
	CHAR			casename[32];
	SHORT           casename_ind,buffshape_ind;
    SE_POINT		shape_points[128];
	int				num_of_points,num_of_parts, part_offsets[10];
	FLOAT			distance; 
	BOOL			identical=TRUE, allpassed=TRUE;

	//init columns names for insert
	number_of_columns = 2;
	base_columns = (CHAR **) malloc (number_of_columns * sizeof(CHAR *));
	for(i=0;i<number_of_columns;i++)
		base_columns[i]=(CHAR *) malloc (SE_MAX_COLUMN_LEN);
	strcpy(	base_columns[0],"CASENAME");
	strcpy(	base_columns[1],"SHAPE");

	/*prepare shape objects*/
	result = SE_layerinfo_create (NULL,&layer);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_create");
	result = SE_coordref_create (&coordref);
	check_rc_return_on_failure (connection,NULL,result,"SE_coordref_create");
	result = SE_layer_get_info (connection,reftable,base_columns[1],layer);
	check_rc_return_on_failure (connection,NULL,result,"SE_layer_get_info");
	result = SE_layerinfo_get_coordref (layer,coordref);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_get_coordref");
	result = SE_shape_create (coordref,&shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_create");
	result = SE_shape_create (coordref,&buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_create");
	result = SE_shape_create (coordref,&tmpshp1);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_create");
	result = SE_shape_create (coordref,&tmpshp2);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_create");

	/*prepare an insert stream*/
	result = SE_stream_create (connection,&stream);
	check_rc_return_on_failure (connection,NULL,result,"SE_stream_create");
	result = SE_stream_insert_table (stream,reftable,number_of_columns,
								   (const CHAR **)base_columns);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_insert_table");
	result = SE_stream_bind_input_column (stream,1,casename,&casename_ind);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_bind_input_column");
	result = SE_stream_bind_input_column (stream,2,buffshape,&buffshape_ind);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_bind_input_column");
	casename_ind  = SE_IS_NOT_NULL_VALUE;
	buffshape_ind = SE_IS_NOT_NULL_VALUE;

	/*
	 * Single part polygons. In this sample, we will generate a circle as the test polygon
	 */
	printf("POLY1: Simple polygon(a circle)\n");
	strcpy(casename,"POLY1");
    shape_points[0].x = 2000.0; shape_points[0].y = 2000.0;
	result= SE_shape_generate_circle (shape_points[0], 1000.0, 500, shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_circle");
	//generate the buffer
	distance=50.0;
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	/*In this case, we will use SE_shape_difference to creae some hole in the polygon*/
    shape_points[0].x = 2000.0; shape_points[0].y = 2000.0;
	result= SE_shape_generate_circle (shape_points[0], 1000.0, 500, tmpshp1);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_circle");
	result= SE_shape_generate_circle (shape_points[0], 100.0, 500, tmpshp2);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_circle");
	result=SE_shape_difference (tmpshp1,tmpshp2,shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_polygon");	

	printf("POLY2: Simple polygon with hole,buffersize<hole_radius\n");
	strcpy(casename,"POLY2");
	//generate the buffer
	distance=50.0;
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	printf("POLY3: Simple polygon with hole,buffersize>hole_radius\n");
	strcpy(casename,"POLY3");
	distance=150.0;
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	/*
	 * Five part polygon that generates a polygon buffer:
	 *  - result polgyon has multiple parts 
	 *  - result polgyon has a single part
	 */
    num_of_points = 25;
	num_of_parts  = 5;
	part_offsets[0] = 0;
	part_offsets[1] = 5;
	part_offsets[2] = 10;
	part_offsets[3] = 15;
	part_offsets[4] = 20;
    shape_points[0].x = 1000.0; shape_points[0].y = 1000.0;//start of part1
    shape_points[1].x = 10000.0; shape_points[1].y = 1000.0;
    shape_points[2].x = 10000.0; shape_points[2].y = 2000.0;
    shape_points[3].x = 1000.0; shape_points[3].y = 2000.0;
    shape_points[4].x = 1000.0; shape_points[4].y = 1000.0;
    shape_points[5].x = 1000.0; shape_points[5].y = 3000.0;//start of part2
    shape_points[6].x = 2000.0; shape_points[6].y = 3000.0;
    shape_points[7].x = 2000.0; shape_points[7].y = 8000.0;
    shape_points[8].x = 1000.0; shape_points[8].y = 8000.0;
    shape_points[9].x = 1000.0; shape_points[9].y = 3000.0;
    shape_points[10].x = 5000.0; shape_points[10].y = 4000.0;//start of part3
    shape_points[11].x = 6000.0; shape_points[11].y = 4000.0;
    shape_points[12].x = 6000.0; shape_points[12].y = 7000.0;
    shape_points[13].x = 5000.0; shape_points[13].y = 7000.0;
    shape_points[14].x = 5000.0; shape_points[14].y = 4000.0;
    shape_points[15].x = 9000.0; shape_points[15].y = 3000.0;//start of part4
    shape_points[16].x = 10000.0; shape_points[16].y = 3000.0;
    shape_points[17].x = 10000.0; shape_points[17].y = 8000.0;
    shape_points[18].x = 9000.0; shape_points[18].y = 8000.0;
    shape_points[19].x = 9000.0; shape_points[19].y = 3000.0;
    shape_points[20].x = 1000.0; shape_points[20].y = 9000.0;//start of part5
    shape_points[21].x = 10000.0; shape_points[21].y = 9000.0;
    shape_points[22].x = 10000.0; shape_points[22].y = 10000.0;
    shape_points[23].x = 1000.0; shape_points[23].y = 10000.0;
    shape_points[24].x = 1000.0; shape_points[24].y = 9000.0;
    result = SE_shape_generate_polygon(num_of_points, num_of_parts,
                part_offsets, shape_points, NULL, NULL, shape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_polygon");

	printf("POLY4: Five part polygon that generates a polygon buffer with multiple parts\n");
	//generate the buffer
	distance=50.0;
	strcpy(casename,"POLY4");
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	printf("POLY5: Five part polygon that generates a polygon buffer with a single part\n");
	//generate the buffer
	distance=2000.0;
	strcpy(casename,"POLY5");
	result=SE_shape_generate_buffer (shape, distance, 1000, buffshape);
	check_rc_return_on_failure (connection,NULL,result,"SE_shape_generate_buffer");
	//insert result data
	result = SE_stream_execute (stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_execute");
	printf("\t---Done\n");

	//free resources
	result = SE_stream_free(stream);
	check_rc_return_on_failure (NULL,stream,result,"SE_stream_free");
	SE_shape_free(shape);
	SE_shape_free(buffshape);
	SE_layerinfo_free(layer);
	SE_coordref_free(coordref);
	for(i=0;i<number_of_columns;i++)
		free(base_columns[i]);
	free(base_columns);

	return(SE_SUCCESS);
}


/***********************************************************************
*
*N  {S_create_layer}  -  create a layer to store the buffer results.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*P  Purpose:
*     create a layer to store the buffer results.
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*A  Parameters:
*     <connection>  ==  (SE_CONNECTION) The connection handle.
*     <table  >     ==  (CHAR*) the result layer name
*     <keyword >    ==  (CHAR*) the keyword for layer creation
*     <precision>   ==  (LONG) layer precision: 32 or 64
*E
***********************************************************************/
static LONG S_create_layer (SE_CONNECTION connection, CHAR *table, 
                             CHAR *keyword,LONG precision)
{
	SE_LAYERINFO        layer;
	SHORT               number_of_columns;
	SE_COLUMN_DEF       column_definitions[8];
	SE_COORDREF         coordref;
	LONG                result;
	SE_REGINFO          registration;

	CHAR ROWID_COL[SE_MAX_COLUMN_LEN];
	CHAR SPATIAL_COL[SE_MAX_COLUMN_LEN];
	CHAR reg_desc[128];

	/* Create the base table. */

	strcpy(ROWID_COL,"ROWID_COL");
	strcpy(SPATIAL_COL,"SHAPE");

	//define columns in the base table
	number_of_columns = 1;
	strcpy(column_definitions[0].column_name,"CASENAME");
	column_definitions[0].sde_type = SE_STRING_TYPE;
	column_definitions[0].size = 32;
	column_definitions[0].decimal_digits = 0;
	column_definitions[0].nulls_allowed = FALSE;

	//delete the table if it existed
	result = SE_table_delete(connection,table);
	if(result!=SE_TABLE_NOEXIST)
		check_rc_return_on_failure (connection,NULL,result,"SE_table_delete");
	//create the table
	result = SE_table_create (connection,table,number_of_columns,
							column_definitions,keyword);
	check_rc_return_on_failure (connection,NULL,result,"SE_table_create");

	/* Add an SDE maintained rowid */
	result = SE_reginfo_create (&registration);
	check_rc_return_on_failure (connection,NULL,result,"SE_reginfo_create");
	result = SE_registration_get_info (connection,table,registration);
	check_rc_return_on_failure (connection,NULL,result,"SE_registration_get_info");
	result = SE_reginfo_set_creation_keyword (registration,keyword);
	check_rc_return_on_failure (connection,NULL,result,"SE_reginfo_set_creation_keyword");
	strcpy(reg_desc,"Buffer sample results.");
	result = SE_reginfo_set_description (registration,reg_desc );
	check_rc_return_on_failure (connection,NULL,result,"SE_reginfo_set_description");
	result = SE_reginfo_set_rowid_column (registration,ROWID_COL,
							   SE_REGISTRATION_ROW_ID_COLUMN_TYPE_SDE);
	check_rc_return_on_failure (connection,NULL,result,"SE_reginfo_set_rowid_column");
	result = SE_registration_alter (connection,registration);
	check_rc_return_on_failure (connection,NULL,result,"SE_registration_alter");
	SE_reginfo_free(registration);

	/* Add the spatial column to the table that will containing the polygon shapes */
	result = SE_coordref_create (&coordref);
	check_rc_return_on_failure (connection,NULL,result,"SE_coordref_create");
	result=SE_coordref_set_xy (coordref, -1000000000.0 , -1000000000.0 , 1.0);
	check_rc_return_on_failure (connection,NULL,result,"SE_coordref_set_xy");
	result=SE_coordref_set_precision (coordref, precision); 
	check_rc_return_on_failure (connection,NULL,result,"SE_coordref_set_xy");

	result = SE_layerinfo_create (coordref,&layer);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_create");

	result = SE_layerinfo_set_grid_sizes (layer,1000.0,0.0,0.0);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_set_grid_sizes");

	result = SE_layerinfo_set_shape_types (layer,SE_AREA_TYPE_MASK | SE_MULTIPART_TYPE_MASK);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_set_shape_types");

	result = SE_layerinfo_set_spatial_column (layer,table,SPATIAL_COL);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_set_spatial_column");

	result = SE_layerinfo_set_creation_keyword (layer,keyword);
	check_rc_return_on_failure (connection,NULL,result,"SE_layerinfo_set_creation_keyword");

	result = SE_layer_create (connection,layer,0,0);
	check_rc_return_on_failure (connection,NULL,result,"SE_layer_create");

	SE_coordref_free (coordref);
	SE_layerinfo_free(layer);
	return(SE_SUCCESS);

}           

/***********************************************************************
*
*N  {check_rc_}  -  check the returned code
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*P  Purpose:
*     Check returned sde error code and print the error messages.
***********************************************************************/
void check_rc_(SE_CONNECTION Connection, SE_STREAM Stream, LONG rc, 
				 char *comment, LONG line_no, char* file_name) 
{

	SE_ERROR	error;
	CHAR		error_string [SE_MAX_MESSAGE_LENGTH];
	LONG		temp_rc=SE_FAILURE;


	if ((rc != SE_SUCCESS) && (rc != SE_FINISHED)) 
	{
		error_string[0] = '\0';
		SE_error_get_string (rc, error_string);

	    printf ("%s encountered a %d error:\"%s\" \nat line %ld in file %s\n",comment, rc,error_string, line_no, file_name);

		/*Print extended error info, if any */
		if ((SE_DB_IO_ERROR == rc) | (SE_INVALID_WHERE == rc) | (SE_SSA_FUNCTION_ERROR == rc)) 
		{
			if (NULL != Stream) 
			{
				/* Assume this is a stream error */
				temp_rc = SE_stream_get_ext_error (Stream, &error);
			}else if (NULL != Connection) {
				/*Assume this is a connection error */
				temp_rc = SE_connection_get_ext_error (Connection, &error);
			}
			if (SE_SUCCESS == temp_rc)
			{
					printf("Extended error code: %d, extended error string:\n%s\n",
					error.ext_error, error.err_msg1);
			}
		} /*End SE_DB_IO_ERROR */

	} 
}