Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: JohnJ от 18-12-2014, 05:42:41

Название: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 18-12-2014, 05:42:41
Есть документ (в приложении), в котором размеры динамического блока, определяемые по следующим точкам,
Код - Text [Выбрать]
  1.     var p1 = br.GeometricExtents.MinPoint;
  2.     var p2 = br.GeometricExtents.MaxPoint;
  3.  
оказываются равны 297 по вертикали и около 3000 по горизонтали, хотя на чертеже этот блок шириной с лист A4 (210), но при некоторых значениях Видимости может расширяться до 3000.

Как определить действительные размеры отображения этого блока при текущем значении Видимости? Я ничего похожего не нашёл среди свойств объекта в отладчике, ничего не нашёл и в интернете по запросу "c# autocad size of dynamic block", кроме одной статьи Accessing visible entities in a dynamic block (http://adndevblog.typepad.com/autocad/2012/05/accessing-visible-entities-in-a-dynamic-block.html) ...
Не знаю, подойдёт ли мне этот метод, возможно есть способ проще? В данной задаче мне не требуется перебирать объекты блока. Просто - узнать контурные размеры.
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Александр Ривилис от 18-12-2014, 09:04:08
В данной задаче мне не требуется перебирать объекты блока. Просто - узнать контурные размеры.
Боюсь что без перебора ничего не получится. Если тебе нужны точные размеры, то придется перебирать все элементы блока и вычислять их размер. Только  не элементы основного динамического блока, а того, который получается в этой видимости (анонимного).
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 18-12-2014, 09:31:53
Понял, т.е. нужно перебирать элементы определения блока, полученного по br.AnonymousBlockTableRecord?
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Александр Ривилис от 18-12-2014, 09:41:02
Да.
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 18-12-2014, 09:55:07
Перебрал все элементы BlockTableRecord от AnonymousBlockTableRecord. Среди них находятся полилинии всех длин (смотрел по GeometricExtensts полилиний), вплоть до 3000 с хвостиком. Как определять, какие видны именно в данный момент?
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Дмитрий Загорулькин от 18-12-2014, 10:23:29
Я использовал метод Explode и определял границы получившихся примитивов. Конечно, есть варианты, когда способ метод может дать неправильный результат, но в моем случае меня устроило. А иначе, нужно: перебрать все примитивы внутри, проверить их видимость (есть какое-то свойство для этого), трансформировать координаты примитива в соответствии с настройками блока...
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Александр Ривилис от 18-12-2014, 12:57:29
Перебрал все элементы BlockTableRecord от AnonymousBlockTableRecord. Среди них находятся полилинии всех длин (смотрел по GeometricExtensts полилиний), вплоть до 3000 с хвостиком. Как определять, какие видны именно в данный момент?
Обратил внимание, что у них свойство Visible в False:
(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fimg-fotki.yandex.ru%2Fget%2F9105%2F7842324.2%2F0_f17c2_438f2edd_orig.jpg&hash=16ce54789592caa93064a458ff208a52) (http://img-fotki.yandex.ru/get/15590/7842324.2/0_f17c1_53b8483f_orig.png) 
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 19-12-2014, 10:23:07
Хех, забавно! Я ещё было подумал: "жаль, что нет свойства какого-нибудь, вроде Visible". Не заметил его что-то...
Спасибо!
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Дмитрий Загорулькин от 19-12-2014, 10:45:14
Тут даже не в матрицах дело... Чтобы было понятнее - прикладываю картинку.
Пока отвечал, вопрос на который отвечал уже удалили  :)
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 19-12-2014, 10:49:47
ну то, что при повороте совсем другая оконтовка - это я понимаю. Поэтому я поворот и не учитываю, что бы не делать сейчас не нужных мне расчётов.
Про матрицы я спрашивал в том смысле, что мне не нравится мой подход: я пересоздаю Extents каждый раз по рассчитанным "вручную" точкам, хотя предчувствую, что должны быть встроенные методы изменения величин с помощью матриц трансформации. Но у меня не получилось их использовать.
Код свой я пока убрал - на пробном чертеже он срабатывал, а на реальном начал сбоить. Сейчас переделаю и выложу ещё раз.
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Александр Ривилис от 19-12-2014, 15:31:51
BlockReference.BlockTransform далжно дать тебе нужную матрицу, при помощи которой ты можешь преобразовать Extents3d методом Extents3d.TransformBy. Но это даст тебе параллельный осям параллелепипед. Тебе это нужно?
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 19-12-2014, 20:43:25
Так замотался, что забыл выложить получившийся код. А ведь хочется услышать советы по оптимизации.
Код - C# [Выбрать]
  1. public Extents3d GetBlockGeometricExtents(BlockReference block, Transaction trn = null) {
  2.             Extents3d? extents = null;
  3.             if (!block.IsDynamicBlock) return block.GeometricExtents;
  4.             MakeInTransaction(trn, tr => {
  5.                 var entities = FindAll(block.BlockTableRecord, TYPE_ANY, tr).Where(e => e.Visible);
  6.                 foreach (var ent in entities) {
  7.                     try {
  8.                         if (extents == null) {
  9.                             extents = ent.GeometricExtents;
  10.                         } else {
  11.                             var mip1 = extents.Value.MinPoint;
  12.                             var mip2 = ent.GeometricExtents.MinPoint;
  13.                             var map1 = extents.Value.MaxPoint;
  14.                             var map2 = ent.GeometricExtents.MaxPoint;
  15.                             var pe1 = new Point3d(Math.Min(mip1.X, mip2.X), Math.Min(mip1.Y, mip2.Y), Math.Min(mip1.Z, mip2.Z));
  16.                             var pe2 = new Point3d(Math.Max(map1.X, map2.X), Math.Max(map1.Y, map2.Y), Math.Max(map1.Z, map2.Z));
  17.                             extents = new Extents3d(pe1, pe2); //extents.Value.AddExtents(ent.GeometricExtents);
  18.                         }
  19.                     } catch { // ent выдаёт ошибку при обращении к GeometricExtents, если это не графический элемент (например, атрибут блока)
  20.                        
  21.                     }
  22.                 }
  23.                 if (extents == null) return;
  24.                 var vp = block.Position.GetAsVector();
  25.                 var p1 = ((Extents3d) extents).MinPoint + vp;
  26.                 var maxp = ((Extents3d) extents).MaxPoint;
  27.                 var scl = block.ScaleFactors;
  28.                 var p2 = new Point3d(maxp.X * scl.X, maxp.Y * scl.Y, maxp.Z * scl.Z) + vp;
  29.                 extents = new Extents3d(p1, p2);
  30.             });
  31.             return extents ?? block.GeometricExtents;
  32.         }
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 19-12-2014, 20:47:19
преобразовать Extents3d методом Extents3d.TransformBy
Возможно это именно то, что мне нужно, надо будет опробовать.
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Александр Ривилис от 19-12-2014, 21:49:14
// ent выдаёт ошибку при обращении к GeometricExtents, если это не графический элемент (например, атрибут блока)
Атрибут (класс AttributeReference) блока это графический примитив, как и определение атрибута (класс AttributeDefinition). И у них есть GeometricExtents. Только вот нужны ли они тебе для работы - это вопрос. Если уж и нужны, то AttributeReference, которые у BlockReference и AttributeDefinition с AttributeDefinition.Constant == true у BlockTableRecord
Я бы активнее пользовался бы Extents3d.AddExtents и Extents3d.AddPoint вместо того чтобы каждый раз создавать новый Extents3d
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 20-12-2014, 05:46:12
Если есть GeometricExtents, откуда тогда Exception в частности в случае с AttributeReference? Ошибка в чертеже?

Extents3d.AddExtents я использовал, но потом закомментировал, так как не получал нужного результата (или мне так показалось). Чуть позже я вернусь к этому, что бы разобраться.
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Александр Ривилис от 21-12-2014, 19:09:56
Если есть GeometricExtents, откуда тогда Exception в частности в случае с AttributeReference? Ошибка в чертеже?
Неплохо бы глянуть на чертеж, но подозреваю что проблема в том, что AttributeReference.TextString возвращает пустую строку, или строку состоящую из непечатаемых знаков, и соотвественно GeometricExtents не может вычислить габаритный контейнер и генерирует Exception.
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: JohnJ от 22-12-2014, 06:32:50
Файл прикладываю.
Перехватил ошибку. Она возникает на элементе (не только на нём, но он попался первым):
- ent {Autodesk.AutoCAD.DatabaseServices.AttributeDefinition} Autodesk.AutoCAD.DatabaseServices.Entity {Autodesk.AutoCAD.DatabaseServices.AttributeDefinition}
- [Autodesk.AutoCAD.DatabaseServices.AttributeDefinition] {Autodesk.AutoCAD.DatabaseServices.AttributeDefinition} Autodesk.AutoCAD.DatabaseServices.AttributeDefinition
Constant false bool
FieldLength 0 int
Invisible false bool
IsMTextAttributeDefinition true bool
LockPositionInBlock true bool
- MTextAttributeDefinition {Autodesk.AutoCAD.DatabaseServices.MText} Autodesk.AutoCAD.DatabaseServices.MText
ActualHeight 8.9473684210526319 double
ActualWidth 27.467195385724587 double
Ascent 3.0 double
Attachment MiddleCenter Autodesk.AutoCAD.DatabaseServices.AttachmentPoint
BackgroundFill false bool
+ BackgroundFillColor "((Autodesk.AutoCAD.DatabaseServices.AttributeDefinition)(ent)).MTextAttributeDefinition.BackgroundFillColor" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" Autodesk.AutoCAD.Colors.Color {Autodesk.AutoCAD.Runtime.Exception}
+ BackgroundScaleFactor "((Autodesk.AutoCAD.DatabaseServices.AttributeDefinition)(ent)).MTextAttributeDefinition.BackgroundScaleFactor" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" double {Autodesk.AutoCAD.Runtime.Exception}
+ BackgroundTransparency "((Autodesk.AutoCAD.DatabaseServices.AttributeDefinition)(ent)).MTextAttributeDefinition.BackgroundTransparency" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" Autodesk.AutoCAD.Colors.Transparency {Autodesk.AutoCAD.Runtime.Exception}
+ ColumnAutoHeight "((Autodesk.AutoCAD.DatabaseServices.AttributeDefinition)(ent)).MTextAttributeDefinition.ColumnAutoHeight" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" bool {Autodesk.AutoCAD.Runtime.Exception}
+ ColumnCount "((Autodesk.AutoCAD.DatabaseServices.AttributeDefinition)(ent)).MTextAttributeDefinition.ColumnCount" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" int {Autodesk.AutoCAD.Runtime.Exception}
+ ColumnFlowReversed "((Autodesk.AutoCAD.DatabaseServices.AttributeDefinition)(ent)).MTextAttributeDefinition.ColumnFlowReversed" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" bool {Autodesk.AutoCAD.Runtime.Exception}
+ ColumnGutterWidth "((Autodesk.AutoCAD.DatabaseServices.AttributeDefinition)(ent)).MTextAttributeDefinition.ColumnGutterWidth" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" double {Autodesk.AutoCAD.Runtime.Exception}
ColumnType NoColumns Autodesk.AutoCAD.DatabaseServices.ColumnType
+ ColumnWidth "((Autodesk.AutoCAD.DatabaseServices.AttributeDefinition)(ent)).MTextAttributeDefinition.ColumnWidth" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" double {Autodesk.AutoCAD.Runtime.Exception}
Contents "ОАО\\P\"Организация\"" string
Descent 0.94736842105263153 double
+ Direction {(1,0,0)} Autodesk.AutoCAD.Geometry.Vector3d
FlowDirection ByStyle Autodesk.AutoCAD.DatabaseServices.FlowDirection
Height 0.0 double
LineSpaceDistance 5.0 double
LineSpacingFactor 1.0 double
LineSpacingStyle AtLeast Autodesk.AutoCAD.DatabaseServices.LineSpacingStyle
+ Location {(-25.0000000000005,7.5,0)} Autodesk.AutoCAD.Geometry.Point3d
+ Normal {(0,0,1)} Autodesk.AutoCAD.Geometry.Vector3d
Rotation 0.0 double
Text "ОАО\r\n\"Организация\"" string
TextHeight 3.0 double
+ TextStyleId {(8755381037328)} Autodesk.AutoCAD.DatabaseServices.ObjectId
TextStyleName "Standard" string
UseBackgroundColor false bool
Width 58.31001039757902 double
+ Статические члены
Preset false bool
Prompt "Наименование организации" string
Tag "NAMEORG" string
Verifiable false bool
+ base {Autodesk.AutoCAD.DatabaseServices.AttributeDefinition} Autodesk.AutoCAD.DatabaseServices.DBObject {Autodesk.AutoCAD.DatabaseServices.AttributeDefinition}
+ BlockId {(8755381152496)} Autodesk.AutoCAD.DatabaseServices.ObjectId
BlockName "*U196" string
CastShadows false bool
CloneMeForDragging true bool
CollisionType Solid Autodesk.AutoCAD.DatabaseServices.CollisionType
+ Color {ПОСЛОЮ} Autodesk.AutoCAD.Colors.Color
ColorIndex 256 int
+ CompoundObjectTransform "ent.CompoundObjectTransform" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" Autodesk.AutoCAD.Geometry.Matrix3d {Autodesk.AutoCAD.Runtime.Exception}
+ Ecs {((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1))} Autodesk.AutoCAD.Geometry.Matrix3d
+ EdgeStyleId {(0)} Autodesk.AutoCAD.DatabaseServices.ObjectId
+ EntityColor {Autodesk.AutoCAD.Colors.EntityColor} Autodesk.AutoCAD.Colors.EntityColor
+ FaceStyleId {(0)} Autodesk.AutoCAD.DatabaseServices.ObjectId
ForceAnnoAllVisible false bool
+ GeometricExtents "ent.GeometricExtents" запустило исключение типа "Autodesk.AutoCAD.Runtime.Exception" Autodesk.AutoCAD.DatabaseServices.Extents3d {Autodesk.AutoCAD.Runtime.Exception}
+ Hyperlinks {Autodesk.AutoCAD.DatabaseServices.HyperLinkCollection} Autodesk.AutoCAD.DatabaseServices.HyperLinkCollection
IsPlanar true bool
Layer "0" string
+ LayerId {(8755381037312)} Autodesk.AutoCAD.DatabaseServices.ObjectId
Linetype "ByLayer" string
+ LinetypeId {(8755381037392)} Autodesk.AutoCAD.DatabaseServices.ObjectId
LinetypeScale 1.0 double
LineWeight ByLayer Autodesk.AutoCAD.DatabaseServices.LineWeight
Material "ByLayer" string
+ MaterialId {(8755381038528)} Autodesk.AutoCAD.DatabaseServices.ObjectId
MaterialMapper null Autodesk.AutoCAD.GraphicsInterface.Mapper
PlotStyleName "ByLayer" string
+ PlotStyleNameId {((0),PlotStyleNameByLayer)} Autodesk.AutoCAD.DatabaseServices.PlotStyleDescriptor
ReceiveShadows false bool
+ Transparency {(0)} Autodesk.AutoCAD.Colors.Transparency
Visible true bool
+ VisualStyleId {(0)} Autodesk.AutoCAD.DatabaseServices.ObjectId
Некоторые сведения об ошибке:
- exception {"eNullExtents"} System.Exception {Autodesk.AutoCAD.Runtime.Exception}
Source "Acdbmgd" string
StackTrace "   в Autodesk.AutoCAD.DatabaseServices.Entity.get_GeometricExtents()\r\n   в AutocadEngine.CadEngine.<>c__DisplayClass31.<GetBlockGeometricExtents>b__2f(Transaction tr) в d:\cad.blocks.cs:строка 477" string
Название: Re: Как узнать текущие размеры динамического блока?
Отправлено: Александр Ривилис от 22-12-2014, 18:22:07
Похоже именно для определения атрибута (AttributeDefinition), а не для атрибута (AttributeReference)  GeometricExtents не работает.
Я в пустом чертеже вручную создал определение атрибута и включил его в блок A. Результат в окне MGDDBG:
(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fimg-fotki.yandex.ru%2Fget%2F15553%2F7842324.2%2F0_f1be0_d4f60616_orig.png&hash=32d54f1d79766b3f0450649e29027fd8) (http://img-fotki.yandex.ru/get/15502/7842324.2/0_f1bdf_13df3264_orig.png)
А вот для атрибута всё нормально:
(https://adn-cis.org/forum/proxy.php?request=http%3A%2F%2Fimg-fotki.yandex.ru%2Fget%2F15489%2F7842324.2%2F0_f1be2_78c7cded_orig.png&hash=8b8e34d5760a37a6f1a34c8bb3e37d1e) (http://img-fotki.yandex.ru/get/15507/7842324.2/0_f1be1_e69d6f4f_orig.png)