Routines (alphabetical) > Object Classes > File Format Object Classes > IDLffShape

# IDLffShape

Superclasses | Creation | Properties | Methods | Version History | Overview of ESRI Shapefiles | Examples

An IDLffShape object contains geometry, connectivity and attributes for graphics primitives accessed from ESRI Shapefiles. See Overview of ESRI Shapefiles.

## Superclasses

None

## Creation

See IDLffShape::Init

## Properties

Objects of this class have the following properties. See IDLffShape Properties for details on individual properties.

- ATTRIBUTE_INFO
- ATTRIBUTE_NAMES
- DBF_ONLY
- ENTITY_TYPE
- FILENAME
- IS_OPEN
- N_ATTRIBUTES
- N_ENTITIES
- N_RECORDS
- UPDATE
- Methods

This class has the following methods:

- IDLffShape::AddAttribute
- IDLffShape::Cleanup
- IDLffShape::Close
- IDLffShape::DestroyEntity
- IDLffShape::GetAttributes
- IDLffShape::GetEntity
- IDLffShape::GetProperty
- IDLffShape::Init
- IDLffShape::Open
- IDLffShape::PutEntity
- IDLffShape::SetAttributes

## Version History

5.4 | Introduced
5.6 | Added N_RECORDS, DBF_ONLY properties

## Overview of ESRI Shapefiles

An ESRI Shapefile stores nontopological geometry and attribute information for the spatial features in a data set.

A Shapefile consists of a main file (`.shp`), an index file (`.shx`), and a dBASE table (`.dbf`). For example, the Shapefile “states” would have the following files:

- states.shp
- states.shx
- states.dbf

### Naming Conventions for a Shapefile

All the files that comprise an ESRI Shapefile must adhere to the 8.3 filename convention and must be lower case. The main file, index file, and dBASE file must all have the same prefix. The prefix must start with an alphanumeric character and can contain any alphanumeric, underscore (_), or hyphen (-). The main file suffix must use the `.shp` extension, the index file the `.shx` extension, and the dBASE table the `.dbf` extension.

### Major Elements of a Shapefile

A Shapefile consists of the following elements that you can access through the IDLffShape class:

- Entities
- Attributes

#### Entities

The geometry for a feature is stored as a shape comprising a set of vector coordinates (referred to as ‘entities’). The (non-null) entities in a Shapefile must all be of the same type. The following are the possible types for entities in a Shapefile:

Shape Type | Type Code
Point | 1
PolyLine | 3
Polygon | 5
MultiPoint | 8
PointZ | 11
PolyLineZ | 13
PolygonZ | 15
MultiPointZ | 18
PointM | 21
PolyLineM | 23
PolygonM | 25
MultiPointM | 28
MultiPatch | 31

When retrieving entities using the IDLffShape::GetEntity method, an IDL structure is returned. This structure has the following fields:

Field | Data Type | Description
SHAPE_TYPE | Long integer | The entity type.
ISHAPE | Long integer | A read-only field containing the index of the specific entity within the shape object. This value is set automatically when the shape file is written.
BOUNDS | Eight-element, double-precision array | A bounding box that specifies the range limits of the entity. This eight element array contains the following information: Index 0 — X minimum value Index 1 — Y minimum value Index 2 — Z minimum value (if Z is supported by type) Index 3 — Measure minimum value (if measure is supported by entity type) Index4 — X maximum value Index5 — Y maximum value Index6 — Z maximum value (if Z is supported by the entity type) Index7 — Measure maximum value (if measure is supported by entity type) If the entity is a point type, the values contained in the bounds array are also the values of the entity.
N_VERTICES | Long integer | The number of vertices in the entity. If this value is one and the entity is a POINT type (POINT, POINTM, POINTZ), the vertices pointer will be set to NULL and the entity value will be maintained in the BOUNDS field.
VERTICES | Pointer to Vertices array | An IDL pointer that contains the vertices of the entity. This pointer contains a double array that has one of the following formats: [2, N] - If Z data is not present [3, N] - If Z data is present where N is the number of vertices. These array formats can be passed to the polygon and polyline objects of IDL Object Graphics. This pointer will be null if the entity is a point type, with the values maintained in the BOUNDS array.
MEASURE | Pointer to Measure array | If the entity has a measure value (this is dependent on the entity type), this IDL pointer will contain a vector array of measure values. The length of this vector is N_VERTICES. This pointer will be null if the entity is of type POINTM, with the values contained in the BOUNDS array.
N_PARTS | Long integer | If the values of the entity are separated into parts, the break points are enumerated in the parts array. This field lists the number of parts in this entity. If this value is 0, the entity is one part and the PARTS pointer will be NULL.
PARTS | Pointer to Parts array | An IDL pointer that contains an array of indices into the vertex/measure arrays. These values represent the start of each part of the entity. The index range of each entity part is defined by the following: Start = Parts[I] End = Parts[I+1]-1 or the end of the array
PART_TYPES | Pointer to part types | This IDL pointer is only valid for entities of type MultiPatch and defines the type of the particular part. If the entity type is not MultiPatch, part types are assumed to be type RING (SHPP_RING). This pointer is NULL if the entity is not type MultiPatch.
ATTRIBUTES | Pointer to Attribute array | If the attributes for an entity were requested, this field contains an IDL pointer that contains a structure of attributes for the entity. For more information on this structure, see Attributes.

#### Attributes

A Shapefile provides the ability to associate information describing each entity (a geometric element) contained in the file. This descriptive information, called attributes, consists of a set of named data elements for each geometric entity contained in the file. The set of available attributes is the same for every entity contained in a Shapefile, with each entity having its own set of attribute values.

An attribute consist of two components:

- A name
- A data value

The name consists of an 11 character string that is used to identify the data value. The data value is not limited to any specific format.

The two components that form an attribute are accessed differently using the shape object. To get the name of attributes for the specific file, the ATTRIBUTE_NAMES keyword to the IDLffShape::GetProperty method is used. This returns a string array that contains the names for the attributes defined for the file.

To get the attribute values for an entity, the IDLffShape::GetAttributes method is called or the ATTRIBUTES keyword of the IDLffShape::GetEntity method is set. In each case, the attribute values for the specified entity is returned as an anonymous IDL structure. The numeric order of the fields in the returned structure map to the numeric order of the attributes defined for the file. The actual format of the returned structure is:

ATTRIBUTE_0 : VALUE,

ATTRIBUTE_1 : VALUE,

ATTRIBUTE_2 : VALUE,

...

ATTRIBUTE_<N-1> : VALUE

To access the values in the returned structure, you can either hard code the structure field names or use the structure indexing feature of IDL.

## Examples

See the following sections for examples of:

- Accessing Shapefiles
- Creating New Shapefiles
- Updating Existing Shapefiles

## Accessing Shapefiles

The following example shows how to access data in a Shapefile. This example sets up a map to display parts of a Shapefile, opens a Shapefile, reads the entities from the Shapefile, and then plots only the state of Colorado:

PRO ex_shapefile

DEVICE, RETAIN=2, DECOMPOSED=0

!P.BACKGROUND = 255

; Define a color table

r = BYTARR(256) & g = BYTARR(256) & b = BYTARR(256)

r[0] = 0 & g[0] = 0 & b[0] = 0 ;Definition of black

r[1] = 100 & g[1] = 100 & b[1] = 255 ;Definition of blue

r[2] = 0 & g[2] = 255 & b[2] = 0 ;Definition of green

r[3] = 255 & g[3] = 255 & b[3] = 0 ;Definition of yellow

r[255] = 255 & g[255] = 255 & b[255] = 255 ;Definition of white

TVLCT, r, g, b

black = 0 & blue = 1 & green = 2 & yellow = 3 & white = 255

; Set up map to plot Shapefile on

MAP_SET, /ORTHO, 45, -120, /ISOTROPIC, $

/HORIZON, E_HORIZON={FILL:1, COLOR:blue}, $

/GRID, COLOR=black, /NOBORDER

; Fill the continent boundaries:

MAP_CONTINENTS, /FILL_CONTINENTS, COLOR=green

; Overplot coastline data:

MAP_CONTINENTS, /COASTS, COLOR=black

; Show national borders:

MAP_CONTINENTS, /COUNTRIES, COLOR=black

; Open the states Shapefile in the examples directory

myshape = OBJ_NEW('IDLffShape', FILEPATH('states.shp', $

SUBDIR=['examples', 'data']))

; Get the number of entities so we can parse through them

myshape->GetProperty, N_ENTITIES=num_ent

; Parsing through the entities and only plotting the state of

; Colorado

FOR x=0L, (num_ent-1) DO BEGIN

; Get the Attributes for entity x

attr = myshape->GetAttributes(x)

; See if 'Colorado' is in ATTRIBUTE_1 of the attributes for

; entity x

IF attr.ATTRIBUTE_1 EQ 'Colorado' THEN BEGIN

; Get entity

ent = myshape->GetEntity(x)

; Plot entity

POLYFILL, (*ent.VERTICES)[0, *], (*ent.VERTICES)[1, *], $

COLOR=yellow

; Clean-up of pointers

myshape->DestroyEntity, ent

ENDIF

ENDFOR

; Close the Shapefile

OBJ_DESTROY, myshape

END

This results in the following:

## Creating New Shapefiles

To create a Shapefile, you need to create a new Shapefile object, define the entity and attributes definitions, and then add your data to the file. For example, the following program creates a new Shapefile (`cities.shp`), defines the entity type to be “Point”, defines 2 attributes (CITY_NAME and STATE_NAME), and then adds an entity to the new file:

PRO ex_shapefile_newfile

; Create the new shapefile and define the entity type to Point

mynewshape = OBJ_NEW('IDLffShape', FILEPATH('cities.shp', $

SUBDIR=['examples', 'data']), /UPDATE, ENTITY_TYPE=1)

; Set the attribute definitions for the new Shapefile

mynewshape->AddAttribute, 'CITY_NAME', 7, 25, PRECISION=0

mynewshape->AddAttribute, 'STAT_NAME', 7, 25, PRECISION=0

; Create structure for new entity

entNew = {IDL_SHAPE_ENTITY}

; Define the values for the new entity

entNew.SHAPE_TYPE = 1

entNew.BOUNDS[0] = -104.87270

entNew.BOUNDS[1] = 39.768040

entNew.BOUNDS[2] = 0.00000000

entNew.BOUNDS[3] = 0.00000000

entNew.BOUNDS[4] = -104.87270

entNew.BOUNDS[5] = 39.768040

entNew.BOUNDS[6] = 0.00000000

entNew.BOUNDS[7] = 0.00000000

entNew.N_VERTICES = 1 ; take out of example, need as workaround

; Create structure for new attributes

attrNew = mynewshape->GetAttributes(/ATTRIBUTE_STRUCTURE)

; Define the values for the new attributes

attrNew.ATTRIBUTE_0 = 'Denver'

attrNew.ATTRIBUTE_1 = 'Colorado'

; Add the new entity to new shapefile

mynewshape->PutEntity, entNew

; Note that because this is a new shapefile, the index of

; the new entity is zero.

entity_index = 0

; Add the Colorado attributes to new shapefile.

mynewshape->SetAttributes, entity_index, attrNew

; Close the shapefile

OBJ_DESTROY, mynewshape

END

## Updating Existing Shapefiles

You can modify existing Shapefiles with the following:

- Adding new entities
- Adding new attributes (only to Shapefiles without any existing values in any attributes)
- Modifying existing attributes

Note: You cannot modify existing entities.

For example, the following program adds an entity and attributes for the city of Boulder to the `cities.shp` file created in the previous example:

PRO ex_shapefile_modify

; Open the cities Shapefile

myshape = OBJ_NEW('IDLffShape', FILEPATH('cities.shp', $

SUBDIR=['examples', 'data']), /UPDATE)

; Create structure for new entity

entNew = {IDL_SHAPE_ENTITY}

; Define the values for the new entity

entNew.SHAPE_TYPE = 1

entNew.ISHAPE = 200

entNew.BOUNDS[0] = -105.25100

entNew.BOUNDS[1] = 40.026878

entNew.BOUNDS[2] = 0.00000000

entNew.BOUNDS[3] = 0.00000000

entNew.BOUNDS[4] = -105.25100

entNew.BOUNDS[5] = 40.026878

entNew.BOUNDS[6] = 0.00000000

entNew.BOUNDS[7] = 0.00000000

entNew.N_VERTICES = 1 ; take out of example, need as workaround

; Create structure for new attributes

attrNew = myshape->GetAttributes(/ATTRIBUTE_STRUCTURE)

; Define the values for the new attributes

attrNew.ATTRIBUTE_0 = 'Boulder'

attrNew.ATTRIBUTE_1 = 'Colorado'

; Add the new entity to new shapefile

myshape->PutEntity, entNew

; Determine the zero-based index of the new entity

myshape->GetProperty, N_ENTITIES=num_entities

entity_index = num_entities-1

; Add the Colorado attributes to new shapefile

myshape->SetAttributes, entity_index, attrNew

; Close the shapefile

OBJ_DESTROY, myshape

END

## Graphing an Updated Shapefile

The following program graphs the `cities.shp` file that was created and updated in the previous examples:

PRO plot_cities

DEVICE, RETAIN=2, DECOMPOSED=0

!P.BACKGROUND = 255

;Define a color table

r=BYTARR(256) & g = BYTARR(256) & b = BYTARR(256)

r[0] = 0 & g[0] = 0 & b[0]=0 ;Definition of black

r[1] = 100 & g[1] = 100 & b[1] = 255 ;Definition of blue

r[2] = 0 & g[2] = 255 & b[2] = 0 ;Definition of green

r[3] = 255 & g[3] = 255 & b[3] = 0 ;Definition of yellow

r[255] = 255 & g[255] = 255 & b[255] = 255 ;Definition of white

TVLCT, r, g, b

black = 0 & blue = 1 & green = 2 & yellow = 3 & white = 255

; Set up map to plot Shapefile on

MAP_SET, /ORTHO, 39, -104, SCALE=9e6, /ISOTROPIC, $

/HORIZON, E_HORIZON={FILL:1, COLOR:green}, COLOR=yellow

; Show state borders:

MAP_CONTINENTS, /USA, COLOR=black

; Open the states Shapefile in the examples directory

myshape = OBJ_NEW('IDLffShape', FILEPATH('states.shp', $

SUBDIR=['examples', 'data']))

; Get the number of entities so we can parse through them

myshape->GetProperty, N_ENTITIES=num_ent

; Parsing through the entities and only plotting the state of

; Colorado

FOR x=1, (num_ent-1) DO BEGIN

; Get the Attributes for entity x

attr = myshape->GetAttributes(x)

; See if 'Colorado' is in ATTRIBUTE_1 of the attributes for

; entity x

IF attr.ATTRIBUTE_1 EQ 'Colorado' THEN BEGIN

; Get entity

ent = myshape->GetEntity(x)

; Plot entity

POLYFILL, (*ent.VERTICES)[0, *], (*ent.VERTICES)[1, *], $

COLOR=yellow

; Clean-up of pointers

myshape->DestroyEntity, ent

ENDIF

ENDFOR

; Close the states Shapefile

OBJ_DESTROY, myshape

; Open the cities Shapefile

myshape = OBJ_NEW('IDLffShape', FILEPATH('cities.shp', $

SUBDIR=['examples', 'data']))

; Get the number of entities so we can parse through them

myshape->GetProperty, N_ENTITIES=num_ent

; Plot the cities on the map of Colorado

FOR x=0, (num_ent-1) DO BEGIN

; Get entity

ent = myshape->GetEntity(x)

; Get city attribute

attr = myshape->GetAttributes(x)

; Plot the cities with a symbol, as well as the city name

PLOTS, ent.BOUNDS[0], ent.BOUNDS[1], PSYM=5, COLOR=black

XYOUTS, ent.BOUNDS[0] + 0.3, ent.BOUNDS[1], $

attr.ATTRIBUTE_0, color=black

; Clean-up of pointers

myshape->DestroyEntity, ent

ENDFOR

; Close the Shapefile

OBJ_DESTROY, myshape

END