Как узнать где во вставляемом блоке находится точка вставки относительно общих размеров?
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Как узнать где во вставляемом блоке находится точка вставки относительно общих размеров?

Как узнать где во вставляемом блоке находится точка вставки относительно общих размеров?

Ответ
Поиск в этой теме
Непрочитано 03.07.2012, 15:11 #1
Как узнать где во вставляемом блоке находится точка вставки относительно общих размеров?
ghost
 
Регистрация: 19.12.2011
Сообщений: 35

Доброго времени суток!

Есть блок который вставляется из стороннего чертежа в текущий чертеж AutoCad, в текущем чертеже есть начерченная таблица в одну из ячеек которой вставляется блок. Ячейка таблицы по размерам равна размерам вставляемого блока, а точка вставки блока может быть где угодно..... Можно ли как то определить координаты точки вставки, блока который вставляется?
Есть ли какой нибудь метод или свойство, в NET библиотеках под C#, которое хранит в себе точку вставки блока или может алгоритм есть с помощью которого можно получить координаты этой точки???

Заранее спасибо!
Просмотров: 6348
 
Непрочитано 03.07.2012, 20:29
#2
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от ghost Посмотреть сообщение
Есть ли какой нибудь метод или свойство, в NET библиотеках под C#, которое хранит в себе точку вставки блока или может алгоритм есть с помощью которого можно получить координаты этой точки???
Следует отличать понятие определение блока от понятия вхождение блока. Насколько я тебя понял - ты имеешь в виду второй вариант. Тогда смотри свойство BlockReference.Position. Не ленись заглядывать в документацию по ObjectARX.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 03.07.2012, 23:57
#3
Олег (jr.)

специалист по околачиванию грушевых деревьев
 
Регистрация: 14.09.2004
Pietari, Venäjä
Сообщений: 811


Цитата:
Сообщение от ghost Посмотреть сообщение
Доброго времени суток!

Есть блок который вставляется из стороннего чертежа в текущий чертеж AutoCad, в текущем чертеже есть начерченная таблица в одну из ячеек которой вставляется блок. Ячейка таблицы по размерам равна размерам вставляемого блока, а точка вставки блока может быть где угодно..... Можно ли как то определить координаты точки вставки, блока который вставляется?
Есть ли какой нибудь метод или свойство, в NET библиотеках под C#, которое хранит в себе точку вставки блока или может алгоритм есть с помощью которого можно получить координаты этой точки???

Заранее спасибо!
Вот так можно вставить определение блока в документ,
а вставку блока в таблицу через ObjectId этого блока:

Код:
[Выделить все]
cell.Contents(0).BlockTableRecordId =  blockId;
Код:
[Выделить все]
  
     //using System.IO;
        [CommandMethod("insa")]
        public static void ExtBlockCopyTest()
        {
            ObjectId blkTblRecId = ObjectId.Null;
          // измени имя файла-ресурса и имя блока :
            InsertBlockFromContainer(@"C:\Test\TitleExample.dwg", "TITLEBLOCK", blkTblRecId);
        }



        public static void InsertBlockFromContainer(string Container, string blkName, ObjectId blkTblRecId)
        {
            // Find the file containing all the blocks

            if (!File.Exists(Container))
            {
                MessageBox.Show("Could not find file !");

                return;

            }

            // Read the database in memory

            Database sourceDb = new Database(false, true);

            sourceDb.ReadDwgFile(Container, FileOpenMode.OpenForReadAndAllShare, false, "");

            using (Transaction sourceTr = sourceDb.TransactionManager.StartTransaction())
            {
                // Find the ObjectId of the block we are interested in.

                BlockTable sourceBt = null;

                sourceBt = sourceTr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead) as BlockTable;

                ObjectId sourceBtId;

                BlockTableRecord sourceBtr = null;

                if (!sourceBt.Has(blkName))
                {

                    MessageBox.Show("Block not found !");

                    return;

                }

                sourceBtr = sourceTr.GetObject(sourceBt[blkName], OpenMode.ForRead) as BlockTableRecord;

                sourceBtId = sourceBtr.ObjectId;

                Database curDoc = HostApplicationServices.WorkingDatabase;

                Editor ed = acApp.DocumentManager.MdiActiveDocument.Editor;

                // Create a new block table record in the current database.
                using (Transaction tr = curDoc.TransactionManager.StartTransaction())
                {

                    BlockTable destBt = null;

                    destBt = tr.GetObject(curDoc.BlockTableId, OpenMode.ForRead) as BlockTable;

                    ObjectId destBtId = destBt.ObjectId;

                    // WBlockClone the BlockTable record to the current database

                    ObjectIdCollection idColl = new ObjectIdCollection();

                    idColl.Add(sourceBtId);

                    // ObjectId of the btr that we want to clone

                    IdMapping idMap = new IdMapping();

                    curDoc.WblockCloneObjects(idColl, destBtId, idMap, DuplicateRecordCloning.Ignore, false);

                    // Create an instance of the block

                    BlockTableRecord destBtr = null;

                    destBtr = tr.GetObject(destBt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                    ObjectId destBtrId;

                    destBtrId = destBt[blkName];

                    // Insert an instance of the block in point(0,0,0)
                    BlockReference bref = new BlockReference(Point3d.Origin, destBtrId);

                    destBtr.AppendEntity(bref);

                    tr.AddNewlyCreatedDBObject(bref, true);
                    // Check, then insert the attributes
                    BlockTableRecord btrec = null;

                    btrec = tr.GetObject(bref.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;

                    if (btrec.HasAttributeDefinitions)
                    {
                        foreach (ObjectId id in btrec)
                        {
                            AttributeDefinition atdef = tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;

                            if (atdef != null)
                            {
                                using (AttributeReference atref = new AttributeReference())
                                {
                                    atref.SetAttributeFromBlock(atdef, bref.BlockTransform);

                                    atref.Position = atdef.Position + bref.Position.GetAsVector();

                                    atref.TextString = atdef.TextString;

                                    bref.AttributeCollection.AppendAttribute(atref);

                                    tr.AddNewlyCreatedDBObject(atref, true);
                                }
                            }
                        }
                    }

                    tr.Commit();
                }

            }
        }
~'o'~

Последний раз редактировалось Олег (jr.), 04.07.2012 в 00:02.
Олег (jr.) вне форума  
 
Автор темы   Непрочитано 04.07.2012, 11:41
#4
ghost


 
Регистрация: 19.12.2011
Сообщений: 35


Уважаемые участники форума!
Я наверное не правильно выразился!
Я знаю как импортировать определение блока из другого чертежа и знаю как создать ссылку для вхождения блока........ Основная проблема в том что я при вставке не могу точно попасть в таблицу которая в текущем чертеже! Потому что точка вставки у самого блока может быль где угодно!
Одни блоки созданы с точкой для вставки в правом верхнем углу, вторые блоки созданы с точкой для вставки в левом нижнем углу, а остальные блоки созданы с точкой для вставки где-то посредине.........
Где какие блоки не известно! Они все вперемешку..... Задача стоит в том что-бы их перед вставкой как то программно позиционировать, что бы они точно влазили в таблицу....... Вот!
ghost вне форума  
 
Непрочитано 04.07.2012, 14:19
#5
bargool


 
Регистрация: 16.08.2006
Санкт-Петербург
Сообщений: 508
<phrase 1=


Вариантов два, если блок не динамический, то у BlockTableRecord есть свойство Origin - оно отвечает за точку вставки блока. Если блок динамический, то возможна ситуация, что определение блока содержит динамический параметр Basepoint, до него можно добраться перебрав у вхождения блока его DynamicBlockReferencePropertyCollection.
Быстрый эксперимент показал, что этому параметру соответствует DynamicBlockReferenceProperty с PropertyName = Origin и PropertyTypeCode = 12, вот только в Value он содержит смещение от своего положения до BlockTableRecord.Origin, похоже.. А дальше уже дело техники определить где полученная точка вставки относительно остальной геометрии в блоке.
Возможно, есть более простой и правильный путь, конечно.
bargool вне форума  
 
Автор темы   Непрочитано 16.07.2012, 17:00
#6
ghost


 
Регистрация: 19.12.2011
Сообщений: 35


Спасибо за ответы!
А можно в коде...... Если не сложно! Хотя бы частично....
Я не очень опытный программист...... Мне в коде будет легче понять!
Блоки у меня обычные не динамические!
Три дня про ковырялся, что то не могу понять!
Заранее спасибо!

P.S. Извините за долгий ответ, я был послан в командировку......
ghost вне форума  
 
Непрочитано 17.07.2012, 11:50
#7
bargool


 
Регистрация: 16.08.2006
Санкт-Петербург
Сообщений: 508
<phrase 1=


Так где конкретно затык? Границы геометрии внутри блока можно определить грубо с помощью GeometricExtents. Т.е. пробегаешься по всем объектам внутри блока, получаешь их GeometricExtents.MaxPoint и GeometricExtents.MinPoint, ищешь максимальную/минимальную точки в целом, отсюда получаешь геометрический центр твоих объектов (или какую точку хочешь получить), ну и смотришь смещение относительно origin
bargool вне форума  
 
Непрочитано 17.07.2012, 11:51
#8
Кулик Алексей aka kpblc
Moderator

LISP, C# (ACAD 200[9,12,13,14])
 
Регистрация: 25.08.2003
С.-Петербург
Сообщений: 40,404


bargool, забыл про атрибуты.
__________________
Моя библиотека lisp-функций
---
Обращение ко мне - на "ты".
Все, что сказано - личное мнение.
Кулик Алексей aka kpblc вне форума  
 
Непрочитано 17.07.2012, 11:58
#9
bargool


 
Регистрация: 16.08.2006
Санкт-Петербург
Сообщений: 508
<phrase 1=


Кулик Алексей aka kpblc, оу! да! Кстати, он ни одной строчки не показал своих мучений
bargool вне форума  
 
Автор темы   Непрочитано 18.07.2012, 09:47
#10
ghost


 
Регистрация: 19.12.2011
Сообщений: 35


Мне кажется в моих экспериментах много бреда.......
По этому я решил не позорится.......

Теперь все стало немного понятней!
Перебрать объекты блока можно так....... На сколько я понял!
Код:
[Выделить все]
BlockTable BT = (BlockTable)trans.GetObject(currDatabase.BlockTableId, OpenMode.ForRead);
BlockTableRecord BTR = (BlockTableRecord)trans.GetObject(BT[NameBlock], OpenMode.ForWrite);

      foreach (ObjectId Id in BTR)
      { 
                
      }
А как добраться до свойства "GeometricExtents" , я так понял оно есть только у вхождения блока "BlockReference"?
Делать для каждого элемента вхождение??????
ghost вне форума  
 
Непрочитано 18.07.2012, 10:36
#11
bargool


 
Регистрация: 16.08.2006
Санкт-Петербург
Сообщений: 508
<phrase 1=


Так, возвращаемся к основам. Этот документ читал? Его перевод у hwd. Далее есть SDK - очень полезная штука.
GeometricExtents - свойство у видимых объектов автокада, т.е. его имеют все объекты по иерархии начиная от Entity.
т.о., в своём цикле можешь получить
Код:
[Выделить все]
 Entity entity = trans.GetObject(Id, OpenMode.ForRead) as Entity;
if (entity!=null)
{
	// тут работаешь с entity.GeometricExtents
}
По поводу атрибутов, положение вхождений атрибутов может отличаться от их позиции в определении блока. В зависимости от задачи возможно придётся проверять ещё и вхождения атрибутов, но будем усложнять задачу шаг за шагом

Последний раз редактировалось bargool, 18.07.2012 в 10:42.
bargool вне форума  
 
Автор темы   Непрочитано 18.07.2012, 13:52
#12
ghost


 
Регистрация: 19.12.2011
Сообщений: 35


Эти ресурсы я почитываю, периодически.....Но частями! По мере надобности!
Но полностью я их не изучил. Времени никак выделить не могу..... "Любимая" работа не позволяет!

У меня возникла очередная проблема:
Код:
[Выделить все]
 

public static double Correct(BlockTable BT, Transaction trans, string NameBlock)
        {
            BlockTableRecord BTR = (BlockTableRecord)trans.GetObject(BT[NameBlock], OpenMode.ForRead);

            double YMax = 0;
            //double YMin = 0;
            

            foreach (ObjectId Id in BTR)
            {
                Entity entity = trans.GetObject(Id, OpenMode.ForRead) as Entity;
                if (entity != null)
                {
                    if (entity.GeometricExtents.MaxPoint.Y > YMax)
                    {
                        YMax = entity.GeometricExtents.MaxPoint.Y;
                    }

                }

            }

            return YMax;

        }

Это пробный метод......
При вызове происходит исключение eNullExtents и возвращается ноль....... Похоже я где-то налажал!
ghost вне форума  
 
Непрочитано 18.07.2012, 15:02
#13
bargool


 
Регистрация: 16.08.2006
Санкт-Петербург
Сообщений: 508
<phrase 1=


так вот наверное, что имел в виду Кулик Алексей aka kpblc!
ошибка выскакивает при появлении определений атрибутов в определении блока
Кстати, я туплю. Ведь можно вставить блок, а затем проверить его GeometricExtents, они не учитывают точку вставки, а учитывают именно геометрию. А точку вставки определить по свойству Position BlockReference

Последний раз редактировалось bargool, 18.07.2012 в 15:13.
bargool вне форума  
 
Автор темы   Непрочитано 18.07.2012, 16:03
#14
ghost


 
Регистрация: 19.12.2011
Сообщений: 35


Да! Если не перебирать атрибуты то исключение исчезает.......
Код:
[Выделить все]
 
public static double Correct(BlockTable BT, Transaction trans, string NameBlock)
        {
            BlockTableRecord BTR = (BlockTableRecord)trans.GetObject(BT[NameBlock], OpenMode.ForRead);
            double YMax = 0;
            foreach (ObjectId Id in BTR)
            {
                Entity entity = trans.GetObject(Id, OpenMode.ForRead) as Entity;
                DBObject DBO = (DBObject)trans.GetObject(Id, OpenMode.ForWrite);
                if (entity != null && !(DBO is AttributeDefinition))
                {
                    if (entity.GeometricExtents.MaxPoint.Y > YMax)
                    {
                        YMax = entity.GeometricExtents.MaxPoint.Y;
                    }
                }
            }
            return YMax;
        }
Но возвращает все равно "0"........!?

А как при добавленной ссылке "поправить" блок? Ссылка то уже добавлена!? И блок уже получается вставлен!
ghost вне форума  
 
Непрочитано 18.07.2012, 17:03
#15
bargool


 
Регистрация: 16.08.2006
Санкт-Петербург
Сообщений: 508
<phrase 1=


Во первых, OpenMode.ForWrite - открытие объекта для записи, операция значительно более длительная, чем для чтения OpenMode.ForRead, да ещё и для каждого объекта может выполняться один раз одновременно. Если не планируется ничего изменять - лучше открывать для чтения. Если менять только некоторые объекты, по условию, то можно вначале открывать для чтения, проверять, нужны ли изменения, а потом уже использовать метод UpgradeOpen().
Во вторых, можно сразу проверять на entity is AttributeDefinition, незачем 2 раза для этого открывать объект.
В третьих, познай силу LINQ, люк
Код:
[Выделить все]
 public static double YMax(BlockTableRecord btr)
{
	return btr.Cast<ObjectId>()
		.Select(n => n.GetObject(OpenMode.ForRead) as Entity)
		.Where(n => n!=null && !(n is AttributeDefinition))
		.Max(n => n.GeometricExtents.MaxPoint.Y);
}
По поводу выяснения к какому типу принадлежит объект - хороший пост со способами и производительностью

По поводу "А как при добавленной ссылке "поправить" блок? Ссылка то уже добавлена!? И блок уже получается вставлен!" - изучай мат. часть. При изменении определения блока меняются и вхождения блоков. В том и смысл. Правда, как всегда с автокадом, с оговорками. Отдельно надо отслеживать вхождения атрибутов и динамику

Да! Забыл про в четвёртых: ты инициализировал YMax = 0, а ведь геометрия блока может быть ниже нуля

Последний раз редактировалось bargool, 18.07.2012 в 17:31. Причина: Добавил про изменения блоков и много чего ещё
bargool вне форума  
 
Автор темы   Непрочитано 20.07.2012, 14:31
#16
ghost


 
Регистрация: 19.12.2011
Сообщений: 35


Цитата:
Сообщение от bargool Посмотреть сообщение
Во вторых, можно сразу проверять на entity is AttributeDefinition, незачем 2 раза для этого открывать объект.
Я еще плохо знаю объектную модель ...... По этому откопипастил по быстрому из рабочего кода! Для пробы! Особо не вникал!

Цитата:
Сообщение от bargool Посмотреть сообщение
В третьих, познай силу LINQ, люк
Уже читаю мастер Оби Ван
Похоже мощная штука.........


Цитата:
Сообщение от bargool Посмотреть сообщение
По поводу "А как при добавленной ссылке "поправить" блок? Ссылка то уже добавлена!? И блок уже получается вставлен!" - изучай мат. часть. При изменении определения блока меняются и вхождения блоков. В том и смысл. Правда, как всегда с автокадом, с оговорками. Отдельно надо отслеживать вхождения атрибутов и динамику
Да! Мат. часть я так предчувствую мне еще долго учить...... Вот бы еще в сутки добавить часа 4....... Но я по мере сил буду разбираться!

Цитата:
Сообщение от bargool Посмотреть сообщение
Да! Забыл про в четвёртых: ты инициализировал YMax = 0, а ведь геометрия блока может быть ниже нуля
Я обязательно учту! Подчеркиваю что, это был всего лишь пример!


Спасибо всем за наставления и отдельное СПАСИБО bargool-у! Теперь есть информация для размышления и изучения!
Проблема решилась следующим способом! Создаю вхождение блока (BlockReference) => Получаю его GeometricExtents.MaxPoint и GeometricExtents.MinPoint => Используя координаты внешней точки вставки, определяю на сколько нужно сместить и куда => Получаю Point3d => И присваиваю Point3d свойству Position того же вхождения (BlockReference) перед выводом! И работает!
ghost вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Как узнать где во вставляемом блоке находится точка вставки относительно общих размеров?



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблемы с расчетом Ж/Б каркаса в ANSYS derik ANSYS 457 04.07.2017 16:16