Topic: Clustering 3D Markers

Hi!
We have a LOT of markers to show in certain areas and it makes our program ridiculously slow. So we are looking into a way to cluster markers like here:
https://developers.google.com/maps/docu … clustering

We saw a demo script for this in the Atlas (http://infinity-code.com/atlas/online-m … ample.html), but we couldn't get this to work correctly. When we zoomed in on the cluster image it never broke down in separate markers, and the separate markers close together never became clusters.
Also this example is for 2D markers and we use 3D markers. Is it possible to do clustering of 3D markers?

Re: Clustering 3D Markers

Hello.

Example of clustering 3D Markers:

using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class Group3DMarkers:MonoBehaviour
{
    public GameObject prefab;
    public GameObject groupPrefab;

    public int countMarkers = 100;
    public float distance = 30f / OnlineMapsUtils.tileSize; // pixels / 256

    private List<OnlineMapsMarker3D> markers;

    private void Start()
    {
        markers = new List<OnlineMapsMarker3D>();

        for (int i = 0; i < countMarkers; i++)
        {
            OnlineMapsMarker3D marker = OnlineMapsControlBase3D.instance.AddMarker3D(new Vector2(Random.Range(-180f, 180f), Random.Range(-80, 80)), prefab);
            marker.label = "Marker " + i;
            markers.Add(marker);
        }

        GroupMarkers();
    }

    private void GroupMarkers()
    {
        List<MarkerGroup> groups = new List<MarkerGroup>();
        float sqrDist = distance * distance;
        OnlineMaps map = OnlineMaps.instance;

        for (int zoom = OnlineMaps.MAXZOOM; zoom >= 3; zoom--)
        {
            List<OnlineMapsMarker3D> ms = markers.ToList();

            for (int j = 0; j < ms.Count - 1; j++)
            {
                OnlineMapsMarker3D marker = ms[j];
                MarkerGroup group = null;
                double px, py;
                marker.GetPosition(out px, out py);
                map.projection.CoordinatesToTile(px, py, zoom, out px, out py);

                int k = j + 1;

                while (k < ms.Count)
                {
                    OnlineMapsMarker3D marker2 = ms[k];

                    double p2x, p2y;
                    marker2.GetPosition(out p2x, out p2y);
                    map.projection.CoordinatesToTile(p2x, p2y, zoom, out p2x, out p2y);

                    if (OnlineMapsUtils.SqrMagnitude(px, py, p2x, p2y) < sqrDist)
                    {
                        if (group == null)
                        {
                            group = new MarkerGroup(zoom, groupPrefab);
                            groups.Add(group);
                            group.Add(marker);
                            if (marker.range.min == 3) marker.range.min = zoom + 1;
                        }
                        group.Add(marker2);
                        if (marker2.range.min == 3) marker2.range.min = zoom + 1;
                        ms.RemoveAt(k);
                        px = group.tilePositionX;
                        py = group.tilePositionY;
                    }
                    else k++;
                }
            }
        }
    }

    internal class MarkerGroup
    {
        public readonly List<OnlineMapsMarker3D> markers;
        public readonly OnlineMapsMarker3D instance;

        public Vector2 center;
        public double tilePositionX, tilePositionY;

        public int zoom;

        public MarkerGroup(int zoom, GameObject prefab)
        {
            markers = new List<OnlineMapsMarker3D>();
            this.zoom = zoom;
            instance = OnlineMapsControlBase3D.instance.AddMarker3D(Vector2.zero, prefab);
            instance.range = new OnlineMapsRange(zoom, zoom);
        }

        public void Add(OnlineMapsMarker3D marker)
        {
            markers.Add(marker);
            center = markers.Aggregate(Vector2.zero, (current, m) => current + m.position) / markers.Count;
            instance.position = center;
            OnlineMaps.instance.projection.CoordinatesToTile(center.x, center.y, zoom, out tilePositionX, out tilePositionY);
            instance.label = "Group. Count: " + markers.Count;
        }
    }
}

However, clustering does not help solve the problem of a large number of markers.
For each marker (even inactive) made a some number of operations in each frame.
To have a great performance, you need to help map and reduce the number of markers.
For example:
http://forum.infinity-code.com/viewtopi … d=650#p650

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Clustering 3D Markers

I'm still having a few issues.
It's not clustering all the markers it should be as can be seen when zoomed out more, and it doesn't always decluster markers, even on zoomlevel 20 (which is het closest zoomlevel).
In these photos the regular white circles are the clusters (not really noticeable I know hehe..).

Post's attachments

Attachment icon zoom clusters.png 429.08 kb, 99 downloads since 2017-01-26 

Re: Clustering 3D Markers

Try to increase the distance.
If the problem persists, please send us the scene (as package) where you have a problem. We will check it.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Clustering 3D Markers

I tried a few distances between 99999 and 0.00001 and nothing seemed to change. I've send you the unity scene through PM.

Re: Clustering 3D Markers

The problem is that the markers are grouped in Start.
You need to make the method «public static void GroupMarkers()», and invoke it after creating of markers.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Clustering 3D Markers

We already do that, after all markers are created, "StartGrouping()" from Group3DMarkers is called.

foreach (var o in obj.response_details)
        {
         [...]
            CreateMarker(o);
        }
        OnlineMaps.instance.GetComponent<Group3DMarkers>().StartGrouping();

-------
public void StartGrouping()
    {
        markers.AddRange(OnlineMapsControlBase3D.instance.markers3D);

        GroupMarkers();
    }

Re: Clustering 3D Markers

I found the problem:
GetData.cs: 86
marker3D.range = new OnlineMapsRange (1, 20);

You can fix this in three ways:
1. Just comment out this line.
2. Use OnlineMapsRange (3, 20);
3. In Group3DMarkers: 56, 59, replace «range.min == 3» to «range.min == 1».

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Clustering 3D Markers

It correctly clusters at far zoomed out levels now smile But some remain clustered even at zoom level 20 (the most zoomed in).

Re: Clustering 3D Markers

Group3DMarkers.GroupMarkers:

for (int zoom = OnlineMaps.MAXZOOM - 1; zoom >= 3; zoom--)
Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.