// Provide classes for simulating a mouse moving in a maze
//
// Copyright 2007 John L Baker. All rights reserved.
//
// This software is provided AS IS under the terms of the Open Source
// MIT License. See http://www.opensource.org/licenses/mit-license.php.
//
// Release: 1.0.0
// Author: John Baker
// Updated: 14 July 2006
//
// File: maze_baker_2003.h
//
// Description:
//
// This header declares classes used to define an environment such a Morris
// Water Maze, though not limited to that specific form of maze. A basic
// definition for associated landmarks, such as might be used for navigation,
// is also provided.
//
// A specific maze of interest is circular with landmarks arranged around the
// periphery. Landmarks are specified by their location in a two dimensional
// space. Each landmark is identified through a group of unspecified "features" which
// can be matched with varying degrees of selectivity through a vector dot product.
//
// References:
//
// O'Keefe J, Burgess N (1996) Geometric determinants of the place fields
// of hippocampal neurons. Nature 381: 425-428.
//
// Hartley T, Burgess N, Lever C, Cacucci F, O'Keefe J (2000) Modeling
// place fields in terms of the cortical inputs to the hippocampus.
// Hippocampus 10: 369-379.
namespace BAKER_2003 {
class Landmark;
class Maze;
class CircularMaze;
}
// --------------------------------------------------------------------
// Only include the definitions in this header once
// --------------------------------------------------------------------
#ifndef __MAZE_BAKER_2003_H_
#define __MAZE_BAKER_2003_H_
// --------------------------------------------------------------------
// MICROSOFT SPECIFIC DECLARATIONS
// --------------------------------------------------------------------
#ifdef WIN32
// Disable warning C4786: symbol greater than 255 character,
#pragma warning( disable: 4786)
#endif
// --------------------------------------------------------------------
// END OF MICROSOFT SPECIFIC DECLARATIONS
// --------------------------------------------------------------------
#include "bnsf.h"
using namespace std;
using namespace BNSF;
// Declare a namespace so that different models
// can be intermixed in the same simulation
namespace BAKER_2003 {
// ----------------------------------------------------------------
// Prototype declarations to allow forward references.
// See below for descriptions of the individual classes.
// ----------------------------------------------------------------
class Landmark;
class Maze;
class CircularMaze;
class RectangularMaze;
class SpatialRegion;
class RectangularRegion;
class CircularRegion;
// ----------------------------------------------------------------
// Vector and iterator typedefs for classes used here.
// Note that by convention pointers are stored in
// vectors so this info is not in the typedef name.
// ----------------------------------------------------------------
typedef vector<Landmark*> LandmarkVector;
typedef LandmarkVector::iterator LandmarkVectorIt;
// ---------------------------------------------------
// CLASS: Landmark
// EXTENDS: none
// DESC: Store information relating to a landmark
// including location and visible features.
// RESP:
// 1. Store landmark location (world coordinates)
// 2. Store category
// 3. Store feature scores.
//
// NOTES: Category is an arbitrary categorization that
// can be supplied for the landmark. Similarly,
// the content of features is not defined except
// by how the values are used outside of this class.
// ---------------------------------------------------
class Landmark {
public:
// Constructors and destructor
Landmark(); // Empty constructor
Landmark(Landmark& lm); // Copy constructor
Landmark( // Alternate constructor
Number x, // Location x coord
Number y, // Location y coord
int cat, // Category
int numFeatEnt, // Number of feature entries
Number features[]); // Feature vector
virtual ~Landmark();
// Accessors
inline Number locX() { return _locX; }
virtual void locX(Number x) { _locX = x; }
inline Number locY() { return _locY; }
virtual void locY(Number y) { _locY = y; }
inline int category() { return _category; }
virtual void category(int cat) { _category = cat; }
inline NumberArray features() { return _features; }
virtual void features(NumberArray fv) { _features = fv; }
protected:
Number _locX; // location x coord
Number _locY; // location y coord
int _category; // category designation
NumberArray _features; // feature values
};
// ---------------------------------------------------
// CLASS: Maze
// EXTENDS: none
// DESC: Abstract class for representing mazes.
// RESP:
// 1. Store maze overall size and origin location.
// 2. Store associated distal landmarks.
//
// NOTES: Subclasses must provide functions for locating
// walls. Absolute angles are measured in a counterclockwise
// direction using a 0 degree orientation along the
// X axis.
//
// Landmark objects are copied when added to the maze.
// Hence the contents of a given landmark can only be
// changed by accessing the landmarks vector directly.
//
// A local coordinate system is imposed to allow some
// generality of maze geometry. Local coordinates do not
// necessarily define a unique location in the world
// coordinate system, but should correspond with the
// type of measurements an animal might make to estimate
// position within the maze, at least locally.
// ---------------------------------------------------
class Maze {
public:
// Constructor and destructor
Maze();
virtual ~Maze();
// Accessors
inline Number originX() { return _originX; }
virtual void originX(Number x) { _originX = x; }
inline Number originY() { return _originY; }
virtual void originY(Number y) { _originY = y; }
inline LandmarkVector& landmarks() { return _landmarks; }
// Add a landmark to the existing set copying from the landmark provided
virtual void add(Landmark* lm);
// Utility functions (may be overridden in subclasses) --------
// Return true if the indicated location is inside the maze.
// Subclasses may want to override a more efficient implementation.
virtual bool isInsideMaze(Number locX, Number locY);
// Select a point at random from inside the maze, as might
// be used to generate place fields. The default method
// assumes that the extent of the maze is plus/minus
// size() in both X and Y coordinates. Output is placed in
// x and y. If the source of random numbers is null,
// the default UniformRandom generator is used.
virtual void randomPointInMaze(
Number& x, // X coordinate value (output)
Number& y, // Y coordinate value (output)
UniformRandom* unif=NULL); // Source of random numbers
// Return a location in local coordinates. These are distance measures
// in different directions as appropriate for this location in the maze.
// By default, distances are returned using the directios north, south,
// east, and west corresponding to vectors as rotated by the local orientation.
virtual void localCoordinates(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number& northDist, // Boundary dist along (0,1)
Number& southDist, // Boundary dist along (0,-1)
Number& eastDist, // Boundary dist along (1,0)
Number& westDist); // Boundary dist along (-1,0)
// Subclass responsibilities ----------------------------------
// Return the overall size of the maze
virtual Number size() = 0;
// Return the approximate area of the maze
virtual Number area() { return 4*size()*size(); } // default only
// Provide a heading defined by local conditions in the maze such as
// the direction of the nearest boundary point. The purpose is to provide
// an orientation for a local coordinate system for this part of the maze.
// Default is a constant vector (1,0). Subclass should override as needed.
virtual void localOrientation(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number& hx, // Unit vector x coord (output)
Number& hy); // Unit vector y coord (output)
// Provide minimum distance to the maze wall from a given location.
// Return a negative value if the current location is outside the maze.
virtual Number boundaryDistance(
Number locX, // Current location X coord
Number locY) = 0; // Current location Y coord
// Provide the distance from maze wall along a unit vector.
// Return a negative value if the current location is outside the maze.
virtual Number boundaryDistance(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number hx, // Unit vector x coord
Number hy) = 0; // Unit vector y coord
protected:
Number _originX; // Maze origin X coord
Number _originY; // Maze origin Y coord
LandmarkVector _landmarks; // Distal landmarks
};
// ---------------------------------------------------
// CLASS: CircularMaze
// EXTENDS: Maze
// DESC: Define a circular maze (ala Water Maze).
// RESP:
// 1. Compute distance to walls in a circle.
//
// NOTE: Origin of maze is the center. If location is
// outside the circle, distance to wall is negative.
// ---------------------------------------------------
class CircularMaze : public Maze {
public:
// Constructor and destructor
CircularMaze(
Number radius=25*UOM::cm, // radius of the circle
Number originX=0, // origin X coord
Number originY=0); // origin Y coord
virtual ~CircularMaze();
// Accessors
inline Number radius() { return _radius; }
virtual void radius(Number r) { _radius = r; }
virtual Number size() { return _radius; }
// Return the area of the maze
virtual Number area() { return Pi*radius()*radius(); }
// Provide a heading defined by local conditions in the maze.
// Value returned is orientation towards nearest boundary point.
virtual void localOrientation(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number& hx, // Unit vector x coord (output)
Number& hy); // Unit vector y coord (output)
// Return a location in local coordinates. These are distance measures
// in different directions as appropriate for this location in the maze.
// By default, distances are returned using the local orientation in
// north, south, east, and west corresponding to vectors as rotated by
// the local orientation.
virtual void localCoordinates(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number& northDist, // Boundary dist along (0,1)
Number& southDist, // Boundary dist along (0,-1)
Number& eastDist, // Boundary dist along (1,0)
Number& westDist); // Boundary dist along (-1,0)
// Provide minimum distance to the maze wall from a given location.
// Return a negative value if the current location is outside the maze.
virtual Number boundaryDistance(
Number locX, // Current location X coord
Number locY); // Current location Y coord
// Provide the distance from maze wall along a unit vector.
// Return a negative value if the current location is outside the maze.
virtual Number boundaryDistance(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number hx, // Unit vector x coord
Number hy); // Unit vector y coord
protected:
Number _radius;
};
// ---------------------------------------------------
// CLASS: RectangularMaze
// EXTENDS: Maze
// DESC: Define a rectangular maze.
// RESP:
// 1. Compute distance to walls in a rectangle.
//
// ---------------------------------------------------
class RectangularMaze : public Maze {
public:
// Constructor and destructor
RectangularMaze(
Number sizeX=25*UOM::cm, // +/- size in X direction
Number sizeY=25*UOM::cm, // +/- size in Y direction
Number originX=0, // origin X coord
Number originY=0); // origin Y coord
virtual ~RectangularMaze();
// Accessors
inline Number sizeX() { return _sizeX; }
virtual void sizeX(Number s) { _sizeX = s; }
inline Number sizeY() { return _sizeY; }
virtual void sizeY(Number s) { _sizeY = s; }
// Get the overall size of the maze
virtual Number size() { return maxval(sizeX(), sizeY()); }
// Return the area of the maze
virtual Number area() { return 4*sizeX()*sizeY(); }
// Provide a heading defined by local conditions in the maze.
// Value returned is orientation towards nearest boundary point.
virtual void localOrientation(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number& hx, // Unit vector x coord (output)
Number& hy); // Unit vector y coord (output)
// Return a location in local coordinates. These are distance measures
// in different directions as appropriate for this location in the maze.
// By default, distances are returned using the local orientation in
// north, south, east, and west corresponding to vectors as rotated by
// the local orientation.
virtual void localCoordinates(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number& northDist, // Boundary dist along (0,1)
Number& southDist, // Boundary dist along (0,-1)
Number& eastDist, // Boundary dist along (1,0)
Number& westDist); // Boundary dist along (-1,0)
// Provide minimum distance to the maze wall from a given location.
// Return a negative value if the current location is outside the maze.
virtual Number boundaryDistance(
Number locX, // Current location X coord
Number locY); // Current location Y coord
// Provide the distance from maze wall along a unit vector.
// Return a negative value if the current location is outside the maze.
virtual Number boundaryDistance(
Number locX, // Current location X coord
Number locY, // Current location Y coord
Number hx, // Unit vector x coord
Number hy); // Unit vector y coord
protected:
Number _sizeX; // size in x direction
Number _sizeY; // size in y direction
};
// ---------------------------------------------------
// CLASS: SpatialRegion
// EXTENDS: none
// DESC: Abstract class to define a region of space
// RESP:
// 1. Given a point determine if the point is
// in this region of space (via subclass).
// 2. Provide the bounding box, i.e. max and
// min X and Y coordinates for the region.
//
// NOTE: A typical use of this hierarchy is to
// differentiate regions within a maze.
// ---------------------------------------------------
class SpatialRegion {
public:
// Constructor and destructor
SpatialRegion() {}
virtual ~SpatialRegion() {}
// Subclass responsibilities ----------------------------------
// Get the bounding box of the region
virtual void getBoundingBox(
Number& xmin,
Number& xmax,
Number& ymin,
Number& ymax) = 0;
// Return true if the point supplied is in the region
virtual bool containsPoint(
Number x,
Number y) = 0;
};
// ---------------------------------------------------
// CLASS: RectangularRegion
// EXTENDS: SpatialRegion
// DESC: Defines a rectangular region
// RESP:
// 1. Given a point determine if the point is
// in this region of space (via subclass).
// 2. Provide the bounding box, i.e. max and
// min X and Y coordinates for the region.
// ---------------------------------------------------
class RectangularRegion : public SpatialRegion {
public:
// Constructor and destructor
RectangularRegion(
Number xmin=0,
Number xmax=0,
Number ymin=0,
Number ymax=0);
virtual ~RectangularRegion();
// Get the bounding box of the region
virtual void getBoundingBox(
Number& xmin,
Number& xmax,
Number& ymin,
Number& ymax);
// Set the bounding box of the region
virtual void setBoundingBox(
Number xmin,
Number xmax,
Number ymin,
Number ymax);
// Return true if the point supplied is in the region
virtual bool containsPoint(
Number x,
Number y);
protected:
Number _xmin;
Number _xmax;
Number _ymin;
Number _ymax;
};
// ---------------------------------------------------
// CLASS: CircularRegion
// EXTENDS: SpatialRegion
// DESC: Defines a circular region
// RESP:
// 1. Given a point determine if the point is
// in this region of space (via subclass).
// 2. Provide the bounding box, i.e. max and
// min X and Y coordinates for the region.
// ---------------------------------------------------
class CircularRegion : public SpatialRegion {
public:
// Constructor and destructor
CircularRegion(
Number xctr=0,
Number yctr=0,
Number r=0);
virtual ~CircularRegion();
// Parameter accessors
inline Number centerX() { return _centerX; }
virtual void centerX(Number x) { _centerX = x; }
inline Number centerY() { return _centerY; }
virtual void centerY(Number y) { _centerY = y; }
inline Number radius() { return _radius; }
virtual void radius(Number x) { _radius = x; }
// Get the bounding box of the region
virtual void getBoundingBox(
Number& xmin,
Number& xmax,
Number& ymin,
Number& ymax);
// Return true if the point supplied is in the region
virtual bool containsPoint(
Number x,
Number y);
protected:
Number _centerX;
Number _centerY;
Number _radius;
};
};
#endif // #ifndef