ArcGIS中的子类型和属性域的应用


GIS数据管理中,涉及到多种分类的数据在同一个表中,表的属性列相同,但属性值可能有很大的区别,可以通过ArcGIS中的图层数据子类型进行管理,具体的应用方式如下,本实例通过ArcGIS10进行讲解,首先打开ArcCatalog,新建一个文件地理数据库。

图一

新建的文件地理数据库为test.gdb;在test.gdb中新建一个要素类

图二

这里新建一个线要素类

图三

增加属性列,包括subtypenamedomaintypetype等;

图四

建立完成之后,在该要素类上右键-〉属性;打开属性页,

图五

图六

切换到子类型页面

图七

选择子类型字段,子类型的字段,能够识别的类型为整型;

图八

选择相应的要分类的字段,之后根据业务类型,增加子类型;

图九

这里以电力为例,为线路管理要素类,设置4个子类型,分别为

编码

描述

0

高压电线

1

高压电缆

2

低压电线

3

低压电缆

可以设置默认的子类型,在进行数据编辑的时候,对于新增的数据默认类型为这个;

在子类型列表中,点击各个子类型,可以设置不同子类型的属性的默认值和属性域。

属性域,一般为key-value的形式,点击属性域按钮,可以对属性域进行设置

图十

可以对属性域进行新增、修改和删除;这里增加两个属性域一个为名称的属性域,一个为类型的属性域;

图十一

其中属性域类型为编码值的类型;如选择为整型,则填充除了整型之外的编码值;

图十二

点击确定,完成属性域的添加;

图十三

选择子类型中的高压电线,设置domaintype字段和type字段的属性域;点击确定,完成子类型和属性域的设置;接下来打开ArcMap,将该图层要素加载进去,进行编辑;

图十四

可以看到加载到ArcMap中去的要素类,自动分为了设置好的四个子类型的类;打开编辑器进行编辑;在创建要素类界面中可以看到不同子类型的要素。

图十五

设置不同类型的类型线路的图例,使得显示有意义;

图十六

增加一段低压电线;点击创建要素中的低压电线,在地图上添加;

图十七

进行属性编辑,发现domaintypetype字段中,没有下拉列表进行属性值的选择;

 

增加一段高压电线;点击创建要素中的高压电线,在地图上添加;

图十八

进行属性编辑,发现domaintypetype字段中,有下拉列表进行属性值的选择;

验证成功。

以上对于ArcGIS中的子类型和属性域进行了简单的介绍,该种应用方式对于较为复杂的空间数据应用比较好。

下面是用代码实现上述过程:

        /// <summary>
        /// 修改字段别名
        /// </summary>
        /// <param name="pTable">表</param>
        /// <param name="strOriFieldName">待修改字段名称</param>
        /// <param name="strDesFieldName">修改后别名</param>
        public void ChangeFieldAliasName(ITable pTable, string strOriFieldName, string strDesFieldName)
        {
            IClassSchemaEdit pClassSchemaEdit = pTable as IClassSchemaEdit;
            ISchemaLock pSchemaLock = (ISchemaLock)pTable;
            pSchemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);

            if (pTable.FindField(strOriFieldName) != -1)
            {
                pClassSchemaEdit.AlterFieldAliasName(strOriFieldName, strDesFieldName);
                pSchemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
            }
            else
            {
                return;
            }
        }

        /// <summary>
        /// 创建属性域
        /// </summary>
        /// <param name="pWs">工作空间</param>
        /// <param name="strDomainName">属性域名称</param>
        /// <param name="dicDomainItems">属性域的项</param>
        public void CreateDomain(IWorkspace pWs,string strDomainName,Dictionary<string,string> dicDomainItems)
        {
            IWorkspaceDomains pWsDomains = (IWorkspaceDomains)pWs;
            ICodedValueDomain pCodeValueDomain = new CodedValueDomainClass();
            范围属性域只适用于数值字段
            //IRangeDomain pRangeDomain = new RangeDomainClass();

            foreach (KeyValuePair<string, string> domainItem in dicDomainItems)
            {
                pCodeValueDomain.AddCode(domainItem.Key, domainItem.Value);
            }

            IDomain pDomain = (IDomain)pCodeValueDomain;
            pDomain.Name = strDomainName;
            pDomain.FieldType = esriFieldType.esriFieldTypeString;
            pDomain.SplitPolicy = esriSplitPolicyType.esriSPTDuplicate;
            pDomain.MergePolicy = esriMergePolicyType.esriMPTDefaultValue;

            pWsDomains.AddDomain(pDomain);
        }

        /// <summary>
        /// 创建子类
        /// </summary>
        /// <param name="pFeaCls">要素</param>
        /// <param name="strSubTypeFieldName">需创建子类的字段名</param>
        /// <param name="dicSubtypeItems">子类项</param>
        public void CreateSubtypes(IFeatureClass pFeaCls,string strSubTypeFieldName,Dictionary<int,string> dicSubtypeItems)
        {
            ISubtypes pSubtypes = pFeaCls as ISubtypes;
            pSubtypes.SubtypeFieldName = strSubTypeFieldName;
            foreach (KeyValuePair<int, string> subtypeItem in dicSubtypeItems)
            {
                pSubtypes.AddSubtype(subtypeItem.Key, subtypeItem.Value);
            }
            pSubtypes.DefaultSubtypeCode = 0;
        }

        /// <summary>
        /// 将子类赋予属性域
        /// </summary>
        /// <param name="pFeatureClass">要素</param>
        /// <param name="strDomainName">属性域</param>
        /// <param name="iSubtypeNumber">子类编号</param>
        /// <param name="strSetFieldName">赋予属性域的字段名</param>
        public void AssignDomainToFieldWithSubtypes(IFeatureClass pFeatureClass, string strDomainName, int iSubtypeNumber, string strSetFieldName)
        {
            IDataset pDataset = (IDataset)pFeatureClass;
            IWorkspace pWs = pDataset.Workspace;
            IWorkspaceDomains pWsDomains = pWs as IWorkspaceDomains;
            IDomain pDistributionDiamDomain = pWsDomains.get_DomainByName(strDomainName);

            ISubtypes pSubtypes = pFeatureClass as ISubtypes;
            pSubtypes.set_Domain(iSubtypeNumber, strSetFieldName, pDistributionDiamDomain);
        }

        private void BtnBegin_Click(object sender, EventArgs e)
        {
            IWorkspaceFactory pWsF = new AccessWorkspaceFactoryClass();
            IWorkspace pWs = pWsF.OpenFromFile(@"C:\Users\ZhangHao\Desktop\属性域示例\系统支撑库.mdb", 0);
            IFeatureClass pFeaCls = (pWs as IFeatureWorkspace).OpenFeatureClass("test");

            Dictionary<int,string> dicSubtype=new Dictionary<int,string>();
            dicSubtype.Add(0,"高压电线");
            dicSubtype.Add(1, "高压电缆");
            dicSubtype.Add(2, "低压电线");
            dicSubtype.Add(3, "低压电缆");
            CreateSubtypes(pFeaCls, "subtype", dicSubtype);

            Dictionary<string, string> dicDomain = new Dictionary<string, string>();
            dicDomain.Add("和平区","和平区高压电线");
            dicDomain.Add("铁西区", "铁西区高压电线");
            dicDomain.Add("沈河区", "沈河区高压电线");
            dicDomain.Add("皇姑区", "皇姑区高压电线");
            CreateDomain(pWs, "name_type_domain", dicDomain);

            AssignDomainToFieldWithSubtypes(pFeaCls, "name_type_domain", 0, "domaintype");
        }


代码详解:

1.Creating domains

// Cast the workspace to the IWorkspaceDomains interface.
IWorkspaceDomains workspaceDomains = (IWorkspaceDomains)workspace;

// The code to create a range domain.
IRangeDomain rangeDomain = new RangeDomainClass();
rangeDomain.MinValue = 0;
rangeDomain.MaxValue = 255;

// The code to set the common properties for the new range domain.
IDomain domain = (IDomain)rangeDomain;
domain.Name = "EightBitUnsignedInt";
domain.FieldType = esriFieldType.esriFieldTypeInteger;
domain.SplitPolicy = esriSplitPolicyType.esriSPTDuplicate;
domain.MergePolicy = esriMergePolicyType.esriMPTAreaWeighted;

// Add the new domain to the workspace.
workspaceDomains.AddDomain(domain);


// Cast the workspace to the IWorkspaceDomains interface.
IWorkspaceDomains workspaceDomains = (IWorkspaceDomains)workspace;

// The code to create a coded value domain.
ICodedValueDomain codedValueDomain = new CodedValueDomainClass();

// Value and name pairs.
codedValueDomain.AddCode("RES", "Residential");
codedValueDomain.AddCode("COM", "Commercial");
codedValueDomain.AddCode("IND", "Industrial");
codedValueDomain.AddCode("BLD", "Building");

// To remove a value:
codedValueDomain.DeleteCode("BLD"); // The "Building" code is removed.

// The code to set the common properties for the new coded value domain.
IDomain domain = (IDomain)codedValueDomain;
domain.Name = "Building Types";
domain.FieldType = esriFieldType.esriFieldTypeString;
domain.SplitPolicy = esriSplitPolicyType.esriSPTDuplicate;
domain.MergePolicy = esriMergePolicyType.esriMPTDefaultValue;

// Add the new domain to the workspace.
workspaceDomains.AddDomain(domain);

2.Opening and modifying domains

IWorkspaceDomains workspaceDomains = (IWorkspaceDomains)workspace;
IDomain requestedDomain = workspaceDomains.get_DomainByName(domainName);


Console.WriteLine("Valid values for domain '{0}':", domain.Name);
if (domain.Type == esriDomainType.esriDTCodedValue)
{
    ICodedValueDomain codedValueDomain = (ICodedValueDomain)domain;
    for (int i = 0; i < codedValueDomain.CodeCount; i++)
    {
        // codedValueDomain.get_Value(i) returns the code that is stored in the geodatabase 
        // (for example, RES).
        // codedValueDomain.get_Name(i) returns the name that is shown in the ArcMap 
        // inspector (for example, Residential).
        Console.WriteLine("Code: {0} Name: {1}", codedValueDomain.get_Value(i),
            codedValueDomain.get_Name(i));
    }
}

else
{
    IRangeDomain rangeDomain = (IRangeDomain)domain;
    Console.WriteLine("Minimum Value: {0} Maximum Value: {1}", rangeDomain.MinValue,
        rangeDomain.MaxValue);
}

3.Assigning domains to fields

Assigning domains to fields in an object or feature class without defined subtypes

// For example: domainName = "Material".
// fieldName = "CP_MATERIAL".
public void AssignDomainToField(IFeatureClass featureClass, String domainName,
    String fieldName)
{
    // Cast the feature class to IDataset to get a reference to the workspace.
    IDataset dataset = (IDataset)featureClass;

    // Get the workspace and cast it to the IWorkspaceDomains interface and get the requested domain.
    IWorkspace workspace = dataset.Workspace;
    IWorkspaceDomains workspaceDomains = (IWorkspaceDomains)workspace;
    IDomain domain = workspaceDomains.get_DomainByName(domainName);

    // Get the field to assign the domain to.
    IFields fields = featureClass.Fields;
    int fieldIndex = featureClass.FindField(fieldName);
    IField field = fields.get_Field(fieldIndex);

    // Check that the field and domain have the same field type.
    if (field.Type == domain.FieldType)
    {
        // Cast the feature class to the ISchemaLock and IClassSchemaEdit interfaces.
        ISchemaLock schemaLock = (ISchemaLock)featureClass;
        IClassSchemaEdit classSchemaEdit = (IClassSchemaEdit)featureClass;

        // Attempt to get an exclusive schema lock.
        try
        {
            // Lock the class and alter the domain.
            schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
            classSchemaEdit.AlterDomain(fieldName, domain);
            Console.WriteLine("The domain was successfully assigned.");
        }
        catch (Exception exc)
        {
            // Handle the exception in a way appropriate for the application.
            Console.WriteLine(exc.Message);
        }
        finally
        {
            // Set the schema lock to be a shared lock.
            schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
        }
    }
    else
    {
        Console.WriteLine("The field and the domain have different field types: " + 
            "Field = {0}, Domain = {1}", field.Type, domain.FieldType);
    }
}

Assigning domains to fields in an object or feature class with defined subtypes

public void AssignDomainToFieldWithSubtypes(IFeatureClass featureClass)
{
    // Cast the feature class to IDataset to get a reference to the workspace.
    IDataset dataset = (IDataset)featureClass;

    // Get the workspace and cast it to the IWorkspaceDomains interface and get the requested domain.
    IWorkspace workspace = dataset.Workspace;
    IWorkspaceDomains workspaceDomains = (IWorkspaceDomains)workspace;

    // Get the domains from the workspace.
    IDomain distributionDiamDomain = workspaceDomains.get_DomainByName("DistDiam");
    IDomain transmissionDiamDomain = workspaceDomains.get_DomainByName("TransDiam");

    // Cast for ISubtypes.
    ISubtypes subtypes = (ISubtypes)featureClass;

    // Assign the domain to the SIZE_ONE field on the distribution main subtype.
    subtypes.set_Domain(1, "SIZE_ONE", distributionDiamDomain);

    // Assign the domain to the SIZE_ONE field on the transmission main subtype.
    subtypes.set_Domain(2, "SIZE_ONE", transmissionDiamDomain);
}

4.Creating subtypes

Adding subtypes to a feature class

public void AddPipeSubtypes(IFeatureClass featureClass)
{
    // Cast the feature class to the ISubtypes interface.
    ISubtypes subtypes = (ISubtypes)featureClass;

    // Assign "PipeType" as the subtype field.
    subtypes.SubtypeFieldName = "PipeType";

    // Add the subtypes.
    subtypes.AddSubtype(1, "Primary");
    subtypes.AddSubtype(2, "Secondary");

    // Assign the default subtype code.
    subtypes.DefaultSubtypeCode = 1;
}

Assigning domains and default values to fields at the subtype level

public void SetDefaultsForSubtypes(IWorkspaceDomains workspaceDomains, ISubtypes
    subtypes)
{
    // The Diameter field in this example is an esriFieldTypeString field while
    // the Material field type is esriFieldTypeInteger.
    // Set the default value for the Diameter field on the primary subtype to 12.
    subtypes.set_DefaultValue(1, "Diameter", "12");

    // Set the domain for the Material field on the primary subtype to be the 
    // PrimaryMaterials domain.
    IDomain primaryMaterialsDomain = workspaceDomains.get_DomainByName(
        "PrimaryMaterials");
    subtypes.set_Domain(1, "Material", primaryMaterialsDomain);

    // Assign remaining domains at the subtype level.
    IDomain primaryDiametersDomain = workspaceDomains.get_DomainByName(
        "PrimaryDiameters");
    subtypes.set_Domain(1, "Diameter", primaryDiametersDomain);
    IDomain secondaryDiametersDomain = workspaceDomains.get_DomainByName(
        "SecondaryDiameters");
    subtypes.set_Domain(2, "Diameter", secondaryDiametersDomain);
    IDomain secondaryMaterialsDomain = workspaceDomains.get_DomainByName(
        "SecondaryMaterials");
    subtypes.set_Domain(2, "Material", secondaryMaterialsDomain);

    // Assign the remaining default values at the subtype level.
    subtypes.set_DefaultValue(1, "Material", 1); 
        // In this case, 1 represents the domain code for steel.
    subtypes.set_DefaultValue(2, "Diameter", "4");
    subtypes.set_DefaultValue(2, "Material", 2); 
        // In this case, 2 represents the domain code for copper.
}

Resetting subtypes codes

public void ResetSubtypes(IObjectClass objectClass)
{
    ISubtypes subtypes = (ISubtypes)objectClass;
    if (subtypes.HasSubtype)
    {
        // The Subtype field can be reset by assigning an empty string to SubtypeFieldName.
        subtypes.SubtypeFieldName = "";
    }
    else
    {
        Console.WriteLine("The class has no subtype defined.");
    }
}



  • 14
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值