📦 ClusterManager: Naver Map 기반 커스텀 클러스터링 구현

 

ClusterManager는 Naver Map 위에서 대량 주문 데이터를 클러스터링하여 가시성 있게 표현하기 위한 커스텀 유틸입니다. 줌 레벨에 따라 유동적으로 클러스터링 범위를 조정하고, 클릭 이벤트에 따라 사용자 액션을 트리거합니다.

 

 


 

🚩 주요 기능

 

  • Haversine 공식을 사용한 거리 기반 클러스터링
  • 줌 레벨에 따라 동적으로 threshold(거리 임계값) 조정
  • 마커 클릭 시 선택 상태 반영 및 카메라 이동
  • 단일 마커/클러스터 마커 각각에 대한 커스텀 뷰 렌더링

 

📌 주요 필드

private val maxDistance = 350.0
private val minDistance = 10.0
private var selectedId: Int? = null
private val markers = mutableListOf<Marker>()
private var items: List<ClusterItem> = mutableListOf()

 


📍 클러스터링 핵심 로직

private fun grouping(items: List<ClusterItem>): List<Pair<LatLng, List<ClusterItem>>> {
    val threshold = when (val zoom = naverMap.cameraPosition.zoom) {
        in 18.0..Float.MAX_VALUE -> 10.0
        in 17.0..18.0 -> 20.0
        in 16.0..17.0 -> 50.0
        in 15.0..16.0 -> 100.0
        in 14.0..15.0 -> 200.0
        // ... 생략 ...
        else -> 5000.0
    }

    val clusters = mutableListOf<Pair<LatLng, List<ClusterItem>>>()
    val visited = mutableSetOf<ClusterItem>()

    for (item in items) {
        if (item in visited) continue

        val group = items.filter { other ->
            !visited.contains(other) && calculateDistance(item, other) < threshold
        }

        visited.addAll(group)
        clusters.add(calculateClusterCenter(group) to group)
    }

    return clusters
}

 

threshold를 세분화해서 계산 했습니다.


 

🗺️ 마커 렌더링

fun update() {
    markers.forEach { it.map = null }
    markers.clear()

    val clusters = grouping(items)

    clusters.forEach { (position, clusterItems) ->
        val marker = Marker().apply {
            this.position = position
            this.tag = clusterItems
            this.icon = // 클러스터 여부에 따라 뷰 생성 생략
            setOnClickListener {
                // 선택 마커 ID 저장 및 콜백 처리
                true
            }
        }
        marker.map = naverMap
        markers.add(marker)
    }
}

 


 

🔄 선택 초기화

fun clearSelection() {
    selectedOrderId = null
    update()
}

 


 

✍️ 사용 예시

val clusterManager = ClusterManager(naverMap, context)
clusterManager.setItems(listOfClusterItems)

 


 

✅ 적용 효과

  • 마커 수가 많을 경우 시각적 복잡도 감소
  • 사용자의 선택과 클러스터 정보를 자연스럽게 연결
  • MapActivity와 연동하여 마커 선택 → 상세 정보 표시 가능

'Android' 카테고리의 다른 글

BackpressCallback  (0) 2024.05.29
네트워크 체크  (0) 2024.05.29

+ Recent posts