Programar bloques y atributos en AutoCAD .NET

CAD-Programm mit dem Symbol eines Ventils und seinen Eigenschaften wie Name, Druck und Temperatur

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 Add en la BlockTable y con AddNewlyCreatedDBObject en la transacción; después siguen los elementos. Al revés, se obtiene ErrorStatus.NotInDatabase.
  • Capa 0: los elementos sin capa indicada acaban, también dentro del bloque, en la capa actual. Establezca LayerId = db.LayerZero para 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. Origin se 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 _ATTSYNC o 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 SetAttributeFromBlock con Matrix3d.Identity en lugar de con la BlockTransform.
  • 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

Fuente: Ebi F. Eilber, AutoCAD .NET API (libro técnico, publicación prevista para 2027), capítulos «Bloques», «Atributos» y «Bloques dinámicos»

CONTACT

Seleccione su idioma

Primera reuniónconcertarPrimera reuniónconcertar