Dynamic display
MyDynamicLayer.cpp
// Copyright 2011 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 

  


#include <stdio.h>
#include <math.h>
#include "MyDynamicLayer.h"

#ifdef ESRI_UNIX
#include <unistd.h>
#else
#include <direct.h>
#include <time.h>
#endif


#define NEGATIVE_VAL(q) q<0?q:-q
#define ABSOLUTE_VAL(q) q<0?-q:q


static char *get_current_directory()
{
  static char sBuf[1024];

#ifdef ESRI_WINDOWS
  _getcwd(sBuf, 1024);
#else
  getcwd(sBuf, 1024);
#endif
  
  return sBuf;
}

MyDynamicLayer::MyDynamicLayer(IMap* pMap): 
  m_ipMap(pMap), 
  m_bAnimate(false),
  m_bDynamicGlyphsCreated(false)
{
  put_Name(L"Tracks");
  
  m_bIsDirty[esriDDPImmediate] = VARIANT_TRUE;
  m_bIsDirty[esriDDPCompiled ] = VARIANT_TRUE;
  m_bAnimate = true;
  
  srand(time(NULL));
}

MyDynamicLayer::~MyDynamicLayer()
{
  //
}

void MyDynamicLayer::UpdateItems(IDisplay* pDisplay)
{
  IScreenDisplayPtr ipScreenDisplay = pDisplay;
  if (ipScreenDisplay == 0)
    return;

  IDisplayTransformationPtr ipDisplayTransformation;
  ipScreenDisplay->get_DisplayTransformation(&ipDisplayTransformation);
  
  IEnvelopePtr ipFittedBounds;
  ipDisplayTransformation->get_FittedBounds(&ipFittedBounds);

  double dXmax, dYmax, dXmin, dYmin;  
  ipFittedBounds->get_XMax(&dXmax);
  ipFittedBounds->get_YMax(&dYmax);
  ipFittedBounds->get_XMin(&dXmin);
  ipFittedBounds->get_YMin(&dYmin);
  
  SNavigationData* pNavData = 0;
  int i;
  for (i=0 ; i<NUM_OF_ITEMS ; i++)
  {
    pNavData = &m_navData[i];
    
    pNavData->x += pNavData->stepX;
    pNavData->y += pNavData->stepY;

    if (pNavData->x > dXmax) 
      pNavData->stepX = NEGATIVE_VAL(pNavData->stepX);
    if (pNavData->x < dXmin) 
      pNavData->stepX = ABSOLUTE_VAL(pNavData->stepX);
    if (pNavData->y > dYmax) 
      pNavData->stepY = NEGATIVE_VAL(pNavData->stepY);
    if (pNavData->y < dYmin) 
      pNavData->stepY = ABSOLUTE_VAL(pNavData->stepY);
        
    pNavData->azimuth = ((int)(360.0 + 90.0 - (atan2(pNavData->stepY, pNavData->stepX) * 180.0 / ESRI_PI))) % 360;
  }
}

void MyDynamicLayer::put_Animate(bool bAnimate)
{
  m_bAnimate = bAnimate;
}

HRESULT MyDynamicLayer::CreateDynamicSymbols(IDynamicDisplay* pDynamicDisplay)
{
  HRESULT hr = S_OK;

  IRgbColorPtr ipTransClr(CLSID_RgbColor);
  ipTransClr->put_Red  (0);
  ipTransClr->put_Green(0);
  ipTransClr->put_Blue (0);

  IRgbColorPtr ipClr(CLSID_RgbColor);
  ipClr->put_Red  (255);
  ipClr->put_Green(255);
  ipClr->put_Blue (255);
    
  ICharacterMarkerSymbolPtr ipCharMarkSym(CLSID_CharacterMarkerSymbol);
  IFontDisp *pFontDisp;
  IFont     *pFont;
  ipCharMarkSym->get_Font(&pFontDisp);
  pFontDisp->QueryInterface(IID_IFont, (void **)&pFont);

  tagCY fontSize; fontSize.int64 = 32;
  pFont->put_Name(L"ESRI Environmental & Icons");
  pFont->put_Size(fontSize);

  ipCharMarkSym->put_Color(ipClr);
  ipCharMarkSym->put_Font(pFontDisp);
  ipCharMarkSym->put_Size(40.0);
  ipCharMarkSym->put_Angle(0.0);
  ipCharMarkSym->put_CharacterIndex(36);
  
  IDynamicGlyphFactoryPtr ipDynamicGlyphFactory;
  hr = pDynamicDisplay->get_DynamicGlyphFactory(&ipDynamicGlyphFactory);
  
  hr = ipDynamicGlyphFactory->CreateDynamicGlyph(((ISymbolPtr)ipCharMarkSym), &m_ipMarkerGlphys[0]);
    
  ipCharMarkSym->put_Size(32);
  ipCharMarkSym->put_CharacterIndex(224);
  hr = ipDynamicGlyphFactory->CreateDynamicGlyph(((ISymbolPtr)ipCharMarkSym), &m_ipMarkerGlphys[1]);
    
  ipTransClr->put_Green(255);
  ipTransClr->put_Blue(255);

  char sBmpPath[1024];    

#ifdef ESRI_WINDOWS
  sprintf(sBmpPath, "%s%c%s%c%s", get_current_directory(), '\\', "icons", '\\', "B2.bmp");
#else
  sprintf(sBmpPath, "%s%c%s%c%s", get_current_directory(), '/', "icons", '/', "B2.bmp");
#endif

  hr = ipDynamicGlyphFactory->CreateDynamicGlyphFromFile(esriDGlyphMarker, CComBSTR(sBmpPath), ipTransClr, &m_ipMarkerGlphys[2]);

  //hr = ipDynamicGlyphFactory->get_DynamicGlyph(1, esriDGlyphText, 1, &m_ipTextGlyph);
  long lGroupId = 0;
  hr = ipDynamicGlyphFactory->LoadDynamicGlyphsGroup(L"WhiteText.xml", &lGroupId);
  hr = ipDynamicGlyphFactory->get_DynamicGlyph(lGroupId, esriDGlyphText, 1, &m_ipTextGlyph);
        
  pFont->Release();
  return S_OK;
}

// IDynamicLayer

HRESULT MyDynamicLayer::get_DynamicLayerDirty(esriDynamicDrawPhase DynamicDrawPhase, VARIANT_BOOL* pDirty)
{
  if (!pDirty) 
    return E_POINTER;
  
  *pDirty = m_bIsDirty[DynamicDrawPhase];
  return S_OK;
}

HRESULT MyDynamicLayer::put_DynamicLayerDirty(esriDynamicDrawPhase DynamicDrawPhase, VARIANT_BOOL bDirty)
{
  m_bIsDirty[DynamicDrawPhase] = bDirty;
  return S_OK;
}

HRESULT MyDynamicLayer::get_DynamicRecompileRate(long* pDynamicRecompileRateTimeMS)
{
  if (!pDynamicRecompileRateTimeMS) 
    return E_POINTER;
  
  *pDynamicRecompileRateTimeMS = ANIMATION_CYCLE_TIME_MS;
  return S_OK;
}

HRESULT MyDynamicLayer::DrawDynamicLayer(esriDynamicDrawPhase phase, IDisplay* pDisplay, IDynamicDisplay* pDynamicDisplay)
{
  if (!pDisplay || !pDynamicDisplay) 
    return E_POINTER;

  VARIANT_BOOL bVisible;
  get_Visible(&bVisible);
  if (bVisible != VARIANT_TRUE) 
    return S_OK;
    
  if (phase == esriDDPImmediate) 
  {
    if (m_bIsDirty[esriDDPImmediate] == VARIANT_TRUE && !m_bDynamicGlyphsCreated)
    {
      GenerateNavigationData(pDisplay);
      CreateDynamicSymbols(pDynamicDisplay);
      m_bDynamicGlyphsCreated = true;
      m_bIsDirty[esriDDPImmediate] = VARIANT_FALSE;
    }
  }
  else if (m_bIsDirty[esriDDPCompiled] == VARIANT_TRUE) // Compiled Phase
  {
    if (m_bAnimate)
      UpdateItems(pDisplay);
    
    DrawItems(pDisplay, pDynamicDisplay);
    m_bIsDirty[esriDDPCompiled] = VARIANT_TRUE; 
  }
    
    return S_OK;
}

HRESULT MyDynamicLayer::GenerateNavigationData(IDisplay* pDisplay)
{
  IScreenDisplayPtr ipScreenDisplay = pDisplay;
  if (ipScreenDisplay == 0)
    return E_FAIL;

  IDisplayTransformationPtr ipDisplayTransformation;
  ipScreenDisplay->get_DisplayTransformation(&ipDisplayTransformation);
  
  IEnvelopePtr ipExtent;
  ipDisplayTransformation->get_FittedBounds(&ipExtent);

  double XStep, YStep, XMax, YMax, XMin, YMin;
  ipExtent->get_Width (&XStep);
  ipExtent->get_Height(&YStep);
  ipExtent->get_XMax  (&XMax );
  ipExtent->get_YMax  (&YMax );
  ipExtent->get_XMin  (&XMin );
  ipExtent->get_YMin  (&YMin );
  XStep /= 1000.0;
  YStep /= 1000.0;

  int i;
  SNavigationData* pNavData = 0;
  for (i=0 ; i<NUM_OF_ITEMS ; i++)
  {
    pNavData = &m_navData[i];
    pNavData->stepX = XStep * GetRandomDouble();
    pNavData->stepY = YStep * GetRandomDouble();
    pNavData->x = XMin + (GetRandomDouble() * (XMax - XMin));
    pNavData->y = YMin + (GetRandomDouble() * (YMax - YMin));
    pNavData->azimuth = ((int)(360.0 + 90.0 - (atan2(pNavData->stepY, pNavData->stepX) * 180.0 / ESRI_PI))) % 360;
    pNavData->type = i % 3;
  }  

  return S_OK;
}

void MyDynamicLayer::DrawItems(IDisplay* pDisplay, IDynamicDisplay* pDynamicDisplay)
{
  IDynamicSymbolProperties2Ptr ipDynamicSymbolProperties = pDynamicDisplay;
  IDynamicCompoundMarker2Ptr   ipDynamicCompoundMarker   = pDynamicDisplay;
  
  double    X, Y, heading;
  IPointPtr ipPoint(CLSID_Point);
  SNavigationData* pNavData = 0;
  int i;
  for (i=0 ; i<NUM_OF_ITEMS ; i++)
  {
    pNavData = &m_navData[i];
    ipPoint->PutCoords(pNavData->x, pNavData->y);
    switch (pNavData->type)
    {
      case 0:
        sprintf(m_sIndex, "Item %.3d", i);
        sprintf(m_sHeading, "%.3f", pNavData->azimuth);
        sprintf(m_sX, "%.3f", pNavData->x);
        sprintf(m_sY, "%.3f", pNavData->y);
        ipDynamicSymbolProperties->put_Heading(esriDSymbolText,0.0);
        ipDynamicSymbolProperties->put_Heading(esriDSymbolMarker, pNavData->azimuth);
        ipDynamicSymbolProperties->put_RotationAlignment(esriDSymbolMarker, esriDSRAScreen);
        ipDynamicSymbolProperties->put_RotationAlignment(esriDSymbolText, esriDSRAScreen);
        ipDynamicSymbolProperties->SetScale(esriDSymbolMarker, 0.8, 0.8);
        ipDynamicSymbolProperties->SetColor(esriDSymbolMarker, 0.0, 0.0, 1.0, 1.0);
        ipDynamicSymbolProperties->SetColor(esriDSymbolText, 1.0, 1.0, 0.0, 1.0);
        ipDynamicSymbolProperties->putref_DynamicGlyph(esriDSymbolMarker, m_ipMarkerGlphys[0]);
        ipDynamicSymbolProperties->putref_DynamicGlyph(esriDSymbolText, m_ipTextGlyph);
        ipDynamicCompoundMarker->DrawCompoundMarker6
          (ipPoint, m_bstrEmptyString, m_bstrEmptyString,
           CComBSTR(m_sIndex), CComBSTR(m_sHeading), CComBSTR(m_sY), CComBSTR(m_sX));
        break;
          
      case 1:
        ipDynamicSymbolProperties->put_Heading(esriDSymbolMarker, pNavData->azimuth);
        ipDynamicSymbolProperties->put_RotationAlignment(esriDSymbolMarker, esriDSRANorth);
        ipDynamicSymbolProperties->SetScale(esriDSymbolMarker, 1.0, 1.0);
        ipDynamicSymbolProperties->SetColor(esriDSymbolMarker, 0.0, 1.0, 0.6, 1.0);
        ipDynamicSymbolProperties->putref_DynamicGlyph(esriDSymbolMarker, m_ipMarkerGlphys[1]);
        pDynamicDisplay->DrawMarker(ipPoint);
        break;
          
      case 2:
        ipDynamicSymbolProperties->put_Heading(esriDSymbolMarker, pNavData->azimuth + 180.0);
        ipDynamicSymbolProperties->put_RotationAlignment(esriDSymbolMarker, esriDSRANorth);
        ipDynamicSymbolProperties->SetScale(esriDSymbolMarker, 1.5, 1.5);
        ipDynamicSymbolProperties->SetColor(esriDSymbolMarker, 1.0, 1.0, 1.0, 1.0);
        ipDynamicSymbolProperties->putref_DynamicGlyph(esriDSymbolMarker, m_ipMarkerGlphys[2]);
        pDynamicDisplay->DrawMarker(ipPoint);
        break;
    } // end switch
  }// end for
}

inline double MyDynamicLayer::GetRandomDouble()
{
  double value = ((double)rand() / (double)RAND_MAX);
  return value;
}