CanvasMap
Getting Started Tutorials 3D Reference

Spatial Model Tutorials

This spatial model is an extension to CanvasMap and can simulate a variety of 2D and 3D phenomenon. The CMSpatialModel class will manage the user interface for you but you can always override classes in any of the classes to customize them as you desire.

The model works by first creating a map to work in and then adding layers for the types of data you want to include in your model. Below is a simple model to add 100 agents to a model with random placement and movement vectors between 0 and 20. Try changing the size of the map, number of individuals, and their velocity range to see how it impacts the movement of the animals.

function SetupModel(MySpatialModel,TheContainerElement)
{
MySpatialModel.Setup(1000,1000); // width, height in reference units

var TheAgents=MySpatialModel.AddAgentLayer(); // add the agent layer to the model

TheAgents.AddRandomInividuals(100,0,20); // add 100 individuals to the agent layer with velocities between 0 and 20
}

Examples

There are a series of examples available:

Below are tutorials based on some of the examples.

Flocking Model

Appearance

The agents are a little boring at this point so lets give them a color and create a polygon that defines their shape. We'll also change the name of the layer to "TheBirds". Your code should look similar to the code below but then try different colors and polygon shapes.

function SetupModel(MySpatialModel,TheContainerElement)
{
MySpatialModel.Setup(1000,1000); // width, height in reference units

var TheBirds=MySpatialModel.AddAgentLayer(); // add the agent layer to the model

TheBirds.AddRandomInividuals(100,0,20); // add 100 individuals to the agent layer with velocities between 0 and 20 TheBirds.SetSetting("Style","fillStyle","Red"); TheBirds.SetPolygon([[0,-10,0,10],[-5,5,0,5]]);
}

Position and Movement

CMLayerAgents maintains data for each agent in the attribute table for the layer. This includes an x,y (and z in 3D) values for the location of each agent. Addtional information is added as needed.

The attributes also include x and y components of velocity vectors. The velocity vectors determine the direction and speed of the agent. Movement of agents can change based on different types of forces that infulence the agents. These include:

Each of these types of forces can have the following settings:

Add the following code to the end of your function and you should see flocking behavior when you click "Start". Try changing the values of the properties to see the impact they have on flocking. Do not worry too much about breaking the model as you can always change the values back and refresh your browser (you can crash a browser with code like this but just close and reopen it and everything should be fine).

 // set the maximum speed for each bird
 TheBirds.SetSetting("Individuals","MaxSpeed",4);
 
 // save the force properties to make the birds flock
 var AlignmentProperties={
 Type:CMLayerAgents.MOVEMENT_ALIGNMENT,
 MaxSpeed:4,
 Distance:50,
 Force:40,
 }
 var CohesionProperties={
 Type:CMLayerAgents.MOVEMENT_COHESION,
 MaxSpeed:4,
 Distance:50,
 Force:40
 }
 var SeparationProperties={
 Type:CMLayerAgents.MOVEMENT_SEPARATION,
 MaxSpeed:4,
 Distance:25,
 Force:40,
 Factor:1.5
 }
 var RandomProperties={
 Type:CMLayerAgents.MOVEMENT_RANDOM,
 Force:0,
 }
 var PositionProperties=[AlignmentProperties,CohesionProperties,SeparationProperties,RandomProperties];
 TheBirds.SetPositionProperties(PositionProperties);

User Interface

We can add user interface controls and connect them to our model with just one line of code. Add the following lines of code to the end of your function. The first line just creates a slider that allows you to control the "MaxSpeed" setting for your agents. The other lines create sliders that will call a function when the user changes the value of the slider. The function at the end then changes the appropriate value in the properties.

 // create a slider for the maximum speed
 CMGUIUtil.SetupSettingSlider(TheContainerElement,TheBirds,"Individuals","MaxSpeed");
 
 // create sliders for the various properties
 CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Separation Force: ",0,100,SeparationProperties.Force,function(NewValue){ SeparationProperties.Force=NewValue; })
 CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Separation Distance: ",0,100,SeparationProperties.Distance,function(NewValue){ SeparationProperties.Distance=NewValue; })
 CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Cohesion Force: ",0,100,CohesionProperties.Force,function(NewValue){ CohesionProperties.Force=NewValue; })
 CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Cohesion Distance: ",0,100,CohesionProperties.Force,function(NewValue){ CohesionProperties.Distance=NewValue; })
 CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Alignment Force: ",0,100,AlignmentProperties.Force,function(NewValue){ AlignmentProperties.Force=NewValue; })
 CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Alignment Distance: ",0,100,AlignmentProperties.Force,function(NewValue){ AlignmentProperties.Distance=NewValue; })
 CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Random Force: ",0,100,RandomProperties.Force,function(NewValue){ RandomProperties.Force=NewValue; })
 

The CMGUIUtil.SetupSettingSlider() function can be used with any of the settings defined for the layer.

CMGUIUtil.SetupCallbackSlider() creates a slider that has a function attached to it that will be called when the slider value changes. The parameters for this function are listed in the reference section below.

Simple Predator/Prey Model

Movement is interesting but we also might want to model life stages and the resource requirements that animals have. To add this, we have taken the flocking sample from above and renamed "TheBirds" to "ThePrey" and saved it in a new file.

Life Stages

Animals go through life stages including being born, growing and dying. Below, we have defined three life stages for a prey animal.

	//****************************************************************
// setup life stages
var DeadStage={
Name:"Dead",
MarkType:CMMARK_TRIANGLE,
CyclesInStage:40,
NextStage:null,
MaxSpeed:0
};
var MatureStage={
Name:"Mature",
MarkType:CMMARK_CIRCLE,
CyclesInStage:100,
CyclesToRepoduce:40,
NextStage:DeadStage
};
var YoungStage={
Name:"Young",
MarkType:CMMARK_SQUARE,
CyclesInStage:40,
NextStage:MatureStage
};

var LifeStages=[YoungStage,MatureStage,DeadStage];
ThePrey.SetLifeStages(LifeStages);

The last stage in the life stages will always be "dead". This causes all movement and requirements consumption to stop.

Controls

We can add sliders for any of the numeric properties for our agents. Below is an exmaple for the number of cycles the agents spend in the mature life stage and for how many cycles it takes between the time they reproduce.

	CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Mature Cycles: ",0,100,MatureStage.CyclesInStage,function(NewValue){ MatureStage.CyclesInStage=NewValue; })
CMGUIUtil.SetupCallbackSlider(TheContainerElement,"Mature Cycles To Repoduce: ",0,100,MatureStage.CyclesToRepoduce,function(NewValue){ MatureStage.CyclesToRepoduce=NewValue; })

Cover

Animals need to feed on something so we are going to add a layer with grass for the animals to feed on. Add the code below to your file.

 //****************************************************************
   // the cover layer
   
   var LAND_COVER_ROCK=102;
   var LAND_COVER_WATER=101;
   
   TheLandCover=TheSpatialModel.AddCoverLayer(100,100);
 // setup our cover types 
     
   // grass pixels will go from 0% (bare ground) to 100% cover.
   var GrassType={
   Name:"Grass",
   Min:0,
   Max:100,
   MinColor:[255,255,255],
   MaxColor:[0,255,0],
   RecoveryPerCycle:1
   };
   // set the cover types into the layer
   var TheCoverTypes=[GrassType];
   
   TheLandCover.SetCoverTypes(TheCoverTypes);
   
   // setup the initial land cover spatial distribution
   TheLandCover.SetValue(99); // set all pixels to 100% grass

Requirements

Our prey animals need to feed on grass so we will add a requirement to them where they need to feed on grass or their "Food" setting will drop.

	//***************************************************************	// setup resource requirements
ThePrey.SetCover(TheLandCover);
var PreyGrassRequirements={
   Name:"Food",
   CoverType:GrassType,
   ChangePerCycle:-1,
   MaxAmountConsumed:10,
   ConversionFactor:1,
   Maximum:100,
   Min:1,
   Default:100
   };
   
   var PreyRequirements=[PreyGrassRequirements];
   ThePrey.SetRequirements(PreyRequirements);
 

We'll want to see how our grass is doing so let's add a chart showing the amount of grass available.

 	// add a chart to track the amount of grass available
TheSpatialModel.AddLabel(TheContainerElement,"Grass Cover");
TheSpatialModel.AddChart(TheContainerElement,TheLandCover,GrassType);

Predators

We add predators by just adding another agent layer. We'll want to give it different symbology so we can tell the difference between the prey and the predators. Add the code below and see how the predators move about the field.

var ThePredators=TheSpatialModel.AddAgentLayer();

ThePredators.SetSetting("Name","Predators");
ThePredators.AddRandomInividuals(10);
ThePredators.SetSetting("Style","fillStyle","Blue");
ThePredators.SetSetting("Mark","Size",20);
 

We can add a cohesive force to have the predators to move toward the prey. This is similar to the cohesion we used earilier except we've added a "Layer2" property to link the predators to the prey layer. We also add a random force so we can set it to 0 or increase it to add some randomness to the predator movement.

 var PredatorCohesionProperties={
 Type:CMLayerAgents.MOVEMENT_COHESION,
 MaxSpeed:4,
 Distance:500,
 MaxForce:5,
 Layer2:ThePrey
 }
 var PredatorRandomProperties={
 Type:CMLayerAgents.MOVEMENT_RANDOM,
 Force:0,
 }
 
 ThePredators.SetPositionProperties([PredatorCohesionProperties]);
 

When you add this, you may notice the predators can become a bit confused when they are equaldistance from their prey.

 

Reference

CMLayerAgents

This layer models agents which can be individuals or groups of individuals that move together. Each agent is modeled as a point.

AddRandomVelocityVectors=function(MinVelocity,MaxVelocity)

AddRandomInividuals=function(NumIndividuals,MinVelocity,MaxVelocity)

CMLayerAgents.prototype.SetCover=function(LandCover)

 

CMLayerAgents.prototype.SetPositionProperties=function(PositionProperties)

Requirements

Requirements are set by creating one or more JavaScirpt objects with the following entries and then calling SetRequirements() with an array containing the requirement objects.

SetRequirements=function([RequirementObject1,RequirementObject2])

CMGUIUtil

CMGUIUtil.SetupCallbackSlider(Label,Min,Max,CurrentValue,Function)