Filtering - digitalcityscience/TOSCA-2 GitHub Wiki

Filtering & Data Processing

This project provides advanced filtering and data processing capabilities using GeoServer, Turf.js, and Pinia for managing filter states. Filters can be applied to vector layers and are integrated into the MapLibre map system.

Important Note on Function Documentation

Each function in the project is documented using TSDoc comments within its respective file. For detailed explanations of function parameters, return values, and usage, please refer directly to the corresponding source files in the project.

For example:

  • API functions → Check store/geoserver.ts and store/participation.ts.
  • Filtering functions → See components/Map/Layer/Filter/AttributeFiltering.vue and GeometryFiltering.vue.
  • State management functions → Refer to store/map.ts, store/filter.ts, etc.

For a complete breakdown of how each function works, refer to its respective TypeScript file and its TSDoc comments.

Technology Stack

  • GeoServer – Provides vector layers for filtering.
  • Turf.js – Performs geometric and spatial queries.
  • Pinia – Manages filtering state globally.

Filtering System Architecture

The filtering components are located in src/components/Map/Layer/Filter/ and handle different types of filtering.

📂 components
 ┣ 📂 Map            # Map-related components
 ┃ ┣ 📂 Layer        # Layer management and filtering
 ┃ ┃ ┣ 📂 Filter     # Filtering and query components
 ┃ ┃ ┃ ┣ 📜 AttributeFiltering.vue   # Attribute-based filtering
 ┃ ┃ ┃ ┣ 📜 GeometryFiltering.vue    # Geometry-based filtering

1. Attribute Filtering

AttributeFiltering.vue

Purpose:

  • Filters vector layers based on feature attributes.
  • Uses filter state to track applied attribute-based filters.

When to Use:

  • When users need to filter features by properties like category, type, or numeric values.

Implementation:

<template>
    <Card class="attribute-filtering w-full">
        <template #title>Attribute Filtering</template>
        <template #subtitle>Select an attribute and operand to filter this layer</template>
        <template #content>
            <div class="current-filters" v-if="filterStore.appliedFiltersList.find((listItem) => {
                return listItem.layerName === props.layer.id && ((listItem.attributeFilters !== undefined && listItem.attributeFilters?.length > 0) || listItem.geometryFilters !== undefined);
            })">
                <!-- Applied filters will be displayed here -->
            </div>
        </template>
    </Card>
</template>

2. Geometry Filtering

GeometryFiltering.vue

Purpose:

  • Filters features based on spatial relationships.
  • Uses Turf.js for spatial analysis and geometry processing.

When to Use:

  • When users need to filter features based on polygon geometries.

Implementation:

<template>
    <div class="geometry-filter w-full" v-if="(props.layer.filterLayer === undefined && isPolygonTiles)">
        <div class="new-filter w-full pt-2" v-if="!hasGeometryFilter">
            <Card>
                <template #title>Geometry Filtering</template>
                <template #subtitle>Select geometry layer to filter this layer</template>
                <template #content>
                    <div class="filterlayer-dropdown w-full">
                        <Dropdown class="w-full" v-model="selectedFilterLayer" @change="applyGeometryFilter" />
                    </div>
                </template>
            </Card>
        </div>
    </div>
</template>

3. Integration with State Management

Filtering state is stored in store/filter.ts and includes:

  • Applied attribute filters.
  • Active geometry filters.
  • Applied spatial queries using Turf.js.

Example Store Implementation:

import { defineStore } from "pinia";
import { ref } from "vue";
import { type MultiPolygon, type FeatureCollection } from "geojson";
import booleanWithin from "@turf/boolean-within";
import { useMapStore } from "./map";

export const useFilterStore = defineStore("filter", {
    state: () => ({
        appliedFiltersList: ref([]),
        selectedGeometry: ref<FeatureCollection<MultiPolygon> | null>(null),
    }),
    actions: {
        setAttributeFilter(filter) {
            this.appliedFiltersList.push(filter);
        },
        setGeometryFilter(geometry) {
            this.selectedGeometry = geometry;
        },
        applyGeometryFiltering() {
            // Uses Turf.js for spatial analysis
            const mapStore = useMapStore();
            if (this.selectedGeometry) {
                mapStore.applyGeometryFilter(this.selectedGeometry);
            }
        }
    }
});

Best Practices

  • Use Attribute Filtering for structured queries (e.g., filtering roads by type).
  • Use Geometry Filtering for spatial queries (e.g., finding buildings within a polygon selection).
  • Leverage Turf.js for efficient spatial operations.

For more details on working with filters, refer to the Map System documentation.

⚠️ **GitHub.com Fallback** ⚠️