Optimized_Renderer
OptimisedRenderer.cpp
// OptimisedRenderer.cpp : Implementation of COptimisedRenderer
#include "stdafx.h"
#include "math.h"
#include "Optimised.h"
#include "OptimisedRenderer.h"

/////////////////////////////////////////////////////////////////////////////
// COptimisedRenderer

STDMETHODIMP COptimisedRenderer::CanRender(IFeatureClass* pFClass, IDisplay* pDisplay, VARIANT_BOOL* pCanRender)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())
  if (!pCanRender)
    return E_POINTER;

  *pCanRender = VARIANT_FALSE;

  if (!pFClass)
    return S_FALSE;

  // Does the layer have a geometry type we support
  esriGeometryType stype;
  pFClass->get_ShapeType(&stype);
  if (stype != esriGeometryNull)
    *pCanRender = VARIANT_TRUE;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::PrepareFilter(IFeatureClass* pFClass, IQueryFilter* pQueryFilter)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())
  esriGeometryType stype;
  m_ipSymbol = 0;
  pFClass->get_ShapeType(&stype);
  switch(stype)
  {
    case esriGeometryPoint:
    case esriGeometryMultipoint:
      m_ipSymbol = m_ipMarkerSymbol;
      break;
    case esriGeometryPolygon:
      m_ipSymbol = m_ipFillSymbol;
      break;
    case esriGeometryPolyline:
      m_ipSymbol = m_ipLineSymbol;
      break;
    default :
      return E_NOTIMPL;
  }
  
  // If an exclusion set is in operation we must make sure the OID is a required field
  long numExcluded = 0;
  if (m_ipExclusionSet)
    m_ipExclusionSet->get_Count(&numExcluded);

  if (numExcluded > 0)
  {
    CComBSTR oidFieldName;
    pFClass->get_OIDFieldName(&oidFieldName);
    pQueryFilter->AddField(oidFieldName);
  }

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::Draw(IFeatureCursor* pCursor, esriDrawPhase drawPhase, IDisplay* pDisplay, ITrackCancel* pTrackCancel)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())
  if ((!pCursor) || (!pDisplay))
    return E_POINTER;

  if (m_ipSymbol == NULL) 
    return E_FAIL;

  if (drawPhase != esriDPGeography)
    return E_FAIL;

  HRESULT hr = pDisplay->SetSymbol(m_ipSymbol);
  if FAILED(hr) return hr;

  IFeaturePtr    ipFeature;
  IGeometryPtr  ipGeometry;

  long featureCount = 0;

  CTime startTime = CTime::GetCurrentTime();
  while(pCursor->NextFeature(&ipFeature) == S_OK)
  {
    if (m_ipExclusionSet)
    {
      long fid;
      ipFeature->get_OID(&fid);
      VARIANT_BOOL excluded;
      m_ipExclusionSet->get_Contains(fid, &excluded);
      if (excluded)
        continue;
    }
    // If we are using the Features draw method then call it with the correct arguments
    // For better performance for simple features we can use our own bit of code for the
    // drawing
    if (m_bUseFeatureDraw == VARIANT_TRUE) 
      ((IFeatureDrawPtr)ipFeature)->Draw(drawPhase, pDisplay, m_ipSymbol, VARIANT_TRUE, 0, esriDSNormal);
    else
    {
      if ((drawPhase == esriDPGeography) ||
          (drawPhase == esriDPSelection) ||
          (drawPhase == esriDPAnnotation))
      {  
        esriGeometryType geomType;
        ipFeature->get_Shape(&ipGeometry);

        ipGeometry->get_GeometryType(&geomType);
        switch (geomType)
        {
          case esriGeometryPoint:
            pDisplay->DrawPoint(ipGeometry);
            break;
          case esriGeometryMultipoint:
            pDisplay->DrawMultipoint(ipGeometry);
            break;
          case esriGeometryPolyline:
            pDisplay->DrawPolyline(ipGeometry);
            break;
          case esriGeometryPolygon:
            pDisplay->DrawPolygon(ipGeometry);
            break;
        }
      }
    }
    if (m_bDisplayTime == VARIANT_TRUE)  featureCount++;
      
    VARIANT_BOOL b;
    if (pTrackCancel && (pTrackCancel->Continue(&b) != S_OK)) 
      return S_OK;
  }  
  
  if (m_bDisplayTime == VARIANT_TRUE) 
  {
    // Display the Number of Features Drawn
    CTime endTime = CTime::GetCurrentTime();
    CTimeSpan elapsedTime = endTime - startTime;
    CString str;
    str.Format(_T("%ld Features drawn in %s"), featureCount, elapsedTime.Format(_T("%M' %S\"")));
    ::MessageBox(NULL, (LPCTSTR)str, _T("Timer"), MB_OK);
  }

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_SymbolByFeature(IFeature * Feature, ISymbol** Symbol)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  if (Symbol == NULL)
    return E_POINTER;
    
  return E_NOTIMPL;
}
STDMETHODIMP COptimisedRenderer::get_RenderPhase(esriDrawPhase drawPhase, VARIANT_BOOL* pResult)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState());
  if (!pResult)
    return E_POINTER;

  if (drawPhase == esriDPGeography)
    *pResult = VARIANT_TRUE;
  else
    *pResult = VARIANT_FALSE;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::putref_ExclusionSet(IFeatureIDSet* pExclusionSet)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())
  m_ipExclusionSet = pExclusionSet;
  
  return S_OK;
}
STDMETHODIMP COptimisedRenderer::putref_LineSymbol(IUnknown* pUnk)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())
  m_ipLineSymbol = pUnk;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::putref_MarkerSymbol(IUnknown* pUnk)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())
  m_ipMarkerSymbol = pUnk;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::putref_FillSymbol(IUnknown* pUnk)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())
  m_ipFillSymbol = pUnk;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_DisplayTime(VARIANT_BOOL *pVal)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())

  *pVal = m_bDisplayTime;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::put_DisplayTime(VARIANT_BOOL newVal)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())

  m_bDisplayTime = newVal;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_UseFeatureDraw(VARIANT_BOOL *pVal)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())

  *pVal = m_bUseFeatureDraw;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::put_UseFeatureDraw(VARIANT_BOOL newVal)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())

  m_bUseFeatureDraw = newVal;

  return S_OK;
}

STDMETHODIMP COptimisedRenderer::get_Enabled(VARIANT_BOOL * Enabled)
{
  if (Enabled == NULL)
    return E_POINTER;
  
  *Enabled = VARIANT_TRUE;

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_Checked(VARIANT_BOOL * Checked)
{
  if (Checked == NULL)
    return E_POINTER;
    
  *Checked = VARIANT_FALSE;
  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_Name(BSTR * Name)
{
  if (Name == NULL)
    return E_POINTER;
  *Name = ::SysAllocString(L"Developer Samples_Optimised Renderer");

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_Caption(BSTR * Caption)
{
  if (Caption == NULL)
    return E_POINTER;
    
  *Caption = ::SysAllocString(L"Optimised Renderer");
  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_Tooltip(BSTR * Tooltip)
{
  if (Tooltip == NULL)
    return E_POINTER;
    
  *Tooltip = ::SysAllocString(L"Optimised Renderer");

  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_Message(BSTR * Message)
{
  if (Message == NULL)
    return E_POINTER;
    
  *Message = ::SysAllocString(L"Configures the optimised renderer");
  return S_OK;
}
STDMETHODIMP COptimisedRenderer::get_HelpFile(BSTR * HelpFile)
{
  if (HelpFile == NULL)
    return E_POINTER;
    
  return E_NOTIMPL;
}
STDMETHODIMP COptimisedRenderer::get_HelpContextID(LONG * helpID)
{
  if (helpID == NULL)
    return E_POINTER;
    
  return E_NOTIMPL;
}
STDMETHODIMP COptimisedRenderer::get_Bitmap(OLE_HANDLE * Bitmap)
{
  if (Bitmap == NULL)
    return E_POINTER;
    
  return E_NOTIMPL;
}
STDMETHODIMP COptimisedRenderer::get_Category(BSTR * categoryName)
{
  if (categoryName == NULL)
    return E_POINTER;
  
  *categoryName = ::SysAllocString(L"Developer Samples");
  return S_OK;;
}
STDMETHODIMP COptimisedRenderer::OnCreate(IDispatch * hook)
{
  m_ipApp = hook;
  
  return S_OK;
}
STDMETHODIMP COptimisedRenderer::OnClick()
{
  IDocumentPtr      ipDoc;

  m_ipApp->get_Document(&ipDoc);
  m_ipApp.AddRef();
  IMxDocumentPtr    ipMxDoc(ipDoc);

  ISymbolPtr ipSymbol;
  ILayerPtr ipLayer;
  IGeoFeatureLayerPtr  ipGeoLayer;
  ISimpleRendererPtr ipSimpleRenderer;
  IFeatureRendererPtr ipFeatureRenderer;
  IFeatureClassPtr  ipFeatureClass;
  esriGeometryType geomType;

  long i  ;
  IMapPtr ipMap;
  ipMxDoc->get_FocusMap(&ipMap);
  long layerCount;
  ipMap->get_LayerCount(&layerCount);

  for (i=0; i < layerCount; i++)
  {
    ipMap->get_Layer(i, &ipLayer);
    ipGeoLayer=0;
    ipGeoLayer = ipLayer;
    if (ipGeoLayer != NULL)
    {
      ipGeoLayer->get_Renderer(&ipFeatureRenderer);
      ipSimpleRenderer = 0;
      ipSimpleRenderer = ipFeatureRenderer;
      if (ipSimpleRenderer != NULL)
      {
        ipSimpleRenderer->get_Symbol(&ipSymbol);
  
        IOptimisedRendererPtr  ipOR(CLSID_OptimisedRenderer);
        ipOR->putref_Application(m_ipApp);
        ipOR->put_DisplayTime(VARIANT_FALSE);
        ipOR->put_UseFeatureDraw(VARIANT_FALSE);
        
        ipGeoLayer->get_FeatureClass(&ipFeatureClass);

        ipFeatureClass->get_ShapeType(&geomType);
        switch (geomType)
        {
          case esriGeometryPoint:
          case esriGeometryMultipoint:
            ipOR->putref_MarkerSymbol(ipSymbol);
            break;
          case esriGeometryPolyline:
            ipOR->putref_LineSymbol(ipSymbol);
            break;
          case esriGeometryPolygon:
            ipOR->putref_FillSymbol(ipSymbol);
            break;
        }
        ipGeoLayer->putref_Renderer((IFeatureRendererPtr)ipOR);
      }
    }
  }

  return S_OK;
}

STDMETHODIMP COptimisedRenderer::putref_Application(IUnknown *pUnk)
{
  AFX_MANAGE_STATE(AfxGetStaticModuleState())

  m_ipApp = pUnk;

  return S_OK;
}