Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

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?

share|improve this question
3  
Did you consider using the InMemoryWorkspaceFactory, then setting up a JOIN to those fields in your existing table/featureclass? –  Kirk Kuykendall Dec 17 '12 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 '12 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? –  Kirk Kuykendall Dec 17 '12 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. –  Kirk Kuykendall Dec 17 '12 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 '12 at 18:10
show 1 more comment

1 Answer

up vote 1 down vote accepted

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);
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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