本文介绍了几何模型的用途、基本构成和快速入门等内容。
模型用途
简介
几何模型是开放地理空间联盟(Open Geospatial Consortium,以下简称为OGC)设计的简单要素访问标准(Simple Features Access standard,以下简称为SFA),用于描述地理空间数据。该标准定义了基本的空间模型Geometry模型及对该模型的操作、转换等行为,以实现各种空间分析任务。
Ganos Geometry是对象关系型数据库PostgreSQL兼容版本(PolarDB PostgreSQL版(兼容Oracle))的一个时空引擎扩展,Ganos Geometry扩展采用了OGC Simple Features规范,它包含了Geometry和Geography两种类型,用于表示平面或曲面上的点、线、面等几何对象。
功能概述
Ganos Geometry支持构建、访问、编辑、处理、聚合、导出空间对象的多种方法,支持空间对象关系查询,支持空间对象线性参考设置等。
Ganos Geometry兼容多种外部格式的直接输入,例如:WKT、WKB、EKWT、EWKB、KML、GML、GeoHash、Geojson等,也支持通过其他工具输入Esri Shape File等格式。
主要业务场景
在实际应用中,Geometry类型可以用于几何对象存储分析的场景:
地图制作和可视化
地图可视化可以直观地展现地理空间中数据的分布、趋势和关系,通过在地图上标记不同的数据点、线、面等元素,选择合适的地图投影、色彩、符号等元素,展示数据在地理空间中的分布情况,实现地图的制作和可视化。Geometry类型可以用于表示地图上的各种要素,例如道路、河流、建筑物等。
位置服务
对位置数据进行空间查询,聚合和分析,可以找到最佳位置、评估风险或计算两点之间距离等。Geometry类型可以描述点状地物同时对点状地物进行各种空间处理,可为位置服务提供支持。
空间关系查询
空间关系查询可以用于多种场景,例如空间数据挖掘、城市规划等。通过空间关系查询,可以快速地找到满足特定条件的空间实体,为决策提供有力的支持。Geometry类型支持多个几何对象之间空间关系的判断,例如确定两个物体是否相交或相切等。
空间分析和计算
空间分析和计算用于各种量测场景,例如计算建筑物的面积、计算两个城市之间的距离等。Geometry类型支持各种空间分析和计算,例如计算面积、长度、距离、质心等。
基本构成
几何模型概述
Geometry模型在二维或三维笛卡尔坐标系中进行建模,其大小与位置由其坐标决定。每一个坐标都有一个X和Y坐标值,同时,可以包含可选的Z和M坐标值。 Z坐标通常用于表示高程。M坐标表示测量值,可以表示时间或距离。 如果Geometry中存在Z或M值,则必须为其中的每个点定义它们。 若Geometry具有Z或M坐标,则其坐标维度为3DZ或3DM,如果它同时具有Z和M,则为4D。
空间参考系
空间参考系(Spatial Reference System,以下简称为 SRS )定义了如何将Geometry对象关联到地球表面上某个具体位置。
Ganos使用一个整数来表示SRS的定义引用,称为SRID。Geometry对象通过其自身的SRID值与SRS关联。
更多内容请参见空间参考。
OGC外部交换格式
SFA规范同时定义了两种用于外部数据交换的格式:
方便阅读的文本形式:Well-Known Text (以下简称为WKT)。
可以保留数据精度且方便传输的二进制形式:Well-Known Binary (以下简称为WKB)。
WKT和WKB均包含对象的类型信息和定义它的坐标信息,但不包含其关联的SRID,也不支持非二维数据。
Ganos扩展WKT/WKB为EKWT/EKWB,添加了对3DZ、3DM、4D数据的支持,同时支持嵌入SRID信息。
EKWT/EKWB为WKT/WKB的超集,当前版本下,任意有效的WKT/WKB都是有效的EKWT/EKWB。
OGC几何类型详情
原子类型
模型名称
模型说明
模型WKT示例
Point
Point是一个零维几何图形,表示坐标空间中的单个位置。
POINT (1 2) * POINT Z (1 2 3)
POINT ZM (1 2 3 4)
LineString
LineString是由连续的线段序列形成的一维线。每条线段由两个点定义,一条线段的终点形成下一条线段的起点。 LineString可以自相交。
LINESTRING (1 2, 3 4, 5 6)
Polygon
Polygon由外部边界和零个或多个内部边界(孔)界定。每个边界都是一个LinearRing 。
POLYGON ((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))
参数化类型
模型名称
模型说明
模型WKT示例
EllipticalString
椭圆弧。
ELLIPTICALSTRING(-2 0,2 0,0 0,0,0,0,2,0.5)
Bezier3Curve
四个点确定的一条三阶贝塞尔曲线。
BEZIER3CURVE(1 1, 2 2, 3 2, 3 1)
集合类型
模型名称
模型说明
模型WKT示例
MultiPoint
MultiPoint是Point的集合。
MULTIPOINT ( (0 0), (1 2) )
MultiLineString
MultiLineString是LineString的集合。
MULTILINESTRING ( (0 0,1 1,1 2), (2 3,3 2,5 4) )
MultiPolygon
MultiPolygon是不重叠、不相邻的Polygon的集合。集合中的Polygon只能在有限点处相接。
MULTIPOLYGON (((1 5, 5 5, 5 1, 1 1, 1 5)), ((6 5, 9 1, 6 1, 6 5)))
GeometryCollection
GeometryCollection是Geometry的集合,可以混合不同类型的Geometry对象。
GEOMETRYCOLLECTION ( POINT(2 3), LINESTRING(2 3, 3 4))
CompoundCurve
含线、椭圆弧或贝塞尔曲线的复合线对象。 CompoundCurve中每个单元对象的几何必须连续。
COMPOUNDCURVE((1 0,2 0),ELLIPTICALSTRING(2 0 ,4 0, 3 0 ,1,0,0,1,0.5))
COMPOUNDCURVE((1 2,2 0),BEZIER3CURVE(2 0,20 20 ,30 10,10 10))
CurvePolygon
含曲线的复合面对象。 CurvePolygon中的各个子对象必须是闭合的。
CURVEPOLYGON(ELLIPTICALSTRING(2 0,2 0,0 0,0,0,0,2,0.5),CIRCULARSTRING(-0.5 0,0.5 0,-0.5 0))
CURVEPOLYGON(BEZIER3CURVE(1 1, 2 2, 3 1, 1 1),CIRCULARSTRING(1.7 1.2,1.9 1.2,1.7 1.2))
空间数据列视图
在Ganos中,geometry_columns是从数据库系统目录表中读取全部几何列的视图。该视图遵循了OGC的Simple Features Specification for SQL标准。
空间数据列视图具有如下结构:
列名 | 类型 | 说明 |
f_table_catalog | varchar(256) | 一般为固定值postgres。 |
f_table_schema | varchar(256) | 该表所在的schema。 |
f_table_name | varchar(256) | 该表的表名。 |
f_geometry_column | varchar(256) | 该表中某个Geometry列的列名。 |
coord_dimension | integer | Geometry列的维度(2,3或4)。 |
srid | integer | Geometry列SRID,是引用到spatial_ref_sys表的外键。 |
type | varchar(30) | Geometry对象的类型,应为OGC标准类型之一。若为混合类型,则值为GEOMETRY。 |
可以通过如下语句查询当前数据库中全部几何数据列:
SELECT * FROM geometry_columns;
索引
空间索引使Ganos处理大型空间数据集时避免对数据库进行全局“顺序扫描”。索引通过将数据组织到搜索树中来加速搜索,可以快速遍历该搜索树以查找特定记录。
Ganos为空间数据提供了三种空间索引:
索引名称 | 索引简介 | 索引特点 |
GiST (Generalized Search Tree) | GiST索引是一种平衡搜索树,是最常用、最通用的空间索引方法,提供非常好的查询性能。 | GiST索引允许定义一些规则将任意类型的数据分布在一棵平衡树上,同时也允许定义一些方法访问这些数据。 |
BRIN (Block Range Index) | BRIN索引通过汇总空间表中一定数量记录的空间范围进行处理。搜索是通过扫描空间范围来完成的。 |
|
SP-GiST (Space-Partitioned Generalized Search Tree) | SP-GiST是一种通用索引方法,支持四叉树、kd树和根基树等分区搜索树。 |
|
快速入门
简介
快速入门帮助用户快速理解Ganos Geometry引擎的基本用法,包括扩展创建、创建表、导入数据、创建索引、空间分析量测、空间关系判断等内容。
更多专业用法可参考Geometry最佳实践文章:
语法说明
创建扩展。
--创建几何扩展 CREATE extension ganos_geometry cascade;
说明建议将扩展安装在public模式下,避免权限问题。
CREATE extension ganos_geometry WITH schema public cascade;
创建几何表。
--方式一:直接创建带geometry字段的表 CREATE TABLE ROADS ( ID int4, ROAD_NAME varchar(25), geom geometry(LINESTRING,3857) ); --方式二:先创建普通表,再附加几何字段 CREATE TABLE ROADS ( ID int4, ROAD_NAME varchar(25) ); SELECT AddGeometryColumn( 'roads', 'geom', 3857, 'LINESTRING', 2);
添加几何约束。
ALTER TABLE ROADS ADD CONSTRAINT geometry_valid_check CHECK (ST_IsValid(geom));
导入几何数据。
INSERT INTO roads (id, geom, road_name) VALUES (1,ST_GeomFromText('LINESTRING(191232 243118,191108 243242)',3857),'北五环'); INSERT INTO roads (id, geom, road_name) VALUES (2,ST_GeomFromText('LINESTRING(189141 244158,189265 244817)',3857),'东五环'); INSERT INTO roads (id, geom, road_name) VALUES (3,ST_GeomFromText('LINESTRING(192783 228138,192612 229814)',3857),'南五环'); INSERT INTO roads (id, geom, road_name) VALUES (4,ST_GeomFromText('LINESTRING(189412 252431,189631 259122)',3857),'西五环'); INSERT INTO roads (id, geom, road_name) VALUES (5,ST_GeomFromText('LINESTRING(190131 224148,190871 228134)',3857),'东长安街'); INSERT INTO roads (id, geom, road_name) VALUES (6,ST_GeomFromText('LINESTRING(198231 263418,198213 268322)',3857),'西长安街');
查询几何对象信息。
SELECT id, ST_AsText(geom) AS geom, road_name FROM roads; -------------------------------- id | geom| road_name --------+-----------------------------------------+----------- 1 | LINESTRING(191232 243118,191108 243242) | 北五环 2 | LINESTRING(189141 244158,189265 244817) | 东五环 3 | LINESTRING(192783 228138,192612 229814) | 南五环 4 | LINESTRING(189412 252431,189631 259122) | 西五环 5 | LINESTRING(190131 224148,190871 228134) | 东长安街 6 | LINESTRING(198231 263418,198213 268322) | 西长安街 (6 rows)
创建索引。
--GiST索引 CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] ); CREATE INDEX [indexname] ON [tablename] USING GIST ([geometryfield] gist_geometry_ops_nd); VACUUM ANALYZE [table_name] [(column_name)]; --举例 Create INDEX sp_geom_index ON ROADS USING GIST(geom); VACUUM ANALYZE ROADS (geom); --BRIN索引 CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geometryfield] ); CREATE INDEX [indexname] ON [tablename] USING BRIN ([geometryfield] brin_geometry_inclusion_ops_3d); CREATE INDEX [indexname] ON [tablename] USING BRIN ([geometryfield] brin_geometry_inclusion_ops_4d); --指定块大小的brin索引 CREATE INDEX [indexname] ON [tablename] USING BRIN ( [geometryfield] ) WITH (pages_per_range = [number]);
空间测量和空间分析。
--Create Table bc_roads: Column | Type | Description ------------+-------------------+------------------- gid | integer | Unique ID name| character varying | Road Name the_geom| geometry | Location Geometry (Linestring) --Create table bc_municipality: Column | Type | Description -----------+-------------------+------------------- gid| integer | Unique ID code | integer | Unique ID name | character varying | City / Town Name the_geom | geometry | Location Geometry (Polygon) --长度计算 SELECT sum(ST_Length(the_geom))/1000 AS km_roads FROM bc_roads; km_roads ------------------ 70842.1243039643 (1 row) --面积计算 SELECT ST_Area(the_geom)/10000 AS hectares FROM bc_municipality WHERE name = 'PRINCE GEORGE'; hectares ------------------ 32657.9103824927 (1 row)
空间关系判断。
--ST_Contains SELECT m.name, sum(ST_Length(r.the_geom))/1000 as roads_km FROM bc_roads AS r, bc_municipality AS m WHERE ST_Contains(m.the_geom,r.the_geom) GROUP BY m.name ORDER BY roads_km; name| roads_km ----------------------------+------------------ SURREY | 1539.47553551242 VANCOUVER | 1450.33093486576 LANGLEY DISTRICT| 833.793392535662 BURNABY | 773.769091404338 PRINCE GEORGE | 694.37554369147 ... --ST_Covers,a circle covering a circle SELECT ST_Covers(smallc,smallc) As smallinsmall, ST_Covers(smallc, bigc) As smallcoversbig, ST_Covers(bigc, ST_ExteriorRing(bigc)) As bigcoversexterior, ST_Contains(bigc, ST_ExteriorRing(bigc)) As bigcontainsexterior FROM (SELECT ST_Buffer(ST_GeomFromText('POINT(1 2)'), 10) As smallc, ST_Buffer(ST_GeomFromText('POINT(1 2)'), 20) As bigc) As foo; --Result smallinsmall | smallcoversbig | bigcoversexterior | bigcontainsexterior --------------+----------------+-------------------+--------------------- t| f | t | f (1 row) --ST_Disjoint SELECT ST_Disjoint('POINT(0 0)'::geometry, 'LINESTRING ( 2 0, 0 2 )'::geometry); st_disjoint --------------- t (1 row) SELECT ST_Disjoint('POINT(0 0)'::geometry, 'LINESTRING ( 0 0, 0 2 )'::geometry); st_disjoint --------------- f (1 row) --ST_Overlaps SELECT ST_Overlaps(a,b) As a_overlap_b, ST_Crosses(a,b) As a_crosses_b, ST_Intersects(a, b) As a_intersects_b, ST_Contains(b,a) As b_contains_a FROM (SELECT ST_GeomFromText('POINT(1 0.5)') As a, ST_GeomFromText('LINESTRING(1 0, 1 1, 3 5)') As b) As foo a_overlap_b | a_crosses_b | a_intersects_b | b_contains_a ------------+-------------+----------------+-------------- f | f | t | t --ST_Relate SELECT ST_Relate(ST_GeometryFromText('POINT(1 2)'), ST_Buffer(ST_GeometryFromText('POINT(1 2)'),2), '0FFFFF212'); st_relate ----------- t --ST_Touches SELECT ST_Touches('LINESTRING(0 0, 1 1, 0 2)'::geometry, 'POINT(1 1)'::geometry); st_touches ------------ f (1 row) SELECT ST_Touches('LINESTRING(0 0, 1 1, 0 2)'::geometry, 'POINT(0 2)'::geometry); st_touches ------------ t (1 row) --ST_Within SELECT ST_Within(smallc,smallc) As smallinsmall, ST_Within(smallc, bigc) As smallinbig, ST_Within(bigc,smallc) As biginsmall, ST_Within(ST_Union(smallc, bigc), bigc) as unioninbig, ST_Within(bigc, ST_Union(smallc, bigc)) as biginunion, ST_Equals(bigc, ST_Union(smallc, bigc)) as bigisunion FROM ( SELECT ST_Buffer(ST_GeomFromText('POINT(50 50)'), 20) As smallc, ST_Buffer(ST_GeomFromText('POINT(50 50)'), 40) As bigc) As foo; --Result smallinsmall | smallinbig | biginsmall | unioninbig | biginunion | bigisunion --------------+------------+------------+------------+------------+------------ t| t | f | t | t | t (1 row)
几何对象存取。
SELECT ST_IsSimple(ST_GeomFromText('POLYGON((1 2, 3 4, 5 6, 1 2))')); st_issimple ------------- t (1 row) SELECT ST_IsSimple(ST_GeomFromText('LINESTRING(1 1,2 2,2 3.5,1 3,1 2,2 1)')); st_issimple ------------- f (1 row) --查询地形中拥有环岛且面积最大的城市 SELECT gid, name, ST_Area(the_geom) AS area FROM bc_municipality WHERE ST_NRings(the_geom) > 1 ORDER BY area DESC LIMIT 1; gid | name | area -----+--------------+------------------ 12 | 安宁市 | 257374619.430216 (1 row)
删除扩展(可选)。
--删除几何扩展 Drop extension ganos_geometry cascade;
SQL参考
详细SQL手册请参见Geometry SQL参考。