Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/ / /

地理空间 - Flutter SDK

在此页面上

  • 地理空间数据类型
  • GeoPoint
  • GeoCircle
  • GeoBox
  • 保留地理空间数据
  • 创建与 GeoJSON 兼容的类
  • 使用嵌入式类
  • 查询地理空间数据

版本 1.6.0 中的新增内容

地理空间数据或“地理数据”指定地球表面上的点和几何对象。 使用地理数据类型,您可以创建查询来检查给定点是否包含在形状中。 例如,您可以查找距离指定点15公里范围内的所有咖啡店。

Flutter SDK 1.6.1及更高版本增加了对 Atlas Device Sync 中地理空间数据的支持。 这允许您订阅同步数据库中的地理空间查询。 如果您尝试使用旧版本的 SDK 订阅地理空间查询,您将收到带有补偿写入的服务器错误。 有关管理同步订阅的更多信息,请参阅管理同步订阅 - Flutter SDK。

有关使用Device Sync查询地理空间数据的更多信息,请参阅App Services文档中的地理空间数据

Flutter SDK 支持使用以下数据类型进行地理空间查询:

  • GeoPoint

  • GeoCircle

  • GeoBox

SDK 提供这些地理空间数据类型是为了简化地理空间数据的查询。 您无法直接持久化这些数据类型。

有关如何保存地理空间数据的信息,请参阅本页的保存地理空间数据部分。

GeoPoint 定义地球表面的特定位置。所有地理空间数据类型都使用GeoPoints来定义其位置。

GeoPoint是具有两个必需属性的对象:

  • lat:双精度值

  • lon:双精度值

GeoPoint 仅用作其他形状的构建基块:GeoCircle 和 GeoBox。 这些形状和 GeoPoint 类型用于查询,而不是用于持久性。

要将地理空间数据保存到数据库,请参阅持久地理空间数据。

GeoCircle 在地球表面定义一个圆。您可以通过提供以下内容来定义GeoCircle

  • 代表圆心的GeoPoint

  • GeoDistance表示圆的距离(半径)

半径距离使用弧度作为测量单位,在 SDK 中实现为双精度值。 SDK 提供了从其他度量单位创建GeoDistance的便捷方法:

以下代码显示了创建圆形的两个示例:

final smallCircle =
GeoCircle(GeoPoint(lon: -121.9, lat: 47.3), 0.25.degrees);
final largeCircleCenter = GeoPoint(lon: -122.6, lat: 47.8);
// The SDK provides convenience methods to convert measurements to radians.
final radiusFromKm = GeoDistance.fromKilometers(44.4);
final largeCircle = GeoCircle(largeCircleCenter, radiusFromKm);
两个 GeoCircle
点击放大

GeoBox 在地球表面定义一个矩形。您可以通过指定左下(西南)角和右上角(东北)角来定义矩形。

以下示例将创建2框:

final largeBox = GeoBox(
GeoPoint(lon: -122.7, lat: 47.3), GeoPoint(lon: -122.1, lat: 48.1));
final smallBoxSouthWest = GeoPoint(lon: -122.4, lat: 47.5);
final smallBoxNorthEast = GeoPoint(lon: -121.8, lat: 47.9);
final smallBox = GeoBox(smallBoxSouthWest, smallBoxNorthEast);
2 GeoBox
点击放大

重要

无法保留地理空间数据类型

目前,您只能保留地理空间数据。 地理空间数据类型无法直接持久化。 例如,您不能声明类型为GeoBox的属性。

这些类型只能用作地理空间查询的参数。

如果要持久保存地理空间数据,则必须符合 GeoJSON 规范

要创建符合 GeoJSON 规范的类,您需要:

  1. 创建嵌入式对象。 有关嵌入式对象的更多信息,请参阅嵌入式对象。

  2. 至少添加 GeoJSON 规范要求的两个字段:

    • 类型为double[]的字段,映射到模式中的“坐标”(区分大小写)属性。

    • 类型为string的字段,映射到“类型”属性。 此字段的值必须是“Point”。

以下示例显示了一个名为MyGeoPoint的嵌入式类,用于保存地理空间数据:

// To store geospatial data, create an embedded object with this structure.
// Name it whatever is most convenient for your application.
@RealmModel(ObjectType.embeddedObject)
class _MyGeoPoint {
// These two properties are required to persist geo data.
final String type = 'Point';
final List<double> coordinates = const [];
// You can optionally implement convenience methods to simplify
// creating and working with geospatial data.
double get lon => coordinates[0];
set lon(double value) => coordinates[0] = value;
double get lat => coordinates[1];
set lat(double value) => coordinates[1] = value;
GeoPoint toGeoPoint() => GeoPoint(lon: lon, lat: lat);
}

然后,您可以在数据模型中使用自定义MyGeoPoint类,如以下示例所示:

// Use the GeoJSON-compatible class as a property in your model.
@RealmModel()
class _Company {
@PrimaryKey()
late ObjectId id;
_MyGeoPoint? location;
}

就像添加任何其他模型一样,将类的实例添加到数据库中。

final realm =
Realm(Configuration.local([MyGeoPoint.schema, Company.schema]));
realm.write(() {
realm.addAll([
Company(
firstCompanyID,
location: MyGeoPoint(coordinates: [-122.35, 47.68]),
),
Company(
secondCompanyID,
location: MyGeoPoint(coordinates: [-121.85, 47.9]),
)
]);
});

下图显示了创建这两个公司对象的结果。

2 个 GeoPoint
点击放大

要查询地理空间数据,可以将geoWithin操作符与RQL结合使用。 geoWithin操作符获取嵌入式对象的“坐标”属性(定义我们正在查询的点)和地理空间形状之一,以检查该点是否包含在该形状中。

注意

无论地理数据区域的形状如何,查询地理空间数据的格式都是相同的。

以下示例展示了如何查询各种形状以返回形状内的公司列表:

GeoCircle

final companiesInSmallCircle =
realm.query<Company>("location geoWithin \$0", [smallCircle]);
final companiesInLargeCircle =
realm.query<Company>("location geoWithin \$0", [largeCircle]);
查询 GeoCircle 示例。
点击放大

GeoBox

final companiesInLargeBox =
realm.query<Company>("location geoWithin \$0", [largeBox]);
final companiesInSmallBox =
realm.query<Company>("location geoWithin \$0", [smallBox]);
查询 GeoBox 示例。

后退

更新 Realm 对象模式