Docs Menu
Docs Home
/ /
Datos del modelo

Datos geoespaciales - Kotlin SDK

Nuevo en la versión 1.11.0.

Los datos geoespaciales, o "geodatos", especifican puntos y objetos geométricos en la superficie de la Tierra.

La versión 1.11.0 y posteriores del SDK de Kotlin incorporan API geoespaciales experimentales que permiten realizar consultas con datos geoespaciales. Estas consultas permiten comprobar si un punto determinado está contenido en una forma. Por ejemplo, se pueden encontrar todas las cafeterías en un radio de 15 km de un punto específico.

Cambiado en la 1.13.0 versión: Datos geoespaciales compatibles con Atlas Device Sync

La versión 1.13.0 y posteriores del SDK de Kotlin añaden compatibilidad con datos geoespaciales en Atlas Device Sync. Esto permite suscribirse a consultas geoespaciales en un dominio sincronizado. Si intenta suscribirse a una consulta geoespacial con una versión anterior del SDK, recibirá un error de servidor con una escritura compensatoria.

Para obtener más información sobre cómo administrar sus suscripciones de sincronización, consulte Administrar suscripciones de sincronización - SDK de Kotlin.

Para obtener más información sobre cómo consultar datos geoespaciales con Device Sync, consulte Datos geoespaciales en la documentación de App Services.

El SDK de Kotlin admite consultas geoespaciales utilizando los siguientes tipos de datos:

  • GeoPoint

  • GeoCírculo

  • GeoBox

  • GeoPolígono

El SDK proporciona estos tipos de datos geoespaciales para simplificar la consulta de datos geoespaciales.No es posible conservar estos tipos de datos directamente.

Para obtener información sobre cómo conservar datos geoespaciales, consulte la sección Conservar datos geoespaciales en esta página.

Un GeoPunto define una ubicación específica en la superficie terrestre. Todos los tipos de datos geoespaciales utilizan GeoPoints para definir su ubicación.

Un GeoCircle define un círculo en la superficie de la Tierra. Defines un GeoCircle proporcionando un GeoPoint para el centro del círculo y un objeto Distance para especificar el radio del círculo.

Nota

Puede definir el radio en kilómetros, millas, grados o radianes.

El siguiente ejemplo crea 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)
)
Dos GeoCírculos
haga clic para ampliar

Un GeoBox define un rectángulo sobre la superficie terrestre. Definis el rectángulo especificando la esquina inferior izquierda (sudoeste) y la esquina superior derecha (noreste).

El siguiente ejemplo crea 2 cajas:

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
haga clic para ampliar

Un GeoPolígono define un polígono en la superficie de la Tierra.

Dado que un polígono es una forma cerrada, debe proporcionar un mínimo de 4 puntos: 3 punto para definir la forma del polígono y un cuarto para cerrar la forma.

Importante

El cuarto punto de un polígono debe ser el mismo que el primer punto.

También se pueden excluir áreas dentro de un polígono definiendo uno o más "huecos". Un hueco es otro polígono cuyos límites encajan completamente dentro del polígono exterior. Los huecos también pueden estar anidados. Una ubicación se considera dentro del polígono si está incluida en un número impar de anillos.

El siguiente ejemplo crea 3 polígonos:

  • Un polígono básico con 5 puntos

  • El mismo polígono con un solo agujero

  • El mismo polígono con dos agujeros.

// 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 GeoPolígonos
haga clic para ampliar

Importante

No se pueden conservar los tipos de datos geoespaciales

Actualmente, solo se pueden conservar datos geoespaciales. Los tipos de datos geoespaciales no se pueden conservar directamente. Por ejemplo, no se puede declarar una propiedad de GeoBox tipo.

Estos tipos solo pueden utilizarse como argumentos para consultas geoespaciales.

Si desea conservar datos geoespaciales, deben cumplir con la especificación GeoJSON.

Para hacer esto con el SDK de Kotlin, puede crear una clase integrada compatible con GeoJSON que luego pueda usar en su modelo de datos.

Para crear una clase que se ajuste a la especificación GeoJSON, debes:

  1. Crea un objeto de reino incrustado (una clase que hereda de EmbeddedRealmObject).

  2. Como mínimo, agregue los dos campos requeridos por la especificación GeoJSON:

    • Un campo de propiedad de tipo String que se asigna a una propiedad type con el valor de "Point": var type: String = "Point"

    • Un campo de tipo RealmList<Double> que se asigna a una propiedad coordinates en el esquema de dominio que contiene un par de latitud/longitud: var coordinates: RealmList<Double> = realmListOf()

El siguiente ejemplo muestra una clase incorporada denominada CustomGeoPoint que se utiliza para conservar datos geoespaciales:

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
}
}

Utilice la clase customGeoPoint en su modelo de reino, como se muestra en el siguiente ejemplo:

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

Luego puedes agregar instancias de tu clase al reino:

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

La siguiente imagen muestra los resultados de crear estos dos objetos Company :

2 GeoPuntos
haga clic para ampliar

Para consultar datos geoespaciales, puede usar el GEOWITHIN operador con RQL. Este método toma la coordinates propiedad de un objeto incrustado y comprueba si ese punto está contenido en la forma geoespacial de ese objeto.

El formato para consultar datos geoespaciales es el mismo, independientemente de la forma de la región de geodatos.

Importante

No se pueden utilizar consultas parametrizadas con datos geoespaciales.

Los siguientes ejemplos muestran cómo realizar consultas sobre varias formas para devolver una lista de empresas dentro de la 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
Ejemplo de consulta de un GeoCircle
haga clic 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
Ejemplo de consulta de un 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
Ejemplo de consulta de un GeoPolygon
haga clic para ampliar

Volver

Relaciones

En esta página