TheSwamp
Code Red => .NET => Topic started by: Kerry 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 ? ?
[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
-
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 ;)
-
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 ....
-
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.
-
....... 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:
-
Nice Work Kerry
-
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 .
-
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.
-
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.
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" );
}
}
(myline (setq pt1 (getpoint "\nLine from: ")) (getpoint pt1 "\nTo point: "))
-
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();
:-)
-
Glenn, Luis ,
The Lab3 Docs actually use WorkingDatabase.CurrentSpaceId
.. so my example could be reworked to :-
//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.
-
or actually, since the database variable is established, I 'spose this is the same/similar
btr = (BlockTableRecord)trans.GetObject (db.CurrentSpaceId,OpenMode.ForWrite );
-
That's what I thought you would do Kerry, nicely done.
Have you tried it thru a viewport though?
-
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.
-
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 ..' :-)
-
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.
-
I'm always interested in a good read!
-
Yeah, me too, Great offer Bobby.
-
Playing with the next step .. adding multiple Entities to the Database in one Transaction
Any Comments ?
The Tester :
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> :
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;
}
//-----------------------------
}
}
-
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.
-
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.