9.6. 拓扑结构存取函数
9.6.1. GetEdgeByPoint
GetEdgeByPoint — 根据给定的点,返回和该点相交的边界ID。
用法
integer GetEdgeByPoint(varchar atopology, geometry apoint, float8 tol);
根据给定的点,返回和该点相交的边界ID。
根据输入的3个参数,该函数返回一个edge的ID整型值。如果参数tolerance=0,那么点必须要与edge相交。 如果输入的点是节点的位置,那么会抛出异常。为了避免这种情况,运行函数GetNodeByPoint。
如果点和输入的edge不相交,则返回0。
如果输入参数tolerance>0,那么会有多个edge靠近该点,这样会抛出异常。
注意
如果tolerance = 0,该函数使用函数ST_Intersects,否则调用ST_DWithin 。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构,这个样例用到了 AddEdge 函数创建的边:
SELECT topology.GetEdgeByPoint('ma_topo',geom, 1) As with1mtol, topology.GetEdgeByPoint('ma_topo',geom,0) As withnotol FROM ST_GeomFromEWKT('SRID=26986;POINT(227622.6 893843)') As geom; with1mtol | withnotol -----------+----------- 2 | 0 SELECT topology.GetEdgeByPoint('ma_topo',geom, 1) As nearnode FROM ST_GeomFromEWKT('SRID=26986;POINT(227591.9 893900.4)') As geom; -- get error -- ERROR: Two or more edges found
参考
AddEdge, GetNodeByPoint
9.6.2. GetFaceByPoint
GetFaceByPoint — 根据给定的点,查找与该点相交的面id值。
用法
integer GetFaceByPoint(varchar atopology, geometry apoint, float8 tol);
描述
根据给定的点,查找与该点相交的面id值。
根据输入的3个参数,该函数返回一个面ID整型值。如果参数tolerance=0,那么点必须要与face相交。如果输入的点是节点的位置,那么会抛出异常。为了避免这种情况,运行函数GetNodeByPoint。
如果点和输入的面不相交,则返回0 。
如果输入参数tolerance>0,那么会有多个面靠近该点,这样会抛出异常。
注意
如果tolerance = 0,该函数使用函数ST_Intersects,否则调用ST_DWithin 。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构,这个样例用到了 AddFace 函数创建的边和面:
SELECT topology.GetFaceByPoint('ma_topo',geom, 10) As with1mtol, topology.GetFaceByPoint('ma_topo',geom,0) As withnotol FROM ST_GeomFromEWKT('POINT(234604.6 899382.0)') As geom; with1mtol | withnotol -----------+----------- 1 | 0 SELECT topology.GetFaceByPoint('ma_topo',geom, 1) As nearnode FROM ST_GeomFromEWKT('POINT(227591.9 893900.4)') As geom; -- get error -- ERROR: Two or more faces found
参考
AddFace, GetNodeByPoint, GetEdgeByPoint
9.6.3. GetNodeByPoint
GetNodeByPoint — 找出一个点位置的结点的ID。
用法
integer GetNodeByPoint(varchar atopology, geometry point, float8 tol);
找出一个点位置的结点的ID。
这个函数根据参数topology,point和tolerance(容差)返回一个整型值(结点的ID)。 如果tolerance = 0 意味着完全位置完全重合,否则将从一个区间获取结点。如果参数point点位置上没有结点,那么函数将返回0。 如果使用tolerance>0,并且靠近point多于一个结点,那么函数将会抛出一个异常。
注意
如果tolerance = 0,该函数使用函数ST_Intersects,否则调用ST_DWithin。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构,这个样例用到了 AddEdge 函数创建的边:
SELECT topology.GetNodeByPoint('ma_topo',geom, 1) As nearnode FROM ST_GeomFromEWKT('SRID=26986;POINT(227591.9 893900.4)') As geom; nearnode ---------- 2 SELECT topology.GetNodeByPoint('ma_topo',geom, 1000) As too_much_tolerance FROM ST_GeomFromEWKT('SRID=26986;POINT(227591.9 893900.4)') As geom; ----get error-- ERROR: Two or more nodes found
参考
AddEdge, GetEdgeByPoint
9.6.4. GetTopologyID
GetTopologyID —根据拓扑名称,返回一个在topology.topology拓扑表中的拓扑结构的ID值。
用法
integer GetTopologyID(varchar toponame);
描述
根据拓扑名称,返回一个在topology.topology 拓扑表中的拓扑结构的ID值。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构:
SELECT topology.GetTopologyID('ma_topo') As topo_id; topo_id --------- 1
参考
CreateTopology, DropTopology, GetTopologyName, GetTopologySRID
9.6.5. GetTopologySRID
GetTopologySRID —根据拓扑名称,返回一个在topology.topology拓扑表中的拓扑结构的SRID值。
用法
integer GetTopologyID(varchar toponame);
描述
根据拓扑名称,返回一个在topology.topology 拓扑表中的拓扑结构的SRID值。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构:
SELECT topology.GetTopologySRID('ma_topo') As SRID; SRID ------- 4326
参考
CreateTopology, DropTopology, GetTopologyName, GetTopologyID
9.6.6. GetTopologyName
GetTopologyName — 根据拓扑编号,返回一个拓扑结构的拓扑名称。
用法
varchar GetTopologyName(integer topology_id);
描述
根据拓扑编号,返回一个拓扑结构的拓扑名称。根据系统表topology.topology的拓扑ID值,返回一个拓扑结构的拓扑名称。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构:
SELECT topology.GetTopologyName(1) As topo_name; topo_name ----------- ma_topo
参考
CreateTopology, DropTopology, GetTopologyID, GetTopologySRID
9.6.7. ST_GetFaceEdges
ST_GetFaceEdges — 返回包围一个面的有序边界集合。
用法
getfaceedges_returntype ST_GetFaceEdges(varchar atopology, integer aface);
描述
返回包围一个面的有序边界集合。每一行输出包含了一个序列和edgeid(边id)。序列号从1开始。 每一个环的边从边id最小的开始计数。边的顺序按照左手定则(面必须在每一个有向边的左侧)来确定的。
该方法实现了SQL-MM规范: SQL-MM 3 Topo-Geo and Topo-Net 3: Routine Details: X.3.5
样例
假设数据库中已存在名为“tt”的拓扑结构:
-- Returns the edges bounding face 1 SELECT (topology.ST_GetFaceEdges('tt', 1)).*; -- result -- sequence | edge ----------+------ 1 | -4 2 | 5 3 | 7 4 | -6 5 | 1 6 | 2 7 | 3 (7 rows) -- Returns the sequenc, edge id, -- and geometry of the edges that bound face 1 -- If you just need geom and seq, can use ST_GetFaceGeometry SELECT t.seq, t.edge, geom FROM topology.ST_GetFaceEdges('tt',1) As t(seq,edge) INNER JOIN tt.edge AS e ON abs(t.edge) = e.edge_id;
参考
GetRingEdges, AddFace, ST_GetFaceGeometry
9.6.8. ST_GetFaceGeometry
ST_GetFaceGeometry —根据给定的拓扑结构和面ID,返回一个polygon 对象。
用法
geometry ST_GetFaceGeometry(varchar atopology, integer aface);
描述
根据给定的拓扑结构和面ID,返回一个polygon对象。该polygon对象就是组成面的边界。
该方法实现了SQL-MM规范: SQL-MM 3 Topo-Geo and Topo-Net 3: Routine Details: X.3.16
样例
假设数据库中已存在名为“ma_topo”的拓扑结构:
-- Returns the wkt of the polygon added with AddFace SELECT ST_AsText(topology.ST_GetFaceGeometry('ma_topo', 1)) As facegeomwkt; -- result -- facegeomwkt -------------------------------------------------------------------------------- POLYGON((234776.9 899563.7,234896.5 899456.7,234914 899436.4,234946.6 899356.9, 234872.5 899328.7,234891 899285.4,234992.5 899145,234890.6 899069, 234755.2 899255.4,234612.7 899379.4,234776.9 899563.7))
参考
AddFace
9.6.9. GetRingEdges
GetRingEdges — 根据给定的边返回一个环的有序边界集合。
用法
getfaceedges_returntype GetRingEdges(varchar atopology, integer aring, integer max_edges=null);
描述
根据给定的边,返回一个组成环的有序边集合。每一行输出包含了一个序列和一个有符号的边ID。序列号从1开始。 如果边ID值是负数,表示给定的边是反向的。可以传递一个负的edgeid表示从反向开始输出。 如果参数max_edges值不是null,那么函数返回的记录数将不超过参数max_edges的值。当可能遇到无效的拓扑结构时候,这是一个安全的参数。
参考
ST_GetFaceEdges, GetNodeEdges
9.6.10. GetNodeEdges
GetNodeEdges — 根据给定的结点,跟着该结点的有序边。
用法
getfaceedges_returntype GetNodeEdges(varchar atopology, integer anode);
描述
根据给定的结点,跟着该结点的有序边。每一行输出包含了一个序列和一个有符号的边ID。序列号从1开始。 一个正向的边的起点是给定的结点,一个负向的边终点是给定的点。封闭的边会出现两次(边id都是有符号的数字)。顺序是从北向开始顺时针开始计算。
注意
这个函数计算边的顺序而不是从元数据中读取数据,因此能用于建立循环边。
参考
GetRingEdges, ST_Azimuth
9.7. 拓扑处理函数
9.7.1. Polygonize 多边形化
Polygonize — 找出并注册所有由拓扑边定义的面。
用法
text Polygonize(varchar toponame);
描述
找出并注册所有由拓扑边定义的面。目标拓扑结构假定包含了没有自相交的边。
注意
所有已知的面都会被识别出来,因此对同一个拓扑结构多次调用 Polygonize 是安全的。
注意
该函数既不会使用,也不会设置边表的 next_left_edge 字段和 next_right_edge 字段。
参考
AddFace, ST_Polygonize
9.7.2. AddNode
AddNode — 在指定 topology schema 的节点表中加入一个 point 节点,并返回这个新节点的 nodeid 。 如果给定的 point 在节点表中已经有一个对应的节点,则返回该节点的 nodeid 。
用法
integer AddNode(varchar toponame, geometry apoint, boolean allowEdgeSplitting=false, boolean computeContainingFace=false);
描述
在指定 topology schema 的节点表中加入一个 point 节点。 AddEdge函数被调用时会自动添加边的起点和终点,因此无需显式地添加边上的节点。 如果添加的边与任何已有的边相交,则会抛出一个异常或者将新加的边切分,具体取决于 allowEdgeSplitting 参数的设置。
如果 computeContainingFace 为 true,一个新加入的节点被哪个面包含将会被计算出来。
注意
如果一个 point 几何对象已经以节点的形式存在于拓扑结构中,将不会添加新的节点,并将现有节点的 nodeid 返回。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构:
SELECT topology.AddNode('ma_topo',ST_GeomFromText('POINT(227641.6893816.5)', 26986) ) As nodeid; -- result -- nodeid -------- 4
参考
AddEdge, CreateTopology
9.7.3. AddEdge
AddEdge — 使用给定的 linestring 几何对象向指定的 topology schema 中加入一条边,并将其起点和终点关联到节点表中相应的点,最后返回新增的边(或现存对应的边)的 edgeid。
用法
integer AddEdge(varchar toponame, geometry aline);
描述
使用给定的 linestring 几何对象,向边表中加入一条边,并将节点关联到指定 topology schema 的边表上,最后返回对应边的 edgeid。 新增的边两侧都是“universe”面,并且链接到其自身。
注意
如果一个aline几何对象穿越现有的 linestring 边,与现有的 linestring 边重叠,包含现有的 linestring 边,或者被现有的 linestring 边包含, 将会抛出一个错误,并且不会加入任何新的边。
注意
给定的aline几何对象必须与给定的拓扑结构具有相同的 SRID,否则将会抛出一个“非法空间坐标参考系”错误。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构:
SELECT topology.AddEdge('ma_topo', ST_GeomFromText('LINESTRING(227575.8 893917.2,227591.9 893900.4)', 26986) ) As edgeid; -- result edgeid -------- 1 SELECT topology.AddEdge('ma_topo', ST_GeomFromText('LINESTRING(227591.9 893900.4,227622.6 893844.2,227641.6 893816.5, 227704.5 893778.5)', 26986) ) As edgeid; -- result -- edgeid -------- 2 SELECT topology.AddEdge('ma_topo', ST_GeomFromText('LINESTRING(227591.2 893900, 227591.9 893900.4, 227704.5 893778.5)', 26986) ) As edgeid; -- gives error -- ERROR: Edge intersects (not on endpoints) with existing edge 1
参考
CreateTopology, 3.3.1节
9.7.4. AddFace
AddFace — 把一个面要素添加到一个拓扑结构中,然后获取它的面ID。
用法
integer AddFace(varchar toponame, geometry apolygon, boolean force_new=false);
描述
把一个面要素添加到一个拓扑结构中,然后获取它的面ID。对于新添加的面,组成该面的边和面里面的对象会被更新成由参数left_face和参数right_face设置的值。面中的孤立点会被更新成参数containing_face的值。
注意
这个函数不使用也不设置edge表的参数next_left_edge 和 next_right_edge。
函数参数topologyname被假定是有效的(不包含自相交的边)。如果出现下面这些情况那么将抛出异常:如果多边形边界不是由已经存在的边完全定义或多边形与一个已经存在的面交叠。
如果参数apolygon几何对象已经作为一个面存在,那么如果参数force_new设置为false (即函数的默认值),那么返回的是已经存在的face面的id;如果force_new 设置为true,那么返回的是新生成的面的ID。
注意
当一个已经存在的面被注册(即添加到系统表中)时候(force_new=true),那么函数不会做任何操作去处理一个引用不定的已经存在的面的边,节点等对象,同时已经存在的面记录的MBR字段也不会更新。由调用者决定怎样处理。
注意
参数apolygon多边形几何对象必须和拓扑结构的SRID值一致,否则将会抛出一个无效的空间参考系错误。
样例
假设数据库中已存在名为“ma_topo”的拓扑结构:
-- first add the edges we use generate_series as an iterator (the below -- will only work for polygons with < 10000 points because of our max in gs) SELECT topology.AddEdge('ma_topo', ST_MakeLine(ST_PointN(geom,i), ST_PointN(geom, i + 1) )) As edgeid FROM (SELECT ST_NPoints(geom) AS npt, geom FROM (SELECT ST_Boundary(ST_GeomFromText('POLYGON((234896.5 899456.7,234914 899436.4,234946.6 899356.9,234872.5 899328.7, 234891 899285.4,234992.5 899145, 234890.6 899069,234755.2 899255.4, 234612.7 899379.4,234776.9 899563.7,234896.5 899456.7))', 26986) ) As geom ) As geoms) As facen CROSS JOIN generate_series(1,10000) As i WHERE i < npt; -- result -- edgeid -------- 3 4 5 6 7 8 9 10 11 12 (10 rows) -- then add the face - SELECT topology.AddFace('ma_topo',ST_GeomFromText('POLYGON((234896.5 899456.7,234914 899436.4,234946.6 899356.9,234872.5 899328.7, 234891 899285.4,234992.5 899145, 234890.6 899069,234755.2 899255.4, 234612.7 899379.4,234776.9 899563.7,234896.5 899456.7))', 26986) ) As faceid; -- result -- faceid -------- 1
参考
AddEdge, CreateTopology, 3.3.1节
9.7.5. ST_Simplify
ST_Simplify — 使用Douglas-Peucker算法,将一个拓扑结构简化成简单的几何对象。
用法
geometry ST_Simplify(TopoGeometry geomA, float tolerance);
描述
使用Douglas-Peucker 算法,将一个拓扑结构的每个边界简化成简单的几何对象。
注意
返回的几何对象可能是非简单的或非有效的。分隔组成边界可能有助于保留简单性及有效性。
参考
Geometry ST_Simplify, ST_IsSimple, ST_IsValid, ST_ModEdgeSplit
9.8. 拓扑结构构建函数
9.8.1. CreateTopoGeom
CreateTopoGeom —从一个拓扑元素数组创建一个拓扑结构。参数tg_type值对应关系如下:
1:[multi]point, 2:[multi]line, 3:[multi]poly, 4:collection
用法
topogeometry CreateTopoGeom(varchar toponame, integer tg_type, integer layer_id, topoelementarray tg_objs); topogeometry CreateTopoGeom(varchar toponame, integer tg_type, integer layer_id);
描述
为函数参数layer_id标识的layer创建一个topogeometry对象,然后把它的信息注册到toposchema为toponame的关系表中。参数tg_type是一个整型值,对应关系如下: 1:[multi]point, 2:[multi]line,3:[multi]poly, 4:collection
layer_id是系统表topology.layer 的layer_id字段。
点图层是由结点组成的,线性图层是由边集合组成的,面积图层是由面的集合组成的,集合图层是由结点,边,和面混合组成的。 如果省略了第三个数组参数,那么将返回一个空的TopoGeometry对象。
样例 : Form from existing edges
假设数据库中已存在名为“ri_topo”的拓扑结构:
-- Create a topogeom in ri_topo schema for layer 2 (our ri_roads), of type(2) LINE, -- for the first edge (we loaded in ST_CreateTopoGeo). INSERT INTO ri.ri_roads(road_name, topo) VALUES('Unknown',topology.CreateTopoGeom('ri_topo',2,2,'{{1,2}}'::topology.topoelementarray);
样例 : Convert an areal geometry to best guess topogeometry
假设我们有一个名为“topo_boston”的 topology schema,有一组由面集合组成的几何对象,一个块分组表,想知道每个块分组的拓扑几何对象。 如果我们的数据是完美对齐的,可以进行如下操作:
-- create our topo geometry column -- SELECT topology.AddTopoGeometryColumn('topo_boston','boston', 'blockgroups', 'topo', 'POLYGON'); -- addtopgeometrycolumn --1 -- update our column assuming -- everything is perfectly aligned with our edges UPDATE boston.blockgroups AS bg SET topo = topology.CreateTopoGeom('topo_boston',3,1, foo.bfaces) FROM (SELECT b.gid, topology.TopoElementArray_Agg(ARRAY[f.face_id,3]) As bfaces FROM boston.blockgroups As b INNER JOIN topo_boston.face As f ON b.geom && f.mbr WHERE ST_Covers(b.geom, topology.ST_GetFaceGeometry('topo_boston', f.face_id)) GROUP BY b.gid) As fooWHERE foo.gid = bg.gid; --the world is rarely perfect allow for some error --count the face if 50% of it falls -- within what we think is our blockgroup boundaryUPDATE boston.blockgroups AS bg SET topo = topology.CreateTopoGeom('topo_boston' ,3,1 , foo.bfaces) FROM (SELECT b.gid, topology.TopoElementArray_Agg(ARRAY[f.face_id,3]) As bfaces FROM boston.blockgroups As b INNER JOIN topo_boston.face As f ON b.geom && f.mbr WHERE ST_Covers(b.geom, topology.ST_GetFaceGeometry('topo_boston', f.face_id)) OR ( ST_Intersects(b.geom, topology.ST_GetFaceGeometry('topo_boston', f.face_id)) AND ST_Area(ST_Intersection(b.geom, topology.ST_GetFaceGeometry('topo_boston', f.face_id) ) ) > ST_Area(topology.ST_GetFaceGeometry('topo_boston', f.face_id))*0.5 ) GROUP BY b.gid) As foo WHERE foo.gid = bg.gid; -- and if we wanted to convert our topogeometry back -- to a denomalized geometry aligned with our faces and edges -- cast the topo to a geometry -- The really cool thing is my new geometries-- are now aligned with my tiger street centerlines UPDATE boston.blockgroups SET new_geom = topo::geometry;
参考
AddTopoGeometryColumn, toTopoGeom ST_CreateTopoGeo, ST_GetFaceGeometry, TopoElementArray, TopoElementArray_Agg
9.8.2. toTopoGeom
toTopoGeom — 把一个简单的几何对象转换成拓扑结构。
用法
topogeometry toTopoGeom(geometry geom, varchar toponame, integer layer_id, float8 tolerance); topogeometry toTopoGeom(geometry geom,topogeometry topogeom, float8 tolerance);
描述
把一个简单的几何对象转换成拓扑结构。
表示拓扑结构要素的输入geometry对象需要添加到底层的拓扑结构中,可能会分割掉已经存在的拓扑,并且他们需要在关系表中与输出的TopoGeometry产生关联。 已经有的TopoGeometry对象(如果给出了topogeom参数值)会保留他们的形状。当参数tolerance给定了后,这个参数会用于把输入的geometry对象分割并装入到已经有拓扑要素中。 在函数的第一种形式中,根据指定的拓扑结构toponame和图层layer_id会创建一个新的TopoGeometry对象。
在第二种形式中转换的结果会被添加到已经存在的TopoGeometry(topogeom)的对象中。
想要让新的形状完全替代就的形状参考clearTopoGeom。
样例
这是一个完全自包含的工作流。假设我们有一个名为“topo_boston_test”的 topology schema :
-- do this if you don’t have a topology setup already -- creates topology not allowing any tolerance SELECT topology.CreateTopology('topo_boston_test', 2249); -- create a new table CREATE TABLE nei_topo(gid serial primary key, nei varchar(30)); -- add a topogeometry column to it SELECT topology.AddTopoGeometryColumn('topo_boston_test', 'public', 'nei_topo', 'topo', 'MULTIPOLYGON') As new_layer_id; new_layer_id ----------- 1 -- use new layer id in populating the new topogeometry column -- we add the topogeoms to the new layer with 0 tolerance INSERT INTO nei_topo(nei, topo) SELECT nei, topology.toTopoGeom(geom, 'topo_boston_test', 1) FROM neighborhoods WHERE gid BETWEEN 1 and 15; -- use to verify what has happened -- SELECT * FROM topology.TopologySummary('topo_boston_test'); -- summary -- Topology topo_boston_test (5), SRID 2249, precision 061 nodes, 87 edges, 35 faces, 15 topogeoms in 1 layers Layer 1, type Polygonal (3), 15 topogeoms Deploy: public.nei_topo.topo -- Shrink all TopoGeometry polygons by 10 meters UPDATE nei_topo SET topo = ST_Buffer(clearTopoGeom(topo), -10); -- Get the no-one-lands left by the above operation -- I think GRASS calls this "polygon0 layer" SELECT ST_GetFaceGeometry('topo_boston_test', f.face_id) FROM topo_boston_test.face f WHERE f.face_id > 0 -- don’t consider the universe face AND NOT EXISTS ( -- check that no TopoGeometry references the face SELECT * FROM topo_boston_test.relation WHERE layer_id = 1 AND element_id = f.face_id );
参考
CreateTopology, AddTopoGeometryColumn, CreateTopoGeom, TopologySummary, clearTopoGeom
9.8.3. TopoElementArray_Agg
TopoElementArray_Agg —返回一个topoelementarray数组,它是element_id,type arrays (topoelements)的集合。
用法
topoelementarray TopoElementArray_Agg(topoelement set tefield);
描述
这个函数用于从TopoElement集合中创建一个TopoElementArray 对象。
样例
SELECT topology.TopoElementArray_Agg(ARRAY[e,t]) As tea FROM generate_series(1,3) As e CROSS JOIN generate_series(1,4) As t; tea -------------------------------------------------------------------------- {{1,1},{1,2},{1,3},{1,4},{2,1},{2,2},{2,3},{2,4},{3,1},{3,2},{3,3},{3,4}}
参考
TopoElement, TopoElementArray