Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ / /

Dados geoespaciais - Kotlin SDK

Nesta página

  • Tipos de dados geoespaciais
  • GeoPoint
  • Círculo geográfico
  • GeoBox
  • GeoPolygon
  • Persistir dados geoespaciais
  • Criar uma classe compatível com GeoJSON
  • Use a classe incorporada
  • Executar query de dados geoespaciais
  • Círculo geográfico
  • GeoBox
  • GeoPolygon

Novidades na versão 1.11.0.

Os dados geoespaciais, ou "geodados", especificam pontos e objetos geométricos na superfície da Terra.

O Kotlin SDK versão 1.11.0 e posterior adiciona APIs geoespaciais experimentais que suportam queries com dados geoespaciais. Estas queries podem verificar se um determinado ponto está contido dentro de uma forma. Por exemplo, você pode encontrar todos os cafés em um raio de 15 km de um ponto especificado.

Alterado na versão 1,13,0: Dados geoespaciais suportados no Atlas Device Sync

O Kotlin SDK versão 1.13.0 e posterior adiciona suporte para dados geoespaciais no Atlas Realm Mobile Sync. Isto permite a você assinar query geoespaciais em um Realm sincronizado. Se você tentar se inscrever em uma query geoespacial com uma versão mais antiga do SDK, receberá um erro de servidor com uma gravação compensatória.

Para obter mais informações sobre como gerenciar suas assinaturas de sincronização, consulte managed assinaturas de sincronização - Kotlin SDK.

Para mais informações sobre query de dados geoespaciais com o Device Sync, consulte Dados geoespaciais na documentação do App Services.

O Kotlin SDK suporta queries geoespaciais utilizando os seguintes tipos de dados:

  • GeoPoint

  • Círculo geográfico

  • GeoBox

  • GeoPolygon

O SDK fornece estes tipos de dados geoespaciais para simplificar a query de dados geoespaciais. Você não pode persistir esses tipos de dados diretamente.

Para obter informações sobre como persistir dados geoespaciais, consulte a seção Persistir dados geoespaciais nesta página.

Um GeoPoint define um local específico na superfície da Terra. Todos os tipos de dados geoespaciais utilizam GeoPoints para definir sua localização.

Um GeoCircle define um círculo na superfície da Terra. Você define um GeoCircle fornecendo um GeoPoint para o centro do círculo e um objeto de distância para especificar o raio do círculo.

Observação

Você pode definir o raio em quilômetros, milhas, graus ou radianos.

O exemplo a seguir cria 2 círculos:

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)
)
Dois círculos geográficos
clique para ampliar

Uma GeoBox define um retângulo na superfície da Terra. Você define o retângulo especificando o canto inferior esquerdo (sudoeste) e o canto superior direito (nordeste).

O exemplo a seguir cria 2 caixas:

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)
)
2 GeoBoxes
clique para ampliar

Um GeoPolygon define um polígono na superfície da Terra.

Como um polígono é uma forma fechada, você deve fornecer um mínimo de 4 pontos: 3 pontos para definir a forma do polígono e um quarto para fechar a forma.

Importante

O quarto ponto em um polígono deve ser igual ao primeiro ponto.

Você também pode excluir áreas dentro de um polígono definindo um ou mais "furos". Um orifício é outro polígono cujos limites se encaixam completamente dentro do polígono externo. Os orifícios também podem ser aninhados uns dentro dos outros. Um local é considerado dentro do polígono se estiver incluído em um número ímpar de anéis.

O exemplo seguinte cria 3 polígonos:

  • Um polígono básico com 5 pontos

  • O mesmo polígono com um único orifício

  • O mesmo polígono com dois orifícios

// 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)
3 GeoPolygons
clique para ampliar

Importante

Não é possível persistir tipos de dados geoespaciais

Atualmente, você só pode persistir dados geoespaciais. Os tipos de dados geoespaciais não podem ser persistidos diretamente. Por exemplo, você não pode declarar uma propriedade do tipo GeoBox.

Estes tipos podem ser utilizados somente como argumentos para queries geoespaciais.

Se você deseja persistir os dados geoespaciais, eles devem estar em conformidade com a especificação GeoJSON.

Para fazer isso com o Kotlin SDK, você pode criar uma classe incorporada compatível com GeoJSON que pode ser usada em seu modelo de dados.

Para criar uma classe que esteja em conformidade com a especificação GeoJSON, você:

  1. Crie um objeto de domínio incorporado (uma classe que herda de EmbeddedRealmObject).

  2. No mínimo, adicione os dois campos exigidos pela especificação GeoJSON:

    • Um campo de propriedade de tipo String que mapeia para uma propriedade type com o valor de "Point": var type: String = "Point"

    • Um campo do tipo RealmList<Double> que mapeia para uma propriedade coordinates no esquema do Realm contendo um par latitude/longitude: var coordinates: RealmList<Double> = realmListOf()

O exemplo seguinte mostra uma classe embarcada denominada CustomGeoPoint que é utilizada para persistir dados geoespaciais:

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"
@Ignore
var latitude: Double
get() = coordinates[1]
set(value) {
coordinates[1] = value
}
@Ignore
var longitude: Double
get() = coordinates[0]
set(value) {
coordinates[0] = value
}
}

Utilize a classe customGeoPoint em seu modelo de Realm, como mostrado no seguinte exemplo:

class Company : RealmObject {
@PrimaryKey
var _id: ObjectId = ObjectId()
var location: CustomGeoPoint? = null
}

Você pode então adicionar instâncias da sua classe ao Realm:

realm.writeBlocking {
copyToRealm(
Company().apply {
location = CustomGeoPoint(47.68, -122.35)
}
)
copyToRealm(
Company().apply {
location = CustomGeoPoint(47.9, -121.85)
}
)
}

A seguinte imagem mostra os resultados da criação destes dois objetos Company :

2 GeoPoints
clique para ampliar

Para query dos dados geoespaciais, você pode usar o operador GEOWITHIN com RealmQL. Este método pega a propriedade coordinates de um objeto embarcado e verifica se este ponto está contido dentro da forma geoespacial desse objeto.

O formato para consultar dados geoespaciais é o mesmo, independentemente da forma da região de dados geoespaciais.

Importante

Você não pode utilizar query parametrizadas com dados geoespaciais.

Os exemplos a seguir mostram a consulta de várias formas para retornar uma lista de empresas dentro da forma.

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
Exemplo de query de um GeoCircle
clique para ampliar
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
Consultando um exemplo do GeoBox
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
Consultando um exemplo do GeoPolygon
clique para ampliar

Voltar

Relacionamentos