Skip to content

Retrieving Locations in a Radius

Chris Ridley edited this page Jul 17, 2018 · 10 revisions

The RadiusAreaProvider class provides a convenient way to iterate through all locations within a radius, given a distance calculation or radius shape, and radius length.

Table of Contents

Code Examples

Code examples in this section show only code in the Main function. The code provided assumes that the following "using" statements are at the top of the code file:

using GoRogue;

Creating a RadiusAreaProvider

The constructor of RadiusAreaProvider takes the center point of the radius, length of the radius, Distance calculation/Radius shape, and optionally a rectangle with which to bound returned values:

Coord center = Coord.Get(5, 6);
// The third parameter is a Distance instance, however Radius instances are implicitly
// convertible to Distance instances, and as such we can pass a Radius shape
RadiusAreaProvider prov = new RadiusAreaProvider(center, 3, Radius.CIRCLE);

// We can also specify the point as two integer values
prov = new RadiusAreaProvider(5, 6, 3, Radius.CIRCLE);

// In either case, we can also specify bounds to respect.  When prov.Positions()
// is called, only positions in the radius that are also within the rectangle given
// will be returned.  We also choose to specify the radius shape as a Distance instance,
// although we could just as easily have used Radius.DIAMOND to achieve the same result.
Rectangle bounds = new Rectangle(4, 4, 10, 10);
prov = new RadiusAreaProvider(center, 3, Distance.MANHATTAN, bounds);

Why a Class?

Given that a RadiusAreaProvider instance's main purpose is to simply return an IEnumerable containing the proper coordinates, you may wonder, why is it a class, as opposed to a static function? The answer lies in memory allocation efficiency. A 2D array the size of the radius must be allocated each time a RadiusAreaProvider is created. While it is an array of boolean values and as such fairly small, it does take significant time to allocate. If the functionality of RadiusAreaProvider was provided as a function, rather than a class, the array would need to be reallocated with each use. Providing it as a class instead allows the re-use of the array for radiuses of the same size (even at different locations), and is thus more efficient.

Modifying RadiusAreaProvider Parameters

Since RadiusAreaProviders are intended to provide re-use, the center-point, radius shape, radius length, and bounds are all modifiable.

Most parameters can be modified freely, however be advised that modifying the radius length requires re-allocation of the underlying 2D array, and as such may incur a performance penalty if done too frequently.

The following code demonstrates modification of the parameters:

RadiusAreaProvider prov = new RadiusAreaProvider(10, 10, 3, Radius.CIRCLE);
prov.Center = Coord.Get(5, 6);
prov.Radius = 4; // This requires reallocation of the underlying array, be careful!
prov.DistanceCalc = Radius.SQUARE;
prov.Bounds = new Rectangle(5, 5, 10, 10); // Set bounds to a previously unbound RadiusAreaProvider
prov.Bounds = Rectangle.EMPTY; // We can also remove all bounds by setting the bounds to the empty rectangle

Retrieving Coordinates Within Radius

Given a RadiusAreaProvider, retrieving the list of positions inside the radius (and any bounding rectangle specified) is as simple as a call to the CalculatePositions() function. This function retrieves an IEnumerable of all the positions:

RadiusAreaProvider prov = new RadiusAreaProvider(5, 6, 3, Radius.CIRCLE);

foreach (Coord pos in prov.CalculatePositions())
    System.Console.Write(pos + ", ");

Order of Returned Coordinates

In the case that MANHATTAN or CHEBYSHEV distance is used, it is guaranteed that locations are returned in order of distance away from the start. Since the class does not use a priority queue, this is not guaranteed if EUCLIDEAN distance is used.