Selector
Reporter
Select members of a collection that have specified properties.
Selection is a universal in interactive systems. In parametric
systems, selection can be part of the model itself. At each
update of the propagation graph, objects can select the
arguments to their update methods. Use this pattern when you
want to locally and dynamically restructure a model depending its
state.
Creating objects and using objects are different acts. You will
often specify, say, a set of points by giving their Cartesian
coordinates. When it comes to using these points, you might be
interested only in those that are close to a line. The selector
pattern allows you to separate object creation and later use,
and express these two common operations in the terms most
suitable for each.
In the Selector pattern, there is
always a collection of given objects and a collection that is
the outcome of the Selector's action.
We call the first list the *target* and the second list
the *result*. The Selector
object mediates between these by determining which elements of
the target to include in the result. The properties that
objects must have or conditions they must meet in order to be
selected we call the Selector's
*behavior*.
For example (See the Sample entitled Distance between Points), the
target may be a list of points and the
Selector a compound of a point, a
circle and a function. The point provides the location of the
Selector; the circle displays the
distance within which selection will occur; and the function
specifies how points will be selected and how selected points
will be constructed. The function embodies the
Selector's behaviour. The aim is to
select the points whose distance to the
Selector point is less than (or
greater than or equal to) the variable $d$
which itself parameterizes the
Selector's behavior.
The simplest representation of a
Selector's behaviour is a function\index{function}
that considers each of the target points individually. For each
target, it computes the behaviour and returns a copy of any
objects that conform. For instance, with selection based on
distance, a Selector compares the
distance between target and Selector
against the threshold $d$. If the target
object satisfies the condition, the function creates a
coincident point and returns this point (acting in a sense as a
Reporter). As a result, the
function's (and Selector's) output
will be a new list of points.
The result is not a subset of the target. Rather, it is a new
set of points, identical to the selected points in the target.
function selectByDistance(Point selector,
Point target,
double distance)
{
for (value i = 0; i < target.Count; ++i)
{
if (Distance(selector,target[i]) < distance)
{
Point result= new Point(this);
result.ByCartesianCoordinates(baseCS,
target[i].X,
target[i].Y,
target[i].Z);
}
}
};

An actual call to the Selector's behaviour function would take the following form:
selectByDistance(selector,target,distance);

where selector and target are points\index{point} (or point
collections) in the model and distance is a value held in a
model variable\index{variable} or object property\index{property}.
Distance between Points
Select points from a collection depending on
their distance to a selector point.
First write a function\index{function} a condition for target points to be
selected. In this sample example, the
distance between the target and the selector point must be
less than variable $d$.
Write a behaviour function that checks the target points one
by one and compares the distance between each point and the
selector point using the threshold $d$. For each member of the list, if the
condition is satisfied, the selector function creates a copy
of the target point.
The behaviour function returns a new list of result points
that are within distance $d$ of the
selector point. Note that the structure of the target and
result my differ. For instance, the target may be a 2D array\index{data structure!array}
and the result a 1D array. You have to make and remember such choices.
Click to download SeleDistanceBetweenPoints.gct
Part of Curve
Select part of a curve depending on its
distance to a point.
Place a collection of parametric points\index{point} on the curve\index{curve}. Use
the same mechanism for selecting these points as in the
sample *Distance between Points.* Write a function
that checks each of the points and reports them if they
satisfy the condition.
Placing a curve through the selected points yields an
approximate copy of part of the original curve. Moving the
selector point, controls the part of the curve to be
copied. The more points on the original curve, the more
accurate the selected curve.
The original points sample the curve and so will not
generally capture the exact point on the curve that is at
the specified distance. This problem may be addressed by
searching between the last selected point and the first
non-selected point for the point at which the distance to
the selector is exactly the threshold. If, however, the original
points are widely spaced, very small sections of the curve
that are within the threshold might fail to be
detected. This can be addressed by projecting\index{transformation!projection} the selector
point onto the curve. If the distance to the selector point
is less than than the threshold, search on either side of
the projected point for the exact end points of the curve.
Click to download SelePartOfACurve.gct
Lines inside Curve
Select all lines that are completely inside a closed curve.
This Selector has two parts.
First, if a line\index{line!segment} segment is entirely inside or outside a curve\index{curve} it
does not intersect the curve. In order to check the position
of a line against a curve, first compute the
intersection. If the result is null, the line may be either
inside or outside.
\begin{bodyNote}
\pbOneCol
{
\input{\GCFigsPath/Patterns/SeleJordanCurve10.tex}
\input{\GCFigsPath/Patterns/SeleJordanCurve20.tex}
}
\end{bodyNote}
Second, if an endpoint of a non-intersecting line is inside
the curve, so is the line. The Jordan Curve theorem\index{Jordan Curve theorem} states
that a point is inside a closed curve if a line segment
between the point and anther points external to the curve
intersects the curve an odd number of times. Use the Jordan
Curve theorem to determine the position of either end of the
line segment against the closed curve. Don't count
tangencies as crossings! If the number of intersections is
odd, the line is inside the curve.
\begin{bodyNote}
\pbOneCol
{
\input{\GCFigsPath/Patterns/SeleJordanCurve30.tex}
\input{\GCFigsPath/Patterns/SeleJordanCurve40.tex}
}
\end{bodyNote}
Write a function\index{function} that performs both of the above tests in
turn. If both succeed (non-intersection of the segment and odd
intersections of a ray from an end point) copy and return the
line.
Click to download SeleLinesInsideCurve.gct
Points inside Sector
Select the points\index{point} that lie inside a 2D sector (two vectors bound to a common point).
The sector comprises a base point and two vectors $u$ and $v$ bound to it. Taken in
order, these define an angle between $0$ and $360\; degrees$. Imagine a target vector $a$ for each target point connecting from the base point to the
target point. Take the two cross products\index{vector!cross product} $$ and $$. Remember from Section
\ref{sec:Frames:cross-prod} that the right hand rule\index{frame!right hand rule}
determines the orientation of the cross product of two
vectors. If the angle between the vectors $u$ and $v$ is less than $180\; degrees$, a target point is between two selector
vectors if the $z$-components of both the cross products of its vector
with the selector vectors are positive. If the angle\index{angle} is greater than $180\; degrees$, the target point is in the sector if one
or both of the cross products are positive.
\begin{bodyNote}
\pbOneCol
{
\input{\GCFigsPath/Geometry/crossProductInLt180.tex}
\input{\GCFigsPath/Geometry/crossProductOutLt180.tex}
}
\vspace{3mm}
\pbOneCol
{
\input{\GCFigsPath/Geometry/crossProductInReflex.tex}
\input{\GCFigsPath/Geometry/crossProductOutReflex.tex}
}
\end{bodyNote}
The scalar product\index{vector!scalar product} determines if the sector given by the base point and $u$ and $v$ is greater than $180\; degrees$. If the sector is between $0s$ and $180\; degrees$, $u.v$
is positive. If the sector is between $180$ and
$360\; degrees$, $u.v$ is negative.
When $u$ and $v$ are
colinear, the sector is either $0\; degrees$ ($u.v\; >\; =\; 0$) or $180\; degrees$ ($u.v\; <\; 0$).
The selector function\index{function} iterates over the target points\index{point} one by
one. For each point, it computes the two cross products\index{vector!cross product}$$ and $$. Using the rules above it determines if each point lies within the sector and includes each successful point in the result.
Click to download SelePointsInsideSector.gct
Click to download SelePointsInside3DSector.gct
Points inside Box
Select points that are inside a box.
Write a behaviour function\index{function} that checks the position of the
target points\index{point} against the box. The function reports their
position in the coordinate system\index{frame} of the selector box one by
one and compares their new coordinates to two opposite corners
of the box. The function then reports them in the result list
if they are inside the box.
Click to download SelePointsInsideBox.gct
\renewcommand{\sampleNewPage}[0]{false}
Length of Line
Select lines based on their length.
Given a list of lines\index{line}, select those whose lengths are equal to
a variable, equal to the length of a selector line, or between
the lengths of two selector lines.
Use a function\index{function} that iterates through the target lines. For
each target line, if it has the desired length, the function
reports it and puts it in a new list of result lines.
Click to download SeleLengthOfLine.gct
Boundary
To be added.
To be added.
Click to download SeleBoundary.gct