Skip to main content

Areas Alarms

|

This example demonstrates how to monitor geographic areas and receive notifications when entering or exiting defined zones during navigation simulation.

Overview

The example demonstrates the following features:

  • Drawing circular geographic areas on the map using polygon markers
  • Calculating routes and displaying them on the map
  • Monitoring geographic areas with AlarmService
  • Receiving boundary crossing notifications during navigation simulation
  • Managing navigation lifecycle with start/stop controls

Code Implementation

Importing SDK Components

index.ts
import { 
GemKit,
GemMap,
Coordinates,
PositionService,
Landmark,
RoutePreferences,
RoutingService,
NavigationService,
GemError,
Marker,
MarkerCollection,
MarkerType,
MarkerCollectionRenderSettings,
AlarmService,
AlarmListener,
CircleGeographicArea,
TaskHandler,
Route,
Color
} from '@magiclane/maps-sdk';

Drawing Geographic Areas

index.ts
function onMapCreated(gemMap: GemMap) {
map = gemMap;

// Draw area on map
const marker = new Marker();
const circleAreaCoords = generateCircleCoordinates(
new Coordinates({ latitude: 50.92396, longitude: 9.54976 }),
200
);

circleAreaCoords.forEach(coord => marker.add(coord));

const markerCollection = MarkerCollection.create(
MarkerType.Polygon,
"Circle"
);
markerCollection.add(marker);

map.preferences.markers.add(
markerCollection, {
settings: new MarkerCollectionRenderSettings({
polygonFillColor: new Color(210, 104, 102, 111)
})}
);
}

// Method for generating coordinates in a circle shape
function generateCircleCoordinates(
center: Coordinates,
radiusMeters: number,
numberOfPoints = 36
): Coordinates[] {
const earthRadius = 6371000; // in meters
const centerLatRad = (center.latitude * Math.PI) / 180;
const centerLonRad = (center.longitude * Math.PI) / 180;

const coordinates: Coordinates[] = [];

for (let i = 0; i < numberOfPoints; i++) {
const angle = (2 * Math.PI * i) / numberOfPoints;
const deltaLat = (radiusMeters / earthRadius) * Math.cos(angle);
const deltaLon = (radiusMeters / (earthRadius * Math.cos(centerLatRad))) * Math.sin(angle);

const pointLat = ((centerLatRad + deltaLat) * 180) / Math.PI;
const pointLon = ((centerLonRad + deltaLon) * 180) / Math.PI;

coordinates.push(new Coordinates({ latitude: pointLat, longitude: pointLon }));
}

return coordinates;
}

Calculating Routes

index.ts
function onBuildRouteButtonPressed() {
// Define the departure
const departureLandmark = Landmark.withLatLng({
latitude: 50.92899490001731,
longitude: 9.544136681645025
});

// Define the destination
const destinationLandmark = Landmark.withLatLng({
latitude: 50.919902402432946,
longitude: 9.55855522546262
});

// Define the route preferences
const routePreferences = new RoutePreferences({});

// Calculate route
routingHandler = RoutingService.calculateRoute(
[departureLandmark, destinationLandmark],
routePreferences,
(err: GemError, routes: Route[]) => {
routingHandler = null;

if (err === GemError.success) {
const routesMap = map?.preferences.routes;

// Display the routes on map
routes.forEach((route, index) => {
routesMap?.add(route, index === 0); // First route is main
});

// Center the camera on routes
map?.centerOnRoutes({ routes });
}

areRoutesBuilt = true;
updateUI();
}
);
}

Monitoring Geographic Areas

index.ts
function startSimulation() {
const routes = map?.preferences.routes;
map?.preferences.routes.clearAllButMainRoute();

if (!routes?.mainRoute) {
showMessage("No main route available");
return;
}

// Register callback for area crossing
alarmListener = AlarmListener.create({
onBoundaryCrossed: (enteredAreas: string[], exitedAreas: string[]) => {
if (enteredAreas.length > 0) {
areaNotification = `Entered area: ${enteredAreas[0]}`;
} else {
areaNotification = `Exited area: ${exitedAreas[0]}`;
}
updateUI();
}
});

// Set the alarms service with the listener
alarmService = AlarmService.create(alarmListener);

alarmService.monitorArea(
new CircleGeographicArea({
radius: 200,
centerCoordinates: new Coordinates({ latitude: 50.92396, longitude: 9.54976 })
}),
"Test area"
);

navigationHandler = NavigationService.startSimulation(
routes.mainRoute,
undefined,
{
onNavigationInstruction: (instruction, events) => {
isSimulationActive = true;
updateUI();
},
onDestinationReached: (landmark) => {
stopSimulation();
cancelRoute();
},
onError: (error) => {
isSimulationActive = false;
areaNotification = null;
updateUI();
cancelRoute();

if (error !== GemError.cancel) {
stopSimulation();
}
}
}
);

// Set the camera to follow position
map?.startFollowingPosition({ zoomLevel: 70, viewAngle: 0 });
}

Managing Navigation State

index.ts
// Stop simulation
function stopSimulation() {
if (navigationHandler) {
NavigationService.cancelNavigation(navigationHandler);
navigationHandler = null;
}
areaNotification = null;
cancelRoute();
isSimulationActive = false;
updateUI();
}

// Cancel route
function cancelRoute() {
map?.preferences.routes.clear();

if (routingHandler) {
RoutingService.cancelRoute(routingHandler);
routingHandler = null;
}

areRoutesBuilt = false;
updateUI();
}

Live Demo

Key Features

  • Geographic Area Visualization: Display circular areas on the map using polygon markers with custom colors
  • Area Monitoring: Monitor when navigation crosses defined geographic boundaries
  • Boundary Notifications: Receive callbacks when entering or exiting monitored areas
  • Navigation Simulation: Simulate route navigation to test area alarm functionality
  • State Management: Track navigation and routing states with TaskHandler references

Explanation of Key Components

  • CircleGeographicArea: Defines a circular geographic zone with a center point and radius for monitoring
  • AlarmService: Service for monitoring geographic areas and triggering notifications
  • AlarmListener: Listener with onBoundaryCrossed callback that fires when boundaries are crossed
  • monitorArea(): Method to start monitoring a specific geographic area with an identifier
  • MarkerCollection: Collection of polygon markers used to visualize the geographic area on the map
  • generateCircleCoordinates(): Utility function that calculates polygon points to approximate a circle
  • NavigationService.startSimulation(): Starts simulated navigation along a route for testing area alarms
  • TaskHandler: Reference object used to cancel ongoing routing or navigation operations

Next Steps