图层渲染是GIS应用之中十分常用的功能,所有基于ArcOjects组件的ArcGIS软件产品(如: ArcGIS Desktop, ArcGIS Engine, ArcGIS Server), 还有ArcIMS和MapObjects(Windows Edition & Java Edition)都提供了各种实用的渲染方法,详细列举如下: ArcOjects提供了SimpleRenderer, UniqueValueMapRenderer, ClassBreaksRenderer, DotDensityRenderer, ProportionalSymbolRenderer, ChartRenderer; ArcIMS提供了SimpleRenderer, SimpleLabelRenderer, ValueMapRenderer, ValueMapLableRenderer, ScaleDependentRenderer, GroupRenderer; MapObjects Windows Edition提供了ValueMapRenderer, ClassBreaksRenderer, DotDensityRenderer, LabelRenderer, EventRenderer, ZRenderer, GroupRenderer; MapObjects JavaEdition提供了SimpleRenderer, ValueMapRenderer, LabelRenderer, ScaleDependentRenderer, GroupRenderer; 跟一般的渲染功能有所不同,在ArcIMS和MapObjects的两个版本中都提供的GroupRender它本身并不利用任何图层的属性来对图层进行渲染,而是通过借用其他Renderer的功能,把它们组合起来,实现对同一个图层进行不同类型的渲染效果的同时展现,比如对一个包含了人口总数量,男性人口数量和女性人口数量的世界地图图层(面状)先利用人口总数量属性现实分类渲染的效果,同时利用男性人口数量和女性人口数量属性用直棒图选然展现出两个数值比较的效果。 可惜的是ArcObjects中偏偏没有实现这种渲染功能。不过基于COM技术的ArcObjects所具有的可扩展性为我们自己去实现"GroupRenderer"提供了可能。 |
ArcObjects中,图层的渲染效果是通过实例化一个实现了某个渲染接口(ISimpleRenderer, IUniqueValueMapRenderer, IClassBreaksRenderer, IDotDensityRenderer, IProportionalSymbolRenderer, IChartRenderer之一)的CoClass类,然后作为该渲染接口类型的变量赋给图层(IGeoFeatureLayer)的Renderer属性来实现的。这个Renderer属性是IFeatureRenderer接口类型,IFeatureRenderer中定义了一个叫做Draw的方法,其实ArcObjects中各种各样的渲染效果就是通过这个Draw方法画出来的,因为各个渲染效果CoClass都实现了IFeatureRenderer接口。所以要实现"GroupRenderer"效果,只要实现了IFeatureRenderer接口就可以了。以下提供VB和ArcGIS Server Java API的例程供大家参考: [VB6: CustomGroupRenderer.cls] Option Explicit
Implements IFeatureRenderer
Private m_Renderers As Collection
Private Sub Class_Initialize() On Error GoTo ErrHand Set m_Renderers = New Collection GoTo EndProc ErrHand: MsgBox "Class Initialize" & Err.Description EndProc: Exit Sub End Sub
Private Function IFeatureRenderer_CanRender(ByVal featClass As esriGeoDatabase.IFeatureClass, ByVal Display As esriDisplay.IDisplay) As Boolean On Error GoTo ErrHand If Not featClass.ShapeType = esriGeometryNull Then IFeatureRenderer_CanRender = True Else IFeatureRenderer_CanRender = False End If GoTo EndProc ErrHand: MsgBox "CanRender" & Err.Description EndProc: Exit Function End Function
Private Sub IFeatureRenderer_Draw(ByVal Cursor As esriGeoDatabase.IFeatureCursor, _ ByVal drawPhase As esriSystem.esriDrawPhase, _ ByVal Display As esriDisplay.IDisplay, _ ByVal trackCancel As esriSystem.ITrackCancel) On Error GoTo ErrHand Dim i As Integer For i = 1 To m_Renderers.Count Dim r As IFeatureRenderer Set r = m_Renderers.Item(i) If (TypeOf r Is ISimpleRenderer) And (drawPhase = esriDPGeography) Then r.Draw Cursor, drawPhase, Display, trackCancel ElseIf (TypeOf r Is IUniqueValueRenderer) And (drawPhase = esriDPGeography) Then r.Draw Cursor, drawPhase, Display, trackCancel ElseIf (TypeOf r Is IClassBreaksRenderer) And (drawPhase = esriDPGeography) Then r.Draw Cursor, drawPhase, Display, trackCancel ElseIf (TypeOf r Is IDotDensityRenderer) And (drawPhase = esriDPGeography) Then r.Draw Cursor, drawPhase, Display, trackCancel ElseIf (TypeOf r Is IProportionalSymbolRenderer) And (drawPhase = esriDPAnnotation) Then r.Draw Cursor, drawPhase, Display, trackCancel ElseIf (TypeOf r Is IChartRenderer) And (drawPhase = esriDPAnnotation) Then r.Draw Cursor, drawPhase, Display, trackCancel End If Next i GoTo EndProc ErrHand: MsgBox "Draw" & Err.Description EndProc: Exit Sub End Sub
Private Sub IFeatureRenderer_PrepareFilter(ByVal pFeatClass As esriGeoDatabase.IFeatureClass, ByVal QueryFilter As esriGeoDatabase.IQueryFilter) Dim i As Integer For i = 1 To m_Renderers.Count Dim r As IFeatureRenderer Set r = m_Renderers.Item(i) r.PrepareFilter pFeatClass, QueryFilter Next i End Sub
Private Property Set IFeatureRenderer_ExclusionSet(ByVal pIDSet As esriCarto.IFeatureIDSet)
End Property
Private Property Get IFeatureRenderer_RenderPhase(ByVal drawPhase As esriSystem.esriDrawPhase) As Boolean On Error GoTo ErrHand IFeatureRenderer_RenderPhase = True Exit Property ErrHand: MsgBox "Get RenderPhase" & Err.Description End Property
Private Property Get IFeatureRenderer_SymbolByFeature(ByVal Feature As esriGeoDatabase.IFeature) As esriDisplay.ISymbol On Error GoTo ErrHand Dim pSym As ISymbol Set pSym = m_LegendGroup.Class(0).Symbol Set IFeatureRenderer_SymbolByFeature = pSym GoTo EndProc ErrHand: MsgBox Err.Description EndProc: Set pSym = Nothing Exit Property End Property
Public Sub AddRenderer(ByVal renderer As esriCarto.IFeatureRenderer) m_Renderers.Add renderer End Sub ==========================================================================================================================================================
[ArcGIS Server Java API]
//IGroupRenderer.java
package com.esri.arcgis.samples.carto.renderers;
import com.linar.jintegra.AutomationException; import java.io.IOException; import java.io.Serializable;
public interface IGroupRenderer extends Serializable { public static final int IID27AC33C1_506B_41F6_B2F0_D6F163CB7699 = 1; public static final int xxDummy = 0; public static final String IID = "27AC33C1-506B-41F6-B2F0-D6F163CB7699";
public void addRenderer(Object iRenderer) throws IOException, AutomationException; }
//CustomGroupRenderer.java
package com.esri.arcgis.samples.carto.renderers;
import java.io.IOException; import java.util.ArrayList; import com.esri.arcgis.server.*; import com.esri.arcgis.carto.*; import com.esri.arcgis.display.*; import com.esri.arcgis.geodatabase.*; import com.esri.arcgis.system.*; import com.esri.arcgis.geometry.esriGeometryType; import com.esri.arcgis.system.esriDrawPhase; import com.linar.jintegra.AutomationException;
public class CustomGroupRenderer implements IFeatureRenderer, IGroupRenderer { private ILegendGroup pLegendGroup; private IServerContext serverContext; private ArrayList renderers = new ArrayList();
public CustomGroupRenderer(IServerContext sc) { try { serverContext = sc; pLegendGroup = new ILegendGroupProxy(serverContext.createObject(LegendGroup.getClsid())); ILegendClass pLegendClass = new ILegendClassProxy(sc.createObject(LegendClass.getClsid())); pLegendGroup.addClass(pLegendClass); pLegendGroup.setVisible(true); pLegendGroup.setEditable(true); } catch (AutomationException e) { System.out.println("AutomationException " + e); } catch (IOException e) { System.out.println("IOException " + e); } }
public boolean canRender(IFeatureClass iFeatureClass, IDisplay iDisplay) throws IOException, AutomationException { if (iFeatureClass.getShapeType() == esriGeometryType.esriGeometryNull) { return true; } else { return false; } }
public void prepareFilter(IFeatureClass iFeatureClass, IQueryFilter iQueryFilter) throws IOException, AutomationException { if (renderers.size() > 0) { for (int i = 0; i < renderers.size(); i++) { IFeatureRenderer pFR = new IFeatureRendererProxy(renderers.get(i)); pFR.prepareFilter(iFeatureClass, iQueryFilter); } } }
public void draw(IFeatureCursor iFeatureCursor, int drawPhase, IDisplay iDisplay, ITrackCancel iTrackCancel) throws IOException, AutomationException { if (renderers.size() > 0) { for (int i = 0; i < renderers.size(); i++) { Object obj = renderers.get(i); if (obj instanceof ISimpleRenderer && drawPhase == esriDrawPhase.esriDPGeography) { IFeatureRenderer pFR = new IFeatureRendererProxy(obj); pFR.draw(iFeatureCursor, drawPhase, iDisplay, iTrackCancel); } if (obj instanceof IUniqueValueRenderer && drawPhase == esriDrawPhase.esriDPGeography) { IFeatureRenderer pFR = new IFeatureRendererProxy(obj); pFR.draw(iFeatureCursor, drawPhase, iDisplay, iTrackCancel); } if (obj instanceof IClassBreaksRenderer && drawPhase == esriDrawPhase.esriDPGeography) { IFeatureRenderer pFR = new IFeatureRendererProxy(obj); pFR.draw(iFeatureCursor, drawPhase, iDisplay, iTrackCancel); } if (obj instanceof IDotDensityRenderer && drawPhase == esriDrawPhase.esriDPGeography) { IFeatureRenderer pFR = new IFeatureRendererProxy(obj); pFR.draw(iFeatureCursor, drawPhase, iDisplay, iTrackCancel); } if (obj instanceof IProportionalSymbolRenderer && drawPhase == esriDrawPhase.esriDPAnnotation) { IFeatureRenderer pFR = new IFeatureRendererProxy(obj); pFR.draw(iFeatureCursor, drawPhase, iDisplay, iTrackCancel); } if (obj instanceof IChartRenderer && drawPhase == esriDrawPhase.esriDPAnnotation) { IFeatureRenderer pFR = new IFeatureRendererProxy(obj); pFR.draw(iFeatureCursor, drawPhase, iDisplay, iTrackCancel); } } } }
public ISymbol getSymbolByFeature(IFeature iFeature) throws IOException, AutomationException { ISymbol pSym = pLegendGroup.esri_getClass(0).getSymbol(); return pSym; }
public boolean isRenderPhase(int drawPhase) throws IOException, AutomationException { return true; }
public void setExclusionSetByRef(IFeatureIDSet iFeatureIDSet) throws IOException, AutomationException {
}
public void addRenderer(Object iRenderer) throws IOException, AutomationException { renderers.add(iRenderer); } }
如果想要在TOC控件上动态的展现出渲染的效果,还需实现ILegendInfo接口,这里不做详细说明。 |