Получение количества объектов в пространстве модели

Автор Тема: Получение количества объектов в пространстве модели  (Прочитано 5974 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Онлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 380
  • Карма: 21
Всех приветствую.
Интересует вопрос как просто получить количество объект в модели пространства. Я использовал такой способ.

Код - C# [Выбрать]
  1. BlockTable bt = tr.GetObject(lxDatabase.BlockTableId, OpenMode.ForRead) as BlockTable;
  2. BlockTableRecord btr = lxTransaction.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  3. int count = 0;
  4. foreach (ObjectId id in btr) { count++; }
  5. ed.WriteMessage($"Количество объектов {count}");
но неужели нет способа легче?

И ещё интересует вопрос. Если я захочу использовать не foreach, а просто for, как мне узнать значение для окончания цикла?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
но неужели нет способа легче?
Они все сводятся к этому способу.
Если я захочу использовать не foreach, а просто for, как мне узнать значение для окончания цикла?
Никак. Эта коллекция не имеет свойства, которое возвращает количество элементов.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Есть такой вариант: https://adn-cis.org/byistroe-poluchenie-kolichestva-primitivov-v-prostranstve-modeli.html
Но не думаю, что он быстрее обычного цикла.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Онлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 380
  • Карма: 21
Есть такой вариант: https://adn-cis.org/byistroe-poluchenie-kolichestva-primitivov-v-prostranstve-modeli.html
Но не думаю, что он быстрее обычного цикла.
Я находил этот пример и его вариации, мне они показались слишком мудрёнными. Я находил Ваш пост от 2010 года, но он почему-то не заработал.
https://forums.autodesk.com/t5/net/fast-methode-to-detect-the-modelspace-count/m-p/2861364#M21920

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Я находил Ваш пост от 2010 года, но он почему-то не заработал.
https://forums.autodesk.com/t5/net/fast-methode-to-detect-the-modelspace-count/m-p/2861364#M21920
Это тоже самое, только на VB.NET, так как спрашивали код именно на нём.
На C#:
Код - C# [Выбрать]
  1. btr.Cast<ObjectId>().Count();
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Онлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 380
  • Карма: 21
Я находил Ваш пост от 2010 года, но он почему-то не заработал.
https://forums.autodesk.com/t5/net/fast-methode-to-detect-the-modelspace-count/m-p/2861364#M21920
Это тоже самое, только на VB.NET, так как спрашивали код именно на нём.
На C#:
Код - C# [Выбрать]
  1. btr.Cast<ObjectId>().Count();
Да вот только у меня не показывает такого метода.

Отмечено как Решение Lemieux 29-03-2020, 19:42:35

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Да вот только у меня не показывает такого метода.
Это у тебя есть:
Код - C# [Выбрать]
  1. using System.Linq;
?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Онлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 380
  • Карма: 21
Да вот только у меня не показывает такого метода.
Это у тебя есть:
Код - C# [Выбрать]
  1. using System.Linq;
?
Круто, спасибо! Прям магия  :)

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Есть такой вариант: https://adn-cis.org/byistroe-poluchenie-kolichestva-primitivov-v-prostranstve-modeli.html
Но не думаю, что он быстрее обычного цикла.

Я LINQ знаю поверхностно, но в статье заголовок некорректен.
"LINQ предлагает легкий способ нахождения числа примитивов в Пространстве Модели без итерации по ней."

LINQ как-раз осуществляет итерацию, и другие вещи используя минимум строк кода.
Предлагаю хотя бы обрезать заголовок "LINQ предлагает легкий способ нахождения числа примитивов в Пространстве Модели."

И еще для продвижения LINQ среди новичков можно вместо:
 System.Collections.Generic.IEnumerable<ObjectId>
               idCollection = btr.Cast<ObjectId>();

написать:
var idCollection = btr.Cast<ObjectId>();

var позволяет "экономить строки" на длинных именах. Новичков в программировании System.Collections.Generic.IEnumerable<ObjectId> отпугивает.

А для подчеркивания мощи LINQ лучше переписать пример так:
int objectCount = btr.Cast<ObjectId>().Count();

т.к. комбинации методов расширения в LINQ позволяют создать функциональный и легко воспринимаемый код.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
но в статье заголовок некорректен.
Увы, но это точный перевод. Так что статью переписывать не буду. Достаточно того, что мы это обсудили. Почти со всеми замечаниями я согласен. Только вот var, в силу своей краткости, маскирует тип результирующего объекта, что не есть хорошо...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Онлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 380
  • Карма: 21
Спасибо за подсказку с Linq. Я тут чуток поэкпериментировал как получать, например, коллекцию block reference.

Код - C# [Выбрать]
  1. namespace Lemieux
  2. {
  3.     public class Test
  4.     {
  5.         [CommandMethod("TestLinq")]
  6.         public void TestLinq()
  7.         {
  8.             Document doc = Application.DocumentManager.MdiActiveDocument;
  9.             Database db = doc.Database;
  10.             Editor ed = doc.Editor;
  11.  
  12.             using (Transaction tr = db.TransactionManager.StartTransaction())
  13.             {
  14.                 BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  15.                 BlockTableRecord ms = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
  16.                 var colBr = ms.OfType<ObjectId>().Where(blRef => blRef.ObjectClass.DxfName == "INSERT");
  17.                 ed.WriteMessage(colBr.Count().ToString());
  18.                 tr.Commit();
  19.             }
  20.         }
  21.     }
  22. }

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Только вот var, в силу своей краткости, маскирует тип результирующего объекта, что не есть хорошо...
Я по той же причине стараюсь его использовать по минимуму. Но изучая различные комментарии и рекомендации, счел что иногда он полезен и стал применять.

1. Исключение "дублирования" в коде при объявлении, например словарей:
Dictionary<int, string> dic = new Dictionary<int,string>();

Так пишется и читается легче:
var dic = new Dictionary<int,string>();

2. Скрытие промежуточных данных:
В данном примере var скрывает громоздкую часть - объявление массива, который нам не важен в данной задаче.
А посмотреть эту информацию можно, если навести на var, а также можно нажать "перейти к определению".


Также люди пишут что везде var применять не стоит, т.к. может скрыть логику программы и принести неудобство просмотра кода:

Dictionary<ObjectId, Hatch> dic = hatchIterator.GetHatch();
В данном примере можно посмотреть все типы Dictionary, ObjectId, Hatch

если переписать с var:
var dic = hatchIterator.GetHatch();
то к типам ObjectId и Hatch уже быстро не перейти с помощью "перейти к определению".

Онлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 380
  • Карма: 21
Только вот var, в силу своей краткости, маскирует тип результирующего объекта, что не есть хорошо...
Я по той же причине стараюсь его использовать по минимуму. Но изучая различные комментарии и рекомендации, счел что иногда он полезен и стал применять.

1. Исключение "дублирования" в коде при объявлении, например словарей:
Dictionary<int, string> dic = new Dictionary<int,string>();

Так пишется и читается легче:
var dic = new Dictionary<int,string>();

2. Скрытие промежуточных данных:
В данном примере var скрывает громоздкую часть - объявление массива, который нам не важен в данной задаче.
А посмотреть эту информацию можно, если навести на var, а также можно нажать "перейти к определению".


Также люди пишут что везде var применять не стоит, т.к. может скрыть логику программы и принести неудобство просмотра кода:

Dictionary<ObjectId, Hatch> dic = hatchIterator.GetHatch();
В данном примере можно посмотреть все типы Dictionary, ObjectId, Hatch

если переписать с var:
var dic = hatchIterator.GetHatch();
то к типам ObjectId и Hatch уже быстро не перейти с помощью "перейти к определению".
Я в своём примере пробовал заменить var на ObjectId[] или ObjectIdCollection, но мне VS выдавал ошибку.

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Я в своём примере пробовал заменить var на ObjectId[] или ObjectIdCollection, но мне VS выдавал ошибку.
1. А зачем ты под моим комментарием написал это? Вещи не связанные!

2. var это не object, это определенный тип, в каждом случае он разный. Если наведешься на var, то увидишь что это за тип.
Ты зачем-то попытался подменить тип на несовместимый, и словил предупреждение.

наверное Александр прав, замени System.Collections.Generic.IEnumerable<ObjectId> на var а новичку все равно непонятно будет :-)

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 805
  • Карма: 166
    • Мои плагины к Автокаду
var позволяет "экономить строки" на длинных именах. Новичков в программировании System.Collections.Generic.IEnumerable<ObjectId> отпугивает.
100% наоборот - неопределенный тип данных заставляет ломать мозг, что ж там такое возвращает это ваше выражение. Если там new SomeClass(), то все понятно. А вашем случае - абсолютно непонятно. так еще и пример на форуме, а не в VS - подсказка типа не всплывет. Собственно Lemieux, тут же , в следующем комментарии, доказал, что var - это зло.
т.к. комбинации методов расширения в LINQ позволяют создать функциональный и легко воспринимаемый код.
Убитьсяапстену, а не код. Вот специально в одну строку напишу:
Код - C# [Выбрать]
  1. int c=0; foreach (ObjectId id in btr) c++;
  2. int objectCount = btr.Cast<ObjectId>().Count();
foreach не только короче писать, он в 100500 раз проще и понятней. И быстрее в разы. В нем вообще не создается никаких коллекций, не выделяется памяти только для того, чтоб потом пересчитать количество еще одним циклом. В нем можно выполнить всю работу за 1 цикл. В нем можно прервать итерации как только ясен результат. И т.д. и т.п. Нравятся извращения - да ради бога. Но не надо ж это пихать новичкам как полезную фичу.
p.s. Извиняюсь за эмоциональность. Карантин...

Онлайн LemieuxАвтор темы

  • ADN OPEN
  • ****
  • Сообщений: 380
  • Карма: 21
что var - это зло
Что интересно, Microsoft в своих примерах использует var.
https://docs.microsoft.com/ru-ru/dotnet/csharp/programming-guide/concepts/linq/introduction-to-linq-queries
На счёт foreach. Иногда лучше использовать linq, а иногда foreach. Но это на основании анализа своего кода в течении суток и переписывании части строк на linq, так что просьба не пинать  ;D

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
foreach не только короче писать, он в 100500 раз проще и понятней. И быстрее в разы. В нем вообще не создается никаких коллекций, не выделяется памяти только для того, чтоб потом пересчитать количество еще одним циклом. В нем можно выполнить всю работу за 1 цикл. В нем можно прервать итерации как только ясен результат. И т.д. и т.п. Нравятся извращения - да ради бога. Но не надо ж это пихать новичкам как полезную фичу.
p.s. Извиняюсь за эмоциональность. Карантин...

Если уж у тебя коллекция создается, несколько циклов и работает в разы медленнее, то тут точно карантин поработал))))))
Ну ладно хоть прервать цикл можно, хоть что-то правда, поставлю плюсик для здоровья))))))

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
И быстрее в разы.
Спорно. Скорее наоборот. Насколько мне известно, foreach вообще аутсайдер по производительности в циклах .NET. Например, тут п.6. Не истина в последней инстанции, но есть такое мнение и оно довольно резонное. Если поискать, можно найти разные тесты по замеру производительности на разных типах циклов. В общем, про "разы быстрее" - это бабка надвое сказала.
var - это зло
Опять спорно. Я не являюсь большим сторонником его использования, но злом его также не считаю. Есть в его использовании удобства и плюсы.
На счёт foreach. Иногда лучше использовать linq, а иногда foreach.
Вот с этим согласен.