Programmare blocchi e attributi in AutoCAD .NET

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

CAD

Il Suo add-in inserisce con un clic il cartiglio in ogni layout. Il blocco ha un bell'aspetto – ma numero di disegno, data e redattore mancano. Oppure la distinta conta meno porte di quante ce ne siano nella pianta. Entrambe le cose hanno una causa semplice.

Timbro e impronta

Una definizione di blocco è come un timbro aziendale: descrive una volta di che cosa è composto il blocco. Ogni riferimento di blocco è un'impronta, che dice solo dove si trova il blocco, come è ruotato e quanto è grande. A differenza che in ufficio, in AutoCAD tutte le impronte cambiano insieme se si reintaglia il timbro – perché il riferimento rimanda solo alla definizione. Lo stesso principio vale per gli attributi:

Che cosaDefinizione (una volta)Riferimento (quante volte si vuole)
Blocco BlockTableRecord nella BlockTable BlockReference
Attributo AttributeDefinition nella definizione di blocco AttributeReference sul riferimento di blocco

Attenzione: BlockReference.BlockTableRecord è un ObjectId, non un oggetto.

Creare una definizione di blocco

Una definizione è un BlockTableRecord come lo spazio modello, solo che essa stessa non viene disegnata. Tre regole risparmiano fastidi:

  • Ordine: prima la definizione entra con Add nella BlockTable e con AddNewlyCreatedDBObject nella transazione, poi seguono gli elementi. Al contrario si ottiene ErrorStatus.NotInDatabase.
  • Layer 0: gli elementi senza indicazione del layer finiscono anche nel blocco sul layer corrente. Imposti LayerId = db.LayerZero, affinché il blocco segua il layer del riferimento. Con il colore DaBlocco (ColorIndex = 0) un elemento segue il colore del riferimento.
  • Punto base: disegni gli elementi attorno all'origine. Origin resta allora (0,0,0), come fa anche il comando _BLOCK.

Creare da sé gli attributi durante l'inserimento

Qui si trova l'errore più frequente. Se l'utente inserisce un blocco con _INSERT, AutoCAD crea per ogni definizione di attributo un attributo sul riferimento. Chi inserisce una BlockReference tramite codice ottiene solo il riferimento. Gli attributi deve crearli da sé:

// Inserire il riferimento di blocco e – come _INSERT – creare da sé gli attributi

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)

    {

        // Gli attributi costanti restano nella definizione, il riferimento non ne riceve

        if (tr.GetObject(elementId, OpenMode.ForRead) is AttributeDefinition attDef

            && !attDef.Constant)

        {

            var attribut = new AttributeReference();

            // Riprende tag, valore predefinito, stile e posizione – convertiti nel disegno

            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 riprende dalla definizione tag, valore predefinito, altezza del testo, stile e layer. Il metodo ha bisogno della BlockTransform del riferimento per la posizione: la definizione ha coordinate di blocco, l'attributo sul riferimento coordinate globali. Con una matrice sbagliata gli attributi si troverebbero attorno all'origine del disegno. Crei il dizionario con StringComparer.OrdinalIgnoreCase, perché i tag vengono spesso scritti in modo diverso.

Leggere e modificare i valori

La AttributeCollection di un riferimento non contiene attributi, ma i loro ObjectId. Ogni attributo lo apre tramite la transazione, lo trova tramite il tag – senza distinguere tra maiuscole e minuscole – e lo apre in scrittura con UpgradeOpen. Per gli attributi centrati o allineati a destra, dopo aver impostato TextString chiami il metodo AdjustAlignment, affinché la posizione venga ricalcolata. Due particolarità:

  • Gli attributi costanti non hanno una AttributeReference. Il loro valore sta solo nella definizione. Chi vuole elencare tutti gli attributi di un riferimento deve guardare anche lì.
  • Le nuove definizioni di attributo non raggiungono da sole i riferimenti esistenti. Solo la sincronizzazione li allinea, con _ATTSYNC o con codice proprio. Chi in questo allinea tramite il tag, perde il valore se un tag è stato rinominato.

Blocchi dinamici: il nome inganna

Se l'utente modifica una proprietà di un blocco dinamico, ad esempio la larghezza della porta, AutoCAD crea un blocco anonimo – una copia con la geometria modificata – e fa puntare il riferimento su di esso. Il suo nome è allora ad esempio *U12. Il nome che l'utente vede lo fornisce DynamicBlockTableRecord. E GetBlockReferenceIds trova solo i riferimenti con valori predefiniti – così nasce l'elenco delle porte troppo corto. Tutti i riferimenti li trova tramite i blocchi anonimi:

// Tutti i riferimenti di un blocco dinamico – anche quelli modificati (*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>());

}

Le proprietà dinamiche non stanno nella AttributeCollection, ma nella DynamicBlockReferencePropertyCollection. Un valore si imposta esattamente con il tipo che ha: Double, Int16 o String, gli angoli in radianti. Un blocco dinamico non si può creare tramite .NET; l'add-in lo recupera con WblockCloneObjects da un disegno di libreria.

Errori tipici

  • Inserire un riferimento tramite codice e dimenticare gli attributi.
  • Chiamare SetAttributeFromBlock con Matrix3d.Identity invece che con la BlockTransform.
  • Creare elementi della definizione senza layer – finiscono sul layer corrente.
  • Contare i blocchi in base al nome e trascurare i blocchi anonimi dei blocchi dinamici.
  • Modificare un elemento della definizione di blocco e credere che sia interessato un solo riferimento.

Come La aiutiamo

  • Formazione: nel corso «AutoCAD .NET API con C#» programma blocchi, attributi e blocchi dinamici con AutoCAD 2027.
  • Check dell'add-in: verifichiamo il Suo add-in rispetto a queste insidie e ad AutoCAD 2027 – come pacchetto di avvio a prezzo fisso.
  • Sviluppo: distinte, cartigli, librerie di blocchi – ci contatti.
  • Il libro: tutto è descritto in dettaglio nel libro tecnico di Ebi F. Eilber «AutoCAD .NET API», la cui uscita è prevista per il 2027.

Fonte: Ebi F. Eilber, AutoCAD .NET API (libro tecnico, uscita prevista nel 2027), capitoli «Blocchi», «Attributi» e «Blocchi dinamici»

CONTACT

Seleziona la tua lingua

Primo colloquiofissare oraPrimo colloquiofissare ora