ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 6월 8일 TIL - 내 위치 기준으로 데이터 불러오기
    TIL(Today I Learned) 2023. 6. 8. 11:28

    ▷ 오늘의 배움

    📖 지도에 내 위치 기준 반경 몇km 데이터 띄우기

     

    ✏️ 데이터 필터링

    💬 위도와 경도 데이터로 두 지점간의 거리를 구해주는 haversine 패키지를 이용해서 내 위치를 기준으로 일정 범위 안의 시설들을 필터링 해보자!

    # 사용 방법
    # 기본적으로 kilometers로 측정된다.
    from haversine import haversine, Unit
    
    lyon = (45.7597, 4.8422) # (lat/위도, lon/경도)
    paris = (48.8567, 2.3508)
    
    haversine(lyon, paris)
    >> 392.2172595594006  # in kilometers
    
    haversine(lyon, paris, unit=Unit.MILES)
    >> 243.71250609539814  # in miles
    
    # you can also use the string abbreviation for units:
    haversine(lyon, paris, unit='mi')
    >> 243.71250609539814  # in miles
    
    haversine(lyon, paris, unit=Unit.NAUTICAL_MILES)
    >> 211.78037755311516  # in nautical miles

     

    반경 2km내의 데이터들을 불러오기 위해서 가장 먼저 (1) 내 위치를 기준으로 +- 2km의 데이터를 불러오기, (2) 불러온 데이터들을 haversine을 적용해서 2km 이내의 데이터들만 걸러내기!

    #(1) 내 위치를 기준으로 +- 2km의 데이터를 불러오기
    # 필터 조건에 __range를 이용하여 범위에 해당하는 오브젝트를 가져올 수 있다.
    Entry.objects.filter(pub__range=(start, end))
    # 필터 조건
    q = Q() # q=Q()로 선언
    # q.add로 조건 추가, 두번째 인자는 앞의 값과 어떻게 연결시킬지를 결정한다.
    q.add( Q(latitude__range  = (latitude - 0.01, latitude + 0.01)) |
           Q(longitude__range = (longitude - 0.015, longitude + 0.015)),
           q.AND) # q가 빈값이기 때문에 q.AND는 의미를 갖지 않는다
    q.add(Q(db_status=1), q.AND)  # 게시글 상태 여부 확인          
    
    # 필터링
    near_articles = (Articles.objects.filter(q))
    #(2) 불러온 데이터들을 haversine을 적용해서 2km 이내의 데이터들만 걸러내기
    near_articles_info = [na for na in near_articles
                           if haversine(position, (na.latitude, na.longitude)) <= 2]

     

    ✏️ 내 위치 지도에 띄우기

    💬 카카오 맵 API를 이용해서 내 위치를 지도에 띄어보겠다. 내 위치는 어제 사용한 navigator.geolocation.getCurrentPosition()를 사용하여 정보를 가져온다음 지도 위에 마크를 찍어보겠다. *공식 사이트에 자세히 설명되어있다.

    function loadMyPosition() {
        // 내 위치 표시하기
        navigator.geolocation.getCurrentPosition(function (position) {
            var container = document.getElementById('map'); //지도를 담을 영역의 DOM 레퍼런스
            var options = { //지도를 생성할 때 필요한 기본 옵션
                center: new kakao.maps.LatLng(position.coords.latitude, position.coords.longitude), //지도의 중심좌표를 내 위치를 기준으로 설정.(위도,경도)
                level: 3 //지도의 레벨(확대, 축소 정도)
            };
            var map = new kakao.maps.Map(container, options); //지도 생성 및 객체 리턴
            
            // 마커 위치를 내 위치로 설정하기
            var markerPosition = new kakao.maps.LatLng(position.coords.latitude, position.coords.longitude);
            // 마커 생성
            var marker = new kakao.maps.Marker({
                position: markerPosition
            });
            // 마커가 지도 위에 표시되도록 설정합니다
            marker.setMap(map);
    
        }, function (error) {
            // 에러 메세지 확인
            console.error(error);
        }, {
            enableHighAccuracy: false,
            maximumAge: 0,
            timeout: 5000
        });
    }

    무사히 찍힌 것을 확인 할 수 있다.

    ✏️ 필터링한 데이터 지도에 띄우기

    💬 백에서 필터링 된 데이터들을 받아와서 내 위치를 맵 위에 띄운것 처럼 forEach로 하나하나 마크를 찍어주었다. 나중에 내 위치는 구별할 수 있도록 마크모양을 바꾸던가 해줘야 보기가 쉬울것 같다.

    // 데이터 요청 함수
    async function getNearPosition(position) {
        const response = await fetch(`${back_base_url}/articles/location-list?latitude=${position.coords.latitude}&longitude=${position.coords.longitude}`)
    
        if (response.status == 200) {
            const response_json = await response.json()
            return response_json
        } else {
            alert("불러오는데 실패하였습니다.")
        }
    }
    // 주변 데이터 표시하기
        // 데이터 요청 보내기
        const nearPositions = await getNearPosition(position)
        // 주변 데이터 마커 생성
        nearPositions.forEach(point => {
            console.log(point)
            console.log(point.coordinate_x)
            // 마커를 표시할 위치입니다 
            var position = new kakao.maps.LatLng(point.coordinate_y, point.coordinate_x);
    
            // 마커를 생성합니다
            var marker = new kakao.maps.Marker({
                position: position,
            });
            // 마커를 지도 위에 표시
            marker.setMap(map);
    
        });

     

    댓글

Designed by Tistory.