4

We are developing a complex ArcMap extension software which contains class extensions, a workspace extension and some ArcMap extensions.

The purpose of the software is to link our existing management sofware to the client's ArcGIS data. This way he can access our software's data without leaving ArcMap and without duplicating data.

This way, some the client's data stays in their feature classes and our data is in a separate database, in another dbms. We have access to our systems's data inside the class extensions via some configurations made in ArcCatalog. We can easily put the needed data in memory for later use.

We now have to implement advanced feature rendering(displaying different symbols for a featureclass) depending on data contained in our management software. On demand, we could fetch and store in memory the data needed to compute the symbol to draw for each feature.

Is there an exising renderer that I could use that works with in-memory data? If not, is there a way to temporarily add the in memory data to the feature class? (add temporary in-memory fields) If it doesn't work I suppose that I need to create my own renderer. Where do I start?

6
  • 3
    Did you consider using the InMemoryWorkspaceFactory, then setting up a JOIN to those fields in your existing table/featureclass? Dec 17, 2012 at 14:38
  • If I understand with an InMemoryWorkspace, I could create an inmemory FeatureClass with the fields relevant to the symbology, and than join it my to existing FeatureClass. Then what? Could I use an unique value renderer on my existing featurelayer and I would have access to the joined fields?
    – Goldorak84
    Dec 17, 2012 at 14:50
  • 3
    Yes, you should be able to do that. However keep in mind if you save and re-open the mxd (or even copy and paste the layer) the in memory data is lost, and the renderer will be broken. Just for rendering, I think you'd create an in-memory table rather than a featureclass. You already have a featureclass on disk, correct? Dec 17, 2012 at 15:06
  • 2
    When you quit arcmap, you'll need to persist the in-memory data somewhere, or at least the information needed to re-hydrate it, in order to have it appear next time you open arcmap. You would need custom extension or something that would re-hydrate it when opening arcmap. It could get messy. Dec 17, 2012 at 17:14
  • 1
    I don't think that the results persistence is a requirement for now. I think I'll go the InMemoryWorkspace way. Thanks for the advice!
    – Goldorak84
    Dec 17, 2012 at 18:10

1 Answer 1

2

As suggested by Kirk Kuykendall, I tried joining my existing feature class with a table created in a InMemoryWorkspaceFactory.

To display symbology, I used a UniqueValue renderer to define symbols based on a field in the generated table.

However, for some reason, the InMemoryWorkspaceFactory didn't do the work, the join operation returned no records (see this post).

To resolve the problem, I kept the same code, but I used a FileGDBScratchWorkspaceFactory to create the table.

Here's the complete code :

            // Create a scratch (temporary) workspace factory.
            IScratchWorkspaceFactory2Ptr ipWorkspaceFactory(CLSID_FileGDBScratchWorkspaceFactory);

            // Create a new scratch (temporary) workspace. This returns a name object.
            IWorkspaceNamePtr ipWorkspaceName;
            IWorkspacePtr ipWorkspace;
            ipWorkspaceFactory->CreateNewScratchWorkspace(&ipWorkspace);

            IFeatureWorkspacePtr ipScratchFeatureWorkspace(ipWorkspace);

            IFieldsEditPtr ipFieldsEdit(CLSID_Fields);

            ... Fields creating code...//Créer le array de champs

            ITablePtr ipTable;
            HRESULT hr4 = ipScratchFeatureWorkspace->CreateTable(L"TemporaryTable",ipFieldsEdit, NULL, NULL, NULL, &ipTable);

            ... Table populating code ...

            //Create a relationship class
            IFeatureWorkspacePtr ipFeatureWorkspace(CTools::GetWorkspaceFromFeatureClass(ipFeatureClass));
            IObjectClassPtr ipObjectClass(ipTable);

            IMemoryRelationshipClassFactoryPtr ipMemoryRelationshipClassFactory(CLSID_MemoryRelationshipClassFactory);
            IRelationshipClassPtr ipRelClass;
            HRESULT hr = ipMemoryRelationshipClassFactory->Open(L"Join", ipFeatureClass, L"Numero_AD", ipObjectClass, L"NumeroAD", L"forward", L"backward", esriRelCardinalityOneToOne, &ipRelClass);

            //Create a relquerytable
            IRelQueryTableFactoryPtr ipRelQueryTableFactory(CLSID_RelQueryTableFactory);
            IRelQueryTablePtr ipQueryTable;
            hr = ipRelQueryTableFactory->Open(ipRelClass, VARIANT_TRUE, NULL, NULL, NULL, VARIANT_TRUE, VARIANT_TRUE,&ipQueryTable);

            IGeoFeatureLayerPtr ipNewGeoFeatureLayer(CLSID_FeatureLayer);
            IFeatureClassPtr ipFCQueryTable(ipQueryTable);
            ipNewGeoFeatureLayer->putref_FeatureClass(ipFCQueryTable);

            //Create the renderer
            IFeatureRendererPtr ipFeatureRenderer(CLSID_UniqueValueRenderer);
            IUniqueValueRendererPtr ipUniqueValueRenderer(ipFeatureRenderer);
            ipUniqueValueRenderer->put_FieldCount(1);
            ipUniqueValueRenderer->put_Field(0, L"VCConduites.DsplValue");
            ipUniqueValueRenderer->put_DefaultLabel(L"Default");
            ipUniqueValueRenderer->put_DefaultSymbol(CTools::CreateSymbol(esriGeometryPolyline, 0));
            ipUniqueValueRenderer->put_UseDefaultSymbol(VARIANT_TRUE);
            ipUniqueValueRenderer->AddValue(L"1", L"1", CTools::CreateSymbol(esriGeometryPolyline, 1));
            ipUniqueValueRenderer->AddValue(L"2", L"1", CTools::CreateSymbol(esriGeometryPolyline, 2));
            ipUniqueValueRenderer->AddValue(L"3", L"1", CTools::CreateSymbol(esriGeometryPolyline, 3));
            ipUniqueValueRenderer->AddValue(L"4", L"1", CTools::CreateSymbol(esriGeometryPolyline, 4));
            ipUniqueValueRenderer->AddValue(L"5", L"1", CTools::CreateSymbol(esriGeometryPolyline, 5));

            ipNewGeoFeatureLayer->putref_Renderer(ipFeatureRenderer);
            ipNewGeoFeatureLayer->put_Name(L"TemporaryLayer");

            ipMxDocument->AddLayer(ipNewGeoFeatureLayer);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.