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 do not
need to be familiar with these features to use the selectors for
shaperead
.
Example 1: Predicate Function in Separate File
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
You can then call
shaperead
like this:roadselector = {@roadfilter, 'CLASS', 'LENGTH'} roadselector = @roadfilter 'CLASS' 'LENGTH' s = shaperead('concord_roads.shp', '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.shp',... '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, thenroadfilter
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.shp',... '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.shp','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.shp', '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.shp', 'Selector', roadselector) s = 115x1 struct array with fields: Geometry BoundingBox X Y STREETNAME RT_NUMBER CLASS ADMIN_TYPE LENGTH