| |  | Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte | | |  | NVIDIA GTC Paris und ISC High Performance-Konferenz 2025, eine Pressemitteilung
|
Autor
|
Thema: Blöcke einlesen (3894 mal gelesen)
|
coLami Mitglied

 Beiträge: 52 Registriert: 26.07.2011 AutoCad Mechanical 2011, .net 3.5 C#
|
erstellt am: 19. Sep. 2011 08:57 <-- editieren / zitieren --> Unities abgeben:         
Ich hänge mal wieder an einer Stelle meiner VBA->C# Portierung Code:
Block = Block_Vorgabepfad + Block_Giebel + ".dwg" Set blockRefObj = ThisDrawing.ModelSpace.InsertBlock(insertionPnt, Block, 1#, 1#, 1#, 0) blockRefObj.Delete
Idee dabei ist, einen Block aus einer Datei zu laden, aber nicht in der Zeichnung anzuzeigen - bzw zu zeichnen und dann wieder zu löschen, sondern quasi nur wie in einer Bibliothek zur Verfügung zu stellen, damit über den Namen darauf zugegriffen und eine Instanz oder Kopie erzeugt und positioniert bzw skaliert werden kann. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
sebastian. Mitglied

 Beiträge: 90 Registriert: 03.09.2009 Windows XP Prof. SP3 AutoCAD 2010 Visual Studio 2008 / 2010 Prof.
|
erstellt am: 19. Sep. 2011 10:09 <-- editieren / zitieren --> Unities abgeben:          Nur für coLami
Hi, wenn ich dich richtig verstehe, möchtest du eine Blockdefinition aus der Ausgangszeichnung kopieren und als Blockdefinition in der Zielzeichnung einfügen. Hier könntest du dann Blockreferenzen in deinem Zeichenbereich einfügen. Ist das richtig? Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
coLami Mitglied

 Beiträge: 52 Registriert: 26.07.2011 AutoCad Mechanical 2011, .net 3.5 C#
|
erstellt am: 19. Sep. 2011 10:14 <-- editieren / zitieren --> Unities abgeben:         
|
sebastian. Mitglied

 Beiträge: 90 Registriert: 03.09.2009 Windows XP Prof. SP3 AutoCAD 2010 Visual Studio 2008 / 2010 Prof.
|
erstellt am: 19. Sep. 2011 10:31 <-- editieren / zitieren --> Unities abgeben:          Nur für coLami
Ich hatte noch im Hinterkopf, dass ich da mal was im "Through the Interface"-Blog gelesen hatte und tatsächlich: Beitrag 1 - suche in den Kommentaren zu diesem Post auch mal nach "ThisDrawing.ModelSpace.InsertBlock(newCoord, "c:\blockName.dwg", xyzScale, xyzScale, xyzScale, 0)"... Beitrag 2 - der Folgebeitrag mit etwas mehr Erklärungen. Beitrag 3 - falls verschiedene / ältere AutoCAD Versionen unterstützt werden sollen. Eventuell findest du auf Through the Interface auch eine Lösung zu deinem Problem mit den dynamischen Blöcken. Hier kenne ich mich allerdings leider nicht aus...einfach mal bei google "through the interface und ein paar Schlagworte zu deinem Problem" eingeben. Vielleicht kannst du deine Lösung später dann ja als Antwort zu deinem eigenen Beitrag posten, damit es anderen weiterhilft, sollten sie mal vor dem gleichen Problem stehen - Danke. Viele Grüße, Sebastian Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
coLami Mitglied

 Beiträge: 52 Registriert: 26.07.2011 AutoCad Mechanical 2011, .net 3.5 C#
|
erstellt am: 19. Sep. 2011 10:32 <-- editieren / zitieren --> Unities abgeben:         
|
coLami Mitglied

 Beiträge: 52 Registriert: 26.07.2011 AutoCad Mechanical 2011, .net 3.5 C#
|
erstellt am: 22. Sep. 2011 11:05 <-- editieren / zitieren --> Unities abgeben:         
Also, ich hab hier jetzt mehrere Lösungen, die teilweise funktionieren Mein Hauptproblem ist es, die Blöcke bzw Blockreferenzen dynamisch zu gestalten, damit ich auf die AttributeCollection und die DynamicBlockReferencePropertyCollection zugreifen kann.
Laden der Datei
fname ist der Pfad der Datei auf der Festplatte Quelle: Through the Interface
Code:
public BlockReference InsertBlock(string fname, Point3d insPt, double angle) { DocumentCollection dm = ACADAPP.Application.DocumentManager; Database destDb = dm.MdiActiveDocument.Database; Database sourceDb = new Database(false, true); BlockReference brRet = null; try { // Read the DWG into a side database sourceDb.ReadDwgFile(fname, System.IO.FileShare.Read, true, ""); // Create a variable to store the list of block identifiers ObjectIdCollection blockIds = new ObjectIdCollection(); Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = sourceDb.TransactionManager; using (Transaction myT = tm.StartTransaction()) { // Open the block table BlockTable bt = (BlockTable)tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false); // Check each block in the block table foreach (ObjectId btrId in bt) { BlockTableRecord btr = (BlockTableRecord)tm.GetObject(btrId, OpenMode.ForRead, false); // Only add named & non-layout blocks to the copy list // und genau hier hakts. Die Zeichnung, die ich lade, bekommt aus irgendwelchen Gründen einen 'dynamischen' Namen, z.B. *U1, // aber ich kann nicht auf die dynamischen Attribute zugreifen. // Außerdem ist IsAnonymous gesetzt, also wir meine Zeichnung nicht geadded if (!btr.IsAnonymous && !btr.IsLayout) { blockIds.Add(btrId); } btr.Dispose(); } } // Copy blocks from source to destination database IdMapping mapping = new IdMapping(); dm.MdiActiveDocument.LockDocument(); sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Ignore, false); //jetzt den Block holen //brRet = InsertExistingBlock(Properties.Lichtband.Default.Block_Zeichenraum, fname, insPt, angle); } catch (Autodesk.AutoCAD.Runtime.Exception ex) { log.Error("\nError during copy: " + ex.Message); } sourceDb.Dispose(); return brRet; }
2ter Versuch, irgendwo aus dem Netz zusammenkopiert und noch etwas rumgeschraubt
loName = "Model" fName ist Dateipfad
Code:
public BlockReference InsertBlock(string loName, string fname, Point3d insPt, double angle) { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; ObjectId RtnObjId = ObjectId.Null; BlockReference bref = null; try { if (!File.Exists(fname)) fname = HostApplicationServices.Current.FindFile(fname, doc.Database, FindFileHint.Default); if (fname == "") return bref; using (Database db = new Database(false, false)) { doc.LockDocument(); //read drawing db.ReadDwgFile(fname, FileShare.Read, true, null); using (Transaction trans = doc.TransactionManager.StartTransaction()) { //insert it as a new block ObjectId idBTR = doc.Database.Insert(fname, db, false); BlockTable bt = (BlockTable)trans.GetObject(doc.Database.BlockTableId, OpenMode.ForRead); bt.UpgradeOpen(); BlockTableRecord btr = new BlockTableRecord(); // Um aus dem Dateipfad nur den Dateinamen zu extrahieren btr.Name = fname.Substring(fname.LastIndexOf("\\") + 1, fname.LastIndexOf(".") - fname.LastIndexOf("\\") - 1); //bref = new BlockReference(insPt, idBTR); //bref.BlockTransform.Translation.RotateBy(angle, new Vector3d(0, 0, 1)); //btr.AppendEntity(bref); bt.Add(btr); trans.AddNewlyCreatedDBObject(btr, false); trans.Commit(); doc.Editor.UpdateScreen(); } } } catch (System.Exception ex) { log.Error("InsertBlock " + ex.Message); } doc.Editor.Regen(); return bref; }
soweit, so gut. (s. http://ww3.cad.de/foren/ubb/Forum352/HTML/000478.shtml) Mit folgender Funktion platziere ich einen bestehenden Block Code:
public BlockReference InsertExistingBlock(string loName, string name, Point3d insPt, double angle) { ObjectId objId = ObjectId.Null; Document doc = ACADAPP.Application.DocumentManager.MdiActiveDocument; //ACDB.Database db = ACDB.HostApplicationServices.WorkingDatabase; ACDB.Database db = doc.Database; try { using (Transaction trans = db.TransactionManager.StartTransaction()) { ACDB.BlockTable bt = (ACDB.BlockTable)(trans.GetObject(db.BlockTableId, ACDB.OpenMode.ForRead)); if (bt.Has(name)) { ObjectId blkId = bt[name]; ACDB.BlockTableRecord btr = (ACDB.BlockTableRecord)trans.GetObject(bt[ACDB.BlockTableRecord.ModelSpace], ACDB.OpenMode.ForWrite); ACDB.BlockReference br = new ACDB.BlockReference(insPt, blkId); btr.AppendEntity(br); ACDB.BlockTableRecord blkDefRecord = (BlockTableRecord)trans.GetObject(blkId, OpenMode.ForRead); trans.AddNewlyCreatedDBObject(br, true); trans.Commit(); objId = br.ObjectId; return br; } } } catch (System.Exception ex) { log.Error("InsertExistingBlock " + ex.Message); } return null; }
Das Platzieren funktioniert auch, nur sind in 'br' die AttributeCollection und die DynamicBlockReferencePropertyCollection leer.
[Diese Nachricht wurde von coLami am 22. Sep. 2011 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
sebastian. Mitglied

 Beiträge: 90 Registriert: 03.09.2009 Windows XP Prof. SP3 AutoCAD 2010 Visual Studio 2008 / 2010 Prof.
|
erstellt am: 22. Sep. 2011 14:19 <-- editieren / zitieren --> Unities abgeben:          Nur für coLami
Hi, zu deinem Problem mit der AttributeCollection (ich denke bei DynamicBlockReferencePropertyCollection ist es ähnlich, aber da kenne ich mich wie gesagt nicht aus): Du musst auch die AttributeCollection der BlockREFERENZ "füllen", sprich die Attribute aus der BlockDEFINITION "kopieren". Code:
if (bt.Has(name)) { ObjectId blkId = bt[name]; ACDB.BlockTableRecord btr = ACDB.BlockTableRecord)trans.GetObject(bt[ACDB.BlockTableRecord.ModelSpace], ACDB.OpenMode.ForWrite); ACDB.BlockReference br = new ACDB.BlockReference(insPt, blkId); btr.AppendEntity(br);
// Brauchtest du bisher nicht?! -> Evtl. kannst du hieraus jetzt aber die Attributdefinitionen abfragen! // ACDB.BlockTableRecord blkDefRecord = (BlockTableRecord)trans.GetObject(blkId, OpenMode.ForRead);
trans.AddNewlyCreatedDBObject(br, true); // Attributreferenz von Attributdefiniton "ableiten" ar = new AttributeReference(); ar.SetAttributeFromBlock(AttDef, br.BlockTransform);
// Attributreferenz der AttributeCollection der Blockreferenz hinzufügen br.AttributeCollection.AppendAttribute(ar); // Dem Transaction Manager den neuen Eintrag mitteilen trans.AddNewlyCreatedDBObject(ar, true);
trans.Commit();
// Brauchst du nicht?! // objId = br.ObjectId;
return br; }
Den fettgedruckten Quelltext musst du evtl. in einer Schleife für alle Attributdefinitionen der Blockdefintion durchlaufen. Leider kann ich dir aus dem Stegreif nicht sagen, wo in dem Blockdefinition-Blocktablerecord du die Attributdefintionen findest. Ich hatte die Attributdefinitionen zuvor per Code erstellt und an meine Blockdefinition über "btrBlockDef.AppendEntity(AttDef);" hinzugefügt und AttDef dann direkt abgespeichert und in meiner BlockInsert-Methode direkt benutzt. Aber ich denke, das sollte dir schon mal weiterhelfen! Und ich schätze mal, mit der DynamicBlockReferencePropertyCollection wird es ähnlich sein. Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
coLami Mitglied

 Beiträge: 52 Registriert: 26.07.2011 AutoCad Mechanical 2011, .net 3.5 C#
|
erstellt am: 22. Sep. 2011 14:48 <-- editieren / zitieren --> Unities abgeben:         
|
sebastian. Mitglied

 Beiträge: 90 Registriert: 03.09.2009 Windows XP Prof. SP3 AutoCAD 2010 Visual Studio 2008 / 2010 Prof.
|
erstellt am: 22. Sep. 2011 15:06 <-- editieren / zitieren --> Unities abgeben:          Nur für coLami
Das ist ein Objekt vom Typ "AttributeDefinition". Wie schon beschrieben, hatte ich mir meine AttributeDefinitionen zuvor per Code erstellt, an die Blockdefinition angefügt und zusätzlich aber abgespeichert. AttDef ist dann so eine abgespeicherte AttributDefinition, welche ich nun wieder verwenden konnte. Wenn du die AttributDefinitionen direkt aus der Blockdefinition auslesen willst, hilft dir vielleicht dieser >Post<. Suche mal nach "For each attribute definition we find...". Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |
coLami Mitglied

 Beiträge: 52 Registriert: 26.07.2011 AutoCad Mechanical 2011, .net 3.5 C#
|
erstellt am: 26. Sep. 2011 16:18 <-- editieren / zitieren --> Unities abgeben:         
Also, es scheint zu funktionieren... der letzte Parameter ist ein boolean, mit dem ich setze, ob eine Referenz zurückgeliefert werden soll, oder nicht. Wird keine Referenz geliefert, wird der Block auch nicht in der Zeichnung platziert Bei dieser Methode wird die DynamicBlockReferencePropertyCollection automatisch mitkopiert Quelle: hauptsächlich through-the-interface
Code:
public BlockReference InsertBlock(string fileName, Point3d insPt, double angle, bool retRef) { Document doc = ACADAPP.Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; Database destDb = doc.Database; BlockReference brRet = null; // Catch exceptions at the file level to allow skipping try { // Suggestion from Thorsten Meinecke... string destName = SymbolUtilityServices.GetSymbolNameFromPathName(fileName, "dwg"); // And from Dan Glassman... destName = SymbolUtilityServices.RepairSymbolName(destName, false); // Create a source database to load the DWG into using (Database db = new Database(false, true)) { // Read the DWG into our side database db.ReadDwgFile(fileName, FileShare.Read, true, ""); bool isAnno = db.AnnotativeDwg; // Insert it into the destination database as // a named block definition ObjectId btrId = destDb.Insert(destName, db, false); if (isAnno) { // If an annotative block, open the resultant BTR // and set its annotative definition status Transaction tr = destDb.TransactionManager.StartTransaction(); using (tr) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForWrite); btr.Annotative = AnnotativeStates.True; tr.Commit(); } } if (retRef) brRet = InsertExistingBlock(destName, insPt, angle); } } catch (System.Exception ex) { log.Error("\nProblem importing \"" + fileName + "\": " + ex.Message + " - file skipped."); } return brRet; }
mit dem folgenden Code wird ein existierender Block in die Zeichnung eingefügt
Quelle: das Posting von sebastian. und http://www.theswamp.org/index.php?topic=38014.0
Code:
public BlockReference InsertExistingBlock(string name, Point3d insPt, double angle) { Document doc = ACADAPP.Application.DocumentManager.MdiActiveDocument; ACDB.Database db = doc.Database; try { using (Transaction trans = db.TransactionManager.StartTransaction()) { // aktuelle Blocktable holen ACDB.BlockTable bt = (ACDB.BlockTable)(trans.GetObject(db.BlockTableId, ACDB.OpenMode.ForRead)); if (bt.Has(name)) { // ID zu dem einzufügenden Objekt holen ObjectId blkId = bt[name]; doc.LockDocument(); // BlocktableRecord für Modelspace holen ACDB.BlockTableRecord btr = (ACDB.BlockTableRecord)trans.GetObject (bt[ACDB.BlockTableRecord.ModelSpace], ACDB.OpenMode.ForWrite); ACDB.BlockTableRecord currBlock = (ACDB.BlockTableRecord)trans.GetObject(blkId, ACDB.OpenMode.ForRead); // neue Blockreferenz für einzufügendes Objekt erzeugen ACDB.BlockReference br = new ACDB.BlockReference(insPt, blkId); br.Rotation = angle; // Blockreferenz zum Modelspace addieren btr.AppendEntity(br); // Blockreferenz in aktuelle Transaction einfügen trans.AddNewlyCreatedDBObject(br, true); // Attribute aus Block auslesen // Da muss man erst mal drauf kommen !!! foreach (ObjectId entityId in currBlock) { if (!(entityId.ObjectClass.Name == "AcDbAttributeDefinition")) { continue; } AttributeDefinition attributeDef = trans.GetObject(entityId, OpenMode.ForRead) as AttributeDefinition; AttributeReference ar = new AttributeReference(); ar.SetAttributeFromBlock(attributeDef, br.BlockTransform); // Attributreferenz der AttributeCollection der Blockreferenz hinzufügen br.AttributeCollection.AppendAttribute(ar); // Dem Transaction Manager den neuen Eintrag mitteilen trans.AddNewlyCreatedDBObject(ar, true); } trans.Commit(); return br; } } } catch (System.Exception ex) { log.Error("InsertExistingBlock " + ex.Message); } return null; }
[Diese Nachricht wurde von coLami am 26. Sep. 2011 editiert.] Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP |

| |
sebastian. Mitglied

 Beiträge: 90 Registriert: 03.09.2009 Windows XP Prof. SP3 AutoCAD 2010 Visual Studio 2008 / 2010 Prof.
|
erstellt am: 27. Sep. 2011 12:43 <-- editieren / zitieren --> Unities abgeben:          Nur für coLami
|
| Anzeige.:
Anzeige: (Infos zum Werbeplatz >>)
 |