Use Cases

This section provides examples for common spatial indexing scenarios.

Store Locator

Find the nearest stores, restaurants, or service points to a customer’s location.

public class Store
{
    private long   id       ;
    private String name     ;
    private String address  ;
    private double latitude ;
    private double longitude;

    // constructors, getters ...
}

public class StoreLocationIndex extends SpatialIndexer.Abstract<Store>
{
    @Override
    protected Double getLatitude(final Store entity)
    {
        return entity.getLatitude();
    }

    @Override
    protected Double getLongitude(final Store entity)
    {
        return entity.getLongitude();
    }
}
StoreLocationIndex storeLocation = new StoreLocationIndex();

GigaMap<Store> stores = GigaMap.<Store>Builder()
    .withBitmapIndex(storeLocation)
    .build();

// Find stores within 25km of the customer
List<Store> nearbyStores = stores.query(storeLocation.near(48.1351, 11.5820, 25.0))
    .stream()
    .toList();

For exact circular distance filtering, combine the bounding box query with a post-filter.

// Bounding box approximation + exact Haversine filtering
List<Store> exactNearby = stores.query(storeLocation.near(48.1351, 11.5820, 25.0))
    .stream()
    .filter(storeLocation.withinRadius(48.1351, 11.5820, 25.0))
    .toList();

Regional Data Analysis

Analyze data within geographic regions such as countries, states, or custom areas.

public class SalesRecord
{
    private long    id       ;
    private double  amount   ;
    private String  product  ;
    private double  latitude ;
    private double  longitude;

    // constructors, getters ...
}

public class SalesLocationIndex extends SpatialIndexer.Abstract<SalesRecord>
{
    @Override
    protected Double getLatitude(final SalesRecord entity)
    {
        return entity.getLatitude();
    }

    @Override
    protected Double getLongitude(final SalesRecord entity)
    {
        return entity.getLongitude();
    }
}
SalesLocationIndex salesLocation = new SalesLocationIndex();

GigaMap<SalesRecord> sales = GigaMap.<SalesRecord>Builder()
    .withBitmapIndex(salesLocation)
    .build();

// Sales in Central Europe (approximate bounding box)
long europeanSales = sales.query(salesLocation.withinBox(47.0, 55.0, 5.0, 15.0)).count();

// Sales in the southern hemisphere
long southernSales = sales.query(salesLocation.latitudeBelow(0.0)).count();

// Sales in the western hemisphere
long westernSales = sales.query(salesLocation.longitudeBelow(0.0)).count();

Fleet Tracking

Track and query vehicle positions in a delivery or logistics system.

public class Vehicle
{
    private String id             ;
    private String type           ;
    private double lastLatitude   ;
    private double lastLongitude  ;

    // constructors, getters ...
}

public class VehiclePositionIndex extends SpatialIndexer.Abstract<Vehicle>
{
    @Override
    protected Double getLatitude(final Vehicle entity)
    {
        return entity.getLastLatitude();
    }

    @Override
    protected Double getLongitude(final Vehicle entity)
    {
        return entity.getLastLongitude();
    }
}
VehiclePositionIndex vehiclePosition = new VehiclePositionIndex();

GigaMap<Vehicle> vehicles = GigaMap.<Vehicle>Builder()
    .withBitmapIndex(vehiclePosition)
    .build();

// Find all vehicles within 5km of the warehouse
List<Vehicle> nearWarehouse = vehicles.query(
    vehiclePosition.near(52.5200, 13.4050, 5.0)
).stream().toList();

// Find vehicles in the delivery zone
List<Vehicle> inZone = vehicles.query(
    vehiclePosition.withinBox(52.4, 52.6, 13.2, 13.6)
).stream().toList();

Search for properties within a map viewport or near a point of interest.

public class Property
{
    private long    id       ;
    private String  title    ;
    private double  price    ;
    private int     rooms    ;
    private double  latitude ;
    private double  longitude;

    // constructors, getters ...
}

public class PropertyLocationIndex extends SpatialIndexer.Abstract<Property>
{
    @Override
    protected Double getLatitude(final Property entity)
    {
        return entity.getLatitude();
    }

    @Override
    protected Double getLongitude(final Property entity)
    {
        return entity.getLongitude();
    }
}
PropertyLocationIndex propertyLocation = new PropertyLocationIndex();

GigaMap<Property> properties = GigaMap.<Property>Builder()
    .withBitmapIndex(propertyLocation)
    .build();

// Properties visible in map viewport
List<Property> visibleOnMap = properties.query(
    propertyLocation.withinBox(52.48, 52.56, 13.35, 13.45)
).stream().toList();

// Properties within walking distance of a subway station
List<Property> nearSubway = properties.query(
    propertyLocation.near(52.5200, 13.4050, 1.0)
).stream().toList();

Combining Spatial with Other Indices

Spatial conditions can be combined with other bitmap index conditions for filtered geographic queries.

public class Restaurant
{
    private long    id       ;
    private String  name     ;
    private String  cuisine  ;
    private int     rating   ;
    private double  latitude ;
    private double  longitude;

    // constructors, getters ...
}

// Define both spatial and regular indexers
RestaurantLocationIndex location = new RestaurantLocationIndex();
Indexer<Restaurant, String> cuisine = new Indexer.Abstract<>()
{
    @Override
    public Class<String> keyType()
    {
        return String.class;
    }

    @Override
    public String indexEntity(Restaurant entity)
    {
        return entity.getCuisine();
    }
};
GigaMap<Restaurant> restaurants = GigaMap.<Restaurant>Builder()
    .withBitmapIndex(location)
    .withBitmapIndex(cuisine)
    .build();

// Italian restaurants within 5km
List<Restaurant> nearbyItalian = restaurants.query(
    location.near(48.1351, 11.5820, 5.0)
        .and(cuisine.is("Italian"))
).stream().toList();

Distance Calculation

Use the static haversineDistance method to calculate great-circle distances between two geographic points.

// Distance from New York to London in kilometers
double distance = SpatialIndexer.haversineDistance(
    40.7128, -74.0060,  // New York
    51.5074,  -0.1278   // London
);
// ~5570 km

This is useful for sorting results by distance or displaying distances in the UI.

double centerLat = 48.1351;
double centerLon = 11.5820;

List<Store> sortedByDistance = stores.query(storeLocation.near(centerLat, centerLon, 50.0))
    .stream()
    .sorted(Comparator.comparingDouble(store ->
        SpatialIndexer.haversineDistance(
            centerLat, centerLon,
            store.getLatitude(), store.getLongitude()
        )
    ))
    .toList();