Main Content

Select Shapefile Data to Read

The shaperead function provides you with a powerful method, called a selector, to select only the data fields and items you want to import from shapefiles.

A selector is a cell array with two or more elements. The first element is a handle to a predicate function (a function with a single output argument of type logical). Each remaining element is a character vector indicating the name of an attribute.

For a given feature, shaperead supplies the values of the attributes listed to the predicate function to help determine whether to include the feature in its output. The feature is excluded if the predicate returns false. The converse is not necessarily true: a feature for which the predicate returns true may be excluded for other reasons when the selector is used in combination with the bounding box or record number options.

The following examples are arranged in order of increasing sophistication. Although they use MATLAB® function handles, anonymous functions, and nested functions, you need not be familiar with these features in order to master the use of selectors for shaperead.

Example 1: Predicate Function in Separate File

  1. Define the predicate function in a separate file. (Prior to Release 14, this was the only option available.) Create a file named roadfilter.m, with the following contents:

     function result = roadfilter(roadclass,roadlength)
     mininumClass = 4;
     minimumLength = 200;
     result = (roadclass  >= mininumClass) && ...
              (roadlength >= minimumLength);
     end
  2. You can then call shaperead like this:

    roadselector = {@roadfilter, 'CLASS', 'LENGTH'}
    
    roadselector = 
        @roadfilter    'CLASS'    'LENGTH'
    
    s = shaperead('concord_roads', 'Selector', roadselector)
    
    s = 
    115x1 struct array with fields:
        Geometry
        BoundingBox
        X
        Y
        STREETNAME
        RT_NUMBER
        CLASS
        ADMIN_TYPE
        LENGTH

    or, in a slightly more compact fashion, like this:

    s = shaperead('concord_roads',...
                  'Selector', {@roadfilter, 'CLASS', 'LENGTH'})
    
    s = 
    115x1 struct array with fields:
        Geometry
        BoundingBox
        X
        Y
        STREETNAME
        RT_NUMBER
        CLASS
        ADMIN_TYPE
        LENGTH

    Prior to Version 7 of the Mapping Toolbox™ software, putting the selector in a file or local function of its own was the only way to work with a selector.

    Note that if the call to shaperead took place within a function, then roadfilter could be defined in a local function thereof rather than in a file of its own.

Example 2: Predicate as Function Handle

As a simple variation on the previous example, you could assign a function handle, roadfilterfcn, and use it in the selector:

roadfilterfcn = @roadfilter
s = shaperead('concord_roads',...
              'Selector', {roadfilterfcn, 'CLASS', 'LENGTH'})
roadfilterfcn = 
@roadfilter
s = 
115x1 struct array with fields:
    Geometry
    BoundingBox
    X
    Y
    STREETNAME
    RT_NUMBER
    CLASS
    ADMIN_TYPE
    LENGTH

Example 3: Predicate as Anonymous Function

Having to define predicate functions in files of their own, or even as local functions, may sometimes be awkward. Anonymous functions allow the predicate function to be defined right where it is needed. For example:

roadfilterfcn = ...
    @(roadclass, roadlength) (roadclass >= 4) && ...
    (roadlength >= 200)

roadfilterfcn = 
    @(roadclass, roadlength) (roadclass >= 4) ...
               && (roadlength >= 200)

s = shaperead('concord_roads','Selector', ...
              {roadfilterfcn, 'CLASS', 'LENGTH'})

s = 
115x1 struct array with fields:
    Geometry
    BoundingBox
    X
    Y
    STREETNAME
    RT_NUMBER
    CLASS
    ADMIN_TYPE
    LENGTH

Example 4: Predicate (Anonymous Function) Defined Within Cell Array

There is actually no need to introduce a function handle variable when defining the predicate as an anonymous function. Instead, you can place the whole expression within the selector cell array itself, resulting in somewhat more compact code. This pattern is used in many examples throughout the Mapping Toolbox documentation and function help.

s = shaperead('concord_roads', 'Selector', ...
    {@(roadclass, roadlength)...
    (roadclass >= 4) && (roadlength >= 200),...
    'CLASS', 'LENGTH'})

s = 
115x1 struct array with fields:
    Geometry
    BoundingBox
    X
    Y
    STREETNAME
    RT_NUMBER
    CLASS
    ADMIN_TYPE
    LENGTH

Example 5: Parametrizing the Selector; Predicate as Nested Function

In the previous patterns, the predicate involves two hard-coded parameters (called minimumClass and minimumLength in roadfilter.m), as well as the roadclass and roadlength input variables. If you use any of these patterns in a program, you need to decide on minimum cut-off values for roadclass and roadlength at the time you write the program. But suppose that you wanted to wait and decide on parameters like minimumClass and minimumLength at run time?

Fortunately, nested functions provide the additional power that you need to do this; they allow you to utilize workspace variables in as parameters, rather than requiring that the parameters be hard-coded as constants within the predicate function. In the following example, the workspace variables minimumClass and minimumLength could have been assigned through a variety of computations whose results were unknown until run-time, yet their values can be made available within the predicate as long as it is defined as a nested function. In this example the nested function is wrapped in a file called constructroadselector.m, which returns a complete selector: a handle to the predicate (named nestedroadfilter) and the two attribute names:

 function roadselector = ...
     constructroadselector(minimumClass, minimumLength)
 roadselector = {@nestedroadfilter, 'CLASS', 'LENGTH'};
     function result = nestedroadfilter(roadclass, roadlength)
         result = (roadclass  >= minimumClass) && ...
                  (roadlength >= minimumLength);
     end
 end

The following four lines show how to use constructroadselector:

minimumClass = 4;     % Could be run-time dependent
minimumLength = 200;  % Could be run-time dependent

roadselector = constructroadselector(...
    minimumClass, minimumLength);

s = shaperead('concord_roads', 'Selector', roadselector)

s = 
115x1 struct array with fields:
    Geometry
    BoundingBox
    X
    Y
    STREETNAME
    RT_NUMBER
    CLASS
    ADMIN_TYPE
    LENGTH