CAD
Su add-in coloca con solo pulsar un botón el cajetín en cada presentación. El bloque se ve bien, pero faltan el número de plano, la fecha y el responsable. O la lista de piezas cuenta menos puertas de las que hay en el plano. Ambas cosas tienen una causa sencilla.
Sello e impresión
Una definición de bloque es como el sello de una empresa: describe una sola vez de qué se compone el bloque. Cada referencia de bloque es una impresión que solo indica dónde está el bloque, cómo está girado y qué tamaño tiene. A diferencia de lo que ocurre en la oficina, en AutoCAD todas las impresiones cambian cuando se retalla el sello, porque la referencia solo apunta a la definición. El mismo principio se aplica a los atributos:
| Qué | Definición (una vez) | Referencia (las veces que se quiera) |
|---|---|---|
| Bloque | BlockTableRecord en la BlockTable |
BlockReference |
| Atributo | AttributeDefinition en la definición de bloque |
AttributeReference en la referencia de bloque |
Atención: BlockReference.BlockTableRecord es un ObjectId, no un objeto.
Crear una definición de bloque
Una definición es un BlockTableRecord como el espacio modelo, solo que ella misma no se dibuja. Tres reglas ahorran disgustos:
- Orden: primero la definición entra con
Adden laBlockTabley conAddNewlyCreatedDBObjecten la transacción; después siguen los elementos. Al revés, se obtieneErrorStatus.NotInDatabase. - Capa 0: los elementos sin capa indicada acaban, también dentro del bloque, en la capa actual. Establezca
LayerId = db.LayerZeropara que el bloque se rija por la capa de la referencia. Con el color PorBloque (ColorIndex = 0), un elemento sigue el color de la referencia. - Punto base: dibuje los elementos alrededor del origen.
Originse queda entonces en (0,0,0), igual que hace el comando_BLOCK.
Crear uno mismo los atributos al insertar
Aquí está el error más frecuente. Cuando el usuario inserta un bloque con _INSERT, AutoCAD crea un atributo en la referencia para cada definición de atributo. Quien inserta una BlockReference por código solo obtiene la referencia. Los atributos tiene que crearlos él mismo:
// Insertar una referencia de bloque y, como _INSERT, crear uno mismo los atributos
public static ObjectId FügeEinMitAttributen(Transaction tr, BlockTableRecord besitzer,
ObjectId blockId, Point3d position, IDictionary<string, string> werte)
{
var referenz = new BlockReference(position, blockId);
var ergebnis = besitzer.AppendEntity(referenz);
tr.AddNewlyCreatedDBObject(referenz, true);
var definition = (BlockTableRecord)tr.GetObject(blockId, OpenMode.ForRead);
foreach (ObjectId elementId in definition)
{
// Los atributos constantes se quedan en la definición; la referencia no recibe ninguno
if (tr.GetObject(elementId, OpenMode.ForRead) is AttributeDefinition attDef
&& !attDef.Constant)
{
var attribut = new AttributeReference();
// Adopta etiqueta, valor por defecto, estilo y posición, convertidos al dibujo
attribut.SetAttributeFromBlock(attDef, referenz.BlockTransform);
if (werte.TryGetValue(attDef.Tag, out var wert))
{
attribut.TextString = wert;
}
referenz.AttributeCollection.AppendAttribute(attribut);
tr.AddNewlyCreatedDBObject(attribut, true);
}
}
return ergebnis;
}
SetAttributeFromBlock adopta de la definición la etiqueta, el valor por defecto, la altura de texto, el estilo y la capa. El método necesita la BlockTransform de la referencia para la posición: la definición tiene coordenadas de bloque, y el atributo de la referencia, coordenadas universales. Con una matriz incorrecta, los atributos quedarían alrededor del origen del dibujo. Cree el diccionario con StringComparer.OrdinalIgnoreCase, porque las etiquetas suelen escribirse de formas distintas.
Leer y modificar valores
La AttributeCollection de una referencia no contiene atributos, sino sus ObjectIds. Cada atributo se abre a través de la transacción, se localiza por su etiqueta, sin tener en cuenta mayúsculas y minúsculas, y se abre para escritura con UpgradeOpen. En los atributos centrados o alineados a la derecha, llame al método AdjustAlignment después de establecer TextString, para que se vuelva a calcular la posición. Dos particularidades:
- Los atributos constantes no tienen
AttributeReference. Su valor solo figura en la definición. Quien quiera listar todos los atributos de una referencia debe buscar también allí. - Las nuevas definiciones de atributo no llegan por sí solas a las referencias existentes. Solo la sincronización las ajusta, con
_ATTSYNCo con código propio. Quien sincroniza por la etiqueta pierde el valor si se ha renombrado una etiqueta.
Bloques dinámicos: el nombre engaña
Cuando el usuario cambia una propiedad de un bloque dinámico, por ejemplo el ancho de una puerta, AutoCAD crea un bloque anónimo (una copia con la geometría modificada) y hace que la referencia apunte a él. Su nombre es entonces, por ejemplo, *U12. El nombre que ve el usuario lo proporciona DynamicBlockTableRecord. Y GetBlockReferenceIds solo encuentra las referencias con los valores por defecto: así surge la lista de puertas demasiado corta. Todas las referencias se encuentran a través de los bloques anónimos:
// Todas las referencias de un bloque dinámico, también las modificadas (*U…)
var definition = (BlockTableRecord)tr.GetObject(definitionId, OpenMode.ForRead);
var alle = definition.GetBlockReferenceIds(true, false).Cast<ObjectId>().ToList();
foreach (ObjectId anonymId in definition.GetAnonymousBlockIds())
{
var anonym = (BlockTableRecord)tr.GetObject(anonymId, OpenMode.ForRead);
alle.AddRange(anonym.GetBlockReferenceIds(true, false).Cast<ObjectId>());
}
Las propiedades dinámicas no están en la AttributeCollection, sino en la DynamicBlockReferencePropertyCollection. Un valor se establece exactamente con el tipo que tiene: Double, Int16 o String, y los ángulos en radianes. Un bloque dinámico no se puede crear mediante .NET; el add-in lo obtiene de un dibujo de biblioteca con WblockCloneObjects.
Errores típicos
- Insertar una referencia por código y olvidar los atributos.
- Llamar a
SetAttributeFromBlockconMatrix3d.Identityen lugar de con laBlockTransform. - Crear elementos de la definición sin capa: acaban en la capa actual.
- Contar los bloques por su nombre y pasar por alto los bloques anónimos de los bloques dinámicos.
- Modificar un elemento de la definición de bloque y creer que solo se ve afectada una referencia.
Cómo le ayudamos
- Formación: en la formación «AutoCAD .NET API con C#» programará bloques, atributos y bloques dinámicos con AutoCAD 2027.
- Revisión de add-ins: revisamos su add-in en busca de estas trampas y en cuanto a AutoCAD 2027, como paquete de inicio a precio fijo.
- Desarrollo: listas de piezas, cajetines, bibliotecas de bloques: póngase en contacto con nosotros.
- El libro: todo se explica en detalle en el libro técnico de Ebi F. Eilber «AutoCAD .NET API», cuya publicación está prevista para 2027.
Fuente: Ebi F. Eilber, AutoCAD .NET API (libro técnico, publicación prevista para 2027), capítulos «Bloques», «Atributos» y «Bloques dinámicos»
