MoleLayers.cpp
// Copyright 2010 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 <QtGui/QtGui> #include <ArcSDK.h> #include <Ao/AoControls.h> #include <AxCtl/qtaxctl.h> #include <olb/esridefensesolutions.h> // implemented in libDefenseSolutionsSDK.so #if defined(ESRI_UNIX) void DsInitialize(); #endif #define SIC_FIELD_NAME "Symbol_ID" #define PARENT_FIELD_NAME "Parent" #define ABORT { \ printf ("abort on line %d of %s\n", __LINE__, __FILE__); \ shutdown(); \ } // the first macro expands the symbol defined on the command line; the second puts quotes around it #define EXPANDSTRING(x) STRINGIFY(x) #define STRINGIFY(x) #x // get the full path of a dataset in the Defense Solutions sample data CComBSTR dsDataPath (const char *relativeDatasetPath) { #if defined(ESRI_UNIX) CComBSTR path (EXPANDSTRING(DATADIRECTORY) "/Samples/data/defensesolutions/"); #elif defined(ESRI_WINDOWS) USES_CONVERSION; CComBSTR path( L"C://Program Files//ArcGIS//DeveloperKit10.0//Samples//data//defensesolutions//"); #endif path.Append (relativeDatasetPath); return path.Copy(); } // shut down arc objects and terminate the application static void shutdown() { IAoInitializePtr ipInit(CLSID_AoInitialize); ipInit->Shutdown(); ::AoUninitialize(); AoExit(0); } // check to see if the feature class has a string field with the indicated characteristics static bool HasStringField (IFeatureClassPtr ipFeatureClass, const char *name, long minimumFieldLength = -1) { // first see if we can find the field by name or alias CComBSTR fieldName (name); long fieldIndex = -1; IFieldsPtr ipFields; ipFeatureClass->get_Fields (&ipFields); ipFields->FindFieldByAliasName (fieldName, &fieldIndex); if ( fieldIndex < 0 ) ipFields->FindField (fieldName, &fieldIndex); if ( fieldIndex >= 0 ) { // if the field exists, check its type IFieldPtr ipField; ipFields->get_Field (fieldIndex, &ipField); esriFieldType type; ipField->get_Type (&type); if ( type != esriFieldTypeString ) fieldIndex = -1; else if ( minimumFieldLength >= 0 ) { // it is a string field, so check its length if specified long actualFieldLength = -1; ipField->get_Length (&actualFieldLength); if ( actualFieldLength < minimumFieldLength ) fieldIndex = -1; } } return ( fieldIndex >= 0 ); } // check to see if the feature class has the indicated extension name with a valid namespace static bool CheckExtensionCLSID (IFeatureClassPtr ipFeatureClass, const char *className) { static const unsigned int numPrefixes = 4; static const char *prefixes[numPrefixes] = { "esriDefenseSolutions.", "esriMOLE.", "moleClassExtensions.", "moleClassExtensions2." }; IUIDPtr ipActualUID (CLSID_UID); ipFeatureClass->get_EXTCLSID (&ipActualUID); if ( ! ipActualUID ) return false; for ( unsigned int i = 0; i < numPrefixes; ++i ) { // compare the class name using each of four possible prefixes CComBSTR bstrCLSID (prefixes[i]); bstrCLSID.Append (className); IUIDPtr ipTargetUID (CLSID_UID); ipTargetUID->put_Value (CComVariant(bstrCLSID)); VARIANT_BOOL isEqual; ipActualUID->Compare (ipTargetUID, &isEqual); if ( isEqual == VARIANT_TRUE ) return true; } return false; } // return true if the feature class can be a force element feature class static bool IsForceElementFC (IFeatureClassPtr ipFeatureClass) { // first try to distinguish by the extension class ID if ( CheckExtensionCLSID(ipFeatureClass, "ForceElements") ) return true; // the extension is not required for MOLE graphics to be rendered; we can also go by feature type and fields // use the presence of the parent field to distinguish force elements from tactical points esriGeometryType shapeType; ipFeatureClass->get_ShapeType (&shapeType); return ( shapeType == esriGeometryPoint && HasStringField(ipFeatureClass, SIC_FIELD_NAME, 15) && HasStringField(ipFeatureClass, PARENT_FIELD_NAME) ); } // return true if the feature class can be a tactical graphic feature class static bool IsTacticalGraphicFC (IFeatureClassPtr ipFeatureClass) { // first try to distinguish by one of the extension class IDs if ( CheckExtensionCLSID(ipFeatureClass, "TacticalPoints") || CheckExtensionCLSID(ipFeatureClass, "TacticalLines") || CheckExtensionCLSID(ipFeatureClass, "TacticalAreas") ) return true; else if ( HasStringField(ipFeatureClass, SIC_FIELD_NAME, 15) ) { // an extension is not required for MOLE graphics to be rendered; we can also go by feature type and fields // use the presence of the parent field to distinguish force elements from tactical points esriGeometryType shapeType; ipFeatureClass->get_ShapeType (&shapeType); if ( shapeType == esriGeometryPoint && ( ! HasStringField(ipFeatureClass, PARENT_FIELD_NAME)) ) return true; else return ( shapeType == esriGeometryPolyline || shapeType == esriGeometryPolygon ); } else return false; } // load a feature layer or MOLE group layer, depending on the type of feature class detected static ILayerPtr LoadLayer (IFeatureWorkspacePtr ipFeatureWS, const char *featureClassName) { ILayerPtr ipLayer; IFeatureClassPtr ipFeatureClass; ipFeatureWS->OpenFeatureClass (CComBSTR(featureClassName), &ipFeatureClass); if ( ! ipFeatureClass ) printf ("failed to open %s\n", featureClassName); else { // figure out what kind of feature class we have opened printf ("opened %s: ", featureClassName); bool isFE = IsForceElementFC (ipFeatureClass); bool isTG = ( isFE ? false : IsTacticalGraphicFC(ipFeatureClass) ); IFeatureLayerPtr ipFeatureLayer (CLSID_FeatureLayer); ipFeatureLayer->putref_FeatureClass (ipFeatureClass); if ( isFE || isTG ) { // group the feature layer with a MOLE graphic layer; don't render the features, just the graphics ipFeatureLayer->put_Name (CComBSTR("Features")); ipFeatureLayer->put_Visible (VARIANT_FALSE); IGroupLayerPtr ipGroupLayer (CLSID_GroupLayer); ipGroupLayer->put_Name (CComBSTR(featureClassName)); ipGroupLayer->Add (ipFeatureLayer); IEnvelopePtr ipEnvelope; IGeoDatasetPtr(ipFeatureClass)->get_Extent (&ipEnvelope); double height; ipEnvelope->get_Height (&height); if ( isFE ) { // the commented lines will dynamically scale the graphics with the size of the display printf ("force elements\n"); IForceElementLayerPtr ipForceElementLayer (CLSID_ForceElementLayer); ipForceElementLayer->put_Size (0.05 * height); //ipForceElementLayer->put_SizeIsRatio (VARIANT_TRUE); //ipForceElementLayer->put_Size (0.03); ICachedGraphicFeatureLayerPtr ipCachedGraphicFeatureLayer (ipForceElementLayer); ipCachedGraphicFeatureLayer->putref_FeatureLayer (IGeoFeatureLayerPtr(ipFeatureLayer)); ipLayer = ipForceElementLayer; ipLayer->put_Name (CComBSTR("Graphics")); ipGroupLayer->Add (ipLayer); } else { printf ("tactical graphics\n"); ITacticalGraphicLayerPtr ipTacticalGraphicLayer (CLSID_TacticalGraphicLayer); ipTacticalGraphicLayer->put_TextSize (0.03 * height); ICachedGraphicFeatureLayerPtr ipCachedGraphicFeatureLayer (ipTacticalGraphicLayer); HRESULT hr = ipCachedGraphicFeatureLayer->putref_FeatureLayer (IGeoFeatureLayerPtr(ipFeatureLayer)); ipLayer = ipTacticalGraphicLayer; ipLayer->put_Name (CComBSTR("Graphics")); ipGroupLayer->Add (ipLayer); } ipLayer = ipGroupLayer; } else { // this is just a plain old feature layer printf ("non-MOLE features\n"); ipFeatureLayer->put_Name (CComBSTR(featureClassName)); ipLayer = ipFeatureLayer; } } return ipLayer; } // compute the union of the envelope with the AOI of the layer static void unionEnvelope (ILayerPtr &ipLayer, IEnvelopePtr &ipEnvelope) { if ( ! ipEnvelope ) ipLayer->get_AreaOfInterest (&ipEnvelope); else { IEnvelopePtr ipAOI; ipLayer->get_AreaOfInterest (&ipAOI); ipEnvelope->Union (ipAOI); } } // add the named tool to the toolbar control static void addTool (IToolbarControlPtr &ipToolbar, const char *name) { CComBSTR toolID ("esriControlCommands."); toolID.Append (name); long itemIndex; ipToolbar->AddItem (CComVariant(toolID), 0, -1, VARIANT_FALSE, 0, esriCommandStyleIconOnly, &itemIndex); } int main(int argc, char **argv) { printf ("calling AoInitialize\n"); ::AoInitialize(NULL); #if defined(ESRI_UNIX) ::DsInitialize(); #endif { printf ("initializing license\n"); IAoInitializePtr ipInit (CLSID_AoInitialize); esriLicenseStatus status; ipInit->Initialize (esriLicenseProductCodeEngine, &status); if ( status != esriLicenseCheckedOut ) { printf ("Invalid Licensing.\n"); AoExit (0); } } printf ("creating application\n"); QApplication qapp(argc, argv); printf ("creating widgets\n"); QSplitter split (NULL); QAxCtl tlbControl (AoPROGID_ToolbarControl, NULL, "Toolbar Control"); QAxCtl tocControl (AoPROGID_TOCControl, &split, "TOC Control"); QAxCtl mapControl (AoPROGID_MapControl, &split, "Map Control"); tlbControl.setMinimumHeight (28); tlbControl.setMaximumHeight (28); split.setOpaqueResize (false); QList<int> sizes (split.sizes()); sizes[0] = 250; sizes[1] = 550; split.setSizes (sizes); QVBoxLayout rootLayout; rootLayout.addWidget (&tlbControl); rootLayout.addWidget (&split); QWidget window; window.resize (800, 600); window.setLayout (&rootLayout); window.setWindowTitle ("Mole Layers"); window.show(); printf ("opening workspace\n"); IWorkspaceFactoryPtr ipWSFact (CLSID_FileGDBWorkspaceFactory); IWorkspacePtr ipWorkspace; CComBSTR bstmp; if ( argc > 1 && strcmp(argv[1], "noexts") == 0 ) ipWSFact->OpenFromFile ((bstmp = dsDataPath("oplan_no_exts.gdb")), 0, &ipWorkspace); else ipWSFact->OpenFromFile ((bstmp = dsDataPath("oplan_93_exts.gdb")), 0, &ipWorkspace); SysFreeString(bstmp); IFeatureWorkspacePtr ipFeatureWS (ipWorkspace); if ( ! ipFeatureWS ) ABORT; printf ("loading layers\n"); ILayerPtr ipLayerFE (LoadLayer(ipFeatureWS, "force_elements")); ILayerPtr ipLayerPointTG (LoadLayer(ipFeatureWS, "tactical_graphic_points")); ILayerPtr ipLayerLineTG (LoadLayer(ipFeatureWS, "tactical_graphic_lines")); ILayerPtr ipLayerAreaTG (LoadLayer(ipFeatureWS, "tactical_graphic_areas")); ILayerPtr ipLayerAOI (LoadLayer(ipFeatureWS, "area_of_interest")); if ( (!ipLayerFE) || (!ipLayerAreaTG) || (!ipLayerLineTG) || (!ipLayerPointTG) || (!ipLayerAOI) ) ABORT; printf ("setting up the controls\n"); IUnknownPtr ipUnknown; mapControl.getInterface (&ipUnknown); IMapControl4Ptr ipMap (ipUnknown); tlbControl.getInterface (&ipUnknown); IToolbarControlPtr ipToolbar (ipUnknown); tocControl.getInterface (&ipUnknown); ITOCControlPtr ipToc (ipUnknown); if ( (!ipMap) || (!ipToolbar) || (!ipToc) ) ABORT; // buddy up and load the toolbar ipToolbar->SetBuddyControl (ipMap); ipToc->SetBuddyControl (ipMap); addTool (ipToolbar, "ControlsMapZoomInTool"); addTool (ipToolbar, "ControlsMapZoomOutTool"); addTool (ipToolbar, "ControlsMapZoomInFixedCommand"); addTool (ipToolbar, "ControlsMapZoomOutFixedCommand"); addTool (ipToolbar, "ControlsMapPanTool"); addTool (ipToolbar, "ControlsMapFullExtentCommand"); addTool (ipToolbar, "ControlsMapZoomToLastExtentBackCommand"); addTool (ipToolbar, "ControlsMapZoomToLastExtentForwardCommand"); printf ("setting up the map\n"); ipMap->AddLayer (ipLayerFE, 0); ipMap->AddLayer (ipLayerPointTG, 1); ipMap->AddLayer (ipLayerLineTG, 2); ipMap->AddLayer (ipLayerAreaTG, 3); ipMap->AddLayer (ipLayerAOI, 4); IEnvelopePtr ipEnvelope; unionEnvelope (ipLayerFE, ipEnvelope); unionEnvelope (ipLayerPointTG, ipEnvelope); unionEnvelope (ipLayerLineTG, ipEnvelope); unionEnvelope (ipLayerAreaTG, ipEnvelope); ipEnvelope->Expand (1.1, 1.1, VARIANT_TRUE); ipMap->put_Extent (ipEnvelope); printf ("passing control to Qt\n"); qapp.exec(); shutdown(); return 0; }