How to use Database.Dxfin()

How to use Database.Dxfin()

Anonymous
Not applicable
2,906 Views
7 Replies
Message 1 of 8

How to use Database.Dxfin()

Anonymous
Not applicable

What is missing in the sample below (e.g. locking, closing, transactions) ?

The example below loads the dxf data but it doesn't show up in the Doc(after zoom all), until the document is saved and reopened.

Also AutoCAD crash if changed from Model to Paper: "Internal error: !dbsymblk.cpp@464:eWasOpenForWrite "

 

[CommandMethod("myCmd")]
        public void myCmd()
        {
            Document myDoc = Application.DocumentManager.MdiActiveDocument;
            Database myDb = myDoc.Database;
            Editor myEd = myDoc.Editor;

            String dxfFilename = @"C:\temp\dxfSample.dxf";
            String logFilename=@"c:\temp\dxfin.log";
            myDb.DxfIn(dxfFilename, logFilename);

            using (Transaction myTrans = myDb.TransactionManager.StartTransaction())
            {
                BlockTable myBlocks = (BlockTable)myDb.BlockTableId.GetObject(OpenMode.ForRead);
                BlockTableRecord myMS = (BlockTableRecord)   myBlocks[BlockTableRecord.ModelSpace].GetObject(OpenMode.ForRead);
                BlockTableRecordEnumerator btrEnum = myMS.GetEnumerator();

                long nMsEnts = myMS.Cast<ObjectId>().Count();
                myEd.WriteMessage("{0} ModelSpace Entities", nMsEnts);
                myTrans.Commit();
            }
        }

 

Thanks for any help.

 

 

0 Likes
Accepted solutions (2)
2,907 Views
7 Replies
Replies (7)
Message 2 of 8

augusto.goncalves
Alumni
Alumni
Accepted solution

Hi,

 

I can see two immediately issues here:

(1) Get the ActiveDocument and set a send file for it is not good. I would suggest you either call Application.DocumentManager.Open if you want yo open on scree, or create a new Database variable you want to read it 'in memory' (without show it on screen).

 

(2) You are using transactions, which is good, but in order to make this work you need to call myTrans.GetObject() instead calling directly entityId.GetObject(). This last approach is probably throwing a compile warning, right?

 

Hope this help.

 

Augusto Goncalves

Autodesk Developer Network

Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
Message 3 of 8

Anonymous
Not applicable
Accepted solution

Create a new Database and load with Dxfin

 

Then on current Database use Insert passing in newly created database

 

http://www.theswamp.org/index.php?topic=37409.msg426596#msg426596

0 Likes
Message 4 of 8

Anonymous
Not applicable

Thanks for your replies.

Insert a new database solved the issue and this solution is even the better one because the dxf entities need to be converted before inserting into the current drawing.

 

@Jeffrey: thanks for pointing me to TheSwamp solutions.

@Augusto: i don't have compiler errors and the modelspace count result in the correct number. The only problem was nothing shown on screen. I liked the ent.GetObject method over the Transaction.GetObject because it shows me immediately where the objects comes from, the Transaction can be bound to anything. However i am going to use your suggestion from now on because i came across other problems using the ent.GetObject method. Thanks!

 

This is the working solution -- including a Zoom Extends.

 

            Document myDoc = Application.DocumentManager.MdiActiveDocument;
            Database myDb = myDoc.Database;
            Editor myEd = myDoc.Editor;

            String dxfFilename = @"C:\temp\dxfSample.dxf";
            String logFilename = @"c:\temp\dxfin.log";
           
            using (Transaction myTrans = myDb.TransactionManager.StartTransaction())
            {
                Database myDxfDb = new Database(false, true);
                myDxfDb.DxfIn(dxfFilename, logFilename);
                Matrix3d dxfTrf = Matrix3d.Identity;
                myDb.Insert(dxfTrf, myDxfDb, true);

                myDb.UpdateExt(true);
                ViewTableRecord vTable = new ViewTableRecord();
                Point3d minPoint = myDb.Extmin;
                Point3d maxPoint = myDb.Extmax;
                Point2d vMax = new Point2d(maxPoint.X, maxPoint.Y);
                Point2d vMin = new Point2d(minPoint.X, minPoint.Y);
                vTable.CenterPoint = vMin + 0.5 * (vMax - vMin);
                vTable.Height = vMax.Y - vMin.Y;
                vTable.Width = vMax.X - vMin.X;
                myDoc.Editor.SetCurrentView(vTable);
                myTrans.Commit();
            }

 

0 Likes
Message 5 of 8

augusto.goncalves
Alumni
Alumni

 

Hi,

 

That looks much better. I would only suggest a missing MyDxfDb.Dispose after the routine to release the file.

 

Regards,

Augusto Goncalves

Autodesk Developer Network

Regards,



Augusto Goncalves
Twitter @augustomaia
Autodesk Developer Network
0 Likes
Message 6 of 8

Anonymous
Not applicable

MyDxfDb.Dispose

Yes of course. Thanks for all the help to solve this part of the program.

 

0 Likes
Message 7 of 8

Anonymous
Not applicable

@Anonymous wrote:

i came across other problems using the ent.GetObject method. Thanks!

 

 

 


 

Could you give some examples of where ObjectId.GetObject() gave you problems. I have used it and not had problems and was wondering where it could cause problems.

 

Accoording to the docs ObjectId.GetObject will use the most recent transaction or the Top Tranction on the stack maintained by the TransactionManager.

0 Likes
Message 8 of 8

Anonymous
Not applicable

The GetObject didn't gave me problems in this particular example. Unfortunately i can't remember where it was.

In this example the problems are in the database initialized in by AutoCAD itself. For newer DXF files we have to use

"new Database(false, true)"

I suppose the initial AutoCAD document is connected to a "new Database(TRUE, false)".

 

The second part of the first example beginning with "using (Transaction myTrans = ..."

had nothing to do with the DXFIN problem. It is counting the Modelspace entities and thus showing me that entities were actual added to my original document.

 

So far i think whether you use Object.getObject or Transaction.getObject is merely a matter of taste

Coming from VB(6|A) i am used to call functions with the AcadDoc object which give me access to the Database, Entities  as well as the Document -- there are no transactions in VB.

It took me some time to find the relations between these objects iin c#

Document myDoc = Application.DocumentManager.MdiActiveDocument;

   Database myDb=myDoc.Database;

 

Database myDb = HostApplicationServices.WorkingDatabase;

   Document myDoc=Application.DocumentManager.GetDocument(myDb); // may not exist

 

Database myDb=myLine.Database;

 

 

But now Transactions:

//from Transaction to Database

using (Transaction myTrans = myDb.TransactionManager.StartTransaction())

   Database myDb=f(myTrans)????

 

//from Database to Transaction

using (Transaction myTrans = myDb.TransactionManager.TopTransaction)  //may not exist

 

So currently i can call my procedures with the Database object and then find the Document and Transaction objects.

And now the point of Augusto Goncalves:

if no transaction exists for myDb  then the next line will result in a crash:

BlockTable myBlocks = (BlockTable)myDb2.BlockTableId.GetObject(OpenMode.ForRead);

 

@Jeffrey: I hope you understand what i am trying to say

 

 

 

 

 

 

 

 

 

 

 

 

0 Likes