Displaying and selecting Pins
Displaying point data and points of interest on the map
Displaying and selecting Pins
One of the common requirements for geo-Apps is the display of point data within the 3D world. Typical use cases are displaying Pins for Points Of Interest (POIs) or search results. This requirement is often coupled with a requirement for users to be able to select Pins in order to reveal related detailed data about each Pin.
The Platform provides facilities for rendering point data as pins within the 3D world. The set of classes providing these facilities are containined in the Eegeo::Pins namespace.
In this section:
Pin Data Model
What’s in a Pin?
In order to display Pins in the world we need an underlying model of the data associated with a single Pin. This is provided by the Eegeo::Pins::Pin class. It should be noted that this class is intended as a model in the model-view-controller sense, and consequently should not deal with display concerns, only the modelling of the underlying pin data.
The key attributes of this class are as follows:
- A unique, integer identifier (ID). The application is free to define these IDs as it likes, providing that the values it supplies are unique for each Pin.
- The location of the Pin on the geoid (Earth Sphere) as specified by a WGS84 latitude/longitude pair.
- The Pin’s height above the terrain in metres.
- An application provided, integer category ID. It is common for applications to map this category ID to different icons. For instance, Pins in the “Coffee Shops” category might be displayed with one icon while Pins in the “Museums” category are displayed with a different icon.
- An optional item of “user data” which is defined and specified by the application.
It is expected that applications will create specialisations (sub-classes) of the Pin class in order to extend the set of data associated with each Pin. For instance a photo viewing application might extend Pin into with the URL of a photo image to form a sub-class named PhotoPin.
Pin objects are constructed as follows:
// Assign a unique ID for the Pin.
Eegeo::Pins::TPinId myPinId = 99;
// Specify the location of the Pin on the geoid (Earth Sphere).
Eegeo::Space::LatLong myPinLocation = Eegeo::Space::LatLong::FromDegrees(37.7858,-122.401);
// Specify a category for the Pin.
int myPinCategory = 45;
// The height of Pin above the terrain metres.
float heightAboveTerrainInMetres = 5;
// Create the Pin.
Eegeo::Pins::Pin* pMyPin = Eegeo_NEW(Eegeo::Pins::Pin)(myPinId, myPinLocation, heightAboveTerrainInMetres, myPinCategory);
Typically an application will maintain a “working set” of Pins that is related to either the user’s current location in the world or to the last query that the application performed against a source of pin data (typically a web service).
The Eegeo::Pins::PinRepository class provides applications with a mechanism for managing this collection of Pins and for receiving notifications when its contents change.”
The following example shows a PinRepository can be created and populated with Pins.
// Create a new, empty PinRepository.
Eegeo::Pins::PinRepository* pRepository = Eegeo_NEW(Eegeo::Pins::PinRepository)();
// Now add a Pin to the repository.
// The repository enforces the constraints that each Pin can only appear in the repository once and that each Pin in the repository has a unique ID.
// Retrieve a Pin by its index in the repository.
Eegeo::Pins::Pin* pMyPinAgain = pRepository->GetPinByIndex(0);
// Find a Pin by ID and then remove it.
Eegeo::Pins::Pin* pFoundPin = pRepository->GetPinById(99);
if(pFoundPin != NULL)
Observing the repository
PinRepository allows provides a mechanism for objects to be notified when a Pin is either added or removed from the repository. In order to receive these notifications the application must create a class which implements Eegeo::Pins::IPinObserver
interface and register an instance of that class with the repository. This is demonstrated in the following example:
// Create a class to observe the repository, implmenting IPinObserver.
class MyObserver : public Eegeo::Pins::IPinObserver
virtual void OnPinAdded(Pin& pin)
Eegeo_TTY("Pin with ID=%d has been added to the repository.\n", pin.GetId());
virtual void OnPinRemoved(Pin& pin)
Eegeo_TTY("Pin with ID=%d has been removed from the repository.\n", pin.GetId());
// Create an instance of the observer.
MyObserver* pObserver = Eegeo_NEW(MyObserver)();
// Register the observer with the repository.
// pObserver will now receive notifications for all calls to AddPin() and RemovePin() on the repository.
N.B. The Platform provided PinController class makes use of this observation feature to create and destory the views associated with Pins as they are added and removed from the repository.
While the set of Pin rendering and display components provided by the Platform is intended to be fine-grained and customisable by applications, it also provides a default configuration of Pin rendering that is adequate for many use-cases. By using this configuration in the Eegeo::Pins::PinsModule class you can get Pin display and selection up and running in your application quickly and then delve into the details later if you want to customise the behaviour or display of pins.
The default configuration implemented by PinsModule provides the following features:
- Displaying Pins contained in a PinRepository as sprites. These sprites are positioned such that the Pin’s location lies in centre of the bottom edge of the sprite.
- Mapping of Pin categories to different icons, stored in a single texture page. The mapping is such that category 0 maps to tile 0 in the texture page.
- Placing Pins relative to the height of the terrain lying beneath them.
- Mapping of Pins to their on-screen bounds.
- Testing the screen bounds of a Pin for selection purposes.
Examples of usage
You can find the default configuration of Pin rendering in the Eegeo::Pins::PinsModule class and examples of how it can be used to display and select Pins in the following examples.
- Find the example application at https://github.com/eegeo/mobile-sdk-harness/blob/master/src/Examples/Pins/PinsExample.cpp
What does the application need to provide?
You’ll see from the examples that the application needs to provide the 3 key pieces of information to PinsModule:
- The texture id of the texture containing the icon images that will be displayed for the various categories.
- The layout of the individual icon tiles within the texture page. That is, which icon appears where in the texture page.
- The dimensions of the sprites to be displayed for each Pin.
Icon texture images
The texture containing the icon images can be loaded using an ITextureFileLoader as shown in the examples. It is worth noting that if the texture contains varying levels of alpha as in the examples, then it should be loaded from a PNG file as this format allows different alpha values to be stored.
The layout of the texture page bears some explanation. The examples use a regular grid texture layout, as follows:
Where the number on the icon denotes the tile index within the texture page. The application can vary the number of icons in the texture page by changing the numOfTilesInEachAxis parameter that is passed to the Eegeo::Rendering::RegularTextureLayout constructor. For instance for a texture page containing 3 x 3 = 9 icons, a value of 3 should be specified for this parameter.
Source code reference for customisation
The key components of the default configuration that are most likely to require customisation for a particular application are:
- Eegeo::Pins::PinsModule which creates/updates and destroys the various components used by the default configuration.
- Eegeo::Pins::PinController which handles the mapping of Pin data models in a repository to PinViews and the updating of those PinViews to reflect changes in the underlying model.
Both of these key components are provided in source code form so as to provide a reference for application developers wishing to customise pin behaviour and display.