mapbox / mapbox/mapbox-maps-flutter

Overlapping Polygons Affect Opacity of Fill Color

Open
#456 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Dart
Stars
380
Forks
204
PR merge metrics
No merged PRs in 30d

Description

Problem:
Currently, our system generates polygons comprising 360 vertices to display a red circle with a fill color set to red and an opacity of 10%. However, when these polygons overlap, the resulting opacity is not consistent. Overlapping polygons cause areas of the circle to become darker than the intended 10% opacity due to the additive effect of overlapping colors.

![image](https://github.com/mapbox/mapbox-maps-flutter/assets/45609500/23adb914-43fa-4be2-887c-05cefcb7dad9)

Expected Behavior:
We expect the fill color opacity to remain consistent at 10% throughout the entire circle, regardless of overlapping polygons.

This is the current situation:
![image](https://cloud.githubusercontent.com/assets/3875803/5132727/3d506d36-70cd-11e4-93fa-9c48ee649a56.png)

What we need is:
![image](https://cloud.githubusercontent.com/assets/3875803/5132732/617ffad2-70cd-11e4-947b-30baf0194bd2.png)

```dart
nonSmokingAreas[result[i].id] =
(await nonSmokingAreaManager?.create(
PolygonAnnotationOptions(
fillColor: Colors.red.withOpacity(0.1).value,
fillSortKey: 1,
geometry: Polygon(
coordinates: [
List.generate(
points.length,
(index) => Position(
points[index].lng,
points[index].lat,
),
),
],
).toJson()),
))!;
```

```dart
import 'dart:math';

/// Generates a list of points representing a regular polygon around a given geographic coordinate (latitude and longitude) with a specified radius.
///
/// Parameters:
/// - `lat` (double): The latitude of the central position of the polygon.
/// - `lng` (double): The longitude of the central position of the polygon.
/// - `radius` (double): The radius of the polygon in meters.
///
/// Returns:
/// - `List<({double lat, double lng})>`: A list of tuples, where each tuple represents a point on the generated polygon. Each point is represented by latitude and longitude.
///
/// Algorithm:
/// The function uses an iterative method to generate the points of the polygon. It calculates the position of each point using the distance (`radius`) and the angle relative to the central position. It uses the `_translateCoordinate` function to compute the geographic coordinates of each point.
///
/// 1. Initialize an empty list `points` to store the generated points.
/// 2. Iterate from 0 to 11 (total of 36 iterations) for creating a regular polygon.
/// 3. Calculate the angle (`angle`) for each point using the index of the iteration.
/// 4. Calculate the displacement (`dx` and `dy`) relative to the radius and angle.
/// 5. Use the `_translateCoordinate` function to compute the geographic coordinates of each point and add them to the `points` list.
/// 6. Return the `points` list containing all the generated points of the polygon.
///
/// Notes:
/// - The algorithm assumes the Earth is a perfect sphere and uses a simple approximation for computing the coordinates.
/// - The function generates a regular polygon with 36 vertices, which corresponds to a regular pentagon. The number of vertices can be changed by adjusting the loop condition.
List<({double lat, double lng})> listgeneratePolygonPoints(
double lat, double lng, double radius) {
List<({double lat, double lng})> points = [];

for (int i = 0; i < 360; i++) {
double angle = (2 * pi * i) / 360;
double dx = radius * cos(angle);
double dy = radius * sin(angle);
final point = _translateCoordinate((lat: lat, lng: lng), dx, dy);
points.add(point);
}

return points;
}

/// Translates the geographic coordinates of a point based on a given origin position, displacement in latitude and longitude, and Earth radius.
///
/// Parameters:
/// - `coordinate` ({double lat, double lng}): The initial coordinates tuple containing latitude and longitude.
/// - `dx` (double): The displacement in longitude.
/// - `dy` (double): The displacement in latitude.
///
/// Returns:
/// - `({double lat, double lng})`: A tuple containing the computed geographic coordinates of the point resulting from the displacement from the origin position.
///
/// Algorithm:
/// 1. Calculate the new latitude component (`lat`) based on the displacement in latitude and the Earth radius.
/// 2. Calculate the new longitude component (`lon`) based on the displacement in longitude, Earth radius, and the cosine of the latitude of the origin position.
/// 3. Return a tuple containing the calculated latitude and longitude of the new point.
///
/// Notes:
/// - The function considers the curvature of the Earth and uses a simple formula to compute the new coordinates.
/// - It is assumed that the displacement (`dx` and `dy`) is relatively small, so the curvature of the Earth can be neglected.
({double lat, double lng}) _translateCoordinate(
({double lat, double lng}) coordinate, double dx, double dy) {
const double earthRadius = 6378137; // Earth radius in meters
double lat = coordinate.lat + (dy / earthRadius) * (180 / pi);
double lon = coordinate.lng +
(dx / earthRadius) * (180 / pi) / cos(coordinate.lat * pi / 180);
return (lat: lat, lng: lon);
}

```

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The report names no repository file or test; start from the PolygonAnnotationOptions/create usage and the 360-vertex polygon generator shown in the issue. Reproduce the red circle with 10% opacity and overlapping polygons, then verify that the rendered circle remains uniformly opaque.

Written by the indexing model from the issue text.

Assessment

Tech stack
dart, flutter
Domain
mobile
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.