明尼苏达州地图服务器是符合OpenGIS网络地图服务规范的互联网网络地图服务器。
地图服务器主页位于 http://mapserver.org 。
OpenGIS Web地图服务规范位于 http://www.opengeospatial.org/standards/wms 。
要在MapServer中使用PostGIS,您需要了解如何配置MapServer,这不在本文档的讨论范围之内。本节介绍特定的PostGIS问题和配置详细信息。
要将PostGIS与MapServer配合使用,您将需要:
PostGIS的0.6版或更高版本。
MapServer 3.5版或更高版本。
MapServer像访问任何其他PostgreSQL客户端一样,使用 libpq
界面。这意味着MapServer可以安装在任何可以通过网络访问PostGIS服务器的计算机上,并使用PostGIS作为数据源。系统之间的连接越快越好。
使用您想要的任何选项编译和安装MapServer,包括“--with-postgis”配置选项。
在MapServer Mapfile 中,添加一个PostGIS图层。例如:
LAYER CONNECTIONTYPE postgis NAME "widehighways" # Connect to a remote spatial database CONNECTION "user=dbuser dbname=gisdatabase host=bigserver" PROCESSING "CLOSE_CONNECTION=DEFER" # Get the lines from the 'geom' column of the 'roads' table DATA "geom from roads using srid=4326 using unique gid" STATUS ON TYPE LINE # Of the lines in the extents, only render the wide highways FILTER "type = 'highway' and numlanes >= 4" CLASS # Make the superhighways brighter and 2 pixels wide EXPRESSION ([numlanes] >= 6) STYLE COLOR 255 22 22 WIDTH 2 END END CLASS # All the rest are darker and only 1 pixel wide EXPRESSION ([numlanes] < 6) STYLE COLOR 205 92 82 END END END
在上面的示例中,特定于PostGIS的指令如下:
对于PostGIS图层,此名称始终为“postgis”。
数据库连接由a‘连接字符串’控制,这是一组标准的键和值,如下所示(在 < > ):
用户= <username> 密码= <password> 数据库名= <username> 主机名= <server> 端口= <5432>
空的连接字符串仍然有效,任何键/值对都可以省略。至少,您通常需要提供要连接的数据库名称和用户名。
此参数的形式为“ <geocolumn> 从… <tablename> 使用SRID= <srid> 使用唯一 <primary key> “其中,列是要呈现到地图的空间列,SRID是列使用的SRID,主键是表主键(或任何其他具有索引的唯一值列)。
您可以省略“USING SRID”和“USING UNIQUE”子句,如果可能,MapServer将自动确定正确的值,但代价是为每个地图绘制在服务器上运行几个额外的查询。
如果有多个层,则输入CLOSE_CONNECTION=DEFER将重用现有连接,而不是关闭它们。这提高了速度。请参阅以了解 MapServer PostGIS性能提示 以获得更详细的解释。
筛选器必须是有效的SQL字符串,对应于SQL查询中通常跟随在“WHERE”关键字之后的逻辑。因此,例如,要仅渲染具有6条或更多车道的道路,请使用过滤器“num_lanes > =6“。
在空间数据库中,确保已为要绘制的任何图层构建了空间(GIST)索引。
CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometrycolumn] );
如果要使用MapServer查询图层,还需要在DATA语句中使用“USING UNIQUE”子句。
在执行查询时,MapServer需要每个空间记录的唯一标识符,而MapServer的PostGIS模块使用您指定的唯一值来提供这些唯一标识符。使用表主键是最佳实践。
这个 USING
伪SQL子句用于添加一些信息,以帮助地图服务器了解更复杂查询的结果。更具体地说,当视图或子选择用作源表时( DATA
定义)对于mapserver来说,自动确定每一行的唯一标识符以及表的SRID更加困难。这个 USING
子句可以为映射服务器提供以下两条信息:
DATA "geom FROM ( SELECT table1.geom AS geom, table1.gid AS gid, table2.data AS data FROM table1 LEFT JOIN table2 ON table1.id = table2.id ) AS new_table USING UNIQUE gid USING SRID=4326"
在执行地图查询时,MapServer要求每行具有唯一的ID,以便标识该行。通常,它从系统表中标识主键。但是,视图和子选择不会自动具有已知的唯一列。如果要使用MapServer的查询功能,则需要确保您的视图或子选择包含唯一值列,并使用 USING UNIQUE
。例如,您可以为此显式选择表的主键值中的一个,或者选择保证对结果集唯一的任何其他列。
![]() | |
“查询地图”是点击地图以查询该位置的地图要素信息的操作。不要将“映射查询”与 |
PostGIS需要知道几何图形正在使用哪个空间参考系统,以便将正确的数据返回给MapServer。通常,可以在PostGIS数据库的“GEOMETRY_COLUMNS”表中找到此信息,但是,对于在即创建的表(如SUBSELECT和VIEW),这是不可能的。因此, USING SRID=
选项允许在 DATA
定义。
让我们从一个简单的例子开始,然后逐步向上。请考虑以下MapServer图层定义:
LAYER CONNECTIONTYPE postgis NAME "roads" CONNECTION "user=theuser password=thepass dbname=thedb host=theserver" DATA "geom from roads" STATUS ON TYPE LINE CLASS STYLE COLOR 0 0 0 END END END
此图层将以黑线显示Roads表中的所有道路几何图形。
现在,假设我们只想显示高速公路,直到我们放大到至少1:100000的比例--下两个层将实现此效果:
LAYER CONNECTIONTYPE postgis CONNECTION "user=theuser password=thepass dbname=thedb host=theserver" PROCESSING "CLOSE_CONNECTION=DEFER" DATA "geom from roads" MINSCALE 100000 STATUS ON TYPE LINE FILTER "road_type = 'highway'" CLASS COLOR 0 0 0 END END LAYER CONNECTIONTYPE postgis CONNECTION "user=theuser password=thepass dbname=thedb host=theserver" PROCESSING "CLOSE_CONNECTION=DEFER" DATA "geom from roads" MAXSCALE 100000 STATUS ON TYPE LINE CLASSITEM road_type CLASS EXPRESSION "highway" STYLE WIDTH 2 COLOR 255 0 0 END END CLASS STYLE COLOR 0 0 0 END END END
第一个层在比例大于1:100000时使用,并且仅以黑线显示“高速公路”类型的道路。这个 FILTER
选项会导致仅显示“高速公路”类型的道路。
第二层在比例小于1:100000时使用,并将高速公路显示为双粗红线,其他道路显示为常规黑线。
因此,我们只使用MapServer功能做了几件有趣的事情,但我们的 DATA
SQL语句保持简单。假设道路的名称存储在另一个表中(无论出于何种原因),我们需要做一个连接来获取它并标记我们的道路。
LAYER CONNECTIONTYPE postgis CONNECTION "user=theuser password=thepass dbname=thedb host=theserver" DATA "geom FROM (SELECT roads.gid AS gid, roads.geom AS geom, road_names.name as name FROM roads LEFT JOIN road_names ON roads.road_name_id = road_names.road_name_id) AS named_roads USING UNIQUE gid USING SRID=4326" MAXSCALE 20000 STATUS ON TYPE ANNOTATION LABELITEM name CLASS LABEL ANGLE auto SIZE 8 COLOR 0 192 0 TYPE truetype FONT arial END END END
当比例尺降至1:20000或更小时,此注释图层会为所有道路添加绿色标签。它还演示了如何在 DATA
定义。
Java客户端可以直接以文本表示形式或使用与PostGIS捆绑在一起的JDBC扩展对象来访问PostgreSQL数据库中的PostGIS“几何”对象。为了使用扩展对象,“postgis.jar”文件必须与“postgresql.jar”JDBC驱动程序包一起位于您的CLASSPATH中。
import java.sql.*; import java.util.*; import java.lang.*; import org.postgis.*; public class JavaGIS { public static void main(String[] args) { java.sql.Connection conn; try { /* * Load the JDBC driver and establish a connection. */ Class.forName("org.postgresql.Driver"); String url = "jdbc:postgresql://localhost:5432/database"; conn = DriverManager.getConnection(url, "postgres", ""); /* * Add the geometry types to the connection. Note that you * must cast the connection to the pgsql-specific connection * implementation before calling the addDataType() method. */ ((org.postgresql.PGConnection)conn).addDataType("geometry",Class.forName("org.postgis.PGgeometry")); ((org.postgresql.PGConnection)conn).addDataType("box3d",Class.forName("org.postgis.PGbox3d")); /* * Create a statement and execute a select query. */ Statement s = conn.createStatement(); ResultSet r = s.executeQuery("select geom,id from geomtable"); while( r.next() ) { /* * Retrieve the geometry as an object then cast it to the geometry type. * Print things out. */ PGgeometry geom = (PGgeometry)r.getObject(1); int id = r.getInt(2); System.out.println("Row " + id + ":"); System.out.println(geom.toString()); } s.close(); conn.close(); } catch( Exception e ) { e.printStackTrace(); } } }
根据类型:点、线串、多边形、多点、多线串、多面,包含特定的拓扑几何对象(抽象类的子类)的包装对象。
PGgeometry geom = (PGgeometry)r.getObject(1); if( geom.getType() == Geometry.POLYGON ) { Polygon pl = (Polygon)geom.getGeometry(); for( int r = 0; r < pl.numRings(); r++) { LinearRing rng = pl.getRing(r); System.out.println("Ring: " + r); for( int p = 0; p < rng.numPoints(); p++ ) { Point pt = rng.getPoint(p); System.out.println("Point: " + p); System.out.println(pt.toString()); } } }
扩展对象的JavaDoc为几何对象中的各种数据访问器函数提供了参考。