Author Topic: Block error after import  (Read 1848 times)

0 Members and 1 Guest are viewing this topic.

JohanMagnusson

  • Guest
Block error after import
« on: April 18, 2010, 05:14:20 AM »
I hava a method that imports blocks from a "import" dwg to the current dwg. This works fine to the point that the blocks are being copied over to the current dwg. I´m using this line for the import...

dbImport.WblockCloneObjects(blockIds, db.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);

The error i´m getting is that when the blocks are imported, they don´t look the same anymore. The blocks are built of some simple lines and a hatch. The hatch is filled and is at the bottom in the "import" dwg, but when imported it is at the top! So the hatch covers all the lines in the block after being imported :(

Can anyone explain to me why this happens or what i´m doing wrong?

I´m using Acad 2010 and Vs2008.

Best regards
Johan

Glenn R

  • Guest
Re: Block error after import
« Reply #1 on: April 18, 2010, 03:47:26 PM »
I or any other member will probably need more code to look at/test and the sample data as well before we can help.

JohanMagnusson

  • Guest
Re: Block error after import
« Reply #2 on: May 03, 2010, 01:07:13 PM »
Thanks for your fast reply, and sorry for my late responce...

I have added the code and the dwg that i´m using to import the blocks.

The blocks in the import dwg has the hatch in the back, but when imported they are always on top?

This is my import method

Code: [Select]
        public static void ImportBlocks(string filePath)
        {
            Document dwg = Utils.Db.GetCurDocument();                                           //get document
            Database db = dwg.Database;
            Database dbImport = new Database(false, true);
           
            try
            {
                dbImport.ReadDwgFile(filePath, System.IO.FileShare.Read, true, "");

                ObjectIdCollection blockIds = new ObjectIdCollection();
               
                DocumentLock dwgLock = dwg.LockDocument();                                      //lock dwg

                using (TransactionHelper trHlp = new TransactionHelper(dbImport))
                {
                    trHlp.Start();

                    BlockTable bt = (BlockTable)trHlp.GetObject(dbImport.BlockTableId,OpenMode.ForRead);

                    foreach (ObjectId id in bt)
                    {
                        BlockTableRecord btr = (BlockTableRecord)trHlp.GetObject(id, OpenMode.ForRead);

                        if (!btr.IsAnonymous && !btr.IsLayout)
                        {
                            blockIds.Add(id);
                        }
                        btr.Dispose();
                    }
               
                    IdMapping mapping = new IdMapping();

                    dbImport.WblockCloneObjects(blockIds, db.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);

                }//disposing...
                dwgLock.Dispose();

                AcadUi.PrintToCmdLine("\nImported " + blockIds.Count.ToString() + " block definitions");
            }
            catch (Autodesk.AutoCAD.Runtime.Exception e)
            {
                dwg.Editor.WriteMessage("\nError during import. Info: " + e.Message);                              //error info
            }
        }

And part of the Transaction Helper used in above code

Code: [Select]
public TransactionHelper(Database db)
{
                    Db = db;
}

Regards

Johan

Glenn R

  • Guest
Re: Block error after import
« Reply #3 on: May 03, 2010, 05:02:42 PM »
Why are you wrapping the Transaction? There's really no need, especially with what you have there. Try doing it normally and see what happens, as that just looks...wrong...

Also, where's the commit? you need to show everything, so members can test quickly - that means working code and data. Sometimes going through the exercise of posting some cut down code for testing will show your error to you straight away.

JohanMagnusson

  • Guest
Re: Block error after import
« Reply #4 on: May 04, 2010, 10:45:59 AM »
Here is the complete code of both the import method and the helper class.

I´m using a wrapper for the transaction to ease some transaction operations. See code below...

Code: [Select]
        public static void ImportBlocks(string filePath)
        {
            Document dwg = Utils.Db.GetCurDocument();                                           //get document
            Database db = dwg.Database;
            Database dbImport = new Database(false, true);
           
            try
            {
                dbImport.ReadDwgFile(filePath, System.IO.FileShare.Read, true, "");

                ObjectIdCollection blockIds = new ObjectIdCollection();
               
                DocumentLock dwgLock = dwg.LockDocument();                                      //lock dwg

                using (TransactionHelper trHlp = new TransactionHelper(dbImport))
                {
                    trHlp.Start();

                    BlockTable bt = (BlockTable)trHlp.GetObject(dbImport.BlockTableId,OpenMode.ForRead);

                    foreach (ObjectId id in bt)
                    {
                        BlockTableRecord btr = (BlockTableRecord)trHlp.GetObject(id, OpenMode.ForRead);

                        if (!btr.IsAnonymous && !btr.IsLayout)
                        {
                            blockIds.Add(id);
                        }
                        btr.Dispose();
                    }
               
                    IdMapping mapping = new IdMapping();

                    dbImport.WblockCloneObjects(blockIds, db.BlockTableId, mapping, DuplicateRecordCloning.Replace, false);

                    trHlp.Commit();
                }//disposing...
                dwgLock.Dispose();

                AcadUi.PrintToCmdLine("\nImported " + blockIds.Count.ToString() + " block definitions");
            }
            catch (Autodesk.AutoCAD.Runtime.Exception e)
            {
                dwg.Editor.WriteMessage("\nError during import. Info: " + e.Message);                              //error info
            }
        }

Code: [Select]
using System;
using System.Diagnostics;
using System.Collections;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;

namespace AcDbHelper
{
    public class TransactionHelper : IDisposable
    {
        private Database db = null;
        protected Database Db
        {
            get { return db; }
            set { db = value; }
        }

        private Transaction trans = null;
        protected Transaction Trans
        {
            get { return trans; }
            set { trans = value; }
        }

public
TransactionHelper()
{
            Db = Utils.Db.GetCurDwg();
}

public
TransactionHelper(Database db)
{    
            Db = db;
}

~TransactionHelper()
{
    Dispose(false);
}

public void
Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void
Dispose(bool disposing)
{
    if (disposing) {
               if (Trans != null) {
                   Trans.Dispose();
               }
    }
}

public virtual void
Start()
{    
            Trans = Db.TransactionManager.StartTransaction();
}

        public virtual void
        Commit()
        { 
            Trans.Commit();
            Trans = null;
        }


        public virtual void
        Abort()
        { 
            Trans.Abort();
            Trans = null;
        }
       
        /// <summary>
        /// return the underlying Transaction
        /// </summary>
       
        public Autodesk.AutoCAD.DatabaseServices.Transaction Transaction
        {
            get { return Trans;  }
        }

        /// <summary>
        /// return the Database that this TransactionHelper goes with
        /// </summary>
       
        public Autodesk.AutoCAD.DatabaseServices.Database Database
        {
            get { return Db;  }
        }

        /// <summary>
        /// Wrapper for GetObject method;
        /// </summary>
        /// <param name="id">Id for object to get.</param>
        /// <param name="mode">OpenMode for the object.</param>
        /// <returns>The object.</returns>
        public DBObject GetObject(ObjectId id, OpenMode mode)
        {
            return Transaction.GetObject(id, mode);
        }

        /// <summary>
        /// See if a SymbolTableRecord of the given name already exists
        /// </summary>
        /// <param name="classType">Type of the SymbolTableRecord (e.g., LayerTableRecord)</param>
        /// <param name="name">Name of the symbol</param>
        /// <returns>True if the symbol already exists, False if it doesn't</returns>
       
        public bool SymbolTableRecExists(System.Type classType, string name)
        {
            ObjectId tblId = Utils.SymTbl.GetSymbolTableId(classType, Db);
           
            SymbolTable tbl = (SymbolTable)Trans.GetObject(tblId, OpenMode.ForRead);
            return tbl.Has(name);
        }
       
        /// <summary>
        /// Add a new SymbolTableRecord to the database (and the current transaction)
        /// </summary>
        /// <param name="newRec">A newly allocated SymbolTableRecord which hasn't yet been added to the database</param>
       
        public virtual void AddNewSymbolRec(SymbolTableRecord newRec)
        { 
            ObjectId tblId = Utils.SymTbl.GetSymbolTableId(newRec.GetType(), Db);
           
            SymbolTable tbl = (SymbolTable)Trans.GetObject(tblId, OpenMode.ForWrite);
            Debug.Assert(tbl.Has(newRec.Name) == false);
               
            tbl.Add(newRec);
            Trans.AddNewlyCreatedDBObject(newRec, true);
        }

    /// <summary>
    /// Define a new named block and add it to the BlockTable.  If the block
    /// definition already exists, its contents will be emptied out so that
    /// the block can be re-defined.
    /// </summary>
    /// <param name="blkName">Name of the BlockDef</param>
    /// <param name="blkRec">New or existing BlockTableRecord</param>
    /// <param name="db">Specific database we are using</param>    
        public BlockTableRecord DefineNewBlockRec(string blkName)
        { 
            BlockTableRecord blkRec = null;
           
            BlockTable tbl = (BlockTable)Trans.GetObject(Db.BlockTableId, OpenMode.ForWrite);
                // if it already exists, we are re-defining it and we need to
                // erase all the existing entities
            if (tbl.Has(blkName)) {
                blkRec = (BlockTableRecord)Trans.GetObject(tbl[blkName], OpenMode.ForWrite);
               
                    // erase all
                DBObject tmpObj = null;
                foreach (ObjectId objId in blkRec) {
                    tmpObj = Trans.GetObject(objId, OpenMode.ForWrite);
                    if (tmpObj != null) {
                        tmpObj.Erase(true);
                    }
                }
            }
            else {
                blkRec = new BlockTableRecord();
                blkRec.Name = blkName;
               
                tbl.Add(blkRec);
                Trans.AddNewlyCreatedDBObject(blkRec, true);
            }
           
            return blkRec;
        }


        /// <summary>
        /// Check if database has a block defined by inputed name.
        /// </summary>
        /// <param name="blkName">Block name to check for.</param>
        /// <returns>True if block excist, else false.</returns>
        public bool Has(string blkName)
        {
            BlockTable tbl = (BlockTable)Trans.GetObject(Db.BlockTableId, OpenMode.ForRead);

            if (tbl.Has(blkName))
                return true;
            else
                return false;
        }


        /// <summary>
        /// Define a new Anonymous block and add it to the BlockTable
        /// </summary>
        /// <param name="db"></param>
        /// <returns>an open BlockTableRecord, ready to add Entities to</returns>
       
        public BlockTableRecord DefineNewAnonymousBlockRec()
        { 
            BlockTableRecord blkRec = null;
           
            BlockTable tbl = (BlockTable)Trans.GetObject(Db.BlockTableId, OpenMode.ForWrite);
            blkRec = new BlockTableRecord();
            blkRec.Name = "*U";
               
            tbl.Add(blkRec);
            Trans.AddNewlyCreatedDBObject(blkRec, true);
           
            return blkRec;
        }
       
        /// <summary>
        /// Given the ObjectId of a SymbolTableRecord, get its name
        /// </summary>
        /// <param name="symId">ObjectId of the SymbolTableRecord</param>
        /// <returns>name of the SymbolTableRecord</returns>
       
        public string SymbolIdToName(ObjectId symId)
{    
    string str = null;
   
            DBObject tmpObj = Trans.GetObject(symId, OpenMode.ForRead);
            SymbolTableRecord rec = tmpObj as SymbolTableRecord;
            if (rec != null)
                str = rec.Name;
           
            return str;
        }
       
        public bool IsOnLockedLayer(Entity ent, bool printMsg)
        {
            Debug.Assert(Trans != null);
           
            LayerTableRecord layer = (LayerTableRecord)Trans.GetObject(ent.LayerId, OpenMode.ForRead);
           
            if (printMsg && layer.IsLocked) {
                Utils.AcadUi.PrintToCmdLine("\nSelected entity is on a locked layer.");
            }
           
            return layer.IsLocked;
        }
       
        public ObjectIdCollection CollectBlockIds(bool excludeMsPs, bool excludeXref, bool excludeXrefDep, bool excludeAnonymous)
        {
            BlockTable blkTbl = (BlockTable)Trans.GetObject(Db.BlockTableId, OpenMode.ForRead);
           
                // iterate over each BlockTableRecord in the BlockTable
            ObjectIdCollection blkRecIds = new ObjectIdCollection();
            foreach (ObjectId tblRecId in blkTbl) {
                BlockTableRecord blkRec = (BlockTableRecord)Trans.GetObject(tblRecId, OpenMode.ForRead);
               
                if (excludeMsPs && blkRec.IsLayout) {
                    ;    // do nothing
                }
                else if ((excludeXrefDep) && blkRec.IsDependent) {
                    ;    // do nothing
                }
                else if ((excludeXref) &&
                        ((blkRec.IsFromExternalReference) ||
                        (blkRec.IsFromOverlayReference))) {
                    ;   // do nothing
                }
                else if (excludeAnonymous && blkRec.IsAnonymous) {
                    ;   // do nothing
                }
                else {
                    blkRecIds.Add(tblRecId);
                }

            }
           
            return blkRecIds;
        }
    }//class
}//namespace