明尼苏达州地图服务器是符合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为几何对象中的各种数据访问器函数提供了参考。