Blokken zijn één van de krachtigste functies van AutoCAD. Ze laten je geometrie hergebruiken, titelbordonderdelen standaardiseren en complexe bibliotheken beheren. In dit artikel ontdek je stap voor stap hoe je via de AutoCAD .NET API blokdefinities aanmaakt, invoegt, attributen instelt en beheert — inclusief valkuilen die elke beginner tegenkomt.
Hoe AutoCAD blokken intern opslaat
Elk DWG-bestand bevat een BlockTable. Die tabel bevat BlockTableRecord-objecten: één voor Model_Space, één voor Paper_Space en één voor elke blokdefinitie die je aanmaakt. Als je een blok "invoegt" in een tekening, maak je eigenlijk een BlockReference aan die verwijst naar de definitie. Wijzig je de definitie, dan veranderen automatisch alle referenties in de tekening.
Attributen werken anders: een AttributeDefinition zit in de blokdefinitie, maar een AttributeReference zit in elke individuele BlockReference. Zo kan elke invoeginstantie een andere tekst tonen.
Een blokdefinitie aanmaken
[CommandMethod("MAAKBLOK")]
public void MaakBlok()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
using (var tr = db.TransactionManager.StartTransaction())
{
var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
if (bt.Has("MijnBlok"))
{
doc.Editor.WriteMessage("\nBlok 'MijnBlok' bestaat al.");
tr.Commit();
return;
}
var btr = new BlockTableRecord { Name = "MijnBlok" };
bt.UpgradeOpen();
var btrId = bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
// Geometrie: een cirkel als symbool
var cirkel = new Circle(Point3d.Origin, Vector3d.ZAxis, 25.0);
btr.AppendEntity(cirkel);
tr.AddNewlyCreatedDBObject(cirkel, true);
// Attribuutdefinitie voor het tagnummer
var attDef = new AttributeDefinition
{
Position = new Point3d(0, -35, 0),
Tag = "TAGNUMMER",
Prompt = "Geef tagnummer:",
TextString = "TAG-001",
Height = 10,
Invisible = false
};
btr.AppendEntity(attDef);
tr.AddNewlyCreatedDBObject(attDef, true);
tr.Commit();
doc.Editor.WriteMessage("\nBlok 'MijnBlok' aangemaakt.");
}
}
Een blok invoegen als BlockReference
Na het aanmaken van de definitie kun je blokreferenties invoegen in modelspace of paperspace. Let op: je moet de BlockReference eerst toevoegen aan de tekenruimte vóór je attribuutreferenties toevoegt — anders is de entity nog niet in de database geregistreerd.
[CommandMethod("INVOEGBLOK")]
public void VoegBlokIn()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
using (var tr = db.TransactionManager.StartTransaction())
{
var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
var ms = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
if (!bt.Has("MijnBlok"))
{
doc.Editor.WriteMessage("\nVoer eerst MAAKBLOK uit.");
return;
}
var blokRef = new BlockReference(new Point3d(100, 100, 0), bt["MijnBlok"]);
blokRef.ScaleFactors = new Scale3d(1.0);
blokRef.Rotation = 0.0; // radialen
ms.AppendEntity(blokRef);
tr.AddNewlyCreatedDBObject(blokRef, true);
// Attribuutreferenties koppelen
var btrDef = (BlockTableRecord)tr.GetObject(bt["MijnBlok"], OpenMode.ForRead);
foreach (ObjectId id in btrDef)
{
var entity = tr.GetObject(id, OpenMode.ForRead);
if (entity is AttributeDefinition attDef && !attDef.Constant)
{
var attRef = new AttributeReference();
attRef.SetAttributeFromBlock(attDef, blokRef.BlockTransform);
attRef.TextString = "TAG-042"; // runtime waarde instellen
blokRef.AttributeCollection.AppendAttribute(attRef);
tr.AddNewlyCreatedDBObject(attRef, true);
}
}
tr.Commit();
doc.Editor.WriteMessage("\nBlok ingevoegd op (100, 100).");
}
}
Attribuutwaarden lezen en aanpassen
Bestaande blokreferenties doorlopen en attributen aanpassen doe je via de AttributeCollection. Let op: open de AttributeReference altijd voor schrijven als je de waarde wil veranderen.
public void PasAttribuutAan(Transaction tr, BlockReference blokRef, string tag, string nieuweWaarde)
{
foreach (ObjectId attId in blokRef.AttributeCollection)
{
var attRef = (AttributeReference)tr.GetObject(attId, OpenMode.ForWrite);
if (attRef.Tag.Equals(tag, StringComparison.OrdinalIgnoreCase))
{
attRef.TextString = nieuweWaarde;
break;
}
}
}
Alle blokreferenties in een tekening vinden
Soms wil je alle instanties van een specifiek blok opsporen — bijvoorbeeld om een tagnummer te controleren of een attribuut bulk te updaten.
public List VindAlleReferenties(Database db, Transaction tr, string bloknaam)
{
var result = new List();
var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
if (!bt.Has(bloknaam)) return result;
var btrId = bt[bloknaam];
var ms = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead);
foreach (ObjectId id in ms)
{
if (tr.GetObject(id, OpenMode.ForRead) is BlockReference blokRef
&& blokRef.BlockTableRecord == btrId)
{
result.Add(blokRef);
}
}
return result;
}
Een blok uit een extern bestand importeren (XREF-vrij)
Je kunt blokdefinities importeren vanuit een ander DWG-bestand zonder XREF. Gebruik daarvoor Database.Insert:
public void ImporteerBlokUitBestand(Database doelDb, string bronPad, string bloknaam)
{
using (var bronDb = new Database(false, true))
{
bronDb.ReadDwgFile(bronPad, FileOpenMode.OpenForReadAndAllShare, false, "");
using (var tr = doelDb.TransactionManager.StartTransaction())
{
// Kopieer de blokdefinitie naar de doeldatabase
doelDb.Insert(bloknaam, bronDb, true);
tr.Commit();
}
}
}
Blok exploderen naar primitieve entiteiten
Soms wil je de geometrie van een blok omzetten naar losse lijnen, cirkels, enz. AutoCAD biedt hiervoor BlockReference.Explode():
[CommandMethod("EXPLODEERBLOK")]
public void ExplodeerBlok()
{
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
var ed = doc.Editor;
var peo = new PromptEntityOptions("\nSelecteer blokreferentie: ");
peo.SetRejectMessage("\nGeen blokreferentie.");
peo.AddAllowedClass(typeof(BlockReference), true);
var per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
using (var tr = db.TransactionManager.StartTransaction())
{
var blokRef = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead);
var ms = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
// Explode geeft een DBObjectCollection terug met losse entiteiten
var objecten = new DBObjectCollection();
blokRef.Explode(objecten);
foreach (Entity ent in objecten)
{
ms.AppendEntity(ent);
tr.AddNewlyCreatedDBObject(ent, true);
}
// Verwijder de originele blokreferentie
blokRef.UpgradeOpen();
blokRef.Erase();
tr.Commit();
ed.WriteMessage($"\n{objecten.Count} entiteiten aangemaakt.");
}
}
Veelgemaakte fouten
1. AppendEntity vóór AddNewlyCreatedDBObject vergeten — de entiteit wordt dan niet correct geregistreerd en de transaction kan crashen bij Commit.
2. AttributeReference toevoegen vóór BlockReference is geappend — attribuutreferenties hebben een geldige ObjectId van hun parent nodig. Voeg eerst de BlockReference toe, dan pas de attribuutreferenties.
3. BlockTableRecord niet voor schrijven openen — als je een bestaande blokdefinitie aanpast (geometrie toevoegen), moet je de record UpgradeOpen() aanroepen of hem direct openen met OpenMode.ForWrite.
4. Schaal vergeten op Scale3d — standaard is Scale3d(1,1,1). Wil je uniform schalen, gebruik dan new Scale3d(2.0).
Samenvatting
Met de AutoCAD .NET API heb je volledige controle over het aanmaken, invoegen en beheren van blokken. De sleutelprincipes zijn: maak eerst de definitie aan in de BlockTable, voeg dan een BlockReference toe aan modelspace, en koppel tenslotte de attribuutreferenties. Door blokken programmatisch te beheren kun je standaardisatieprocessen volledig automatiseren en uren aan handwerk besparen.
Comments
No comments yet — be the first!
Leave a comment
Sign in to skip moderation — anonymous comments are reviewed before appearing.