/// <summary> /// Синхронизация атрибутов блока. Требуется запущенная транзакция /// </summary> public static void SynchronizeAttributes([NotNull] this BlockTableRecord target) { if (target == null) { throw new ArgumentNullException(nameof(target)); } var tr = target.Database.TransactionManager.TopTransaction; if (tr == null) { throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions); } var attDefs = target.GetAttributes(tr); foreach (ObjectId id in target.GetBlockReferenceIds(true, false)) { var br = id.GetObjectT <BlockReference>(); br.ResetAttributes(attDefs, tr); } if (target.IsDynamicBlock) { target.UpdateAnonymousBlocks(); foreach (ObjectId id in target.GetAnonymousBlockIds()) { var btr = id.GetObjectT <BlockTableRecord>(); attDefs = btr.GetAttributes(tr); foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false)) { var br = brId.GetObject <BlockReference>(OpenMode.ForWrite); br?.ResetAttributes(attDefs, tr); } } } }
public static void SynchronizeAttributes(this BlockTableRecord target) { if (target == null) { throw new ArgumentNullException("target"); } Transaction tr = target.Database.TransactionManager.TopTransaction; if (tr == null) { throw new Autodesk.AutoCAD.Runtime.Exception(ErrorStatus.NoActiveTransactions); } List <AttributeDefinition> attDefs = target.GetAttributes(tr); foreach (ObjectId id in target.GetBlockReferenceIds(true, false)) { BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite); br.ResetAttributes(attDefs, tr); } if (target.IsDynamicBlock) { target.UpdateAnonymousBlocks(); foreach (ObjectId id in target.GetAnonymousBlockIds()) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead); attDefs = btr.GetAttributes(tr); foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false)) { BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForWrite); br.ResetAttributes(attDefs, tr); } } } }
private static void SendWipeoutToBack(BlockTableRecord btr) { using (var wipeoutCollection = new ObjectIdCollection()) { var foundWipeout = false; foreach (var objectId in btr) { if (objectId.IsNull) { continue; } var wipeout = objectId.GetObject(OpenMode.ForRead) as Wipeout; if (wipeout == null) { continue; } wipeoutCollection.Add(objectId); foundWipeout = true; } if (!foundWipeout) { return; } // found wipeout using (var drawOrderTable = btr.DrawOrderTableId.GetObject(OpenMode.ForWrite) as DrawOrderTable) { drawOrderTable.MoveToBottom(wipeoutCollection); } //foreach (ObjectId id in wipeoutCollection) //{ // using (var w = id.GetObject(OpenMode.ForWrite) as Wipeout) // { // w.Erase(true); // } //} btr.UpdateAnonymousBlocks(); } //var anonymBlocks = btr.GetAnonymousBlockIds(); //foreach (ObjectId anonymObjectId in anonymBlocks) //{ // using (var anonymBtr = anonymObjectId.GetObject(OpenMode.ForRead) as BlockTableRecord) // { // if (anonymBtr == null) continue; // SendWipeoutToBack(anonymBtr); // } //} //var blockRefs = btr.GetBlockReferenceIds(true, false); //foreach (ObjectId brObjectId in blockRefs) //{ // using (var br = brObjectId.GetObject(OpenMode.ForRead) as BlockReference) // { // if (br == null) continue; // System.Diagnostics.Debug.Print($"Name: {br.Name} | BlockName: {br.BlockName}"); // using (var parentBtr = br.DynamicBlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord) // { // SendWipeoutToBack(parentBtr); // } // } //} }
/// <summary> /// Синхронизация вхождений блоков с их определением /// via http://sites.google.com/site/bushmansnetlaboratory/moi-zametki/attsynch /// </summary> /// <param name="btr">Запись таблицы блоков, принятая за определение блока</param> /// <param name="directOnly">Следует ли искать только на верхнем уровне, или же нужно /// анализировать и вложенные вхождения, т.е. следует ли рекурсивно обрабатывать блок в блоке: /// true - только верхний; false - рекурсивно проверять вложенные блоки.</param> /// <param name="removeSuperfluous"> /// Следует ли во вхождениях блока удалять лишние атрибуты (те, которых нет в определении блока).</param> /// <param name="setAttDefValues"> /// Следует ли всем атрибутам, во вхождениях блока, назначить текущим значением значение по умолчанию.</param> public static void AttSync(this BlockTableRecord btr, bool directOnly, bool removeSuperfluous, bool setAttDefValues) { Database db = btr.Database; // using (Bushman.AutoCAD.DatabaseServices.WorkingDatabaseSwitcher wdb = new Bushman.AutoCAD.DatabaseServices.WorkingDatabaseSwitcher(db)) { using (Transaction t = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)t.GetObject(db.BlockTableId, OpenMode.ForRead); //Получаем все определения атрибутов из определения блока IEnumerable <AttributeDefinition> attdefs = btr.Cast <ObjectId>() .Where(n => n.ObjectClass.Name == "AcDbAttributeDefinition") .Select(n => (AttributeDefinition)t.GetObject(n, OpenMode.ForRead)) .Where(n => !n.Constant);//Исключаем константные атрибуты, т.к. для них AttributeReference не создаются. //В цикле перебираем все вхождения искомого определения блока foreach (ObjectId brId in btr.GetBlockReferenceIds(directOnly, false)) { BlockReference br = (BlockReference)t.GetObject(brId, OpenMode.ForWrite); //Проверяем имена на соответствие. В том случае, если вхождение блока "A" вложено в определение блока "B", //то вхождения блока "B" тоже попадут в выборку. Нам нужно их исключить из набора обрабатываемых объектов //- именно поэтому проверяем имена. if (br.Name != btr.Name) { continue; } //Получаем все атрибуты вхождения блока IEnumerable <AttributeReference> attrefs = br.AttributeCollection.Cast <ObjectId>() .Select(n => (AttributeReference)t.GetObject(n, OpenMode.ForWrite)); //Тэги существующих определений атрибутов IEnumerable <string> dtags = attdefs.Select(n => n.Tag); //Тэги существующих атрибутов во вхождении IEnumerable <string> rtags = attrefs.Select(n => n.Tag); //Если требуется - удаляем те атрибуты, для которых нет определения //в составе определения блока if (removeSuperfluous) { foreach (AttributeReference attref in attrefs.Where(n => rtags .Except(dtags).Contains(n.Tag))) { attref.Erase(true); } } //Свойства существующих атрибутов синхронизируем со свойствами их определений foreach (AttributeReference attref in attrefs.Where(n => dtags .Join(rtags, a => a, b => b, (a, b) => a).Contains(n.Tag))) { AttributeDefinition ad = attdefs.First(n => n.Tag == attref.Tag); //Метод SetAttributeFromBlock, используемый нами далее в коде, сбрасывает //текущее значение многострочного атрибута. Поэтому запоминаем это значение, //чтобы восстановить его сразу после вызова SetAttributeFromBlock. string value = attref.TextString; attref.SetAttributeFromBlock(ad, br.BlockTransform); //Восстанавливаем значение атрибута attref.TextString = value; if (attref.IsMTextAttribute) { } //Если требуется - устанавливаем для атрибута значение по умолчанию if (setAttDefValues) { attref.TextString = ad.TextString; } attref.AdjustAlignment(db); } //Если во вхождении блока отсутствуют нужные атрибуты - создаём их IEnumerable <AttributeDefinition> attdefsNew = attdefs.Where(n => dtags .Except(rtags).Contains(n.Tag)); foreach (AttributeDefinition ad in attdefsNew) { AttributeReference attref = new AttributeReference(); attref.SetAttributeFromBlock(ad, br.BlockTransform); attref.AdjustAlignment(db); br.AttributeCollection.AppendAttribute(attref); t.AddNewlyCreatedDBObject(attref, true); } } btr.UpdateAnonymousBlocks(); t.Commit(); } //Если это динамический блок if (btr.IsDynamicBlock) { using (Transaction t = db.TransactionManager.StartTransaction()) { foreach (ObjectId id in btr.GetAnonymousBlockIds()) { BlockTableRecord _btr = (BlockTableRecord)t.GetObject(id, OpenMode.ForWrite); //Получаем все определения атрибутов из оригинального определения блока IEnumerable <AttributeDefinition> attdefs = btr.Cast <ObjectId>() .Where(n => n.ObjectClass.Name == "AcDbAttributeDefinition") .Select(n => (AttributeDefinition)t.GetObject(n, OpenMode.ForRead)); //Получаем все определения атрибутов из определения анонимного блока IEnumerable <AttributeDefinition> attdefs2 = _btr.Cast <ObjectId>() .Where(n => n.ObjectClass.Name == "AcDbAttributeDefinition") .Select(n => (AttributeDefinition)t.GetObject(n, OpenMode.ForWrite)); //Определения атрибутов анонимных блоков следует синхронизировать //с определениями атрибутов основного блока //Тэги существующих определений атрибутов IEnumerable <string> dtags = attdefs.Select(n => n.Tag); IEnumerable <string> dtags2 = attdefs2.Select(n => n.Tag); //1. Удаляем лишние foreach (AttributeDefinition attdef in attdefs2.Where(n => !dtags.Contains(n.Tag))) { attdef.Erase(true); } //2. Синхронизируем существующие foreach (AttributeDefinition attdef in attdefs.Where(n => dtags .Join(dtags2, a => a, b => b, (a, b) => a).Contains(n.Tag))) { AttributeDefinition ad = attdefs2.First(n => n.Tag == attdef.Tag); ad.Position = attdef.Position; #if ACAD2009 ad.TextStyle = attdef.TextStyle; #else ad.TextStyleId = attdef.TextStyleId; #endif //Если требуется - устанавливаем для атрибута значение по умолчанию if (setAttDefValues) { ad.TextString = attdef.TextString; } ad.Tag = attdef.Tag; ad.Prompt = attdef.Prompt; ad.LayerId = attdef.LayerId; ad.Rotation = attdef.Rotation; ad.LinetypeId = attdef.LinetypeId; ad.LineWeight = attdef.LineWeight; ad.LinetypeScale = attdef.LinetypeScale; ad.Annotative = attdef.Annotative; ad.Color = attdef.Color; ad.Height = attdef.Height; ad.HorizontalMode = attdef.HorizontalMode; ad.Invisible = attdef.Invisible; ad.IsMirroredInX = attdef.IsMirroredInX; ad.IsMirroredInY = attdef.IsMirroredInY; ad.Justify = attdef.Justify; ad.LockPositionInBlock = attdef.LockPositionInBlock; ad.MaterialId = attdef.MaterialId; ad.Oblique = attdef.Oblique; ad.Thickness = attdef.Thickness; ad.Transparency = attdef.Transparency; ad.VerticalMode = attdef.VerticalMode; ad.Visible = attdef.Visible; ad.WidthFactor = attdef.WidthFactor; ad.CastShadows = attdef.CastShadows; ad.Constant = attdef.Constant; ad.FieldLength = attdef.FieldLength; ad.ForceAnnoAllVisible = attdef.ForceAnnoAllVisible; ad.Preset = attdef.Preset; ad.Prompt = attdef.Prompt; ad.Verifiable = attdef.Verifiable; ad.AdjustAlignment(db); } //3. Добавляем недостающие foreach (AttributeDefinition attdef in attdefs.Where(n => !dtags2.Contains(n.Tag))) { AttributeDefinition ad = new AttributeDefinition(); ad.SetDatabaseDefaults(); ad.Position = attdef.Position; #if ACAD2009 ad.TextStyle = attdef.TextStyle; #else ad.TextStyleId = attdef.TextStyleId; #endif ad.TextString = attdef.TextString; ad.Tag = attdef.Tag; ad.Prompt = attdef.Prompt; ad.LayerId = attdef.LayerId; ad.Rotation = attdef.Rotation; ad.LinetypeId = attdef.LinetypeId; ad.LineWeight = attdef.LineWeight; ad.LinetypeScale = attdef.LinetypeScale; ad.Annotative = attdef.Annotative; ad.Color = attdef.Color; ad.Height = attdef.Height; ad.HorizontalMode = attdef.HorizontalMode; ad.Invisible = attdef.Invisible; ad.IsMirroredInX = attdef.IsMirroredInX; ad.IsMirroredInY = attdef.IsMirroredInY; ad.Justify = attdef.Justify; ad.LockPositionInBlock = attdef.LockPositionInBlock; ad.MaterialId = attdef.MaterialId; ad.Oblique = attdef.Oblique; ad.Thickness = attdef.Thickness; ad.Transparency = attdef.Transparency; ad.VerticalMode = attdef.VerticalMode; ad.Visible = attdef.Visible; ad.WidthFactor = attdef.WidthFactor; ad.CastShadows = attdef.CastShadows; ad.Constant = attdef.Constant; ad.FieldLength = attdef.FieldLength; ad.ForceAnnoAllVisible = attdef.ForceAnnoAllVisible; ad.Preset = attdef.Preset; ad.Prompt = attdef.Prompt; ad.Verifiable = attdef.Verifiable; _btr.AppendEntity(ad); t.AddNewlyCreatedDBObject(ad, true); ad.AdjustAlignment(db); } //Синхронизируем все вхождения данного анонимного определения блока _btr.AttSync(directOnly, removeSuperfluous, setAttDefValues); } //Обновляем геометрию определений анонимных блоков, полученных на основе //этого динамического блока btr.UpdateAnonymousBlocks(); t.Commit(); } } // } }