小伙伴在用百度高德这类地图的时候有木有发现当地图放大到一定倍数之后就会出现三维效果(2.5纬)。作为一个爱寻根究底的人,我们一定会问,这种地图是如何实现的呢?基于arcgis或者超图吗?NONONO,这类软件太贵!基于Unity3D这类开源的三维引擎做的?NONONO,这是真三维地图。笔者的原则就是能用开源软件就绝不会用商业软件。由于现在主流的制作web地图的开源软件是geoserver+openlayers+postgresql。因此笔者就思索如何基于geoserver和openlayer制作一个伪三维地图。
由于geoserver不支持直接导入三维模型,隐藏笔者直接着眼于sld,看看能不能通过sld来表达三维效果,经过网上的搜索,找到了类似的配置,试验一下成功。
<?xml version="1.0" encoding="ISO-8859-1"?> <StyledLayerDescriptor version="1.0.0" xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- a Named Layer is the basic building block of an SLD document --> <NamedLayer> <Name>default_polygon</Name> <UserStyle> <!-- Styles can have names, titles and abstracts --> <Title>Default Polygon</Title> <Abstract>A sample style that draws a polygon</Abstract> <!-- FeatureTypeStyles describe how to render different features --> <!-- A FeatureTypeStyle for rendering polygons --> <FeatureTypeStyle> <Rule> <PolygonSymbolizer> <Geometry> <ogc:Function name="isometric"> <ogc:PropertyName>geom</ogc:PropertyName> <ogc:Literal>0.00001</ogc:Literal> </ogc:Function> </Geometry> <Fill> <CssParameter name="fill">#dddddd</CssParameter> </Fill> <Stroke> <CssParameter name="stroke">#999999</CssParameter> <CssParameter name="stroke-width">0.1</CssParameter> </Stroke> </PolygonSymbolizer> </Rule> </FeatureTypeStyle> <FeatureTypeStyle> <Rule> <PolygonSymbolizer> <Geometry> <ogc:Function name="offset"> <ogc:PropertyName>geom</ogc:PropertyName> <ogc:Literal>0</ogc:Literal> <ogc:Literal>0.00001</ogc:Literal> </ogc:Function> </Geometry> <Fill> <CssParameter name="fill">#ffffe0</CssParameter> </Fill> <Stroke> <CssParameter name="stroke">#999999</CssParameter> <CssParameter name="stroke-width">0.1</CssParameter> </Stroke> </PolygonSymbolizer> </Rule> </FeatureTypeStyle> </UserStyle> </NamedLayer> </StyledLayerDescriptor>
OK,可以看到三维效果。
但是,总感觉有点不对劲。于是打开百度地图,看看别人家的实现。发现他们在地图缩小的时候是二维效果,只有当地图放大到一定级别之后才会显示2.5纬效果。这种效果如何实现呢?很简单。把地图的样式设为按照比例尺进行表达,不同的比例尺有不同的效果了,当放大到设定的比例尺时显示三维效果。
<?xml version="1.0" encoding="UTF-8"?> <sld:StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml" version="1.0.0"> <sld:UserLayer> <sld:LayerFeatureConstraints> <sld:FeatureTypeConstraint/> </sld:LayerFeatureConstraints> <sld:UserStyle> <sld:Name>hikvision2qi b3 tingchewei</sld:Name> <sld:FeatureTypeStyle> <sld:Name>group 0</sld:Name> <sld:FeatureTypeName>Feature</sld:FeatureTypeName> <sld:SemanticTypeIdentifier>generic:geometry</sld:SemanticTypeIdentifier> <sld:SemanticTypeIdentifier>simple</sld:SemanticTypeIdentifier> <sld:Rule> <sld:Name>Large</sld:Name> <sld:MaxScaleDenominator>200.0</sld:MaxScaleDenominator> <sld:PolygonSymbolizer> <sld:Geometry> <ogc:Function name="isometric"> <ogc:PropertyName>geom</ogc:PropertyName> <ogc:Literal>0.00001</ogc:Literal> </ogc:Function> </sld:Geometry> <sld:Fill> <sld:CssParameter name="fill">#FFE7A6</sld:CssParameter> </sld:Fill> <sld:Stroke> <sld:CssParameter name="stroke">#E8D1AE</sld:CssParameter> <sld:CssParameter name="stroke-width">0.2</sld:CssParameter> </sld:Stroke> </sld:PolygonSymbolizer> <sld:TextSymbolizer> <sld:Label> <ogc:PropertyName>number</ogc:PropertyName> </sld:Label> <sld:Font> <sld:CssParameter name="font-family">Arial</sld:CssParameter> <sld:CssParameter name="font-size">12.0</sld:CssParameter> <sld:CssParameter name="font-style">normal</sld:CssParameter> <sld:CssParameter name="font-weight">normal</sld:CssParameter> </sld:Font> <sld:LabelPlacement> <sld:PointPlacement> <sld:AnchorPoint> <sld:AnchorPointX>0.5</sld:AnchorPointX> <sld:AnchorPointY>0.5</sld:AnchorPointY> </sld:AnchorPoint> <sld:Displacement> <sld:DisplacementX>0.0</sld:DisplacementX> <sld:DisplacementY>0.0</sld:DisplacementY> </sld:Displacement> <sld:Rotation> <ogc:PropertyName>lblrotate</ogc:PropertyName> </sld:Rotation> </sld:PointPlacement> </sld:LabelPlacement> <sld:Fill> <sld:CssParameter name="fill">#404040</sld:CssParameter> </sld:Fill> <sld:VendorOption name="maxDisplacement">0</sld:VendorOption> <sld:VendorOption name="spaceAround">-5</sld:VendorOption> </sld:TextSymbolizer> </sld:Rule> <sld:Rule> <sld:Name>small</sld:Name> <sld:MinScaleDenominator>200.0</sld:MinScaleDenominator> <sld:MaxScaleDenominator>400.0</sld:MaxScaleDenominator> <sld:PolygonSymbolizer> <sld:Fill> <sld:CssParameter name="fill">#FFE7A6</sld:CssParameter> </sld:Fill> <sld:Stroke> <sld:CssParameter name="stroke">#E8D1AE</sld:CssParameter> <sld:CssParameter name="stroke-width">0.2</sld:CssParameter> </sld:Stroke> </sld:PolygonSymbolizer> <sld:TextSymbolizer> <sld:Label> <ogc:PropertyName>number</ogc:PropertyName> </sld:Label> <sld:Font> <sld:CssParameter name="font-family">Arial</sld:CssParameter> <sld:CssParameter name="font-size">10.0</sld:CssParameter> <sld:CssParameter name="font-style">normal</sld:CssParameter> <sld:CssParameter name="font-weight">normal</sld:CssParameter> </sld:Font> <sld:LabelPlacement> <sld:PointPlacement> <sld:AnchorPoint> <sld:AnchorPointX>0.5</sld:AnchorPointX> <sld:AnchorPointY>0.5</sld:AnchorPointY> </sld:AnchorPoint> <sld:Displacement> <sld:DisplacementX>0.0</sld:DisplacementX> <sld:DisplacementY>0.0</sld:DisplacementY> </sld:Displacement> <sld:Rotation> <ogc:PropertyName>lblrotate</ogc:PropertyName> </sld:Rotation> </sld:PointPlacement> </sld:LabelPlacement> <sld:Fill> <sld:CssParameter name="fill">#404040</sld:CssParameter> </sld:Fill> <sld:VendorOption name="maxDisplacement">0</sld:VendorOption> <sld:VendorOption name="spaceAround">-5</sld:VendorOption> </sld:TextSymbolizer> </sld:Rule> <sld:Rule> <sld:Name>medium</sld:Name> <sld:MinScaleDenominator>400.0</sld:MinScaleDenominator> <sld:MaxScaleDenominator>600.0</sld:MaxScaleDenominator> <sld:PolygonSymbolizer> <sld:Fill> <sld:CssParameter name="fill">#FFE7A6</sld:CssParameter> </sld:Fill> <sld:Stroke> <sld:CssParameter name="stroke">#E8D1AE</sld:CssParameter> <sld:CssParameter name="stroke-width">0.2</sld:CssParameter> </sld:Stroke> </sld:PolygonSymbolizer> <sld:TextSymbolizer> <sld:Label> <ogc:PropertyName>number</ogc:PropertyName> </sld:Label> <sld:Font> <sld:CssParameter name="font-family">Arial</sld:CssParameter> <sld:CssParameter name="font-size">6.0</sld:CssParameter> <sld:CssParameter name="font-style">normal</sld:CssParameter> <sld:CssParameter name="font-weight">normal</sld:CssParameter> </sld:Font> <sld:LabelPlacement> <sld:PointPlacement> <sld:AnchorPoint> <sld:AnchorPointX>0.5</sld:AnchorPointX> <sld:AnchorPointY>0.5</sld:AnchorPointY> </sld:AnchorPoint> <sld:Displacement> <sld:DisplacementX>0.0</sld:DisplacementX> <sld:DisplacementY>0.0</sld:DisplacementY> </sld:Displacement> <sld:Rotation> <ogc:PropertyName>lblrotate</ogc:PropertyName> </sld:Rotation> </sld:PointPlacement> </sld:LabelPlacement> <sld:Fill> <sld:CssParameter name="fill">#404040</sld:CssParameter> </sld:Fill> <sld:VendorOption name="maxDisplacement">0</sld:VendorOption> <sld:VendorOption name="spaceAround">-5</sld:VendorOption> </sld:TextSymbolizer> </sld:Rule> <sld:Rule> <sld:Name>Smallest</sld:Name> <sld:MinScaleDenominator>600.0</sld:MinScaleDenominator> <sld:PolygonSymbolizer> <sld:Fill> <sld:CssParameter name="fill">#FFE7A6</sld:CssParameter> </sld:Fill> <sld:Stroke> <sld:CssParameter name="stroke">#E8D1AE</sld:CssParameter> <sld:CssParameter name="stroke-width">0.2</sld:CssParameter> </sld:Stroke> </sld:PolygonSymbolizer> </sld:Rule> </sld:FeatureTypeStyle> <sld:FeatureTypeStyle> <sld:Rule> <sld:Name>Large</sld:Name> <sld:MaxScaleDenominator>200.0</sld:MaxScaleDenominator> <sld:PolygonSymbolizer> <sld:Geometry> <ogc:Function name="offset"> <ogc:PropertyName>geom</ogc:PropertyName> <ogc:Literal>0</ogc:Literal> <ogc:Literal>0.00001</ogc:Literal> </ogc:Function> </sld:Geometry> <sld:Fill> <sld:CssParameter name="fill">#d8e5f2</sld:CssParameter> </sld:Fill> <sld:Stroke> <sld:CssParameter name="stroke">#999999</sld:CssParameter> <sld:CssParameter name="stroke-width">0.1</sld:CssParameter> </sld:Stroke> </sld:PolygonSymbolizer> </sld:Rule> </sld:FeatureTypeStyle> </sld:UserStyle> </sld:UserLayer> </sld:StyledLayerDescriptor>