Menu Docs

Página inicial do DocsDesenvolver aplicaçõesAtlas Device SDKs

Geoespacial - React Native 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
  • Gravar a classe incorporada

Novo na versão 12.0.0.

Os dados geoespaciais, ou "geodata", especificam pontos e objetos geométricos na superfície da Terra. Com os tipos de dados geográficos, você pode criar consultas que verificam 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 realm@12.3.0: Dados geoespaciais suportados no Atlas Device Sync

Realm.js v12.3. O 0 e posterior adiciona suporte para dados geoespaciais no Atlas Device Sync. Isto permite que você se inscreva em queries geoespaciais em um domínio 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 Geospatial - React Native SDK.

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

O SDK suporta query 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.

Para query dos dados geoespaciais, você pode usar o operador geoWithin com RealmQL. O operador geoWithin pega a propriedade coordinates de um objeto incorporado que define o ponto que estamos consultando e uma das formas geoespaciais para verificar se esse ponto está contido dentro da forma.

Observação

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

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.

GeoPoint pode ser um dos três tipos:

  • Um objeto com:

    • latitude: um valor numérico

    • longitude: um valor numérico

    • altitude: um valor de número opcional

  • CanonicalGeoPoint: uma interface que satisfaz as especificações GeoJSON para um ponto

  • GeoPosition: uma matriz com longitude, latitude e uma altura opcional

Um GeoPoint é utilizado apenas como um bloco de construção das outras formas: GeoCircle, GeoBox e GeoPolygon. Estas formas, e o tipo GeoPoint, são usadas em query, não para persistência.

Para salvar dados geoespaciais no Realm, consulte Persistir Dados Geoespaciais nesta página.

Um GeoCircle define um círculo na superfície da Terra. Você define um GeoCircle fornecendo:

  • Um GeoPoint para o centro do círculo

  • Um número para a distância (raio) do círculo

A distância do raio utiliza radianos como unidade de medida. O SDK fornece os métodos kmToRadians e miToRadians para converter quilômetros ou milhas para radianos.

O seguinte código mostra dois exemplos de criação de um círculo:

import React from 'react';
import {View, Text} from 'react-native';
import {GeoCircle, GeoPoint, kmToRadians} from 'realm';
import {useQuery} from '@realm/react';
function Geocircle(): JSX.Element {
// Define a GeoCircle
const smallCircle: GeoCircle = {
center: [-121.9, 47.3],
// The GeoCircle radius is measured in radians.
// This radian distance corresponds with 0.25 degrees.
distance: 0.004363323,
};
// Realm provides `kmToRadians` and `miToRadians`
// to convert these measurements. Import the relevant
// convenience method for your app's needs.
const radiusFromKm = kmToRadians(44.4);
// Define a GeoPoint within a GeoCircle
const largeCircleCenter: GeoPoint = {
longitude: -122.6,
latitude: 47.8,
};
const largeCircle: GeoCircle = {
center: largeCircleCenter,
distance: radiusFromKm,
};
// Query geospatial data
const companiesInSmallCircle = useQuery(
Company,
collection => collection.filtered('location geoWithin $0', smallCircle),
[smallCircle],
);
// Query geospatial data
const companiesInLargeCircle = useQuery(
Company,
collection => collection.filtered('location geoWithin $0', largeCircle),
[largeCircle],
);
return (
<View>
<Text>Small circle: {companiesInSmallCircle.length}</Text>
<Text>Large circle: {companiesInLargeCircle.length}</Text>
</View>
);
}

A imagem a seguir mostra os resultados da criação de dois objetos: um círculo pequeno e um círculo grande.

Dois círculos geográficos
clique para ampliar

Query de dados geoespaciais retornam Objeto de Realm dentro das formas que você define. No exemplo acima, este é o resultado de nossa query:

Consultando um exemplo do GeoCircle.
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). Uma GeoBox se comporta da mesma forma que o GeoPolygon correspondente.

O exemplo a seguir cria 2 caixas:

import React from 'react';
import {View, Text} from 'react-native';
import {GeoBox, GeoPoint} from 'realm';
import {useQuery} from '@realm/react';
function Geobox(): JSX.Element {
// Define a GeoBox
const largeBox: GeoBox = {
bottomLeft: [-122.7, 47.3],
topRight: [-122.1, 48.1],
};
// Define GeoBox corners
const smallBoxBottomLeft: GeoPoint = {
longitude: -122.4,
latitude: 47.5,
};
const smallBoxTopRight: GeoPoint = {
longitude: -121.8,
latitude: 47.9,
};
const smallBox: GeoBox = {
bottomLeft: smallBoxBottomLeft,
topRight: smallBoxTopRight,
};
// Query geospatial data
const companiesInLargeBox = useQuery(
Company,
collection => collection.filtered('location geoWithin $0', largeBox),
[largeBox],
);
// Query geospatial data
const companiesInSmallBox = useQuery(
Company,
collection => collection.filtered('location geoWithin $0', smallBox),
[smallBox],
);
return (
<View>
<Text>Small box: {companiesInSmallBox.length}</Text>
<Text>Large box: {companiesInLargeBox.length}</Text>
</View>
);
}

A imagem a seguir mostra os resultados da criação de dois objetos: uma caixa pequena e uma caixa grande.

2 GeoBoxes
clique para ampliar

Query de dados geoespaciais retornam Objeto de Realm dentro das formas que você define. No exemplo acima, este é o resultado de nossa query:

Consultando um exemplo do GeoBox.

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. O exemplo abaixo cria 3 polígonos: um é um polígono básico com 5 pontos, um é o mesmo polígono com um único orifício e o terceiro é o mesmo polígono com dois orifícios:

import React from 'react';
import {View, Text} from 'react-native';
import {GeoPolygon, GeoPoint} from 'realm';
import {useQuery} from '@realm/react';
function Geopolygon(): JSX.Element {
// Define a basic GeoPolygon
const basicPolygon: GeoPolygon = {
outerRing: [
[-122.8, 48.0],
[-121.8, 48.2],
[-121.6, 47.6],
[-122.0, 47.0],
[-122.6, 47.2],
[-122.8, 48.0],
],
};
// Define a GeoPolygon with one hole
const outerRing: GeoPoint[] = [
[-122.8, 48.0],
[-121.8, 48.2],
[-121.6, 47.6],
[-122.0, 47.0],
[-122.6, 47.2],
[-122.8, 48.0],
];
const hole: GeoPoint[] = [
[-122.6, 47.8],
[-122.2, 47.7],
[-122.6, 47.4],
[-122.5, 47.6],
[-122.6, 47.8],
];
const polygonWithOneHole: GeoPolygon = {
outerRing: outerRing,
holes: [hole],
};
// Add a second hole to the GeoPolygon
const hole2: GeoPoint[] = [
{
longitude: -122.05,
latitude: 47.55,
},
{
longitude: -121.9,
latitude: 47.55,
},
{
longitude: -122.1,
latitude: 47.3,
},
{
longitude: -122.05,
latitude: 47.55,
},
];
const polygonWithTwoHoles: GeoPolygon = {
outerRing: outerRing,
holes: [hole, hole2],
};
// Query geospatial data
const companiesInBasicPolygon = useQuery(
Company,
collection => collection.filtered('location geoWithin $0', basicPolygon),
[basicPolygon],
);
// Query geospatial data
const companiesInPolygonWithTwoHoles = useQuery(
Company,
collection =>
collection.filtered('location geoWithin $0', polygonWithTwoHoles),
[polygonWithTwoHoles],
);
return (
<View>
<Text>Basic polygon: {companiesInBasicPolygon.length}</Text>
<Text>
Polygon with two holes: {companiesInPolygonWithTwoHoles.length}
</Text>
</View>
);
}

A imagem a seguir mostra os resultados da criação de três objetos: um polígono, um polígono com um orifício e um polígono com dois orifícios.

3 GeoPolygons
clique para ampliar

Query de dados geoespaciais retornam Objeto de Realm dentro das formas que você define. No exemplo acima, este é o resultado de nossa query:

Consultando um exemplo do GeoPolygon.
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.

Para persistir dados geoespaciais, eles devem estar em conformidade com a especificação GeoJSON.

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

  1. Crie um Objeto de Realm incorporado. Para mais informações sobre objetos incorporados, consulte Objetos incorporados - React Native SDK.

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

    • Um campo do tipo double[] que mapeia para uma propriedade de "coordenadas" (diferencia maiúsculas de minúsculas) no esquema do Realm.

    • Um campo do tipo string que mapeia para uma propriedade "type". O valor deste campo deve ser "Ponto".

Para simplificar a persistência de geodados, você pode definir um modelo que implementa CanonicalGeoPoint, que já tem a forma correta. The following example shows an embedded class named MyGeoPoint that is used to persist geospatial data.

Em seguida, você usa a classe personalizada MyGeoPoint no seu modelo de Realm, conforme mostrado no exemplo a seguir. You add instances of your class to the realm just like any other Realm model. No entanto, neste exemplo, como a classe MyGeoPoint não estende Realm.Object, devemos especificar MyGeoPoint.schema ao abrir o Realm:

import React from 'react';
import Realm, {ObjectSchema, CanonicalGeoPoint, GeoPosition} from 'realm';
import {RealmProvider} from '@realm/react';
// Implement `CanonicalGeoPoint`
// for convenience when persisting geodata.
class MyGeoPoint implements CanonicalGeoPoint {
coordinates!: GeoPosition;
type = 'Point' as const;
constructor(long: number, lat: number) {
this.coordinates = [long, lat];
}
static schema: ObjectSchema = {
name: 'MyGeoPoint',
embedded: true,
properties: {
type: 'string',
coordinates: 'double[]',
},
};
}
class Company extends Realm.Object<Company> {
_id!: number;
location!: MyGeoPoint;
static schema: ObjectSchema = {
name: 'Company',
properties: {
_id: 'int',
location: 'MyGeoPoint',
},
primaryKey: '_id',
};
}
export const Geospatial = () => {
return (
<View>
{/*
`MyGeoPoint` does not extend `Realm.Object`, so you pass
only the `.schema` when opening the realm.
*/}
<RealmProvider schema={[Company, MyGeoPoint.schema]}>
<WriteGeospatialObjects />
</RealmProvider>
</View>
);
};

Dentro de RealmProvider, crie seus objetos geoespaciais combinando a classe embarcada com classes que estendem Realm.Object.

import React from 'react';
import {View} from 'react-native';
import {useEffect} from 'react';
import {useRealm, useQuery} from '@realm/react';
function WriteGeospatialObjects(): JSX.Element {
const realm = useRealm();
const companies = useQuery(Company);
useEffect(() => {
if (!companies.length) {
// Add geospatial objects to realm.
writeNewCompany({_id: 6, location: new MyGeoPoint(-122.35, 47.68)});
writeNewCompany({_id: 9, location: new MyGeoPoint(-121.85, 47.9)});
}
}, []);
type CompanyProps = {
_id: number;
location: MyGeoPoint;
};
const writeNewCompany = ({_id, location}: CompanyProps) => {
// Add geospatial object to realm.
realm.write(() => {
realm.create(Company, {
_id,
location,
});
});
};
return (
<View>
<Geocircle />
<Geobox />
<Geopolygon />
</View>
);
}

A imagem a seguir mostra os resultados da criação desses dois objetos de empresa.

2 GeoPoints
clique para ampliar
← Objetos incorporados - React SDK nativo