Author Topic: Adding Objects to the DrawingDataBase  (Read 6787 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Adding Objects to the DrawingDataBase
« on: December 04, 2005, 08:44:33 PM »
This is in response to a PM.
Please note that I will usually ignore personal requests, but in this case I had something handy, so ...

The process of adding entities to a drawing Database is/canbe broken into 6 basic stages.

//
//Start a database transaction

//
//Create object
       
//
//Open modelspace for writing

//
//Add the object to modelspace

//
//Inform the transaction of the new object

//
//Commit the transaction

and here's some sample code.
There are several ways to achieve this, with helpers etc, but the process will always break down to the 6 steps

Any Comments ? ?
Code: [Select]
        [CommandMethod("CX1", CommandFlags.Modal)]
        public static void CircleX1()
        {
            Database db = AcadApp.DocumentManager.MdiActiveDocument.Database;

            //
            // Confirm the layer exists
            ObjectId layerId = LibTools.CreateLayer("LayerCX1", 113, "CONTINUOUS");

            //
            // This point is in World UCS, irrespective of UCS
            // Look at Matrix translations
            Point3d centerPoint = new Point3d(20.0, 20.0, 0.0);
            Vector3d normalZ = new Vector3d(0.0, 0.0, 1.0);
            double radius = 50.20;

            //
            //Start a database transaction
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                //
                //Create object
                Circle squircle = new Circle(centerPoint, normalZ, radius);
                squircle.Layer = "LayerCX1";

                //
                //Open modelspace for writing
                BlockTableRecord modelSpace = (BlockTableRecord)tr.GetObject(GetActiveModelSpaceId(db), OpenMode.ForWrite);


                //
                //Add the object to modelspace
                modelSpace.AppendEntity(squircle);

                //
                //Inform the transaction of the new object
                // tr.TransactionManager.AddNewlyCreatedDBObject(squircle, true);  // rev kwb1217
                tr.AddNewlyCreatedDBObject(squircle, true);

                //
                //Commit the transaction
                tr.Commit();
            }
        }

        public static ObjectId GetActiveModelSpaceId(Database db)
        {
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                return (ObjectId)bt[BlockTableRecord.ModelSpace];
            }
        }


// rev kwb1217
« Last Edit: December 16, 2005, 11:18:24 PM by Kerry Brown »
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

MickD

  • Gator
  • Posts: 3313
  • (x-in)->[process]->(y-out)
Re: Adding Objects to the DrawingDataBase
« Reply #1 on: December 04, 2005, 09:06:11 PM »
heh, how many sides does a 'squircle' have :D

Another way to get the normal for the circle would be to get the current ucs from the current db like so -

normalZ = db.Ucsxdir.CrossProduct(db.Ucsydir);//the db only has the x and y vector properties available, therefore the crossproduct

this way your circle will be facing the right way as expected in different ucs', same would apply for text ;)
Forth is like the Tao: it is a Way, and is realized when followed.
Its fragility is its strength; its simplicity is its direction - Michael Ham

Lao Tzu: “To attain knowledge, add things
every day; to obtain wisdom, remove things every day.”

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #2 on: December 04, 2005, 09:11:34 PM »
hehehe ..
a squircle is one of my custom objects ...  :wink:

I agree about the Z Vector Mick. I just didn't want to confuse the issue with translations and Vectors  ..

and ..

The determination of the <translated> centerPoint and Z Vector are outside the actual creation process, so ....
« Last Edit: December 04, 2005, 09:38:03 PM by Kerry Brown »
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Adding Objects to the DrawingDataBase
« Reply #3 on: December 05, 2005, 05:35:43 AM »
Nicely done Kerry.

Instead of always going for modelspace, you might want to take a look at CurrentSpaceId off the dbase.
This will return the BlockTableRecord of the current space, either model or paper.

I can't remember from ARX if it was smart enough to know if you were inside a viewport in paperspace though...you might want to test that.

I take it your library is coming along nicely. Fun isn't it? :)

Cheers,
Glenn.
Me

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #4 on: December 05, 2005, 05:46:40 AM »
.......  I take it your library is coming along nicely. Fun isn't it? :)

Cheers,
Glenn.

I don't know about nicely, but it is evolving :-)

I'll have a look at CurrentSpaceId. I recall playing with something that determined if paperspace was active, but that was last week   :lol: :lol:



Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Swift

  • Swamp Rat
  • Posts: 596
Re: Adding Objects to the DrawingDataBase
« Reply #5 on: December 05, 2005, 08:13:36 AM »
Nice Work Kerry

Bobby C. Jones

  • Swamp Rat
  • Posts: 514
  • Cry havoc and let loose the dogs of war.
Re: Adding Objects to the DrawingDataBase
« Reply #6 on: December 09, 2005, 11:05:08 AM »
Nice Work Kerry

Indeed, very nice.  I really like the idea of breaking the steps down into something easy to follow :)
Bobby C. Jones

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #7 on: December 09, 2005, 11:12:42 AM »
Can't claim credit for it Bobby, in principle that's straight out of the AutoCAD Docs  .. one of the PowerPoint presentations if I recall.

How was AU for you this year ? Hope you had a good attendance .
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Bobby C. Jones

  • Swamp Rat
  • Posts: 514
  • Cry havoc and let loose the dogs of war.
Re: Adding Objects to the DrawingDataBase
« Reply #8 on: December 09, 2005, 11:24:11 AM »
How was AU for you this year ? Hope you had a good attendance .

It went well, thanks!  I didn't particularly like the way one of my classes went, but the other one was fantastic.  I'll know for sure in a few weeks when the results of the survey cards are compiled.
Bobby C. Jones

LE

  • Guest
Re: Adding Objects to the DrawingDataBase
« Reply #9 on: December 09, 2005, 10:23:05 PM »
Nicely done Kerry.

Instead of always going for modelspace, you might want to take a look at CurrentSpaceId off the dbase.
This will return the BlockTableRecord of the current space, either model or paper.

I can't remember from ARX if it was smart enough to know if you were inside a viewport in paperspace though...you might want to test that.

Yes it does, here is a way to do it in objectarx [also noticed the old form I was using before to define the current space]:

HTH.

Code: [Select]
static int ads_myline(void)
{
struct resbuf *pArgs =acedGetArgs () ;

if( !pArgs ||
pArgs->restype != RTPOINT ||
!pArgs->rbnext ||
pArgs->rbnext->restype != RTPOINT ||
pArgs->rbnext->rbnext )

{
ads_point& pnt1 = pArgs->resval.rpoint;
AcGePoint3d pntStart( pnt1[X], pnt1[Y], pnt1[Z] );

ads_point& pnt2 = pArgs->rbnext->resval.rpoint;
AcGePoint3d pntEnd( pnt2[X], pnt2[Y], pnt2[Z] );

AcDbLine *pLine = new AcDbLine(pntStart, pntEnd);

////AcDbBlockTable *pBlockTable = NULL;

////AcDbDatabase* pDB = acdbHostApplicationServices()->workingDatabase();
////pDB->getSymbolTable(pBlockTable, AcDb::kForRead);

////char space[50];
////if (pDB->tilemode() == Adesk::kFalse)
////{
//// struct resbuf rb;
//// acedGetVar("CVPORT", &rb);
//// if (rb.resval.rint == 1) {
//// strcpy(space, ACDB_PAPER_SPACE);
//// }
//// else {
//// strcpy(space, ACDB_MODEL_SPACE);
//// }
////}
////else {
//// strcpy(space, ACDB_MODEL_SPACE);
////}

////AcDbBlockTableRecord* pBlockTableRecord = NULL;
////pBlockTable->getAt(space, pBlockTableRecord, AcDb::kForWrite);

////pBlockTable->close();

AcDbDatabase* db = acdbCurDwg();
AcDbObjectId curSpaceId = db->currentSpaceId();
AcDbBlockTableRecord *pBlkRec = NULL;
if (acdbOpenObject(pBlkRec, curSpaceId, AcDb::kForWrite)==Acad::eOk) {
AcDbObjectId lineId = AcDbObjectId::kNull;
pBlkRec->appendAcDbEntity(lineId, pLine);
pBlkRec->close();
pLine->close();
}
acedRetVoid () ;
return (RSRSLT) ;
}
else   
{
acutPrintf( "\nInvalid argument list: function expects two points!\n" );
}

}

Code: [Select]
(myline (setq pt1 (getpoint "\nLine from: ")) (getpoint pt1 "\nTo point: "))

LE

  • Guest
Re: Adding Objects to the DrawingDataBase
« Reply #10 on: December 09, 2005, 10:51:13 PM »
Quote
Yes it does, here is a way to do it in objectarx [also noticed the old form I was using before to define the current space]:

Mean.... on how to use currentSpaceId();

 :-)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #11 on: December 09, 2005, 10:56:44 PM »
Glenn, Luis ,

The Lab3 Docs actually use WorkingDatabase.CurrentSpaceId

.. so my example could be reworked to :-
Code: [Select]
//Open current active space for writing
BlockTableRecord btr = (BlockTableRecord)trans.GetObject
                                 (HostApplicationServices.WorkingDatabase.CurrentSpaceId,OpenMode.ForWrite );

//Add the object to <whatever>space
btr.AppendEntity(squircle);

Haven't tried it, but should be OK if the design presupposes the current active space is the required destination for the object.
« Last Edit: December 09, 2005, 11:32:01 PM by Kerry Brown »
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #12 on: December 09, 2005, 11:10:20 PM »
or actually, since the database variable is established, I 'spose this is the same/similar

Code: [Select]
btr = (BlockTableRecord)trans.GetObject (db.CurrentSpaceId,OpenMode.ForWrite );
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Adding Objects to the DrawingDataBase
« Reply #13 on: December 10, 2005, 07:53:09 PM »
That's what I thought you would do Kerry, nicely done.

Have you tried it thru a viewport though?
Me

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #14 on: December 10, 2005, 08:24:24 PM »
I haven't made the time to fire up the IDE for a few days Glenn. Next week will see a change to that, hopefully.

Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #15 on: December 10, 2005, 10:42:51 PM »
Nice Work Kerry

Indeed, very nice.  I really like the idea of breaking the steps down into something easy to follow :)
Can't claim credit for it Bobby, in principle that's straight out of the AutoCAD Docs  .. one of the PowerPoint presentations if I recall.

How was AU for you this year ? Hope you had a good attendance .

Just reading one of your AU2004 Handouts Bobby<CP24-2> .. see that you do  'like the idea of breaking the steps down ..' :-)
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Bobby C. Jones

  • Swamp Rat
  • Posts: 514
  • Cry havoc and let loose the dogs of war.
Re: Adding Objects to the DrawingDataBase
« Reply #16 on: December 12, 2005, 10:12:51 PM »
Quote
Just reading one of your AU2004 Handouts Bobby<CP24-2> .. see that you do  'like the idea of breaking the steps down ..' :-)

Ack!  I remember that one :-)  I didn't get good vibes from it.

However, it went *much* better this year.  And it had a lot more code examples.  I'll see if I can get them up on the board this week if anyone is interested.
Bobby C. Jones

Swift

  • Swamp Rat
  • Posts: 596
Re: Adding Objects to the DrawingDataBase
« Reply #17 on: December 13, 2005, 07:21:58 AM »
I'm always interested in a good read!

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #18 on: December 13, 2005, 10:27:44 AM »
Yeah, me too, Great offer Bobby.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #19 on: January 08, 2006, 07:13:07 PM »
Playing with the next step .. adding multiple Entities to the Database in one Transaction

Any Comments ?

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

using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using AcadDatabase = Autodesk.AutoCAD.DatabaseServices.Database;
using AcadEditor = Autodesk.AutoCAD.EditorInput.Editor;
using AcadTransaction = Autodesk.AutoCAD.DatabaseServices.Transaction;
using AcadTransactionManager = Autodesk.AutoCAD.DatabaseServices.TransactionManager;

using KdubTest.Util;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Colors;

// NOTE: LoaderLock exception break toggled OFF to suit vs2005 in AC2006. kwb

[assembly: CommandClass(typeof(KdubTest.TestClass))]
namespace KdubTest
{
    public class TestClass
    {
        //----------------------------
        [CommandMethod("TestCircles", CommandFlags.Modal)]
        static public void TestCircles()
        {
            AcadDatabase db = AcadApplication.DocumentManager.MdiActiveDocument.Database;
           
            // These points are in World UCS, irrespective of current UCS
            // Look at Matrix translations
            Point3d centerPoint_01 = new Point3d(70.0, 70.0, 0.0);
            Vector3d normalZ = new Vector3d(0.0, 0.0, 1.0);
            double radius_01 = 20.0;
            double radius_02 = 30.0;
            double radius_03 = 40.0;
            double radius_04 = 50.0;
            double radius_05 = 60.0;
            double radius_06 = 70.0;           

            Circle circle_01 = new Circle(centerPoint_01, normalZ, radius_01);
            Circle circle_02 = new Circle(centerPoint_01, normalZ, radius_02);
            Circle circle_03 = new Circle(centerPoint_01, normalZ, radius_03);
            Circle circle_04 = new Circle(centerPoint_01, normalZ, radius_04);
            Circle circle_05 = new Circle(centerPoint_01, normalZ, radius_05);
            Circle circle_06 = new Circle(centerPoint_01, normalZ, radius_06);
           
            Tbl.AddEntities(db, new Entity[] {circle_01, circle_02, circle_03, circle_04, circle_05, circle_06 });           
        }
        ////----------------------------
    }
}

From the Library <snipped> :
Code: [Select]
using System;
using System.Diagnostics;
using System.Collections;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;

using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using AcadDatabase = Autodesk.AutoCAD.DatabaseServices.Database;
using AcadEditor = Autodesk.AutoCAD.EditorInput.Editor;
using AcadTransaction = Autodesk.AutoCAD.DatabaseServices.Transaction;
using AcadTransactionManager = Autodesk.AutoCAD.DatabaseServices.TransactionManager;

namespace KdubTest.Util
{
    public sealed class Tbl
    {
        public Tbl()
        {
        } 
        //-----------------------------
        public static ObjectIdCollection AddEntities(Database db, params Entity[] ents)
        {
            ObjectIdCollection collection = new ObjectIdCollection();
            using (Transaction tr = db.TransactionManager.StartTransaction()) {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); ;
                Entity[] entityArray = ents;
                foreach (Entity ent in ents) {
                    collection.Add(btr.AppendEntity(ent));
                    tr.AddNewlyCreatedDBObject(ent, true);
                }
                tr.Commit();
            }
            return collection;
        }
        //-----------------------------
    }
}
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--

Glenn R

  • Water Moccasin
  • Posts: 1932
  • What idiot child of married cousins wrote this?!
Re: Adding Objects to the DrawingDataBase
« Reply #20 on: January 08, 2006, 07:48:11 PM »
Kerry,

From my quick look, nicely done. The only thing I would add would be to check the validity of the incoming ents array.
if null or length == 0, return null immediately.

Other than that, which is just personal, it looks solid.

Cheers,
Glenn.
Me

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: Adding Objects to the DrawingDataBase
« Reply #21 on: January 08, 2006, 08:07:44 PM »
Hi Glenn

I have a note on my version to test for null

I did have a test for if ents.length == 0 return null; which worked fine, but still needed to test each array item for null, 'cause it spat the dummy if any of the items were null when I tested it.

I think the code is about as tight as it will ever get.


Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

--> Donate to theSwamp<--