지리 공간적 데이터 - Kotlin SDK
이 페이지의 내용
버전 1.11.0의 새로운 기능.
지리 공간적 데이터 또는 "지리 데이터"는 지구 표면의 지점과 기하학적 객체를 지정합니다.
Kotlin SDK 버전 1.11.0 이상에는 지리 공간적 데이터를 사용한 쿼리를 지원하는 실험적 지리 공간적 API가 추가되었습니다. 이러한 쿼리는 주어진 점이 도형 내에 포함되어 있는지 확인할 수 있습니다. 예를 들어, 지정된 점에서 15km 이내에 있는 모든 커피숍을 찾을 수 있습니다.
버전 1.13.0에서 변경됨 : Atlas Device Sync에서 지원되는 지리 공간적 데이터
Kotlin SDK 버전 1.13.0 이상에는 Atlas Device Sync에서 지리 공간적 데이터에 대한 지원이 추가되었습니다. 이를 통해 동기화된 영역에서 지리 공간적 쿼리를 구독할 수 있습니다. 이전 버전의 SDK에서 지리 공간적 쿼리를 구독하려고 하면 보정용 쓰기와 함께 서버 오류가 발생합니다.
동기화 구독 관리에 대한 자세한 내용은 동기화 구독 관리 - Kotlin SDK를 참조하세요.
Device Sync 를 사용하여 지리 공간적 데이터를 쿼리하는 방법에 대한 자세한 내용은 App Services 문서에서 지리 공간적 데이터를 참조하세요.
지리 공간적 데이터 유형
Kotlin SDK는 다음 데이터 유형을 사용하여 지리적 공간 쿼리를 지원합니다:
GeoPoint
GeoCircle
GeoBox
GeoPolygon
SDK는 이러한 지리 공간적 데이터 유형을 제공하여 지리 공간적 데이터 쿼리를 간소화합니다. 이러한 데이터 유형을 직접 유지할 수 는 없습니다 .
지리 공간적 데이터를 유지하는 방법에 대한 자세한 내용은 이 페이지의 지리 공간적 데이터 유지 섹션을 참조하세요.
GeoPoint
GeoPoint 는 지구 표면의 특정 위치를 정의합니다. 모든 지리 공간적 데이터 유형은 GeoPoints
를 사용하여 위치를 정의합니다.
GeoCircle
GeoCircle 은 지구 표면에 원을 정의합니다. 원의 중심에 GeoPoint
를 제공하고 원의 반지름을 지정하는 거리 객체를 제공하여 GeoCircle
를 정의합니다.
참고
반지름은 킬로미터, 마일, 도 또는 라디안 단위로 정의할 수 있습니다.
다음 예에서는 2개의 원을 만듭니다:
val circle1 = GeoCircle.create( center = GeoPoint.create(47.8, -122.6), radius = Distance.fromKilometers(44.4) ) val circle2 = GeoCircle.create( center = GeoPoint.create(47.3, -121.9), radius = Distance.fromDegrees(0.25) )
GeoBox
GeoBox 는 지구 표면에 사각형을 정의합니다. 왼쪽 하단(남서) 모서리와 오른쪽 상단(북동쪽) 모서리를 지정하여 사각형을 정의합니다.
다음 예에서는 2 상자를 만듭니다.
val box1 = GeoBox.create( bottomLeft = GeoPoint.create(47.3, -122.7), topRight = GeoPoint.create(48.1, -122.1) ) val box2 = GeoBox.create( bottomLeft = GeoPoint.create(47.5, -122.4), topRight = GeoPoint.create(47.9, -121.8) )
GeoPolygon
GeoPolygon 은 지구 표면의 다각형 을 정의합니다.
다각형은 닫힌 모양이므로 최소 4개 점을 제공해야 합니다(다각형 모양을 정의하는 데 3개, 모양을 닫는 데 네 번째 점).
중요
다각형의 네 번째 점은 첫 번째 점과 같아야 합니다.
하나 이상의 "홀"을 정의하여 다각형 내의 영역을 제외할 수도 있습니다. 구멍은 경계가 외부 다각형 내에 완전히 들어가는 또 다른 다각형입니다. 구멍은 서로 중첩될 수도 있습니다. 위치가 홀수의 링에 포함된 경우 위치는 다각형 내부로 간주됩니다.
다음 예제에서는 3개의 다각형을 만듭니다:
점이 5개인 기본 다각형
단일 구멍이 있는 동일한 다각형
두 개의 구멍이 있는 동일한 다각형
// Create a basic polygon val basicPolygon = GeoPolygon.create( listOf( GeoPoint.create(48.0, -122.8), GeoPoint.create(48.2, -121.8), GeoPoint.create(47.6, -121.6), GeoPoint.create(47.0, -122.0), GeoPoint.create(47.2, -122.6), GeoPoint.create(48.0, -122.8) ) ) // Create a polygon with a single hole val outerRing = listOf( GeoPoint.create(48.0, -122.8), GeoPoint.create(48.2, -121.8), GeoPoint.create(47.6, -121.6), GeoPoint.create(47.0, -122.0), GeoPoint.create(47.2, -122.6), GeoPoint.create(48.0, -122.8) ) val hole1 = listOf( GeoPoint.create(47.8, -122.6), GeoPoint.create(47.7, -122.2), GeoPoint.create(47.4, -122.6), GeoPoint.create(47.6, -122.5), GeoPoint.create(47.8, -122.6) ) val polygonWithOneHole = GeoPolygon.create(outerRing, hole1) // Add a second hole to the polygon val hole2 = listOf( GeoPoint.create(47.55, -122.05), GeoPoint.create(47.5, -121.9), GeoPoint.create(47.3, -122.1), GeoPoint.create(47.55, -122.05) ) val polygonWithTwoHoles = GeoPolygon.create(outerRing, hole1, hole2)
지리 공간적 데이터 유지
중요
지리 공간적 데이터 유형을 지속할 수 없음
현재는 지리 공간적 데이터만 유지할 수 있습니다. 지리 공간적 데이터 유형은 직접 유지할 수 없습니다 . 예를 들어 GeoBox
유형의 속성은 선언할 수 없습니다.
이러한 유형은 지리공간 쿼리의 인수로만 사용할 수 있습니다.
지리 공간적 데이터를 유지하려면 GeoJSON 사양을 준수해야 합니다.
Kotlin SDK로 이 작업을 수행하려면 Realm 데이터 모델에서 사용할 수 있는 GeoJSON 호환 임베디드 클래스를 생성하면 됩니다.
GeoJSON 호환 클래스 만들기
GeoJSON 사양을 준수하는 클래스를 만들려면 다음을 수행합니다.
포함된 Realm 객체 ( EmbeddedRealmObject 를 상속하는 클래스)를 만듭니다.
최소한 GeoJSON 사양에 필요한 두 개의 필드를 추가합니다.
값이
"Point"
인type
속성에 매핑되는 유형String
속성의 필드:var type: String = "Point"
위도/경도 쌍을 포함하는 영역 스키마의
coordinates
속성에 매핑되는RealmList<Double>
유형의 필드:var coordinates: RealmList<Double> = realmListOf()
다음 예제에서는 지리 공간적 데이터를 유지하는 데 사용되는 CustomGeoPoint
이라는 포함된 클래스를 보여줍니다.
class CustomGeoPoint : EmbeddedRealmObject { constructor(latitude: Double, longitude: Double) { coordinates.apply { add(longitude) add(latitude) } } // Empty constructor required by Realm constructor() : this(0.0, 0.0) // Name and type required by Realm var coordinates: RealmList<Double> = realmListOf() // Name, type, and value required by Realm private var type: String = "Point" var latitude: Double get() = coordinates[1] set(value) { coordinates[1] = value } var longitude: Double get() = coordinates[0] set(value) { coordinates[0] = value } }
임베디드 클래스 사용
다음 예제와 같이 영역 모델에서 customGeoPoint
클래스를 사용합니다.
class Company : RealmObject { var _id: ObjectId = ObjectId() var location: CustomGeoPoint? = null }
그런 다음 클래스의 인스턴스를 Realm에 추가할 수 있습니다.
realm.writeBlocking { copyToRealm( Company().apply { location = CustomGeoPoint(47.68, -122.35) } ) copyToRealm( Company().apply { location = CustomGeoPoint(47.9, -121.85) } ) }
다음 이미지는 두 개의 Company
객체를 생성한 결과를 보여줍니다.
지리 공간적 데이터 쿼리
지리 공간적 데이터를 쿼리하려면 GEOWITHIN
연산자를 RQL 과 함께 사용할 수 있습니다. 이 메서드는 내장된 객체의 coordinates
속성을 사용하여 해당 점이 해당 객체의 지리 공간적 모양 내에 포함되어 있는지 확인합니다.
지리 공간적 데이터를 쿼리하는 형식은 지리 데이터 리전의 형태에 관계없이 동일합니다.
중요
지리 공간적 데이터에는 매개 변수화된 쿼리를 사용할 수 없습니다.
다음 예제에서는 다양한 형태에 대해 쿼리하여 형태 내의 회사 목록을 반환하는 방법을 보여 줍니다.
GeoCircle
val companiesInLargeCircle = realm.query<Company>("location GEOWITHIN $circle1").find() println("Companies in large circle: ${companiesInLargeCircle.size}") val companiesInSmallCircle = realm.query<Company>("location GEOWITHIN $circle2").find() println("Companies in small circle: ${companiesInSmallCircle.size}")
Companies in large circle: 1 Companies in small circle: 0
GeoBox
val companiesInLargeBox = realm.query<Company>("location GEOWITHIN $box1").find() println("Companies in large box: ${companiesInLargeBox.size}") val companiesInSmallBox = realm.query<Company>("location GEOWITHIN $box2").find() println("Companies in small box: ${companiesInSmallBox.size}")
Companies in large box: 1 Companies in small box: 2
GeoPolygon
val companiesInBasicPolygon = realm.query<Company>("location GEOWITHIN $basicPolygon").find() println("Companies in basic polygon: ${companiesInBasicPolygon.size}") val companiesInPolygonWithHoles = realm.query<Company>("location GEOWITHIN $polygonWithTwoHoles").find() println("Companies in polygon with holes: ${companiesInPolygonWithHoles.size}")
Companies in basic polygon: 2 Companies in polygon with holes: 1