Поиск объектов, имеющих определенное значение определенного свойства в чертеже Autocad

У меня есть объекты на чертеже Autocad со свойством Base. Я пытаюсь найти все объекты на этом чертеже со свойством Base, имеющим определенное строковое значение, например "Pipe".

Я могу повторять объекты на чертеже и получать идентификаторы всех объектов. Затем я получаю все свойства объекта с этим идентификатором и проверяю, есть ли свойство с именем Base = "Pipe".

Производительность итерации недостаточно высока. Есть ли способ напрямую получить идентификаторы объектов со свойством Base = "Pipe"?

Вот как я перебираю все объекты:

    List<ObjectId> ObjectIds = new List<ObjectId>();

    foreach (Document Document in Documents)
    {
        Database Database = Document.Database;

        using (Transaction Transaction = Database.TransactionManager.StartTransaction())
        {
            for (long i = Database.BlockTableId.Handle.Value; i < Database.Handseed.Value; i++)
            {
                ObjectId Id;

                if (Database.TryGetObjectId(new Handle(i), out Id))
                {
                        ObjectIds.Add(Id);
                }
            }

            Transaction.Commit();
        }
    }

И вот как я получаю все свойства объектов в моей коллекции ObjectIds.

public static DataLinksManager DataLinks
{
    get
    {
        if (null == _DataLinks)
        {
            StringCollection Coll = Autodesk.ProcessPower.DataLinks.DataLinksManager.GetLinkManagerNames();

            if (Coll.Count > 0)
            {
                if (Coll[0] != string.Empty)
                {
                    _DataLinks = Autodesk.ProcessPower.DataLinks.DataLinksManager.GetManager(Coll[0]);
                }
            }
        }

        return _DataLinks;
    }
}

private static DataLinksManager _DataLinks;

foreach(var Id in ObjectIds)
{
    List<KeyValuePair<string, string>> Properties = DataLinks.GetAllProperties(Id, true);
    // I check existence of my property and if so its value.
}

person Demir    schedule 26.12.2012    source источник
comment
Пожалуйста, опубликуйте код, который у вас есть в настоящее время.   -  person Mike Perrenoud    schedule 26.12.2012
comment
Вы пытаетесь найти все ссылки на блоки со значением атрибута «База», равным «Труба»?   -  person vinayan    schedule 28.12.2012
comment
Да, @vinayan, это то, что я пытаюсь сделать в приемлемом исполнении.   -  person Demir    schedule 28.12.2012


Ответы (2)


Если кому-то нужно, вот код, который является решением моей проблемы. Хитрость заключается в методе Iterate. Это основано на эта статья Филиппа Лифсма. Я добавляю к этому методу список ObjectClass свойств найденных ObjectId экземпляров. У моего образца галочка около 8500 ObjectIds. Однако меня интересуют объекты с базовыми классами acppasset и acppdynamicasset, и количество таких объектов равно 90.

using Autodesk.AutoCAD.ApplicationServices;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;

public static void GetObjects()
{
    List<KeyValuePair<string, ObjectId>> ObjectIds = new List<KeyValuePair<string, ObjectId>>();

    List<string> Filter = new List<string>() { "acppasset", "acppdynamicasset" };

    foreach (Document Document in this.Documents)
    {
        ObjectIdCollection Ids = this.Iterate(Document, Filter);
        if (null != Ids) foreach (var Id in Ids.OfType<ObjectId>()) ObjectIds.Add(new KeyValuePair<string, ObjectId>(System.IO.Path.GetFileNameWithoutExtension(Document.Name), Id));
    }

    this.Results = new Dictionary<string, List<List<KeyValuePair<string, string>>>>();

    foreach (var Id in ObjectIds)
    {
        try
        {
            var Properties = this.GetObject(Id.Value);
            if (null == Properties) continue;

            var Base = Properties.Where(x => x.Key == "Base").FirstOrDefault();

            if (string.IsNullOrWhiteSpace(Base.Value)) continue;

            if (!this.Results.ContainsKey(Base.Value)) this.Results.Add(Base.Value, new List<List<KeyValuePair<string, string>>>());

            this.Results[Base.Value].Add(Properties);
        }   catch { }
    }
}

 public ObservableCollection<Document> Documents { get; set; }

 public ObjectIdCollection Iterate(Document Document, List<string> Filter = null)
        {
            ads_name Instance = new ads_name();
            Database Database = Document.Database;

            ObjectIdCollection ValidIds = new ObjectIdCollection();

            // Get the last handle in the Database
            Handle Handseed = Database.Handseed;

            // Copy the handseed total into an efficient raw datatype
            long HandseedTotal = Handseed.Value;

            for (long i = 1; i < HandseedTotal; ++i)
            {
                string Handle = Convert.ToString(i, 16);

                int Result = acdbHandEnt(Handle, ref Instance);
                if (Result != 5100) continue; // RTNORM

                ObjectId Id = new ObjectId(Instance.a);

                if (!Id.IsValid) continue;

                try
                {
                    if (null != Filter)
                    {
                        if (!Filter.Contains(Id.ObjectClass.Name.ToLower())) continue;
                    }

                    using (DBObject DBObject = Id.Open(OpenMode.ForRead, false))
                    {
                        ValidIds.Add(Id);
                        DBObject.Dispose();
                    }
                }   catch { }
            }

            return ValidIds;
    }

    public List<KeyValuePair<string, string>> GetObject(ObjectId Id)
    {
        if (Command.DataLinks != null) try { return Command.DataLinks.GetAllProperties(Id, true); } catch { return null; }
        return null;
    }

public static DataLinksManager DataLinks
{
    get
    {
        if (null == _DataLinks)
        {
            StringCollection Coll = Autodesk.ProcessPower.DataLinks.DataLinksManager.GetLinkManagerNames();

            if (Coll.Count > 0)
            {
                if (Coll[0] != string.Empty)
                {
                    _DataLinks = Autodesk.ProcessPower.DataLinks.DataLinksManager.GetManager(Coll[0]);
                }
            }
        }

            return _DataLinks;
        }
    }

private static DataLinksManager _DataLinks;

public Dictionary<string, List<List<KeyValuePair<string, string>>>> Results { get; set; }
person Demir    schedule 02.01.2013

Низкая производительность здесь связана с тем, что он пытается прочитать все объекты и проверить, содержит ли он какой-либо атрибут. Насколько мне известно, атрибуты существуют только для ссылок на блоки (вставки). Итак, если фильтры выбора, мы могли бы получить прямой доступ только к тем записям на основе критериев фильтра.

Я нашел довольно простой пример здесь с использованием фильтра выбора, который выбирает все блоки с определенным именем.

Копирование части этого кода для справки. Это выбирает только ссылки на блоки. Вы можете повторить отсюда.

TypedValue[] filterlist = new TypedValue[1];
filterlist[0] = new TypedValue(0, "INSERT");
SelectionFilter filter =  new SelectionFilter(filterlist);

PromptSelectionResult selRes =  ed.SelectAll(filter);

if (selRes.Value.Count != 0)
{
    SelectionSet set = selRes.Value;

    foreach (ObjectId id in set.GetObjectIds())
    {
        BlockReference oEnt = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
        //do something with oEnt..;
    }

}

Если вы можете усложнить фильтр, вам нужно будет повторить только очень небольшой набор.

person vinayan    schedule 28.12.2012
comment
Спасибо за ваше предложение @vinayan. Использование фильтра выбора работает, если я выбираю объекты. В моем случае я не должен выбирать какой-либо объект, просто просматриваю базу данных чертежей. - person Demir; 02.01.2013
comment
@Demir - хорошо, что ты потрудился! немного изменено, чтобы избежать взаимодействия с пользователем :) - person vinayan; 02.01.2013