TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: Mark on December 05, 2008, 09:19:49 AM
-
Using the attached .dwg, show us how fast you can convert the existing entities/objects into something else. i.e. from points to circles.
the .dwg contains about 10,000 ACAD points.
-
i turned it into an empty drawing...
was that fast, or was that fast??
:lol:
-
:)
-
PS: Isn't the count more like 11336?
-
:)
that was fast! :-)
-
My routine took about 12 seconds on my old machine. :oops:
-
mine :oops:
(defun c:doit ( / activedocument c e iacadapplication modelspace s)
(vl-load-com)
(setq IAcadApplication (vlax-get-acad-object)
ActiveDocument (vla-get-ActiveDocument IAcadApplication)
ModelSpace (vla-get-ModelSpace ActiveDocument)
)
(setq s (ssget "X" (list (cons 0 "POINT"))))
(setq c 0)
(if s
(progn
(While (< c (sslength s))
(setq e (vlax-ename->vla-object (cdr (car (entget (ssname s c))))))
(vla-Addcircle ModelSpace (vlax-3d-point (vlax-get e 'Coordinates )) 15)
(vla-Erase e)
(setq c (1+ c))
)
)
(alert (strcat "Could Not find any Points"))
)
(princ)
)
-
about 8 second
-
About 2 seconds using VBA.
Public Sub ConverterPoints()
Dim objPoint As AcadPoint
Dim objCircle As AcadCircle
Dim StartTime, EndTime As Date
StartTime = Now
For Each objPoint In ThisDrawing.ModelSpace
Set objCircle = ThisDrawing.ModelSpace.AddCircle(objPoint.Coordinates, 30)
objPoint.Delete
Next objPoint
EndTime = Now
Debug.Print DateDiff("s", StartTime, EndTime)
End Sub
-
I changed 'em all to crosses instantly... pdmode :wink:
... just don't set it to 4... sends yer eyes wappy
-
Hey Matt this is a LISP forum.
:evil:
-
< Elapsed time: 0.953000 seconds. > :-)
(defun c:test (/ ss *time*)
(setq *time* (getvar 'MILLISECS)
ss (mapcar 'cadr (ssnamex (ssget "_x" '((0 . "POINT")))))
)
(while ss
(entmakex (list '(0 . "CIRCLE")
(assoc 10 (entget (car ss)))
'(40 . 1.0)
)
)
(entdel (car ss))
(setq ss (cdr ss))
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'MILLISECS) *time*) 1000.0) 2 6)
" seconds. > "
)
)
)
-
nice 8-)
-
Looks like the vla-add method is the fastest lisp. Twice as fast as my entmake. :x
-
< Elapsed time: 0.687000 seconds. > :-D
*updated per MP's comment
(defun c:test (/ *time* n e ss)
(setq *time* (getvar 'millisecs)
ss (ssget "_x" '((0 . "POINT")))
n -1
)
(repeat (sslength ss)
(entmakex
(list '(0 . "CIRCLE")
'(62 . 1)
(assoc 10 (entget (setq e (ssname ss (setq n (1+ n))))))
'(40 . 1.0)
)
)
(entdel e)
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
" seconds. > "
)
)
)
-
Hey Matt this is a LISP forum.
:evil:
I know. Just offering up an alternative.
-
another way.. not fast though
(defun c:doit ( / activedocument e iacadapplication modelspace)
(vl-load-com)
(setq IAcadApplication (vlax-get-acad-object)
ActiveDocument (vla-get-ActiveDocument IAcadApplication)
ModelSpace (vla-get-ModelSpace ActiveDocument)
)
(vlax-for e ModelSpace
(vla-Addcircle ModelSpace (vla-get-Coordinates e) 15)
(vla-Erase e))
)
-
Daniel that is basically the same as Matts code, but offers more overhead due to the interpretive nature of lisp.
-
Daniel that is basically the same as Matts code, but offers more overhead due to the interpretive nature of lisp.
correct.
-
(defun c:test (/ *time* n ss)
(setq *time* (getvar 'millisecs)
ss (ssget "_x" '((0 . "POINT")))
n -1
)
(repeat (sslength ss)
(entmakex
(list '(0 . "CIRCLE")
'(62 . 1)
(cons 10
(cdr (assoc 10 (entget (ssname ss (setq n (1+ n))))))
)
'(40 . 1.0)
)
)
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
" seconds. > "
)
)
)
Why this --
(list '(0 . "CIRCLE")
'(62 . 1)
(cons 10
(cdr (assoc 10 (entget (ssname ss (setq n (1+ n))))))
)
'(40 . 1.0)
)
When you could do this --
(list '(0 . "CIRCLE")
'(62 . 1)
(assoc 10 (entget (ssname ss (setq n (1+ n)))))
'(40 . 1.0)
)
:)
-
You are correct MP...too much coffee this morning :-)
-
...too much coffee this morning :-)
That never happens to me. :whistle:
:D
-
well, it's slower but works more like 'convert', preserving layer and color and maybe smth else :)
(defun c:test3 (/ ss *time* n EntName)
(setq *time* (getvar 'millisecs)
ss (ssget "_x" '((0 . "POINT")))
n -1
)
(while (setq EntName (ssname ss (setq n (1+ n))))
(entmakex
(subst '(40 . 1.0)
'(50 . 0.0)
(subst '(0 . "CIRCLE") '(0 . "POINT") (entget EntName))
)
)
;;; (entdel EntName)
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
" seconds. > "
)
)
)
-
have been a while.... don't know if say something, but was able to play with very simple coding, and doing some minor changes to the code (ok no erase of the points so, no idea if this counts, but was fun)
;; < Elapsed time: 1.703000 seconds. >
;; < Elapsed time: 2.454000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i 0)
;;; (while (< i (sslength ss))
;;; (setq pt (cdr (assoc 10 (entget (ssname ss i)))))
;;; (entmake
;;; (list '(0 . "CIRCLE")
;;; '(100 . "AcDbEntity")
;;; '(67 . 0)
;;; '(410 . "Model")
;;; '(8 . "0")
;;; '(100 . "AcDbCircle")
;;; (cons 10 pt)
;;; '(40 . 1.0)
;;; '(210 0.0 0.0 1.0)))
;;; (setq i (1+ i))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
;; < Elapsed time: 2.016000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i 0)
;;; (while (< i (sslength ss))
;;; (setq pt (cdr (assoc 10 (entget (ssname ss i)))))
;;; (entmake
;;; (list '(0 . "CIRCLE")
;;; ;;'(100 . "AcDbEntity")
;;; ;;'(67 . 0)
;;; ;;'(410 . "Model")
;;; ;;'(8 . "0")
;;; '(100 . "AcDbCircle")
;;; (cons 10 pt)
;;; '(40 . 1.0)
;;; ;;'(210 0.0 0.0 1.0)
;;; ))
;;; (setq i (1+ i))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
;; < Elapsed time: 1.938000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i 0)
;;; (while (< i (sslength ss))
;;; (setq pt (cdr (assoc 10 (entget (ssname ss i)))))
;;; (entmakex
;;; (list '(0 . "CIRCLE")
;;; '(100 . "AcDbCircle")
;;; (cons 10 pt)
;;; '(40 . 1.0)
;;; ))
;;; (setq i (1+ i))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
;; < Elapsed time: 1.890000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i 0)
;;; (setq num (sslength ss))
;;; (while (< i num) ;;(< i (sslength ss))
;;; (setq pt (cdr (assoc 10 (entget (ssname ss i)))))
;;; (entmakex
;;; (list '(0 . "CIRCLE")
;;; '(100 . "AcDbCircle")
;;; (cons 10 pt)
;;; '(40 . 1.0)
;;; ))
;;; (setq i (1+ i))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
;; < Elapsed time: 1.953000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i 0)
;;; (setq num (sslength ss))
;;; (while (< i num)
;;; (setq ename (ssname ss i))
;;; (setq lst (entget ename))
;;; (setq pt (cdr (assoc 10 lst)))
;;; (entmakex
;;; (list '(0 . "CIRCLE")
;;; '(100 . "AcDbCircle")
;;; (cons 10 pt)
;;; '(40 . 1.0)
;;; ))
;;; (setq i (1+ i))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
;; < Elapsed time: 1.860000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i 0)
;;; (setq num (sslength ss))
;;; (repeat num
;;; (setq pt (cdr (assoc 10 (entget (ssname ss i)))))
;;; (entmakex
;;; (list '(0 . "CIRCLE")
;;; '(100 . "AcDbCircle")
;;; (cons 10 pt)
;;; '(40 . 1.0)
;;; ))
;;; (setq i (1+ i))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
;; < Elapsed time: 1.859000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i 0)
;;; (setq num (sslength ss))
;;; (repeat num
;;; ;;(setq pt (cdr (assoc 10 (entget (ssname ss i)))))
;;; (entmakex
;;; (list '(0 . "CIRCLE")
;;; '(100 . "AcDbCircle")
;;; (cons 10 (cdr (assoc 10 (entget (ssname ss i)))))
;;; '(40 . 1.0)
;;; ))
;;; (setq i (1+ i))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
;; < Elapsed time: 1.765000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i 0)
;;; (setq num (sslength ss))
;;; (repeat num
;;; (entmakex
;;; (list (cons 0 "CIRCLE")
;;; (cons 100 "AcDbCircle")
;;; (cons 10 (cdr (assoc 10 (entget (ssname ss i)))))
;;; (cons 40 1.0)
;;; ))
;;; (setq i (1+ i))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
;; < Elapsed time: 1.703000 seconds. >
(defun C:TST (/ ss i pt)
(setq *time* (getvar 'millisecs))
(if (setq ss (ssget "x" '((0 . "point"))))
(progn
(setq i -1)
(setq num (sslength ss))
(repeat num
(entmakex
(list (cons 0 "CIRCLE")
(cons 100 "AcDbCircle")
(cons 10 (cdr (assoc 10 (entget (ssname ss (setq i (1+ i)))))))
(cons 40 1.0)))
)
))
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
" seconds. > "
)
)
(princ)
)
;; < Elapsed time: 1.734000 seconds. >
;;;(defun C:TST (/ ss i pt)
;;; (setq *time* (getvar 'millisecs))
;;; (if (setq ss (ssget "x" '((0 . "point"))))
;;; (progn
;;; (setq i -1 num (sslength ss))
;;; (repeat num
;;; (entmakex
;;; (list (cons 0 "CIRCLE")
;;; (cons 100 "AcDbCircle")
;;; (cons 10 (cdr (assoc 10 (entget (ssname ss (setq i (1+ i)))))))
;;; (cons 40 1.0)
;;; ))
;;; )
;;; ))
;;; (princ
;;; (strcat "\n < Elapsed time: "
;;; (rtos (/ (- (getvar 'millisecs) *time*) 1000.0) 2 6)
;;; " seconds. > "
;;; )
;;; )
;;; (princ)
;;; )
-
Hey Matt this is a LISP forum.
:evil:
I know. Just offering up an alternative.
:wink:
Command: doit
Total running time: 0.28 seconds
typedef AcDbObjectPointer<AcDbPoint> AcDbPointPointer;
typedef AcDbObjectPointer<AcDbCircle> AcDbCirclePointer;
static void CRPDArxConvert_doit(void)
{
CLapseTime ltTotal;
Acad::ErrorStatus es;
long ssLength = 0;
ads_name sel;
AcDbObjectIdArray ids;
resbuf *rbFilter = acutBuildList(RTDXF0, _T("POINT"), RTNONE);
TCHAR* mode = _T("X");
if (acedSSGet(mode, NULL, NULL, rbFilter, sel) != RTNORM)
{
acutRelRb(rbFilter);
return;
}
if(acedSSLength(sel, &ssLength) != RTNORM || ssLength == 0)
{
acedSSFree(sel);
return;
}
if(acedGetCurrentSelectionSet(ids) != Acad::eOk)
{
acedSSFree(sel);
return;
}
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTableRecordPointer pBTR(pDb->currentSpaceId(), AcDb::kForWrite); //<<<<<
for(int i = 0 ; i < ids.length(); i++)
{
AcDbPointPointer smartPointer(ids[i],AcDb::kForRead);
if(smartPointer.openStatus() == Acad::eOk)
{
AcDbCirclePointer pCircle;
if(pCircle.create() == Acad::eOk)
{
pCircle->setRadius(15.0);
pCircle->setCenter( smartPointer->position());
pBTR->appendAcDbEntity(pCircle);
smartPointer->upgradeOpen();
smartPointer->erase();
}
}
}
acedSSFree(sel);
acutRelRb(rbFilter);
acutPrintf(_T("\nTotal running time: %.4f seconds"), ltTotal.LapseTimeSeconds());
}
-
Hey Matt this is a LISP forum.
:evil:
I know. Just offering up an alternative.
:wink:
Command: doit
Total running time: 0.28 seconds
Oooooohhh... Looks like you win!
-
acedSSFree(sel);
acutPrintf(_T("\nTotal running time: %.2f seconds"), ltTotal.LapseTimeSeconds());
}
that's not fair.... for the lisp world.....
ok then, how about a version using a point container iterator... eh...... and see if lower the time :)
I mean something like:
AcDbDatabase* pDb = curDoc()->database();
AcDbBlockTableRecordPointer modelSpace(ACDB_MODEL_SPACE, pDb, AcDb::kForWrite); // and do another for paper_space
if(modelSpace.openStatus() != Acad::eOk) return;
AcDbBlockTableRecordIterator* pIterator = NULL;
modelSpace->newIterator(pIterator);
for (pIterator->start(); !pIterator->done(); pIterator->step())
{
AcDbObjectId objId;
pIterator->getEntityId(objId);
AcDbObjectPointer<AcDbPoint> pointObj(objId, AcDb::kForRead); // open for what?
if (pointObj.openStatus() == Acad::eOk)
{
}
}
delete pIterator;
-
Command: doit
Total running time: 0.2810 seconds
Command: test
Total running time: 0.2180 seconds
static void CRPDArxConvert_test(void)
{
CLapseTime ltTotal;
AcDbObjectId objId;
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTableRecordPointer pBTR(pDb->currentSpaceId(), AcDb::kForWrite);
AcDbBlockTableRecordIterator* pIterator = NULL;
pBTR->newIterator(pIterator);
for (pIterator->start(); !pIterator->done(); pIterator->step())
{
pIterator->getEntityId(objId);
AcDbObjectPointer<AcDbPoint> smartPointer(objId, AcDb::kForRead);
if (smartPointer.openStatus() == Acad::eOk)
{
AcDbCirclePointer pCircle;
if(pCircle.create() == Acad::eOk)
{
pCircle->setRadius(15.0);
pCircle->setCenter( smartPointer->position());
pBTR->appendAcDbEntity(pCircle);
smartPointer->upgradeOpen();
smartPointer->erase();
}
}
}
acutPrintf(_T("\nTotal running time: %.4f seconds"), ltTotal.LapseTimeSeconds());
delete pIterator;
}
-
Command: test
Total running time: 0.2180 seconds
Good,
Now wait to see the C# (.NET) version..... (hope someone post a sample too).... :)
-
Off topic, but where did "CLapseTime" come from?
-
Off topic, but where did "CLapseTime" come from?
From master Paul .. attached to this thread
http://www.theswamp.org/index.php?topic=15784.msg305476#msg305476
-
Ah ok, Thanks Daniel
-
Daniel, for reference your latest runs 0.156 seconds on my system.
I hadn't noticed that it was just blasting throught the BTR and I
wrote one that does the same except without smart pointers, with
a run time of 0.094 seconds.
CLapseTime ltTotal;
AcDbDatabase * pDb = acdbHostApplicationServices()->workingDatabase();
AcDbBlockTableRecord * pRec;
if(acdbOpenAcDbObject((AcDbObject *&) pRec,pDb->currentSpaceId(), AcDb::kForWrite) == Acad::eOk)
{
AcDbBlockTableRecordIterator * pIter;
if(pRec->newIterator(pIter) == Acad::eOk) {
for(pIter->start(); !pIter->done(); pIter->step()) {
AcDbObjectId objId;
AcDbEntity * pEnt;
if(pIter->getEntity(pEnt, AcDb::kForRead) == Acad::eOk) {
AcDbPoint * pPoint = AcDbPoint::cast(pEnt);
if(pPoint) {
AcDbCircle * pCircle = new AcDbCircle(pPoint->position(), pPoint->normal(), 15.0);
if(pCircle) {
if(pRec->appendAcDbEntity(pCircle) == Acad::eOk)
pCircle->close();
else
delete pCircle;
}
}
pEnt->close();
}
}
delete pIter;
}
pRec->close();
}
acutPrintf(_T("\nTotal run time: %.3f seconds"), ltTotal.LapseTimeSeconds());
-
Dang! That’s fast. I was considering using pointers, but I didn’t want to rub-it-in :evil:
-
Now wait to see the C# (.NET) version..... (hope someone post a sample too).... :)
As there's no more place lisping, I try something, but I'm newbie with C#...
EDIT : follow Kerry's suggestion and add a chrono: 0.563 second.
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace Point2Circle
{
public class MyClass
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
[CommandMethod("Test")]
public void Test()
{
DateTime start = DateTime.Now;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
foreach (ObjectId objId in btr)
{
Entity ent = (Entity)tr.GetObject(objId, OpenMode.ForWrite);
DBPoint pt = ent as DBPoint;
if (pt != null)
{
Circle c = new Circle(pt.Position, pt.Normal, 15.0);
ent.Erase();
btr.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
}
}
tr.Commit();
DateTime stop = DateTime.Now;
double time = (stop.Second + stop.Millisecond / 1000.0) - (start.Second + start.Millisecond / 1000.0);
ed.WriteMessage("Ellapsed time: {0} seconds", time);
}
}
}
}
-
Nice start gile :)
Perhaps the routine could be more efficient if the 'is' methodology was replaced with 'as' methodology.
I have some work to finish, but I'd like to play with this later as well.
///kdub
-
Thanks Kerry,
I edited the code according to what you suggested (if I'd understood ?) and add a chrono.
It seems to be far away behind the C++ codes, but I'm quite proud: it works :kewl:
-
That looks better gile .. can you repost the previous code, just for a comparison ( please :) )
-
:) to be fair though, the
DateTime start = DateTime.Now;
probably could be higher up the process chain :)
-
That looks better gile .. can you repost the previous code, just for a comparison :-)
I just replaced:
if (ent is DBPoint) {DBPoint pt = ent as DBPoint; ...}
by
DBPoint pt = ent as DBPoint;
if (pt != null) {...}
PS: i put the start chrono higher, it doesn't change, the times are still between 0.53 and 0.58
-
</start Rant of drunk guy that writes slow code>
OK, just to open up another topic of discussion:
Why do all the "How fast...." threads always use elapsed run time as the basis of comparison?
For my money (and my clients' money), a snippet of code that takes 3 minutes to write and 1.5 seconds to execute is worth a whole lot more than a snippet of code that takes 29.37 minutes to write, compile, and load and 0.047 seconds to execute.
I think that the time measurement should be started when the problem explanation is completed and stopped when the required result is delivered to the client.
And I understand that if a program is going to be run thousands of times, execution time will matter. But in the CAD world, how many times does that happen.
But even in the 'made-up' example above, the faster program would have to execute about 34,000 times just to 'break even'. Not very many of my routines run that many times.
</end Rant of drunk guy that writes slow code>
-
Command: netload
Command: test1
Ellapsed time: 0.875 seconds
Command: u
Command: test1
Ellapsed time: 0.78125 seconds
Command: u
Command: test2
Ellapsed time: 0.78125 seconds
ps: I added a line to the drawing to make sure it was selective ok :)
[assembly: AcRx.CommandClass(typeof(kdub.Testing.Commands.ConvertPoints))]
namespace kdub.Testing.Commands
{
/// <summary>
/// Summary description for Routine.
/// </summary>
public class ConvertPoints
{
[AcRx.CommandMethod("Test1")]
static public void Test1()
{
DateTime timeStart = DateTime.Now;
Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
foreach (ObjectId objId in btr)
{
Entity ent = (Entity)tr.GetObject(objId, OpenMode.ForWrite);
DBPoint pt = ent as DBPoint;
if (pt != null)
{
Circle c = new Circle(pt.Position, pt.Normal, 15.0);
ent.Erase();
btr.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
}
}
tr.Commit();
}
TimeSpan TimeDuration = (DateTime.Now - timeStart);
ed.WriteMessage("Ellapsed time: {0} seconds", (TimeDuration.TotalSeconds));
}
[AcRx.CommandMethod("Test2")]
static public void Test2()
{
DateTime timeStart = DateTime.Now;
Editor ed = AcadApp.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
as BlockTableRecord;
foreach (ObjectId objId in btr)
{
// make the assignment more direct
//
DBPoint pt = tr.GetObject(objId, OpenMode.ForWrite) as DBPoint;
if (pt != null)
{
Circle c = new Circle(pt.Position, pt.Normal, 15.0);
pt.Erase();
btr.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
}
}
tr.Commit();
}
TimeSpan TimeDuration = (DateTime.Now - timeStart);
ed.WriteMessage("Ellapsed time: {0} seconds", (TimeDuration.TotalSeconds ));
}
}
}
-
Ah, cause it is called a challenge and it's an opportunity for people to explore
and learn from others using small well defined problem space.
Cheers!!
Paul
-
Cheers! again :lol:
-
David,
I usually don't spend a lot of time looking for the extra 0.01 of a second ... I understand all about a return on investment when writing code.
but, as Paul indicated so succintly , these are ' an opportunity for people to explore and learn from others '
not an appendage measuring competition :)
-
Command: Test4
Ellapsed time: 0.0625 seconds
This had me a little excited till I realised that all the points were already converted to circles :D
-
Stumbled across this:
-
hey, Alan ... don't just sit there with an enigmatic smile on your face ; tell us the story :)
-
I was trying to run down some info on reactors & stumbled into this in my library. 8-)
See pages 27+
-
Thanks Alan.
-
Great stuff, Thanks Cab
-
Right place at the right time. :-)
Still looking for more material on vLisp Object Reactors. All I've found are simple examples.
-
Here is my stab.-
Total run time: 0.078 seconds
(if I removed those lines marked with total run time)
static void PointsToCircles(void)
{
CLapseTime ltTotal;
AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForWrite);
if (pBTR.openStatus() != Acad::eOk) return;
AcDbBlockTableRecordIterator* pIterator = NULL;
if (pBTR->newIterator(pIterator) != Acad::eOk) return;
for (pIterator->start(); !pIterator->done(); pIterator->step())
{
AcDbObjectId objId;
pIterator->getEntityId(objId);
//if (pIterator->getEntityId(objId) != Acad::eOk) return; // Total run time: 0.125 seconds
AcDbObjectPointer<AcDbPoint> pPoint(objId, AcDb::kForRead);
if(pPoint.openStatus() == Acad::eOk)
{
AcDbCircle *pCircle = new AcDbCircle(pPoint->position(), pPoint->normal(), 1.0);
if (pCircle && pBTR->appendAcDbEntity(pCircle) == Acad::eOk)
{
pCircle->close(); // Total run time: 0.078 seconds
pPoint->upgradeOpen(); // Total run time: 0.109 seconds
pPoint->erase();
}
else
delete pCircle; // Total run time: 0.094 seconds
}
}
delete pIterator;
acutPrintf(_T("\nTotal run time: %.3f seconds"), ltTotal.LapseTimeSeconds());
}
-
Here is my stab.-
Total run time: 0.078 seconds
(if I removed those lines marked with total run time)
static void PointsToCircles(void)
{
CLapseTime ltTotal;
AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForWrite);
if (pBTR.openStatus() != Acad::eOk) return;
AcDbBlockTableRecordIterator* pIterator = NULL;
if (pBTR->newIterator(pIterator) != Acad::eOk) return;
for (pIterator->start(); !pIterator->done(); pIterator->step())
{
AcDbObjectId objId;
pIterator->getEntityId(objId);
//if (pIterator->getEntityId(objId) != Acad::eOk) return; // Total run time: 0.125 seconds
AcDbObjectPointer<AcDbPoint> pPoint(objId, AcDb::kForRead);
if(pPoint.openStatus() == Acad::eOk)
{
AcDbCircle *pCircle = new AcDbCircle(pPoint->position(), pPoint->normal(), 1.0);
if (pCircle && pBTR->appendAcDbEntity(pCircle) == Acad::eOk)
{
pCircle->close(); // Total run time: 0.078 seconds
pPoint->upgradeOpen(); // Total run time: 0.109 seconds
pPoint->erase();
}
else
delete pCircle; // Total run time: 0.094 seconds
}
}
delete pIterator;
acutPrintf(_T("\nTotal run time: %.3f seconds"), ltTotal.LapseTimeSeconds());
}
But, after running Paul code and including the erase of the point - his approach takes the same 0.094 seconds vs. 0.125 seconds ==== 0.031 dif.
Was a great excercise !
-
I make advantage of this challenge to keep on learning C# (even it's a LISP forum, sorry CAB).
I tried a way using a selection set rather than scanning all database, it seems to be a little faster (0.5 on my system).
Thanks to Kerry for all the nice little tricks he shows me.
using System;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
namespace Point2Circle
{
public class MyClass
{
[CommandMethod("Test2")]
public void Test2()
{
DateTime start = DateTime.Now;
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
TypedValue[] tValues = { new TypedValue((int)DxfCode.Start, "POINT") };
SelectionFilter selFilter = new SelectionFilter(tValues);
PromptSelectionResult result = ed.SelectAll(selFilter);
if (result.Status == PromptStatus.OK)
{
ObjectId[] selSet = result.Value.GetObjectIds();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
foreach (ObjectId objId in selSet)
{
DBPoint pt = tr.GetObject(objId, OpenMode.ForWrite) as DBPoint;
if (pt != null)
{
Circle c = new Circle(pt.Position, pt.Normal, 15.0);
pt.Erase();
btr.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
}
}
tr.Commit();
TimeSpan time = (DateTime.Now - start);
ed.WriteMessage("Elapsed time: {0} seconds", (time.TotalSeconds));
}
}
}
}
}
-
I'm just jealous of your multilingual programmers. 8-)
-
I'm very very much comfortable with LISP
Here's a little comparative between foreach, mapcar, repeat and while statements.
Commande: TEST_FOREACH
< Elapsed time: 1.188000 seconds. >
Commande: TEST_MAPCAR
< Elapsed time: 1.172000 seconds. >
Commande: TEST_REPEAT
< Elapsed time: 1.140000 seconds. >
Commande: TEST_WHILE
< Elapsed time: 1.125000 seconds. >
(defun c:test_foreach (/ time ss)
(setq time (getvar 'millisecs))
(and
(setq ss (ssget "x" '((0 . "point"))))
(foreach p (ssnamex ss)
(entmakex
(list
(cons 0 "CIRCLE")
(assoc 10 (entget (cadr p)))
(cons 40 15.0)
)
)
(entdel (cadr p))
)
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) time) 1000.0) 2 6)
" seconds. > "
)
)
(princ)
)
(defun c:test_mapcar (/ time ss)
(setq time (getvar 'millisecs))
(and (setq ss (ssget "_X" '((0 . "POINT"))))
(mapcar '(lambda (x)
(entmakex
(list
'(0 . "CIRCLE")
(assoc 10 (entget (cadr x)))
'(40 . 15.)
)
)
(entdel (cadr x))
)
(ssnamex ss)
)
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) time) 1000.0) 2 6)
" seconds. > "
)
)
(princ)
)
(defun c:test_repeat (/ time ss n pt)
(setq time (getvar 'millisecs))
(and
(setq ss (ssget "x" '((0 . "POINT"))))
(repeat (setq n (sslength ss))
(setq pt (ssname ss (setq n (1- n))))
(entmakex
(list
(cons 0 "CIRCLE")
(assoc 10 (entget pt))
(cons 40 15.0)
)
)
(entdel pt)
)
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) time) 1000.0) 2 6)
" seconds. > "
)
)
(princ)
)
(defun c:test_while (/ time ss n pt)
(setq time (getvar 'millisecs))
(and (setq ss (ssget "_X" '((0 . "POINT"))))
(setq n -1)
(while (setq pt (ssname ss (setq n (1+ n))))
(entmakex
(list
'(0 . "CIRCLE")
(assoc 10 (entget pt))
'(40 . 15.)
)
)
(entdel pt)
)
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) time) 1000.0) 2 6)
" seconds. > "
)
)
(princ)
)
-
Another variant for mapcar :) < Elapsed time: 1.031000 seconds. >
(defun c:test_mapcar (/ time addcircle)
(defun addcircle (e /)
(entmakex (list
'(0 . "CIRCLE")
(assoc 10 (entget e))
'(40 . 15.)
)
)
(entdel e)
)
(setq time (getvar 'millisecs))
(mapcar 'addcircle
(mapcar 'cadr (ssnamex (ssget "_X" '((0 . "POINT")))))
)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'millisecs) time) 1000.0) 2 6)
" seconds. > "
)
)
(princ)
)
-
Duration: 0.586035376004492 sec :laugh:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
[assembly: CommandClass(typeof(ExecMethod.Commands))]
//++--
namespace ExecMethod
{
public class Commands
{
[CommandMethod("doit")]
public static void doit()
{
HiPerfTimer pt = new HiPerfTimer();
pt.Start();
Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
Database db = AcDb.HostApplicationServices.WorkingDatabase;
AcDb.TransactionManager tm = db.TransactionManager;
try
{
using (Transaction tr = tm.StartTransaction())
{
BlockTableRecord blockTableRecord =
tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db),
OpenMode.ForWrite) as BlockTableRecord;
foreach (ObjectId entId in blockTableRecord)
{
DBPoint point = tr.GetObject
(entId, OpenMode.ForWrite, false) as DBPoint;
if (point != null)
{
Circle c = new Circle(point.Position, point.Normal, 15.0);
blockTableRecord.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
point.Erase();
}
}
tr.Commit();
}
pt.Stop();
ed.WriteMessage("Duration: {0} sec\n", pt.Duration);
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.Message);
ed.WriteMessage(ex.StackTrace);
}
}
}
}
-
Duration: 0.586035376004492 sec :laugh:
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
[assembly: CommandClass(typeof(ExecMethod.Commands))]
//++--
namespace ExecMethod
{
public class Commands
{
[CommandMethod("doit")]
public static void doit()
{
HiPerfTimer pt = new HiPerfTimer();
pt.Start();
Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument.Editor;
Database db = AcDb.HostApplicationServices.WorkingDatabase;
AcDb.TransactionManager tm = db.TransactionManager;
try
{
using (Transaction tr = tm.StartTransaction())
{
BlockTableRecord blockTableRecord =
tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db),
OpenMode.ForWrite) as BlockTableRecord;
foreach (ObjectId entId in blockTableRecord)
{
DBPoint point = tr.GetObject
(entId, OpenMode.ForWrite, false) as DBPoint;
if (point != null)
{
Circle c = new Circle(point.Position, point.Normal, 15.0);
blockTableRecord.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
point.Erase();
}
}
tr.Commit();
}
pt.Stop();
ed.WriteMessage("Duration: {0} sec\n", pt.Duration);
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.Message);
ed.WriteMessage(ex.StackTrace);
}
}
}
}
Cheater...that's like bringing a gun to a knife fight :-D
-
Doh! , Its just about identical to Kerry’s oops :? :-o :oops:
-
... something about great minds thinking alike comes to mind ... :wink: :)
-
... but then, there are only so many ways this beast can be tamed
-
... but then, there are only so many ways this beast can be tamed
the “great minds thinking alike” is what it is. :laugh:
-
“great minds thinking alike”
So do I ? (http://www.theswamp.org/index.php?topic=26243.msg316955#msg316955) :?
I tried also using a selection set (here (http://www.theswamp.org/index.php?topic=26243.msg317048#msg317048)), it seems to be a little faster : 0.5156 vs 0.5625
-
“great minds thinking alike”
So do I ? (http://www.theswamp.org/index.php?topic=26243.msg316955#msg316955) :?
I tried also using a selection set (here (http://www.theswamp.org/index.php?topic=26243.msg317048#msg317048)), it seems to be a little faster : 0.5156 vs 0.5625
yes yes :lol:
-
Kerry this is quite a bit faster than test2 (having adjusted yours to accept a fixed normal Vector3d normal = Vector3d.ZAxis;)
Why it should be faster, I don't know.(Perhaps the deleting process must be cleaner in its own transaction.)
public class ConvertPoints
{
[AcRx.CommandMethod("Test1")]
static public void Test1()
{
DateTime timeStart = DateTime.Now;
Editor ed = acadApp.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
DBPoint pt;
PromptSelectionResult psr=ed.SelectAll();
if (psr.Status != PromptStatus.OK) return;
SelectionSet ss = psr.Value;
ObjectIdCollection ids = new ObjectIdCollection(ss.GetObjectIds());
Point3dCollection pts = new Point3dCollection();
Vector3d normal = Vector3d.ZAxis;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (ObjectId id in ids)
{
pt = tr.GetObject(id, OpenMode.ForWrite) as DBPoint;
if (pt != null)
{
pts.Add(pt.Position);
}
pt.Erase();
}
tr.Commit();
}
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord modelspace = tr.GetObject
(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
foreach (Point3d pt3d in pts)
{
Circle c = new Circle(pt3d, normal, 15.0);
modelspace.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
}
tr.Commit();
}
TimeSpan TimeDuration = (DateTime.Now - timeStart);
ed.WriteMessage("Ellapsed time: {0} seconds", (TimeDuration.TotalSeconds));
}
-
That's odd the computer at work is reading
Command: TEST1 Ellapsed time: 1.7502688 seconds
Command: TEST2 Ellapsed time: 1.9065428 seconds
whereas at home it was more like 1.3 to 1.7
I've had coffee and it's too early for a beer so ???.
-
Thats an interesting variation Bryco.
I'd have thought the overhead of making a new collection to hold the points locations would slow it down ... deserves some more testing ...
// kerry
-
... and yes, having the vector as variable instead of recalculating based on the point normal should tweek a couple more ticks from the time.
//kwb
-
Agreed, looks like more overhead.
It's also interesting how using if (pt != null) is actually seemed faster than making a filter for the selection set and removing the if (pt != null).
The filter must be using is.
-
Here is your test2 with apples to apples
[CommandMethod("Test2")]
static public void Test2()
{
DateTime timeStart = DateTime.Now;
Editor ed = acadApp.DocumentManager.MdiActiveDocument.Editor;
Database db = HostApplicationServices.WorkingDatabase;
Vector3d normal = Vector3d.ZAxis;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite)
as BlockTableRecord;
foreach (ObjectId objId in btr)
{
// make the assignment more direct
//
DBPoint pt = tr.GetObject(objId, OpenMode.ForWrite) as DBPoint;
if (pt != null)
{
Circle c = new Circle(pt.Position, normal, 15.0);
pt.Erase();
btr.AppendEntity(c);
tr.AddNewlyCreatedDBObject(c, true);
}
}
tr.Commit();
}
TimeSpan TimeDuration = (DateTime.Now - timeStart);
ed.WriteMessage("Ellapsed time: {0} seconds", (TimeDuration.TotalSeconds ));
}
-
:lol:
< Elapsed time: 32.703000 seconds.>
;;;AutoLisp
(defun c:test (/ ss *time*)
(setq *time* (getvar 'MILLISECS))
(L#TEST)
(princ
(strcat "\n < Elapsed time: "
(rtos (/ (- (getvar 'MILLISECS) time*) 1000.0) 2 6)
" seconds. > "
)
)
)
;;;L#
(def L#TEST ()
(= pDb (HostApplicationServices.WorkingDatabase))
(= tm (.TransactionManager pDb))
(= tr (.StartTransaction tm))
(= id (SymbolUtilityServices.GetBlockModelSpaceId pDb))
(= forWrite (OpenMode.ForWrite))
(= forRead (OpenMode.ForRead))
(= blockTableRecord (.GetObject tr id forWrite))
(each e
blockTableRecord
(= dbo (.GetObject tr e forWrite))
(= str(.ToString dbo))
(if (is str "Autodesk.AutoCAD.DatabaseServices.DBPoint")
(progn
(= c
(new "Circle"
(.Position dbo)
(.Normal dbo)
15
)
)
(= id2(.AppendEntity blockTableRecord c))
(.AddNewlyCreatedDBObject tr c true)
(.Erase dbo)
)
)
)
(.Commit tr)
(.Dispose tr)
)
-
I was thinking about coding one in F# ... but real work and sleep keep getting in the way ...
//kdub
-
I was thinking about coding one in F# ... but real work and sleep keep getting in the way ...
//kdub
Would that be with a guitar or keyboard?
-
Would that be with a guitar or keyboard?
Guitar Hero, of course :-)
-
I was thinking about coding one in F# ... but real work and sleep keep getting in the way ...
//kdub
Sorry to dredge up old posts, but I was bored over lunch. I don't imagine this will run much different than the C# versions.
module Acad
open System
open Autodesk.AutoCAD.ApplicationServices
open Autodesk.AutoCAD.DatabaseServices
open Autodesk.AutoCAD.Geometry
open Autodesk.AutoCAD.Runtime
let GetActiveDoc () =
Application.DocumentManager.MdiActiveDocument
let GetPoints () =
let db = GetActiveDoc().Database
use trans = db.TransactionManager.StartTransaction()
let blocks = trans.GetObject(db.BlockTableId, OpenMode.ForRead) :?> BlockTable
let modelSpace = trans.GetObject(blocks.[BlockTableRecord.ModelSpace], OpenMode.ForWrite) :?> BlockTableRecord
for id in modelSpace do
let dbObj = trans.GetObject(id, OpenMode.ForWrite)
match dbObj with
| :? DBPoint as pnt->
let circ = new Circle(pnt.Position, Vector3d.ZAxis, 4.0)
modelSpace.AppendEntity(circ) |> ignore
trans.AddNewlyCreatedDBObject(circ, true)
pnt.Erase()
| _ -> ()
trans.Commit()
let Timer f =
let timer = new System.Diagnostics.Stopwatch()
timer.Start()
f()
timer.Stop()
timer.Elapsed.TotalSeconds
let Print x =
GetActiveDoc().Editor.WriteMessage("\n" + x.ToString())
[<CommandMethod("pts")>]
let pts () =
Timer GetPoints
|> Print
0.4217323