/*
* Local function prototypes
*/
static int _calc_shapelen (
GeomType type,
int numpoints,
int numparts
);
static void _get_extrema (
int num_points,
Point *pt,
double *z,
double *m,
double *xy_bnd,
double *z_bnd,
double *m_bnd
);
static int _get_shp_parts (
char *cp,
int swap_bytes,
Geometry *geom
);
static int _get_shp_multipoint (
char *cp,
int swap_bytes,
Geometry *geom
);
static int _get_shp_point (
char *cp,
int swap_bytes,
Geometry *geom
);
/***************************************************************************
*
* geom_to_shape - takes a geometry and converts it into a shape
* representation.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Purpose:
* Converts a geometry into its ESRI shape representation.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Parameters:
* geom == (Geometry *) The geometry object
* max_alloced == (int *) The maximum number of bytes
* allocated to the binary array.
* data_len == (int *) The number of bytes in the shape.
* binary == (char **) The shape binary.
*
* RETURN == (void)
*
****************************************************************************/
void geom_to_shape (
Geometry *geom,
int *max_alloced,
int *data_len,
char **binary
)
{
char *cp;
double xy_bnd[4];
double z_bnd[2];
double m_bnd[2];
int i;
int swap;
int npoints = geom->num_points;
int nparts = geom->num_parts;
Point *pt = geom->pt;
double *m = geom->m;
double *z = geom->z;
ShpType type;
ENDIAN_TEST (i); /* Sets i = 0 if big-endian, 1 if little-endian */
swap = 1 - i;
/* Calculate data_len. */
*data_len = _calc_shapelen (geom->type, npoints, nparts);
/* Allocate memory to the binary character array, set max_alloced
equal to data_len if this is the first call to put_shape.
Otherwise, if the data_len is larger then max_alloced,
reallocate the larger data_len to the binary character array. */
if (*max_alloced == 0)
{
*binary = (char *)malloc (*data_len);
*max_alloced = *data_len;
}
else if (*max_alloced < *data_len)
{
*binary = (char *) realloc (*binary, *data_len);
*max_alloced = *data_len;
}
/* Copy the address of the binary character array to the
character pointer cp. */
cp = *binary;
/* The put_integer function byte swaps an integer value if necessary,
and advances the cp character pointer after the interger value
just added.
The put_xy and put_double functions operate in the same manner as
put_integer does, except they add an array of double precision
numbers. */
switch (geom->type)
{
case geomEmpty:
/* Geometry is empty so the buffer only contains its datatype */
type = shpNil;
put_integer (&cp, swap, 1, (int *)&type);
break;
case geomPoint: /* Point */
type = shpPoint;
put_integer (&cp, swap, 1, (int *)&type);
put_xy (&cp, swap, 1, pt); /* Add the X, Y coordinate */
break;
case geomPointM: /* Point with measure */
type = shpPointM;
put_integer (&cp, swap, 1, (int *)&type);
put_xy (&cp, swap, 1, pt); /* Add the X, Y coordinate */
put_double (&cp, swap, 1, m); /* Add the measure */
break;
case geomPointZ: /* Point with Z coordinate */
type = shpPointZ;
put_integer (&cp, swap, 1, (int *)&type);
put_xy (&cp, swap, 1, pt); /* Add the X, Y coordinate */
put_double (&cp, swap, 1, z); /* Add the Z coordinate */
break;
case geomPointZM: /* Point with Z coordinate and measure. */
type = shpPointZM;
put_integer (&cp, swap, 1, (int *)&type);
put_xy (&cp, swap, 1, pt); /* Add the X, Y coordinate */
put_double (&cp, swap, 1, z); /* Add the Z coordinate */
put_double (&cp, swap, 1, m); /* Add the measure */
break;
case geomMultiPoint: /* Multipoint. */
type = shpMultiPoint;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
put_xy (&cp, swap, npoints, pt); /* Add the X, Y coords */
break;
case geomMultiPointM: /* Multipoint with measure. */
type = shpMultiPointM;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y and measures */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
put_xy (&cp, swap, npoints, pt); /* Add the X, Y coords */
put_double (&cp, swap, 2, m_bnd); /* Add the extreme measures */
put_double (&cp, swap, npoints, m); /* Add the measures */
break;
case geomMultiPointZ: /* Multipoint with Z ordinates */
type = shpMultiPointZ;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y, Z and measures. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
put_xy (&cp, swap, npoints, pt); /* Add the X, Y coordinates */
put_double (&cp, swap, 2, z_bnd); /* Add the Z extrema */
put_double (&cp, swap, npoints, z); /* Add the Z ordinates */
break;
case geomMultiPointZM: /* Multipoint with Z ordinates and measures */
type = shpMultiPointZM;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y, Z and measures. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
put_xy (&cp, swap, npoints, pt); /* Add the X, Y coords */
put_double (&cp, swap, 2, z_bnd); /* Add the Z extreme */
put_double (&cp, swap, npoints, z); /* Add the Z ordinates */
put_double (&cp, swap, 2, m_bnd); /* Add the extreme measures */
put_double (&cp, swap, npoints, m); /* Add the measures */
break;
case geomLineString:
case geomMultiLineString:
type = shpPolyline;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
if (nparts > 1)
{
/* There is more that one part; add the part offsets array */
put_integer (&cp, swap, nparts, geom->offsets);
}
else
{
/* There is only one part; set the part offsets array to 0. */
memset (cp, 0, sizeof (int));
cp += sizeof (int); /* Advance the character pointer cp */
}
put_xy (&cp, swap, npoints, pt); /* Add the point array */
break;
case geomLineStringM:
case geomMultiLineStringM:
type = shpPolylineM;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y and measures. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
if (nparts > 1)
{
/* There is more that one part; add the part offsets array */
put_integer (&cp, swap, nparts, geom->offsets);
}
else
{
/* There is only one part; set the part offsets array to 0. */
memset (cp, 0, sizeof (int));
cp += sizeof (int); /* Advance the character pointer cp */
}
put_xy (&cp, swap, npoints, pt); /* Add the points array */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
put_double (&cp, swap, 2, m_bnd); /* Add the measure extremes */
put_double (&cp, swap, npoints, m); /* Add the measures array */
break;
case geomLineStringZ:
case geomMultiLineStringZ:
type = shpPolylineZ;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y, Z and measures. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
if (nparts > 1)
{
/* There is more that one part; add the part offsets array */
put_integer (&cp, swap, nparts, geom->offsets);
}
else
{
/* There is only one part; set the part offsets array to 0. */
memset (cp, 0, sizeof (int));
cp += sizeof (int); /* Advance the character pointer cp */
}
put_xy (&cp, swap, npoints, pt); /* Add the no. of points */
put_double (&cp, swap, 2, z_bnd); /* Add the Z extremes */
put_double (&cp, swap, npoints, z); /* Add the Z array */
break;
case geomLineStringZM:
case geomMultiLineStringZM:
type = shpPolylineZM;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y, Z and measures. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
if (nparts > 1)
{
/* There is more that one part; add the part offsets array */
put_integer (&cp, swap, nparts, geom->offsets);
}
else
{
/* There is only one part; set the part offsets array to 0. */
memset (cp, 0, sizeof (int));
cp += sizeof (int); /* Advance the character pointer cp */
}
put_xy (&cp, swap, npoints, pt); /* Add the no. of points */
put_double (&cp, swap, 2, z_bnd); /* Add the Z extemes */
put_double (&cp, swap, npoints, z); /* Add the Z array */
put_double (&cp, swap, 2, m_bnd); /* Add the measure extremes */
put_double (&cp, swap, npoints, m); /* Add the measure array */
break;
case geomPolygon:
case geomMultiPolygon:
type = shpPolygon;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
if (nparts > 1)
{
/* There is more that one part; add the part offsets array */
put_integer (&cp, swap, nparts, geom->offsets);
}
else
{
/* There is only one part; set the part offsets array to 0. */
memset (cp, 0, sizeof (int));
cp += sizeof (int); /* Advance the character pointer cp */
}
put_xy (&cp, swap, npoints, pt); /* Add the point array */
break;
case geomPolygonM:
case geomMultiPolygonM:
type = shpPolygonM;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y and measures. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
if (nparts > 1)
{
/* There is more that one part; add the part offsets array */
put_integer (&cp, swap, nparts, geom->offsets);
}
else
{
/* There is only one part; set the part offsets array to 0. */
memset (cp, 0, sizeof (int));
cp += sizeof (int); /* Advance the character pointer cp */
}
put_xy (&cp, swap, npoints, pt); /* Add the points array */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
put_double (&cp, swap, 2, m_bnd); /* Add the measure extremes */
put_double (&cp, swap, npoints, m); /* Add the measures array */
break;
case geomPolygonZ:
case geomMultiPolygonZ:
type = shpPolygonZ;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y, Z and measures. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
if (nparts > 1)
{
/* There is more that one part; add the part offsets array */
put_integer (&cp, swap, nparts, geom->offsets);
}
else
{
/* There is only one part; set the part offsets array to 0. */
memset (cp, 0, sizeof (int));
cp += sizeof (int); /* Advance the character pointer cp */
}
put_xy (&cp, swap, npoints, pt); /* Add the no. of points */
put_double (&cp, swap, 2, z_bnd); /* Add the Z extremes */
put_double (&cp, swap, npoints, z); /* Add the Z array */
break;
case geomPolygonZM:
case geomMultiPolygonZM:
type = shpPolygonZM;
put_integer (&cp, swap, 1, (int *)&type);
/* Calculate the extreme X, Y, Z and measures. */
_get_extrema (npoints, pt, z, m, xy_bnd, z_bnd, m_bnd);
put_double (&cp, swap, 4, xy_bnd); /* Add the X, Y extremes */
put_integer (&cp, swap, 1, &nparts); /* Add the no. of parts */
put_integer (&cp, swap, 1, &npoints); /* Add the no. of points */
if (nparts > 1)
{
/* There is more that one part; add the part offsets array */
put_integer (&cp, swap, nparts, geom->offsets);
}
else
{
/* There is only one part; set the part offsets array to 0. */
memset (cp, 0, sizeof (int));
cp += sizeof (int); /* Advance the character pointer cp */
}
put_xy (&cp, swap, npoints, pt); /* Add the no. of points */
put_double (&cp, swap, 2, z_bnd); /* Add the Z extemes */
put_double (&cp, swap, npoints, z); /* Add the Z array */
put_double (&cp, swap, 2, m_bnd); /* Add the measure extremes */
put_double (&cp, swap, npoints, m); /* Add the measure array */
break;
}
}
/***************************************************************************
*
* _calc_shapelen - Calculates the number of bytes in the shape.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Purpose:
* Calculate the number of bytes in the shape.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Parameters:
* type == (GeomType) The geometry data type.
* num_points == (int) The number of points in the geometry.
* num_parts == (int) The number of parts into the geometry.
*
* RETURN == (void)
*
****************************************************************************/
static int _calc_shapelen (
GeomType type,
int numpoints,
int numparts
)
{
int data_len;
data_len = sizeof (int); /* Add the size of the data type */
switch (type)
{
case geomEmpty: /* Shape is empty. */
break;
case geomPoint: /* Shape is a point. */
data_len += (2 * sizeof (double));
break;
case geomPointZ: /* Shape is a point with a Z coordinate */
case geomPointM: /* Shape is a point with a measure. */
data_len += (3 * sizeof (double));
break;
case geomPointZM: /* Shape is a point with a Z coordinate and a measure */
data_len += (4 * sizeof (double));
break;
case geomMultiPoint: /* Shape is a multipoint. */
data_len += ((2 * numpoints) + 4) * sizeof(double) + sizeof (int);
break;
case geomMultiPointZ: /* Shape is a multipoint with Z coordinates. */
case geomMultiPointM: /* Shape is a multipoint with measures. */
data_len += ((3 * numpoints) + 6) * sizeof(double) + sizeof (int);
break;
case geomMultiPointZM: /* Shape is a multipoint with Z coords and measures */
data_len += ((4 * numpoints) + 8) * sizeof(double) + sizeof (int);
break;
case geomLineString: /* Shape is a polyline or polygon. */
case geomMultiLineString:
case geomPolygon:
case geomMultiPolygon:
data_len += (2 + numparts) * sizeof (int);
data_len += ((2 * numpoints) + 4) * sizeof(double);
break;
case geomLineStringM: /* Shape is a polyline or polygon with measures. */
case geomMultiLineStringM:
case geomPolygonM:
case geomMultiPolygonM:
case geomLineStringZ: /* Shape is a polyline or polygon with Z coords. */
case geomMultiLineStringZ:
case geomPolygonZ:
case geomMultiPolygonZ:
data_len += (2 + numparts) * sizeof (int);
data_len += ((3 * numpoints) + 6) * sizeof(double);
break;
case geomLineStringZM: /* Shape is a polyline or polygon with */
case geomPolygonZM: /* Z coordinates and measures. */
case geomMultiLineStringZM:
case geomMultiPolygonZM:
data_len += (2 + numparts) * sizeof (int);
data_len += ((4 * numpoints) + 8) * sizeof(double);
break;
}
return data_len;
}
/***************************************************************************
*
* _get_extrema - Calculates the extremes of the X, Y, Z and measures.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Purpose:
* Calculates the extremes of the X, Y, Z and measures.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Parameters:
* num_points == (int) The number of points in the geometry.
* pt == (Point *) Array of X, Y coordinates.
* z == (double *) Array of Z ordinates.
* m == (double *) Array of measures.
* xy_bnd == (double *) X, Y coordinate extremes.
* z_bnd == (double *) Z ordinate extremes.
* m_bnd == (double *) Measure extremes.
*
* RETURN == (void)
*
****************************************************************************/
static void _get_extrema (
int num_points,
Point *pt,
double *z,
double *m,
double *xy_bnd,
double *z_bnd,
double *m_bnd
)
{
int i;
/* Initialize the extremes */
xy_bnd[0] = xy_bnd[1] = DBL_MAX; /* min x, min y */
xy_bnd[2] = xy_bnd[3] = -DBL_MAX; /* max x, max y */
z_bnd[0] = m_bnd[0] = DBL_MAX; /* min z, min m */
z_bnd[1] = m_bnd[1] = -DBL_MAX; /* max z, max m */
for (i = 0; i < num_points; i++)
{
/* Find the min & max values */
if (pt[i].x < xy_bnd[0])
xy_bnd[0] = pt[i].x;
if (pt[i].y < xy_bnd[1])
xy_bnd[1] = pt[i].y;
if (pt[i].x > xy_bnd[2])
xy_bnd[2] = pt[i].x;
if (pt[i].y > xy_bnd[3])
xy_bnd[3] = pt[i].y;
if (z)
{
if (z[i] < z_bnd[0])
z_bnd[0] = z[i];
if (z[i] > z_bnd[1])
z_bnd[1] = z[i];
}
if (m)
{
if (m[i] < m_bnd[0])
m_bnd[0] = m[i];
if (m[i] > m_bnd[1])
m_bnd[1] = m[i];
}
}
}
/***************************************************************************
*
* geom_to_shape - takes a geometry and converts it into a shape
* representation.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Purpose:
* Converts a geometry into a shape.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Parameters:
* binary == (char **) The shape binary.
*
* RETURN == (int) Error code
*
****************************************************************************/
int shape_to_geom (
char *binary,
Geometry *geom
)
{
ShpType shape_type;
int rc;
char *cp;
int swap_bytes;
int i;
ENDIAN_TEST (i); /* Sets i = 0 if big-endian, 1 if little-endian */
swap_bytes = 1 - i;
cp = binary;
get_integer (&cp, swap_bytes, 1, (int *) &shape_type);
switch (shape_type)
{
/* copy the points based on shape type */
case shpNil:
/* Nothing to do, we already made the shape nil */
break;
case shpPoint:
geom->type = geomPoint;
rc = _get_shp_point (cp, swap_bytes, geom);
break;
case shpPointM:
geom->type = geomPointM;
rc = _get_shp_point (cp, swap_bytes, geom);
break;
case shpPointZ:
geom->type = geomPointZ;
rc = _get_shp_point (cp, swap_bytes, geom);
break;
case shpPointZM:
geom->type = geomPointZM;
rc = _get_shp_point (cp, swap_bytes, geom);
break;
case shpMultiPoint:
geom->type = geomMultiPoint;
rc = _get_shp_multipoint (cp, swap_bytes, geom);
break;
case shpMultiPointM:
geom->type = geomMultiPoint;
rc = _get_shp_multipoint (cp, swap_bytes, geom);
break;
case shpMultiPointZ:
geom->type = geomMultiPointZ;
rc = _get_shp_multipoint (cp, swap_bytes, geom);
break;
case shpMultiPointZM:
geom->type = geomMultiPointZM;
rc = _get_shp_multipoint (cp, swap_bytes, geom);
break;
case shpPolyline:
geom->type = geomLineString;
rc = _get_shp_parts (cp, swap_bytes, geom);
break;
case shpPolygon:
geom->type = geomPolygon;
rc = _get_shp_parts (cp, swap_bytes, geom);
break;
case shpPolylineM:
geom->type = geomLineStringM;
rc = _get_shp_parts (cp, swap_bytes, geom);
break;
case shpPolygonM:
geom->type = geomPolygonM;
rc = _get_shp_parts (cp, swap_bytes, geom);
break;
case shpPolylineZ:
geom->type = geomLineStringZ;
rc = _get_shp_parts (cp, swap_bytes, geom);
break;
case shpPolygonZ:
geom->type = geomPolygonZ;
rc = _get_shp_parts (cp, swap_bytes, geom);
break;
case shpPolylineZM:
geom->type = geomLineStringZM;
rc = _get_shp_parts (cp, swap_bytes, geom);
break;
case shpPolygonZM:
geom->type = geomPolygonZM;
rc = _get_shp_parts (cp, swap_bytes, geom);
break;
default:
rc = GEOM_INVALID_SHP_TYPE;
}
return rc;
}
/***************************************************************************
*
* _get_shp_parts - Extracts polygon or polyline parts from the
* ESRI binary shape representation of a geometry.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Purpose:
* This function builds a polygon or polyline shape from the ESRI binary
* shape representation of a geometry. Since it is a common routine for
* lines and polygons, and the "multi" equivalents, it does not set
* set the geometry, or verify the geometry. This is the caller's
* responsibility. This function just fills in the numofpts, pt, zpt,
* and mval fields.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
*A Parameters:
* cp == (char *) a pointer into the binary buffer
* swap_bytes == (int) 1 if bytes need to be swapped
* geom == (Geometry *) The geometry object
*
* RETURN == (int) Error code
*
****************************************************************************/
static int _get_shp_parts (
char *cp,
int swap_bytes,
Geometry *geom
)
{
int rc;
int num_points;
int num_parts;
int has_m = geom->type & 0x01;
int has_z = geom->type & 0x02;
int prev_offset;
int i;
/* Skip over the double precision bounding box, we will
calculate the envelope when needed */
cp += 4 * sizeof(double);
/* Get the number of parts */
get_integer (&cp, swap_bytes, 1, &num_parts);
if (num_parts <= 0)
return GEOM_INVALID_NUM_PARTS;
/* Get the total number of points */
get_integer (&cp, swap_bytes, 1, &num_points);
if (num_points <= 0)
return GEOM_TOO_FEW_POINTS;
/* Allocate the parts offsets, then extract them */
if (geom->offsets != NULL)
free (geom->offsets);
geom->offsets = malloc (num_parts * sizeof(int));
if (NULL == geom->offsets)
return GEOM_OUT_OF_MEMORY;
get_integer (&cp, swap_bytes, num_parts, geom->offsets);
/* make sure each part offset is legal */
prev_offset = 0;
if (geom->offsets[0] != 0)
return GEOM_INVALID_PART_OFFSET;
for (i = 1; i < num_parts; i++)
{
if (geom->offsets[i] < prev_offset + 2)
{
/* Offsets should be monotonically increasing,
and each part needs at least 2 points */
return GEOM_INVALID_PART_OFFSET;
}
prev_offset = geom->offsets[i];
}
/* Check the last offset */
if (num_points < prev_offset + 2)
return GEOM_INVALID_PART_OFFSET;
/* Allocate space for the geometry points. */
rc = geom_allocate (geom, num_points);
if (rc != GEOM_SUCCESS)
return rc;
geom->num_points = num_points;
get_xy (&cp, swap_bytes, num_points, geom->pt);
if (has_z)
{
cp += 2 * sizeof(double); /* Skip over Z extrema */
get_double (&cp, swap_bytes, num_points, geom->z);
}
if (has_m)
{
cp += 2 * sizeof(double); /* Skip over M extrema */
get_double (&cp, swap_bytes, num_points, geom->m);
}
return GEOM_SUCCESS;
}
/***************************************************************************
*
* _get_shp_multipoint - Extracts a multipoint shape from the ESRI binary
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Purpose:
* This function builds a multipoint shape from the ESRI binary shape
* representation of a geometry.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Parameters:
* cp == (char *) a pointer into the binary buffer
* swap_bytes == (int) 1 if bytes need to be swapped
* geom == (Geometry *) The geometry object
*
* RETURN == (int) Error code
*
****************************************************************************/
static int _get_shp_multipoint (
char *cp,
int swap_bytes,
Geometry *geom
)
{
int rc;
int num_points;
int has_m = geom->type & 0x01;
int has_z = geom->type & 0x02;
/* Skip over the double precision bounding box, we will
calculate the envelope when needed */
cp += 4 * sizeof(double);
get_integer (&cp, swap_bytes, 1, &num_points);
if (num_points <= 0)
return GEOM_TOO_FEW_POINTS;
/* Allocate space for the shape points. */
rc = geom_allocate(geom, num_points);
if (rc != GEOM_SUCCESS)
return rc;
geom->num_points = num_points;
/* Get an array of xy points */
get_xy (&cp, swap_bytes, num_points, geom->pt);
if (has_z)
{
/* Skip over the double precision Z extrema */
cp += 2 * sizeof(double);
/* Get the Z values */
get_double (&cp, swap_bytes, num_points, geom->z);
}
if (has_m)
{
/* Skip over the double precision M extrema */
cp += 2 * sizeof(double);
/* Get the measure values */
get_double (&cp, swap_bytes, num_points, geom->m);
}
return GEOM_SUCCESS;
}
/***************************************************************************
*
* _get_shp_point - Extracts a point shape from the ESRI binary
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Purpose:
* This function builds a point shape from the ESRI binary shape
* representation of a shape.
*
*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
*
* Parameters:
* swap_bytes == (int) 1 if bytes need to be swapped
* cp == (char *) a pointer into the binary buffer
* geom == (Geometry *) The geometry object
*
* RETURN == (int) Error code
*
****************************************************************************/
static int _get_shp_point (
char *cp,
int swap_bytes,
Geometry *geom
)
{
int rc;
int has_m = geom->type & 0x01;
int has_z = geom->type & 0x02;
/* Allocate space for the shape point */
rc = geom_allocate(geom, 1);
if (rc != GEOM_SUCCESS)
return rc;
geom->num_points = 1;
/* Get a single xy point, followed by the Z and/or M values */
get_xy (&cp, swap_bytes, 1, geom->pt);
if (has_z)
get_double (&cp, swap_bytes, 1, geom->z);
if (has_m)
get_double (&cp, swap_bytes, 1, geom->m);
return GEOM_SUCCESS;
}