# Spatial Geography

In Insight Maker, each Agent Population can be given dimensions in terms of a width and a height. By default, agents are placed at a random location within this region. You can, however, choose a different placement method for the starting position of the agents. The following placement methods are available:

Random: The default. Agents are placed at random positions within the geometry specified for the agent population.

Grid: Agents are aligned in a grid within the population. When using this placement method, you will need to ensure that you have enough agents so that the grid is complete. You might need to experiment with increasing or decreasing the number of agents to make the grid fit perfectly for a given set of region dimensions.

Ellipse: Agents are arranged in a single ellipse within the region. If the region geometry is a square, then the agents will be arranged in a circle.

Network:: Assuming network connections between agents have been specified, the agents will be arranged in an attempt to create a pleasing layout of the network structure.

Custom Function: Here you can specify a custom function to control the layout of the agents. This function will be called once for each agent in the population and should return a two-element vector where the first element is the x-coordinate of the agent, and the second element is the y-coordinate. The variable Self in this function will refer to the agent that is being positioned.

## Spatial Find Functions

When working with a spatially explicit model, a number of additional find functions are available for you to obtain references to agents that match given spatial criteria.

FindNearby() is a function that returns a vector of agents that are within a given proximity to a target agent within an agent population. It takes two arguments: the agent target for which you want nearby neighbors and a distance. All agents within the agent population within the specified distance to the target agent will be returned as a vector.

It is useful now to introduce a concept that will be very helpful to you. When used in an Agent, Self always refers to the agent itself. If you have a primitive within an agent, Self can be used from that primitive to get a reference to the agent containing the primitive. So the following equation in an agent will return a vector of agents that are within 15 miles of the agent itself:

`[Population].FindNearby(Self, {15 Miles})`

Two other useful functions for finding agents in spatial relation to each other are FindNearest() and FindFurthest(). FindNearest returns the nearest agent to the target in a population while FindFurthest returns the agent that is farthest away from it. Each of them also supports an optional second argument determining how many nearby (or far away) agents to return (this optional argument defaults to one when omitted).

For example, the following equation finds the nearest agent to the current agent:

`[Population].FindNearest(Self)`

While this finds the three agents that are furthest from the current agent:

`[Population].FindFurthest(Self, 3)`

## Movement Functions

You can also move agents to new locations during simulation. To do this, it is helpful to introduce a new primitive we have not yet discussed. This primitive is the Action primitive. Action primitives are designed to execute some action that changes the state of your model. For instance, they can be used to move agents or change the values of the primitives within an agent. An action is triggered in the same way a transition is triggered. Like a transition, there are three possible methods of triggering the action: timeout, probability, and condition.

For instance, we can use an action primitive in an agent and the Move() function to make agents move during the simulation. The Move function takes one argument: a vector containing the x- and y-distances to move the agent. Thus, we could place an action primitive in our agent and give it the following action property to make the agent move randomly over time. The equation will move the agent a random distance between -0.5 and 0.5 units in the x-direction and a random distance between -0.5 and 0.5 units in the y-direction.

`Self.Move({rand(), rand()} - 0.5)`

Another useful movement function is the MoveTowards() function. MoveTowards moves an agent towards (or away from) the location of another agent. MoveTowards takes two arguments: the target agent to move towards and how far to move towards that agent (with negative values indicating movement away). The following command would move an agent one meter closer to its nearest neighbor in the population.

`Self.MoveTowards([Population].FindNearest(Self), {1 Meter})`