Skip to content

Software Development at Program Tom LTD

Place for coding, programming, development and software in general.

Menu
  • Blog
  • PDF Booklets
  • Dev Utils & Content
  • Java Spring Boot Or Web Apps
  • English
    • български
    • English
    • Español
    • Português
    • हिन्दी
    • Русский
    • Deutsch
    • Français
    • Italiano
    • العربية
  • About Us
Menu
Flutter a search for pins filter the not visible out

Flutter a search for pins filter the not visible out

Posted on August 19, 2025 by Toma Velev

To filter out pins that are not visible within the rectangular screen area in a Flutter application, you need to determine which pins from the circular search area (defined by a center latitude/longitude and maximum distance) fall within the rectangular bounds of the visible map area. Here’s a step-by-step approach to achieve this:

Steps to Filter Pins

  1. Understand the Input Data:
    • Circular Search Area: You have a list of pins within a circular area defined by a center point (latitude, longitude) and a maximum distance (radius, typically in meters or kilometers).
    • Rectangular Screen Area: The visible area on the screen is a rectangle, typically represented by the map’s viewport bounds (e.g., southwest and northeast corners in latitude/longitude).
  2. Get the Map’s Visible Bounds:
    • Use the map widget’s API (e.g., GoogleMap from the google_maps_flutter package) to obtain the visible region’s bounds.
    • The GoogleMapController provides a method like getVisibleRegion() that returns a LatLngBounds object, containing:
      • southwest: The bottom-left corner of the visible rectangle (minimum latitude, minimum longitude).
      • northeast: The top-right corner of the visible rectangle (maximum latitude, maximum longitude).
  3. Filter Pins Based on Rectangular Bounds:
    • For each pin in the list (from the circular search), check if its coordinates (latitude, longitude) lie within the rectangular bounds.
    • A pin is within the rectangle if:
      • Its latitude is between southwest.latitude and northeast.latitude.
      • Its longitude is between southwest.longitude and northeast.longitude.
  4. Handle Edge Cases:
    • Longitude Wrapping: If the map crosses the 180° meridian (e.g., near the International Date Line), the southwest.longitude may be greater than northeast.longitude. In this case, adjust the logic to handle the wrap-around (e.g., check if longitude lies outside the range or use modulo arithmetic).
    • Coordinate System: Ensure all coordinates are in the same format (degrees for latitude/longitude).
  5. Implementation in Flutter:
    • Assuming you’re using the google_maps_flutter package, here’s a sample code snippet to filter pins:
import 'package:google_maps_flutter/google_maps_flutter.dart';

// List of pins from circular search (e.g., from a backend API)
List<LatLng> pins = [
  LatLng(37.7749, -122.4194), // Example pin
  LatLng(37.7849, -122.4294),
  // Add more pins
];

// Function to filter pins within the visible rectangular bounds
List<LatLng> filterVisiblePins(LatLngBounds visibleBounds, List<LatLng> pins) {
  return pins.where((pin) {
    // Check if pin's latitude is within bounds
    bool isLatInBounds = pin.latitude >= visibleBounds.southwest.latitude &&
        pin.latitude <= visibleBounds.northeast.latitude;

    // Check if pin's longitude is within bounds
    bool isLngInBounds;
    if (visibleBounds.southwest.longitude <= visibleBounds.northeast.longitude) {
      // Normal case: southwest.lng <= northeast.lng
      isLngInBounds = pin.longitude >= visibleBounds.southwest.longitude &&
          pin.longitude <= visibleBounds.northeast.longitude;
    } else {
      // Handle 180° meridian crossing
      isLngInBounds = pin.longitude >= visibleBounds.southwest.longitude ||
          pin.longitude <= visibleBounds.northeast.longitude;
    }

    return isLatInBounds && isLngInBounds;
  }).toList();
}

// Example usage in a GoogleMap widget
class MapScreen extends StatefulWidget {
  @override
  _MapScreenState createState() => _MapScreenState();
}

class _MapScreenState extends State<MapScreen> {
  GoogleMapController? _mapController;
  Set<Marker> _markers = {};

  // Update markers when map bounds change
  void _updateVisiblePins() async {
    if (_mapController != null) {
      LatLngBounds bounds = await _mapController!.getVisibleRegion();
      List<LatLng> visiblePins = filterVisiblePins(bounds, pins);

      // Convert visible pins to markers
      setState(() {
        _markers = visiblePins.map((pin) {
          return Marker(
            markerId: MarkerId(pin.toString()),
            position: pin,
          );
        }).toSet();
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return GoogleMap(
      onMapCreated: (GoogleMapController controller) {
        _mapController = controller;
        _updateVisiblePins();
      },
      onCameraIdle: _updateVisiblePins, // Update when camera stops moving
      initialCameraPosition: CameraPosition(
        target: LatLng(37.7749, -122.4194), // Example center
        zoom: 12,
      ),
      markers: _markers,
    );
  }
}

Explanation of the Code

  • Pin Filtering: The filterVisiblePins function checks each pin’s coordinates against the LatLngBounds of the visible map area.
  • Map Interaction: The onCameraIdle callback ensures the pins are filtered whenever the user stops moving the map (e.g., after panning or zooming).
  • Markers: Filtered pins are converted to Marker objects and displayed on the map.
  • Meridian Handling: The longitude check accounts for cases where the map crosses the 180° meridian.

Additional Considerations

  • Performance: If the pin list is large, consider using a spatial index (e.g., a quadtree) to optimize filtering, though this is often unnecessary for small datasets.
  • Dynamic Updates: Call _updateVisiblePins in response to map events like onCameraMove, onCameraIdle, or when new pins are fetched.
  • API Integration. If pins are fetched from a backend, ensure the circular search radius is slightly larger than the visible rectangle to avoid edge cases where pins near the boundary are missed.
  • Zoom Level: You may want to adjust the filtering logic based on the map’s zoom level to avoid showing too many pins at high zoom levels.

Alternative Approach

If you’re using a custom map widget or need to calculate the visible rectangle manually, you can convert screen coordinates to latitude/longitude using the map’s projection (e.g., GoogleMapController.getLatLng for screen points). However, getVisibleRegion() is typically sufficient for most use cases.

This approach ensures that only pins within the visible rectangular area are shown, improving performance and user experience by reducing unnecessary markers.

  • Skipping AI? You’re a Relic – Time to Evolve or Perish!
  • 2026 Flutter Launch Blueprint: Your 10-Step Checklist to App Store Domination
  • Product Requirements Document – for different software development levels
  • The Bottleneck Factory: AI Production Line vs. Human Quality Gate
  • Most Important Things You Could Code in 2026

Categories

  • Apps (25)
  • ChatGPT (26)
  • Choosing a Framework (38)
  • Flutter (280)
  • Graphical User Interface (14)
  • Marketing (119)
  • Software Development (292)
  • Spring (45)
  • StartUp (22)
  • Uncategorized (14)
  • Uncategorized (4)
  • Vaadin (16)

Tags

Algorithms (9) crypto (29) flutterdev (39) General (86) Java (7) QR & Bar Codes (3) Software Dev Choices (33) Spring Boot (1) standards (1) Theme (3) User Authentication & Authorization (9) User Experience (10) Utilities (19) WordPress (11)

Product categories

  • All Technologies (87)
    • Flutter Apps (26)
    • GPT (4)
    • Java (39)
    • Native Android (3)
    • PHP (9)
    • Spring (Boot) / Quarkus (36)
    • Utils (15)
    • Vaadin 24+ (28)
    • Vaadin 8 (1)
  • Apps (18)
    • Employees DB (1)
    • Notes (6)
    • Personal Budget (1)
    • Recipes Book (1)
    • Stuff Organizer (1)
    • To-Do (2)
  • PDF Books (3)
  • Source Code Generators (8)

Recent Posts

  • Skipping AI? You’re a Relic – Time to Evolve or Perish!
  • 2026 Flutter Launch Blueprint: Your 10-Step Checklist to App Store Domination
  • Product Requirements Document – for different software development levels
  • The Bottleneck Factory: AI Production Line vs. Human Quality Gate
  • Most Important Things You Could Code in 2026

Post Categories

  • Apps (25)
  • ChatGPT (26)
  • Choosing a Framework (38)
  • Flutter (280)
  • Graphical User Interface (14)
  • Marketing (119)
  • Software Development (292)
  • Spring (45)
  • StartUp (22)
  • Uncategorized (14)
  • Uncategorized (4)
  • Vaadin (16)