Skip to main content

Territories

|

The Territory class enables users to manage geographical areas within the VRP system. Territories are used to define service areas, organize operations, and manage orders within specific regions. This API provides endpoints to:

  • Add new territories to the system.
  • Retrieve and update territory details such as name, type, and geographical data.
  • Delete territories when they are no longer needed.
  • Generate territories dynamically based on provided coordinates.
  • Retrieve orders inside the territory, then those orders can be used to create a new optimization.

Territory Structure

Each territory object consists of the following attributes:

NameTypeDescriptionSetterGetter
IdLargeIntegerUnique identifier for the territory.
NameStringName of the territory.
TypeETerritoryType

Type of the territory
Possible values:
TT_Polygo (0): Territory is polygon shape.
TT_Circle (1): Territory is circle shape.
TT_Rectangle (2): Territory is rectangle shape

DataDoubleListList

Data defining the territory shape.
Details:
• Circle: center and a point on the circle.
• Rectangle: two diagonally opposite points.
• Polygon: all its points.

ColorRgbaColor of the territory.
OrdersOrderListList of orders located inside the territory.

Managing Territories

Creating a Territory

Territories must be created before they can be used for optimizations.

Note

If the operation is successful, the territory will have an id assigned; which can be retrieved using the method territory.getId().

How it works

  1. Create a vrp::Territory and set the name, type (Circle, in this case), color and data. The data must contain the center's coordinates and the radius.
  2. Create a ProgressListener and vrp::Service.
  3. Call the addTerritory() method from the vrp::Service using the vrp::Territory and ProgressListener and wait for the operation to be done.

Example

// Create a Territory object and set its properties
gem::vrp::Territory territory;
territory.setName("Delivery Zone 1");
territory.setType(gem::vrp::ETerritoryType::TT_Circle);
territory.setColor(gem::Rgba(255, 42, 0, 1));

gem::DoubleListList data;
gem::DoubleList center = { 46.603125, 0.354550 };
gem::DoubleList radius = { 46.593494, 0.376579 };
data.push_back(center);
data.push_back(radius);
territory.setData(data);

// Initialize Service and Listener
ProgressListener listener;
gem::vrp::Service service;

// Call the addTerritory method
int res = service.addTerritory(&listener, territory);

if (res == gem::KNoError)
{
// Wait for completion
WAIT_UNTIL(std::bind(&ProgressListener::IsFinished, &listener), 5000);

// Check operation success
if (listener.IsFinished() && listener.GetError() == gem::KNoError)
std::cout << "Territory added successfully. ID: " << territory.getId() << std::endl;
else
std::cout << "Failed to add territory: Operation timed out or server returned an error." << std::endl;
}
else
std::cout << "Failed to send addTerritory request." << std::endl;

Retrieving Territories

There are two ways to retrieve territory data:

a) Get a Territory by ID

Get a certain territory.

How it works

  1. Create a ProgressListener, a vrp::Service and a vrp::Territory.
  2. Call the getTerritory() method from the vrp::Service using the vrp::Territory from 1.), the ID of the territory that you want to retrieve and the ProgressListener.
  3. Once the operation completes, the vrp::Territory from 1.) will be populated.
// Retrieve a specific territory by id
ProgressListener listener;
gem::vrp::Service service;

gem::vrp::Territory territory;
LargeInteger territoryId = 0; // Set your territory id
int res = service.getTerritory(listener, territory, territoryId);

if (res == gem::KNoError)
{
WAIT_UNTIL(std::bind(&ProgressListener::IsFinished, &listener), 5000);
if (listener.IsFinished() && listener.GetError() == gem::KNoError)
std::cout << "Territory returned successfully" << std::endl;
else
std::cout << "Failed to retrive territory: Operation timed out or server returned an error." << std::endl;
}
else
std::cout << "Failed to send getTerritory request." << std::endl;

b) Get All Territories (with optional filtering)

Returns all territories of the API user (which contain the search term).

How it works

  1. Create a ProgressListener, a vrp::Service and a vrp::TerritoryList.
  2. Call the getAllTerritories() method from the vrp::Service using the list from 1.) and the ProgressListener.
  3. Once the operation completes, the list from 1.) will be populated.
// Retrieve all territories
ProgressListener listener;
gem::vrp::Service service;

gem::vrp::TerritoryList territories;
gem::String searchTerm = "North";
int res = service.getTerritories(listener, territories, searchTerm);

if (res == gem::KNoError)
{
WAIT_UNTIL(std::bind(&ProgressListener::IsFinished, &listener), 20000);
if (listener.IsFinished() && listener.GetError() == gem::KNoError)
std::cout << territories.size() << " territories returned successfully" << std::endl;
else
std::cout << "Failed to retrive territories: Operation timed out or server returned an error." << std::endl;
}
else
std::cout << "Failed to send getTerritories request." << std::endl;

Updating a Territory

Territories can be updated with new names, types, or geographical data.

note

If the shape or the size of the territory is updated, then the list of orders that are inside the territory was also updated. You can access it using the method territory.getOrders().

How it works

  1. Create a ProgressListener and a vrp::Service.
  2. Retrieve the territory you want to update (see Get Territory) in a vrp::Territory.
  3. Change the desired fields of the vrp::Territory.
  4. Call the updateTerritory() method from the vrp::Service using the vrp::Territory from 2.) and the ProgressListener and wait for the operation to be done.

Example

// Retrieve an existing territory by id
ProgressListener listener;
gem::vrp::Service service;

gem::vrp::Territory territory;
LargeInteger territoryId = 0; // Set your territory id
int res = service.getTerritory(listener, territory, territoryId);
if (res == gem::KNoError)
{
WAIT_UNTIL(std::bind(&ProgressListener::IsFinished, &listener), 20000);

if(listener.IsFinished() && listener.GetError() == gem::KNoError)
{
// Update territory properties
territory.setName("Updated Delivery Zone");
territory.setType(gem::vrp::ETerritoryType::TT_Rectangle);
gem::DoubleListList newData;
gem::DoubleList corner1 = { 46.575722, 0.345311 };
gem::DoubleList corner2 = { 46.582438, 0.358969 };
newData.push_back(corner1);
newData.push_back(corner2);
territory.setData(newData);

// Save the updated details
res = service.updateTerritory(listener, territory);
if (res == gem::KNoError)
{
WAIT_UNTIL(std::bind(&ProgressListener::IsFinished, &listener), 5000);
if (listener.IsFinished() && listener.GetError() == gem::KNoError)
std::cout << "Territory updated successfully" << std::endl;
else
std::cout << "Failed to update territory: Operation timed out or server returned an error." << std::endl;
}
else
std::cout << "Failed to send updateTerritory request." << std::endl;
}
else
std::cout << "Failed to retrive territory: Operation timed out or server returned an error." << std::endl;
}
else
std::cout << "Failed to send getTerritory request." << std::endl;

Deleting a Territory

Territories can be deleted individually or in bulk.

How it works

  1. Create a ProgressListener and vrp::Service.
  2. Call the deleteTerritory() method from the vrp::Service using the territory's ID and ProgressListener and wait for the operation to be done.
ProgressListener listener;
gem::vrp::Service service;

// Remove multiple territories by IDs
LargeIntList territoriesToDelete = {111, 222, 333};
int res = service.deleteTerritory(listener, territoriesToDelete);
if (res == gem::KNoError)
{
WAIT_UNTIL(std::bind(&ProgressListener::IsFinished, &listener), 5000);

if (listener.IsFinished() && listener.GetError() == gem::KNoError)
std::cout << "Territory deleted successfully" << std::endl;
else
std::cout << "Failed to delete territory: Operation timed out or server returned an error." << std::endl;
}
else
std::cout << "Failed to send deleteTerritory request." << std::endl;

Retrieving Territory Orders

Returns all orders that are inside the territory with the ID sent from the user.

How it works

  1. Create a ProgressListener and vrp::Serviceand a vrp::OrderList in which the orders will be returned.
  2. Call the getTerritoriesOrders() method from vrp::Service and the ProgressListener. using the lists from .
  3. Once the operation completes, the list from 1.) will contain the orders that are inside territory.

Example

ProgressListener listener;
gem::vrp::Service service;

gem::LargeInteger territoryId = 0 // Set your territory id
gem::vrp::OrderList ordersInsideTerritory;

// Get orders inside territories
ret = m_service.getTerritoriesOrders(&m_listener, territoryId, ordersInsideTerritory);
if (res == gem::KNoError)
{
WAIT_UNTIL(gp::make_binder(m_listener, &MockProgressListener::IsFinished), 20000);

if (listener.IsFinished() && listener.GetError() == gem::KNoError && territories.size() == 3)
std::cout << "Orders retrived successfully" << std::endl;
else
std::cout << "Failed to retrive orders inside territories: Operation timed out or server returned an error." << std::endl;
}
else
std::cout << "Failed to send getTerritoriesOrders request." << std::endl;

Generating Territories

Generate territories based on a list of coordinates.

Note

To generate one territory, minimum 3 coordinates are needed; remember that the number of coordinates should be at least 3 times the number of territories that you want to create.If the number of territories to be created is not specified, the algorithm will determinate how many should be created.

How it works

  1. Create a CoordinatesList and add all the Coordinates.
  2. Create a ProgressListener, vrp::Service and vrp::Territorylist, in which the territories will be returned.
  3. Call the generateTerritories() method from vrp::Service using the lists from 2.) and 1., specify the number of territories that you want to create and the progress listener.
  4. Once the operation completes, the list from 2.) will contain the generated territories.

Example

gem::CoordinatesList coords = { gem::Coordinates(47.592266,8.089206), gem::Coordinates(48.568867,9.122461), gem::Coordinates(50.487137,14.161686),
gem::Coordinates(49.851322,20.489012), gem::Coordinates(49.471581,7.480935), gem::Coordinates(46.858112,21.328030),
gem::Coordinates(51.427933,9.794261), gem::Coordinates(46.602039,10.907111), gem::Coordinates(48.667385,17.154114),
gem::Coordinates(46.674530,25.333998), gem::Coordinates(48.248165,18.071995), gem::Coordinates(48.694458,19.731777) };

ProgressListener listener;
gem::vrp::Service service;
gem::vrp::TerritoryList territories;
int territoriesNumber = 3;
int res = service.generateTerritories(&listener, territories, coords, territoriesNumber); // To generate one territory minimum 3coordinates are needed, so to create 3 territories, coords's size should be at least 9
if (res == gem::KNoError)
{
WAIT_UNTIL(std::bind(&ProgressListener::IsFinished, &listener), 10000);
if (listener.IsFinished() && listener.GetError() == gem::KNoError && territories.size() == 3)
std::cout << "Territories generated successfully" << std::endl;
else
std::cout << "Failed to generate territories: Operation timed out or server returned an error." << std::endl;
}
else
std::cout << "Failed to send generateTerritories request." << std::endl;

Error Handling

This API returns specific error codes to indicate potential issues. Below is a summary of common errors and how to resolve them:

Error CodeDescriptionSolution
KInvalidInputMissing required fields or invalid territory data.Ensure all mandatory fields are properly filled.
KNotFoundThe specified territory ID does not exist.Verify that the correct territory ID is provided.
KInternalAbortServer-side issue or unexpected parsing error.Retry the request or check API status.