Author Topic: Adding Objects to the DrawingDataBase  (Read 15550 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 »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3636
  • (x-in)->[process]->(y-out) ... simples!
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 ;)
"Programming is really just the mundane aspect of expressing a solution to a problem."
- John Carmack

"Short cuts make long delays,' argued Pippin.”
- J.R.R. Tolkien

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 »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
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.

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:



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

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: 516
  • 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 .
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • 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 »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

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 );
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
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?

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.

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

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 ..' :-)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Bobby C. Jones

  • Swamp Rat
  • Posts: 516
  • 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.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

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;
        }
        //-----------------------------
    }
}
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Glenn R

  • Guest
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.

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.


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