2014-11-11 8 views
8

Sto provando a inserire un blocco di un disegno preesistente nel disegno corrente su cui è in esecuzione un plug-in. Per fare questo, ho un pulsante sul mio C# .NET forma chiamare il seguente metodoInserimento di un disegno AutoCAD preesistente in un disegno corrente

public void MakeAndInsertObject() //Method to add all windows and doors templates to drawing database for use later 
{ 
    Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; //Stores the active document 
    Editor ed = doc.Editor; //Stores the document's editor 
    Database dtb = ed.Document.Database; //Stores the database from the editor 

    Transaction tr = dtb.TransactionManager.StartTransaction(); //Start a transaction with the document's database 
    DocumentLock docLock = doc.LockDocument(); 

    using (tr)  
    using (docLock) 
    { 
     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(dtb.CurrentSpaceId, OpenMode.ForWrite); //Opens the block table record so you can write to it 
     BlockTableRecord newBlockDef = new BlockTableRecord(); //Creates a new record in the block table 
     BlockTable blockTable = (BlockTable)tr.GetObject(dtb.BlockTableId, OpenMode.ForWrite); //Opens the block table so it can be written to 
     //Pointing new block to correct drawing file 
     newBlockDef.Name = "Door"; 
     newBlockDef.PathName = "C:/Users/Administrator/Documents/All Code/clearspan-autocad-tools-development/Templates/locks/DOOR.dwg"; 
     blockTable.Add(newBlockDef); //Adds the block table record to the block table 
     BlockReference newBlock = new BlockReference(new Point3d(0, 0, 0), newBlockDef.ObjectId); //Insert a block reference with the newly created block 
     btr.AppendEntity(newBlock); //Inserts the block into the current space (Model or Paper) via the block table record 
     //Updates the Transaction with all new database objects 
     tr.AddNewlyCreatedDBObject(newBlockDef, true); 
     tr.AddNewlyCreatedDBObject(newBlock, true); 
     tr.Commit(); //Applies all changes made as part of the current transaction 
     tr.Dispose(); 
    } 
} 

Il codice viene eseguito completamente, ma il blocco nel mio file DOOR.dwg non appare nella posizione (0, 0, 0) e non so perché non lo fa

risposta

3

Ho preso un frammento dal Keen Walmsley e lo ho modificato per non essere così ingombrante e leggibile. Questo è piuttosto semplice. Dovresti leggere alcune delle cose di Keen è abbastanza buono e lui è molto descrittivo nei suoi appunti. vedere il codice qui sotto per l'utilizzo.

public void ImportBlocks() 
{ 
    DocumentCollection dm = 
    Application.DocumentManager; 
    Editor ed = dm.MdiActiveDocument.Editor; 
    Database destDb = dm.MdiActiveDocument.Database; 
    Database sourceDb = new Database(false, true); 
    try 
    { 
     // Get name of DWG from which to copy blocks 
     var sourceFileName = ed.GetString("\nEnter the path of the source drawing: "); 

     // Read the DWG into a side database 
     sourceDb.ReadDwgFile(sourceFileName.StringResult, System.IO.FileShare.Read, true, ""); 

     // Create a variable to store the list of block identifiers 
     ObjectIdCollection blockIds = new ObjectIdCollection(); 

     var tm = sourceDb.TransactionManager; 

     using (var myT = tm.StartOpenCloseTransaction()) 
     { 
      // Open the block table 
      BlockTable bt = (BlockTable)myT.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false); 

      // Check each block in the block table 
      foreach (ObjectId btrId in bt) 
      { 
       BlockTableRecord btr = 
       (BlockTableRecord)myT.GetObject(btrId, OpenMode.ForRead, false); 

       // Only add named & non-layout blocks to the copy list 
       if (!btr.IsAnonymous && !btr.IsLayout) 
        blockIds.Add(btrId); 
       btr.Dispose(); 
      } 
     } 
     // Copy blocks from source to destination database 
     var mapping = new IdMapping(); 
     sourceDb.WblockCloneObjects(blockIds, 
      destDb.BlockTableId, 
      mapping, 
      DuplicateRecordCloning.Replace, 
      false); 
    } 
    catch(Autodesk.AutoCAD.Runtime.Exception ex) 
    { 
     ed.WriteMessage("\nError during copy: " + ex.Message); 
    } 
    sourceDb.Dispose(); 
} 

Solo per curiosità, se qualcuno avesse sviluppato un'API di Python per l'utilizzo in AutoCAD, l'usereste? o dargli un colpo?

+0

Grazie per la risposta. E sì, sembra davvero interessante! Stai considerando di farlo? –

+0

@NickG, Sì. Ho già iniziato. Ho bisogno di fare un commit, ma sentitevi liberi di andare a guardare https://www.github.com/xxzer0xx/pyrrha –

0

È necessario utilizzare il metodo wblockcloneObjects per ottenere il blocco dal dwg di origine al blocco DWG di destinazione. Quindi puoi inserirlo.

nel codice vb:

Dim doc As Document = Application.DocumentManager.MdiActiveDocument 
     Using lock = doc.LockDocument 

      Using OpenDb As New Database(False, False) 
       OpenDb.ReadDwgFile(PathDwg, System.IO.FileShare.ReadWrite, True, "") 
       Dim ids As New ObjectIdCollection() 
       Dim bt As BlockTable 
       Dim sourceBlockId As ObjectId = ObjectId.Null 
       Using tr As Transaction = OpenDb.TransactionManager.StartTransaction() 

        bt = DirectCast(tr.GetObject(OpenDb.BlockTableId, OpenMode.ForRead), BlockTable) 
        If bt.Has(NaamBlok) Then 
         ids.Add(bt(NaamBlok)) 
         sourceBlockId = bt(NaamBlok) 
        End If 

        If ids.Count <> 0 Then 
         Dim destdb As Database = doc.Database 
         Dim iMap As New IdMapping() 
         OpenDb.WblockCloneObjects(ids, destdb.BlockTableId, iMap, DuplicateRecordCloning.Replace, False) 

        End If 

        tr.Commit() 

       End Using 
      End Using 
     End Using 
0
 /// <summary> 
     /// the source drawig should be drawn as number of 
     /// separate entites with or without attributes. 
     /// Throws NotImplementedException if invoked with .dxf file 
     /// </summary> 
     /// <param name="sourceDrawing"></param> 
     /// <param name="insertionPoint"></param> 
     /// <returns>ObjectID of the Block Def that was imported.</returns> 
     public void ImportDwgAsBlock(string sourceDrawing, Point3d insertionPoint) 
     { 
      Matrix3d ucs = _ed.CurrentUserCoordinateSystem; 

      string blockname = sourceDrawing.Remove(0, sourceDrawing.LastIndexOf("\\", StringComparison.Ordinal) + 1); 
      blockname = blockname.Substring(0, blockname.Length - 4); // remove the extension 

      try 
      { 
       using (_doc.LockDocument()) 
       { 
        using (var inMemoryDb = new Database(false, true)) 
        { 
         #region Load the drawing into temporary inmemory database 
         if (sourceDrawing.LastIndexOf(".dwg", StringComparison.Ordinal) > 0) 
         { 
          inMemoryDb.ReadDwgFile(sourceDrawing, System.IO.FileShare.Read, true, ""); 
         } 
         else if (sourceDrawing.LastIndexOf(".dxf", StringComparison.Ordinal) > 0) 
         { 
          _logger.Error(MethodBase.GetCurrentMethod().DeclaringType.FullName + "." + MethodBase.GetCurrentMethod().Name + " : Tried to invoke the method with .dxf file."); 
          throw new NotImplementedException("Importing .dxf is not supported in this version."); 
          //inMemoryDb.DxfIn("@" + sourceDrawing, System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase) + "\\log\\import_block_dxf_log.txt"); 
         } 
         else 
         { 
          throw new ArgumentException("This is not a valid drawing."); 
         } 
         #endregion 

         using (var transaction = _db.TransactionManager.StartTransaction()) 
         { 
          BlockTable destDbBlockTable = (BlockTable)transaction.GetObject(_db.BlockTableId, OpenMode.ForRead); 
          BlockTableRecord destDbCurrentSpace = (BlockTableRecord)_db.CurrentSpaceId.GetObject(OpenMode.ForWrite); 

          // If the destination DWG already contains this block definition 
          // we will create a block reference and not a copy of the same definition 
          ObjectId sourceBlockId; 
          if (destDbBlockTable.Has(blockname)) 
          { 

           //BlockTableRecord destDbBlockDefinition = (BlockTableRecord)transaction.GetObject(destDbBlockTable[blockname], OpenMode.ForRead); 
           //sourceBlockId = destDbBlockDefinition.ObjectId; 

           sourceBlockId = transaction.GetObject(destDbBlockTable[blockname], OpenMode.ForRead).ObjectId; 

           // Create a block reference to the existing block definition 
           using (var blockReference = new BlockReference(insertionPoint, sourceBlockId)) 
           { 
            _ed.CurrentUserCoordinateSystem = Matrix3d.Identity; 
            blockReference.TransformBy(ucs); 
            _ed.CurrentUserCoordinateSystem = ucs; 
            var converter = new MeasurementUnitsConverter(); 
            var scaleFactor = converter.GetScaleRatio(inMemoryDb.Insunits, _db.Insunits); 
            blockReference.ScaleFactors = new Scale3d(scaleFactor); 
            destDbCurrentSpace.AppendEntity(blockReference); 
            transaction.AddNewlyCreatedDBObject(blockReference, true); 
            _ed.Regen(); 
            transaction.Commit(); 
            // At this point the Bref has become a DBObject and (can be disposed) and will be disposed by the transaction 
           } 
           return; 
          } 

          //else // There is not such block definition, so we are inserting/creating new one 

          sourceBlockId = _db.Insert(blockname, inMemoryDb, true); 
          BlockTableRecord sourceBlock = (BlockTableRecord)sourceBlockId.GetObject(OpenMode.ForRead); 
          sourceBlock.UpgradeOpen(); 
          sourceBlock.Name = blockname; 
          destDbCurrentSpace.DowngradeOpen(); 
          var sourceBlockMeasurementUnits = inMemoryDb.Insunits; 
          try 
          { 
           CreateBlockReference(sourceBlock.Name, sourceBlockMeasurementUnits, 
                insertionPoint, 
                destDbCurrentSpace, 
                destDbBlockTable); 
          } 
          catch (ArgumentException argumentException) 
          { 
           _logger.Error("Error. Check inner exception.", argumentException); 
          } 

          _ed.Regen(); 
          transaction.Commit(); 
         } 
        } 
       } 
      } 
      catch (Autodesk.AutoCAD.Runtime.Exception exception) 
      { 
       _logger.Error("Error in ImportDrawingAsBlock().", exception); 

      } 
     } 

UPDATE Ecco il convertitore mi mancava:

#if !bcad 
using Autodesk.AutoCAD.DatabaseServices; 
#else 
using Teigha.DatabaseServices; 
#endif 
using Castle.Core.Logging; 
using System.Collections.Generic; 

namespace KojtoCAD.Utilities 
{ 
    public class MeasurementUnitsConverter 
    { 
     private ILogger _logger = NullLogger.Instance; 

    private readonly Dictionary<UnitsValue, double> _linkBetweenDrawingUnitsAndMilimeters; 

    public MeasurementUnitsConverter() 
    { 
     _linkBetweenDrawingUnitsAndMilimeters = new Dictionary<UnitsValue, double> 
                { 
                 { 
                  UnitsValue.Angstroms, 
                  0.0000001 
                 }, 
                 { 
                  UnitsValue.Astronomical, 
                  149600000000000 
                 }, 
                 { 
                  UnitsValue.Centimeters, 10 
                 }, 
                 { 
                  UnitsValue.Decimeters, 100 
                 }, 
                 { 
                  UnitsValue.Dekameters, 
                  10000 
                 }, 
                 { UnitsValue.Feet, 304.8 }, 
                 { 
                  UnitsValue.Gigameters, 
                  1000000000000 
                 }, 
                 { 
                  UnitsValue.Hectometers, 
                  100000 
                 }, 
                 { UnitsValue.Inches, 25.4 }, 
                 { 
                  UnitsValue.Kilometers, 
                  1000000 
                 }, 
                 { 
                  UnitsValue.LightYears, 
                  9460700000000000000 
                 }, 
                 { UnitsValue.Meters, 1000 }, 
                 { 
                  UnitsValue.MicroInches, 
                  0.0000254 
                 }, 
                 { UnitsValue.Microns, 0.001 }, 
                 { 
                  UnitsValue.Miles, 1609344.0 
                 }, 
                 { UnitsValue.Millimeters, 1 }, 
                 { UnitsValue.Mils, 25400 }, 
                 { 
                  UnitsValue.Nanometers, 
                  0.000001 
                 }, 
                 { UnitsValue.Undefined, 1.0 }, 
                 { UnitsValue.Yards, 914.4 } 
                }; 
     //_linkBetweenDrawingUnitsAndMilimeters.Add(UnitsValue.Parsecs, 30857000000000000000); 
    } 

    public double GetScaleRatio(UnitsValue sourceUnits, UnitsValue targetUnits) 
    { 
     if (sourceUnits == UnitsValue.Undefined || targetUnits == UnitsValue.Undefined 
      || !_linkBetweenDrawingUnitsAndMilimeters.ContainsKey(sourceUnits) 
      || !_linkBetweenDrawingUnitsAndMilimeters.ContainsKey(targetUnits)) 
     { 
      return 1; 
     } 
     return _linkBetweenDrawingUnitsAndMilimeters[sourceUnits] 
      /_linkBetweenDrawingUnitsAndMilimeters[targetUnits]; 
    } 
} 
} 
+1

E dov'è l'implementazione di MeasurementUnitsConverter e CreateBlockReference? –