(defun entprev ( e / ss en ssxelst )
(if (eq (type e) 'ename)
(if (setq ss (ssget "_X"))
(progn
(setq en (ssname ss (- (sslength ss) 1)))
(setq ssxelst (cons en ssxelst))
(while (setq en (entnext en))
(setq ssxelst (cons en ssxelst))
)
(cadr (member e ssxelst))
)
)
(progn (prompt "\n; error: bad argument type: lentityp ")(princ e)(princ))
)
)
; Version 1.00 - 22/11/2013
;
(defun ALE_EntPrevious (EntNam / SelSet Countr SsLngt)
(if (eq (type EntNam) 'ename)
(if (setq SelSet (ssget "_X"))
(progn
(setq Countr 0 SsLngt (sslength SelSet))
(while (> SsLngt Countr)
(if (eq EntNam (ssname SelSet Countr))
(setq SsLngt 0)
(setq Countr (1+ Countr))
)
)
(ssname SelSet (1+ Countr))
)
)
(progn (prompt "\n; error: bad argument type: lentityp ")(princ EntNam)(princ))
)
)
(defun entprev ( e / ss en ssxelst )
(if (eq (type e) 'ename)
(if (setq ss (ssget "_X"))
(progn
(setq en (ssname ss (- (sslength ss) 1)))
(setq ssxelst (cons en ssxelst))
(while (and (/= (setq en (entnext en)) nil) (/= en e))
(setq ssxelst (cons en ssxelst))
)
(setq ssxelst (cons en ssxelst))
(cadr (member e ssxelst))
)
)
(progn (prompt "\n; error: bad argument type: lentityp ")(princ e)(princ))
)
)
; Version 1.00 - 22/11/2013
;
(defun ALE_NEntPrevious (EntNam / SelSet Countr SsLngt EntOut EntNxt)
(if (eq (type EntNam) 'ename)
(if (setq SelSet (ssget "_X"))
(progn
(setq Countr 0 SsLngt (sslength SelSet))
(while (> SsLngt Countr)
(if (eq EntNam (ssname SelSet Countr))
(setq SsLngt 0 EntOut (ssname SelSet (1+ Countr)) EntNxt EntOut)
(setq Countr (1+ Countr))
)
)
(while (and EntNxt (setq EntNxt (entnext EntNxt)))
(if (eq EntNxt EntNam) (setq EntNxt nil) (setq EntOut EntNxt))
)
EntOut
)
)
(progn (prompt "\n; error: bad argument type: lentityp ")(princ EntNam)(princ))
)
)
Comando: (entget (ALE_nEntPrevious kkkk))
((-1 . <Nome entità: 7ffffb18880>) (0 . "SEQEND") (330 . <Nome entità: 7ffffb18870>) (5 . "5C10") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "$0__NORM") (6 . "Continuous") (-2 . <Nome entità: 7ffffb18870>))
Comando: (entget (entprev kkkk))
((-1 . <Nome entità: 7ffffb18880>) (0 . "SEQEND") (330 . <Nome entità: 7ffffb18870>) (5 . "5C10") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "$0__NORM") (6 . "Continuous") (-2 . <Nome entità: 7ffffb18870>))
Comando: (entget (lm_entprev kkkk))
((-1 . <Nome entità: 7ffffb18980>) (0 . "VERTEX") (330 . <Nome entità: 7ffffb18870>) (5 . "5C20") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "$0__NORM") (6 . "Continuous") (100 . "AcDbVertex") (100 . "AcDb2dVertex") (10 502.003 -324.114 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0713466) (91 . 0) (70 . 0) (50 . 5.68134))
(defun ALE_NEntPrevious (EntNam / SelSet Countr SsLngt EntOut EntNxt)
(if (eq (type EntNam) 'ename)
(if (setq SelSet (ssget "_X"))
(progn
(setq Countr 0 SsLngt (sslength SelSet))
(while (> SsLngt Countr)
(if (eq EntNam (ssname SelSet Countr))
(setq SsLngt 0)
(setq Countr (1+ Countr))
)
)
(setq EntOut (ssname SelSet (1+ Countr)) EntNxt EntOut)
(while (and EntNxt (setq EntNxt (entnext EntNxt)))
(if (eq EntNxt EntNam) (setq EntNxt nil) (setq EntOut EntNxt))
)
EntOut
)
)
(progn (prompt "\n; error: bad argument type: lentityp ")(princ EntNam)(princ))
)
)
@Lee I think there is something wrong:
(defun c:Test ( )
(setq kkkk (car (entsel)))
(princ "\nkkkk ") (princ kkkk)
(princ "\nALE_NEntPrevious ") (princ (entnext (ALE_NEntPrevious kkkk)))
(princ "\nLM_entprev3 ") (princ (entnext (LM_entprev3 kkkk)))
(princ "\nentprev ") (princ (entnext (entprev kkkk)))
(princ)
)
Selezionare oggetto:
kkkk <Nome entità: 7ffffb081b0>
ALE_NEntPrevious <Nome entità: 7ffffb081b0>
LM_entprev3 <Nome entità: 7ffffb081b0>
entprev <Nome entità: 7ffffb080d0>
Command: !e
<Entity name: 7ffffb05c60>
Command: (entnext e)
<Entity name: 7ffffb05c80>
Command: (entprev e)
<Entity name: 7ffffb05c50>
Command: (entprev (entnext e))
nil
Command: (entnext (entprev e))
<Entity name: 7ffffb05c60>
Command: (entprev (entnext e))
nil
Command: (entprev (entnext e))
<Entity name: 7ffffb05c60>
Command: (entnext (entprev e))
<Entity name: 7ffffb05c60>
(defun lastEnt (/ a b) (if (setq a (entlast)) (while (setq b (entnext a)) (setq a b))) a)
(defun previousEnt (/ le pe) (setq le (lastEnt)) (entdel le) (setq pe (lastEnt)) (entdel le) pe)
I don't see where Luis is supplying entity from witch are result to be retrieved...no problem, was just trying to add something on the plate - eventually if I get a chance will try to write the function with the from entity argument.... but my lisp skills are dead. have fun
(defun alt_hex-- ( hex / foo)
(defun foo (lst)
(cond
((null lst) nil)
((= 65 (car lst)) (cons 57 (cdr lst)))
((= 48 (car lst)) (cons 70 (foo (cdr lst))))
((cons (1- (car lst)) (cdr lst)))
)
)
(vl-list->string (reverse (foo (reverse (vl-string->list hex)))))
)
@ Lee Mac:
Test 1.
Create a dwg with 2 entities:
(LM_entprev (entlast)) => nil
Test 2.
Create a dwg with 3 entities and delete the 2nd entity:
(LM_entprev (entlast)) => <Entity name: #>
(entget (LM_entprev (entlast))) => nil
Took me a while to understand your (hex--). Interesting approach.
But why not?:Code: [Select](defun alt_hex-- ( hex / foo)
(defun foo (lst)
...
)
I don't see where Luis is supplying entity from witch are result to be retrieved...
(defun lastEnt (/ a b) (if (setq a (entlast)) (while (setq b (entnext a)) (setq a b))) a)
(defun previousEnt (/ le pe) (setq le (lastEnt)) (entdel le) (setq pe (lastEnt)) (entdel le) pe)
(defun previousEntFromEnt (e / a b l pe)
(setq a e)
(while (setq b (entnext a))
(setq l (cons b l))
(setq a b))
(foreach i l (entdel i))
(setq pe (previousEnt))
(foreach i l (entdel i))
pe)
(defun c:tst (/ e p)
(if (setq e (car (entsel)))
(progn
(if (setq p (previousEntFromEnt e))
(redraw p 3)))))
(defun entprev (e / e1 e2)
(setq e1 (entnext))
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
Code: [Select](defun entprev (e / e1 e2)
(setq e1 (entnext))
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
be careful with decreasing hex, sometimes handles in custom generated dxfs are total mess
nice... I tried a similar approach but no luck -- I recall seeing a ent prev function on the old CompuServe forums that was also a simple one... again nice stuff.Code: [Select](defun entprev (e / e1 e2)
(setq e1 (entnext))
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
be careful with decreasing hex, sometimes handles in custom generated dxfs are total mess
I figured why Antonio's code isn't working as it should...Yes previous version do not works with nested entity (my tests was with entsel not with nentsel).
When (entprev (entnext e))
(entnext e) is actually nested entity from entity e, so when supplied this kind of entity, ...
; Version 1.10 - 23/11/2013
(defun ALE_NEntPrevious_110 (EntNam / SelSet EntDat Countr SsLngt EntOut EntNxt PrnEnt)
(if (and (eq (type EntNam) 'ename) (assoc 410 (setq EntDat (entget EntNam))))
(if (= "BLOCK_RECORD" (DXF 0 (entget (setq PrnEnt (DXF 330 EntDat)))))
(if (setq SelSet (ssget "_X"))
(progn
(setq Countr 0 SsLngt (sslength SelSet))
(while (> SsLngt Countr)
(if (eq EntNam (ssname SelSet Countr))
(setq SsLngt 0)
(setq Countr (1+ Countr))
)
)
(setq EntOut (ssname SelSet (1+ Countr)) EntNxt EntOut)
(while (and EntNxt (setq EntNxt (entnext EntNxt)))
(if (eq EntNxt EntNam) (setq EntNxt nil) (setq EntOut EntNxt))
)
)
)
(progn
(setq EntOut PrnEnt)
(while (and PrnEnt (setq PrnEnt (entnext PrnEnt)))
(if (eq PrnEnt EntNam) (setq PrnEnt nil) (setq EntOut PrnEnt))
)
)
)
)
EntOut
)
...
You may agree with me or you may not, but I was trying to make some reasonable conclusion...
M.R.
(defun entprev (e / e1 e2)
(setq e1 (cdr (assoc 360
(entget (cdr (assoc 330 (entget e))))
)
)
)
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
test it with nentsel
little improvement (i hope)I have tested but I had some problems. This is another version with your contribution:Code: [Select](defun entprev (e / e1 e2)
test it with nentsel
(setq e1 (cdr (assoc 360
(entget (cdr (assoc 330 (entget e))))
)
)
)
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
; Version 2.00 - 23/11/2013
(defun ALE_NEntPrevious_2 (EntNam / EntNm2 EntDat SsLngt EntOut PrnEnt)
(if
(and
(assoc 410 (setq EntDat (entget EntNam)))
(= "BLOCK_RECORD" (DXF 0 (entget (setq PrnEnt (DXF 330 EntDat)))))
)
(setq EntOut (entnext))
(setq EntOut PrnEnt)
)
(while (and EntOut (not (eq EntNam (setq EntNm2 (entnext EntOut)))))
(setq EntOut EntNm2)
)
EntOut
)
; Version 3.00 - 2013/11/24
(defun ALE_EntPrevious (EntNam / SelSet EntDat Countr SsLngt EntOut PrnEnt)
(if
(and
(assoc 410 (setq EntDat (entget EntNam)))
(= "BLOCK_RECORD" (DXF 0 (entget (setq PrnEnt (DXF 330 EntDat)))))
)
(progn
(setq SelSet (ssget "_X") Countr 0 SsLngt (sslength SelSet))
(while (> SsLngt Countr)
(if (eq EntNam (ssname SelSet Countr)) (setq SsLngt 0) (setq Countr (1+ Countr)))
)
(setq EntOut (ssname SelSet (1+ Countr)) PrnEnt EntOut)
)
(setq EntOut PrnEnt)
)
(while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
(setq EntOut PrnEnt)
)
EntOut
)
Command: (entnext (entprev (entlast)))
<Entity name: 7ffff5beb30>
Command: (entlast)
<Entity name: 7ffff5bec40>
Command: (entprev (entnext (entlast)))
; error: ActiveX Server returned the error: unknown name: Item
Even more optimized...
Code - Auto/Visual Lisp: [Select]
Stefan, your version isn't good, although another cunning approach...You are right Marko. I didn't test my lisp on 2dpolylines. My mistake.
Here are results :Code: [Select]Command: (entnext (entprev (entlast)))
<Entity name: 7ffff5beb30>
Command: (entlast)
<Entity name: 7ffff5bec40>
Command: (entprev (entnext (entlast)))
; error: ActiveX Server returned the error: unknown name: Item
Even more optimized...
You sure about that...? :?
Your code is retrieving a new selection set (and hence iterating over the entire drawing database) for every iteration of the while loop... :-oQuote from: ribarmCode - Auto/Visual Lisp: [Select]
Stefan, your version isn't good, although another cunning approach...You are right Marko. I didn't test my lisp on 2dpolylines. My mistake.
Here are results :Code: [Select]Command: (entnext (entprev (entlast)))
<Entity name: 7ffff5beb30>
Command: (entlast)
<Entity name: 7ffff5bec40>
Command: (entprev (entnext (entlast)))
; error: ActiveX Server returned the error: unknown name: Item
About the last error, (entnext (entlast)) is always nil, so (entprev nil) ends with an error as it should be. But you are right again, I should catch this error and print a message instead.
It depends where our entity supplied to function is situated...
It depends where our entity supplied to function is situated...
You are missing the point - the code is painfully inefficient regardless of the position of the supplied entity in the drawing database.
Think about how the while loop is being evaluated: the code is retrieving a new selection set of all objects in an entire drawing layout every time the index variable is incremented.
Your code is doing the following:
Iterate over the drawing database to retrieve a selection set of all objects in a drawing layout
Query the entity at index 0
Iterate over the drawing database to retrieve a selection set of all objects in a drawing layout
Query the entity at index 1
Iterate over the drawing database to retrieve a selection set of all objects in a drawing layout
....
No, Stefan (entnext (entlast)) if (entlast) is polyline entity is very next nested entity to parent (entlast)... In my case where (entlast) is polyline (entnext (entlast)) = VERTEX entity...
(defun c:tst (/ ent e efound)
(if (setq e (car (entsel)))
(progn
(setq ent (entnext))
(while (not (eq ent e))
(setq efound ent)
(setq ent (entnext ent)))
(if efound
(redraw efound 3)))))
static void GetEntityPreviousFrom(void)
{
ads_name eName;
ads_point pt;
if (RTNORM != acedEntSel(_T("\nSelect from entity: "), eName, pt)) return;
AcDbObjectId id;
acdbGetObjectId(id, eName);
AcDbObjectPointer<AcDbEntity> pObj(id, AcDb::kForRead);
if (pObj.openStatus() != Acad::eOk) return;
AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForRead);
if (pBTR.openStatus() != Acad::eOk) return;
AcDbBlockTableRecordIterator* pIterator = NULL;
if (pBTR->newIterator(pIterator) != Acad::eOk) return;
AcDbEntity* pEnt = NULL;
if (pIterator->seek(pObj) == Acad::eOk)
{
pIterator->step(false, true);
AcDbObjectId objId;
pIterator->getEntityId(objId);
AcDbObjectPointer<AcDbEntity> pEnt(objId, AcDb::kForRead);
if (pEnt.openStatus() == Acad::eOk) pEnt->highlight();
}
delete pIterator;
}
Awesome idea with the ARX LE! I was wondering if it's possible to directly access the drawing database and simply obtain the previous record. Thanks to you I now know it "is possible".Thank you irneb, and just to try to provide the function that could be used from autolisp (if it is compiled - not tested have not done arx in years now - HTH):
static int ads_entpreviousFrom(void)
{
struct resbuf *rb = acedGetArgs();
if (!rb)
{
acutPrintf(_T("\nError: function requires an ENAME argument. \n"));
return RSERR;
}
AcDbObjectId objId;
if (rb && (rb->restype == RTENAME))
{
if (acdbGetObjectId(objId, rb->resval.rlname) == Acad::eOk)
{
AcDbObjectPointer<AcDbEntity> pObj(objId, AcDb::kForRead);
if (pObj.openStatus() == Acad::eOk)
{
AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForRead);
if (pBTR.openStatus() == Acad::eOk)
{
AcDbBlockTableRecordIterator* pIterator = NULL;
if (pBTR->newIterator(pIterator) == Acad::eOk)
{
AcDbEntity* pEnt = NULL;
if (pIterator->seek(pObj) == Acad::eOk) // if found from ename
{
pIterator->step(false, true); // step back
AcDbObjectId objId;
pIterator->getEntityId(objId);
AcDbObjectPointer<AcDbEntity> pEnt(objId, AcDb::kForRead);
if (pEnt.openStatus() == Acad::eOk)
{
ads_name objName;
if (acdbGetAdsName(objName, objId) == Acad::eOk)
{
acedRetName(objName, RTENAME); // return the previous entity
}
}
}
delete pIterator;
}
}
}
}
}
return (RSRSLT);
}
Usage: (entpreviousFrom <ename>)
Return: Previous entity or nil
Louis.Awesome idea with the ARX LE! I was wondering if it's possible to directly access the drawing database and simply obtain the previous record. Thanks to you I now know it "is possible".Thank you irneb, and just to try to provide the function that could be used from autolisp (if it is compiled - not tested have not done arx in years now - HTH):Code: [Select]static int ads_entpreviousFrom(void)
{
struct resbuf *rb = acedGetArgs();
if (!rb)
{
acutPrintf(_T("\nError: function requires an ENAME argument. \n"));
return RSERR;
}
AcDbObjectId objId;
if (rb && (rb->restype == RTENAME))
{
if (acdbGetObjectId(objId, rb->resval.rlname) == Acad::eOk)
{
AcDbObjectPointer<AcDbEntity> pObj(objId, AcDb::kForRead);
if (pObj.openStatus() == Acad::eOk)
{
AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForRead);
if (pBTR.openStatus() == Acad::eOk)
{
AcDbBlockTableRecordIterator* pIterator = NULL;
if (pBTR->newIterator(pIterator) == Acad::eOk)
{
AcDbEntity* pEnt = NULL;
if (pIterator->seek(pObj) == Acad::eOk) // if found from ename
{
pIterator->step(false, true); // step back
AcDbObjectId objId;
pIterator->getEntityId(objId);
AcDbObjectPointer<AcDbEntity> pEnt(objId, AcDb::kForRead);
if (pEnt.openStatus() == Acad::eOk)
{
ads_name objName;
if (acdbGetAdsName(objName, objId) == Acad::eOk)
{
acedRetName(objName, RTENAME); // return the previous entity
}
}
}
delete pIterator;
}
}
}
}
}
return (RSRSLT);
}QuoteUsage: (entpreviousFrom <ename>)
Return: Previous entity or nil
edit: removed the first delete pIterator; line - not required there, and added the latest compiled arx file, including entPreviousFrom [/b] function for autoLisp.
...Here is my test drawing, with your function if I "nentsel" the yellow ellipse in the magenta rectangle I get the cyan ellipse
Also Marco, if you have a test drawing, that I can use to run my tests.
...
Here is my test drawing, with your function if I "nentsel" the yellow ellipse in the magenta rectangle I get the cyan ellipseHi Marco,
but the entprev entity is a vertex of the yellow ellipse.
BTW: I tried my function with Bricscad 13 and I get strange behavior...
Ciao.
AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForRead);
With:AcDbBlockTableRecordPointer pBTR(pObj->ownerId(), AcDb::kForRead);
Command: (setq entp (ALE_NENTPREVIOUS e))
nil
acutPrintf(_T("\nThe sub entity is of type %s"), pObj->isA()->name());
if (pObj->isKindOf(AcDb2dVertex::desc()))
{
AcDbObjectPointer<AcDb2dPolyline> pPline(pObj->ownerId(), AcDb::kForRead);
if (pPline.openStatus() == Acad::eOk)
{
AcDbObjectIterator* pVertIterator = pPline->vertexIterator();
pVertIterator->setPosition(pObj);
pVertIterator->start(true);
pVertIterator->step(true);
AcDbObjectPointer<AcDb2dVertex> pVertex(pVertIterator->objectId(), AcDb::kForRead);
if (pVertex.openStatus() == Acad::eOk)
{
acutPrintf(_T("\nNested previous vertex [%s] of color [%ld] found... \n"), pVertex->isA()->name(), pVertex->colorIndex()); // debug...
}
delete pVertIterator;
}
}
...Try this:
I tried your function: ALE_NENTPREVIOUS and returns nil
; Version 3.01 - 2013/11/26
(defun ALE_EntPrevious (EntNam / SelSet EntDat Countr SsLngt EntOut PrnEnt PrnDat TrueFl)
(if
(and
(setq EntDat (entget EntNam))
(setq TrueFl (= "BLOCK_RECORD" (DXF 0 (setq PrnDat (entget (setq PrnEnt (DXF 330 EntDat)))))))
(assoc 410 EntDat)
)
(progn
(setq SelSet (ssget "_X") Countr 0 SsLngt (sslength SelSet))
(while (> SsLngt Countr)
(if (eq EntNam (ssname SelSet Countr)) (setq SsLngt 0) (setq Countr (1+ Countr)))
)
(setq EntOut (ssname SelSet (1+ Countr)) PrnEnt EntOut)
)
(if TrueFl (setq EntOut (DXF 360 PrnDat)) (setq EntOut PrnEnt))
)
(while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
(setq EntOut PrnEnt)
)
EntOut
)
(defun entprev (e / e1 e2)
(setq e1 (entget (cdr (assoc 330 (entget e))))
e1 (cdr (cond ((assoc 360 (reverse e1)))
((assoc -1 e1))
)
)
)
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
...Try to bench with my sample DWG, I think it is faster because you do not need
Marc'Antonio, why do you use (ssget "_X")?
static int ads_entpreviousFrom(void)
{
struct resbuf *rb = acedGetArgs();
if (!rb)
{
acutPrintf(_T("\nError: function requires an ENAME argument. \n"));
return RSERR;
}
AcDbObjectId objId;
ads_name objName;
if (rb && (rb->restype == RTENAME))
{
if (acdbGetObjectId(objId, rb->resval.rlname) == Acad::eOk)
{
AcDbObjectPointer<AcDbEntity> pObj(objId, AcDb::kForRead);
if (pObj.openStatus() == Acad::eOk)
{
if (pObj->isKindOf(AcDb2dVertex::desc()))
{
AcDbObjectPointer<AcDb2dPolyline> pPline(pObj->ownerId(), AcDb::kForRead);
if (pPline.openStatus() == Acad::eOk)
{
AcDbObjectIterator* pVertIterator = pPline->vertexIterator();
pVertIterator->setPosition(pObj);
pVertIterator->start(true);
pVertIterator->step(true);
AcDbObjectPointer<AcDb2dVertex> pVertex(pVertIterator->objectId(), AcDb::kForRead);
if (pVertex.openStatus() == Acad::eOk)
{
if (acdbGetAdsName(objName, objId) == Acad::eOk)
{
acedRetName(objName, RTENAME); // return the previous entity
}
}
delete pVertIterator;
}
}
else
{
AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForRead); //pObj->ownerId()
if (pBTR.openStatus() == Acad::eOk)
{
AcDbBlockTableRecordIterator* pIterator = NULL;
if (pBTR->newIterator(pIterator) == Acad::eOk)
{
AcDbEntity* pEnt = NULL;
if (pIterator->seek(pObj) == Acad::eOk) // if found from ename
{
pIterator->step(false, true); // step back
AcDbObjectId objId;
pIterator->getEntityId(objId);
AcDbObjectPointer<AcDbEntity> pEnt(objId, AcDb::kForRead);
if (pEnt.openStatus() == Acad::eOk)
{
if (acdbGetAdsName(objName, objId) == Acad::eOk)
{
acedRetName(objName, RTENAME); // return the previous entity
}
}
}
delete pIterator;
}
}
}
}
}
}
return (RSRSLT);
}
but entnext doesn't step into nested objects...Try to bench with my sample DWG, I think it is faster because you do not need
Marc'Antonio, why do you use (ssget "_X")?
to pass all nested entities.
but entnext doesn't step into nested objects
@Lee: Yes, thanks for your clarification.but entnext doesn't step into nested objects
By 'nested', I think Marc is referring to Attributes & Vertices in this case.
now i see, thanks. but in this case (entnext (entprev e)) will not be equal to ebut entnext doesn't step into nested objects
By 'nested', I think Marc is referring to Attributes & Vertices in this case.
@VovKa: the last version do not work on "normal" entities...yep, thank you
...(ssget "_X") make a selection of all entities in all layout:
now i see, thanks. but in this case (entnext (entprev e)) will not be equal to e
and more (ssget "_X") will iterate through all entities on all layouts
Command: (setq kkkk (ssget "_X"))
<Selection set: b2>
(sslength kkkk)
Marco.-OK Louis, I'm sorry I did not realize... read below...
The entPreviousFrom it is an autolisp function and accepts one argument - what do you mean by that accept argument?.
Where: <ename> normal or nested
Usage: (entPreviousFrom <ename>)
Benchmark.lsp | © 2005 Michael Puckett | All Rights Reserved
>>> from "nested" entity
Elapsed milliseconds / relative speed for 16384 iteration(s):
(ALE_ENTPREVIOUS KKKK).....1451 / 1.27 <fastest>
(entpreviousfrom KKKK).....1841 / 1 <slowest>
>>> from "nested" entity
Elapsed milliseconds / relative speed for 16384 iteration(s):
(entpreviousfrom KKKK).....2418 / 1.18 <fastest>
(ALE_ENTPREVIOUS KKKK).....2855 / 1 <slowest>
>>> from "nested" entity
Elapsed milliseconds / relative speed for 16384 iteration(s):
(entpreviousfrom KKKK).....1077 / 1.26 <fastest>
(ALE_ENTPREVIOUS KKKK).....1357 / 1 <slowest>
>>> from "normal" entity
Elapsed milliseconds / relative speed for 16384 iteration(s):
(entpreviousfrom KKKK).......1794 / 64.37 <fastest>
(ALE_ENTPREVIOUS KKKK).....115487 / 1 <slowest>
But from "normal" entity I get wrong results
(defun c:TestL ( / EntRef EntPrv)
(setq EntRef (car (nentsel)))
(princ "\nEntRef ") (princ EntRef)
(princ "\nentPreviousFrom") (princ (entnext (setq EntPrv (entPreviousFrom EntRef))))
(princ "\nALE_EntPrevious") (princ (entnext (setq EntPrv (ALE_EntPrevious EntRef))))
(princ "\n")
(textpage)(princ)
)
Select object:
EntRef <Entity name: 7ffffb40240>
entPreviousFrom<Entity name: 7ffffb401f0>
ALE_EntPrevious<Entity name: 7ffffb40240>
Command: TESTL
Select object:
EntRef <Entity name: 7ffffb06c00>
entPreviousFrom<Entity name: 7ffffb06c00>
ALE_EntPrevious<Entity name: 7ffffb06c00>
Command: TESTL
Select object:
EntRef <Entity name: 7ffffb06bf0>
entPreviousFrom<Entity name: 7ffffb06ae0>
ALE_EntPrevious<Entity name: 7ffffb06bf0>
Command: (sslength kkkk)Command: (setq kkkk (ssget "_X"))
<Selection set: b2>Code: [Select](sslength kkkk)
Command: (sslength kkkk)(ssget "_X") returns entities in the following order:
2396
so if are looking for an entity that is in the model space you will iterate through all layout entities firstI think we might be talking in circles. The OP was about a function which operates in reverse from what entnext does.
Try my new test DWG and put a counter inside your function:Command: (sslength kkkk)(ssget "_X") returns entities in the following order:
2396
EntitiesOnLayout1+EntitiesOnLayout2...+...EntitiesOnLayoutN+EntitiesInModelSpace
so if are looking for an entity that is in the model space you will iterate through all layout entities first
; Version 3.02_Test - 2013/11/27 - no DXF function
(defun ALE_EntPrevious_Test (EntNam / SelSet EntDat Countr SsLngt EntOut PrnEnt PrnDat TrueFl)
(setq Countr 0);test
(if
(and
(setq EntDat (entget EntNam))
(setq TrueFl
(=
"BLOCK_RECORD"
(cdr (assoc 0 (setq PrnDat (entget (setq PrnEnt (cdr (assoc 330 EntDat)))))))
)
)
(assoc 410 EntDat)
)
(progn
(setq SelSet (ssget "_X") Countr 0 SsLngt (sslength SelSet))
(while (> SsLngt Countr)
(if (eq EntNam (ssname SelSet Countr)) (setq SsLngt 0) (setq Countr (1+ Countr)))
)
(setq EntOut (ssname SelSet (1+ Countr)) PrnEnt EntOut)
)
(setq EntOut (if TrueFl (cdr (assoc 360 PrnDat)) PrnEnt))
)
(while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
(setq EntOut PrnEnt Countr (1+ Countr));test
; (setq EntOut PrnEnt)
)
(list EntOut Countr);test
; EntOut
)
(defun c:Test ( / EntRef EntPrv)
(setq EntRef (car (nentsel)))
(princ "\nEntRef ") (princ EntRef)
(princ "\nALE_EntPrevious_Test") (princ (entnext (car (setq EntPrv (ALE_EntPrevious_Test EntRef)))))
(princ " ")(princ (cadr EntPrv))
(princ "\nVK_entprev1 ") (princ (entnext (car (setq EntPrv (VK_entprev1 EntRef)))))
(princ " ")(princ (cadr EntPrv))
(textpage)(princ)
)
Select the red line on magenta rectangle, is the (entlast) in model space,
results:
Selezionare oggetto:
EntRef <Nome entità: 7ffffb61930>
ALE_EntPrevious_Test<Nome entità: 7ffffb61930> 2814
VK_entprev1 <Nome entità: 7ffffb61930> 12515
I think we might be talking in circles. The OP was about a function which operates in reverse from what entnext does.Do you think that there is, at this time, a function that meets these three points?
So:
- If supplied argument = nil (unfortunately ALisp doesn't allow for optional arguments in defuns), then get entlast (instead of the 1st entity in the DWG)
- If supplied argument is an ename of an enetity contained either in the Model Space or any Paper Space then get the previous entity
- That could be a joined entity like an attribute, not to be confused with nested entities like lines inside blocks.
- Note entnext runs along all entities in MS/PS1/PS2 ... PSn as if they're all contained in one group (not each separately).
- If the argument is an entity nested inside a complex entity like a block definition, then get the previous entity inside that block - stop at the block record itself.
Hi Marco,Grazie a te, spero di ritrovarti ancora.
Thank you a lot for taking the time to run the tests and doing the benchmarking.... for me I guess it is all about my contribution on this thread, was fun but I do not use autolisp nor I work with objectarx anymore or even use AutoCAD nowadays. My sample code is there open, so anyone can use it and update it and make it better!!!.
Have fun!
:)
Select the red line on magenta rectangle, is the (entlast) in model space,ssget generates selections set in a reversed order i.e. entlast is the first element. and still your function is iterating 2814 times. why? because it searches though all layouts.
results:
ssget generates selections set in a reversed order i.e. entlast is the first element. and still your function is iterating 2814 times. why? because it searches though all layouts.> entlast is the first element
entnext starts from the beginning and steps through all vertexes but doesn't go into layouts.I think entnext steps through all entities (DWG with only 3 entities):
(defun VK_entprev1 (e / e1 e2 Countr)
(setq Countr 0)
(setq e1 (entnext))
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2 Countr (1+ Countr))
(princ "\n ") (princ (entget e2) )
)
(list e1 Countr)
)
>
((-1 . <Nome entità: 7ffffb60d60>) (0 . VERTEX) (330 . <Nome entità: 7ffffb60d50>) (5 . AE8E) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (62 . 2) (100 . AcDbVertex) (100 . AcDb2dVertex) (10 1887.13 222.152 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0465439) (91 . 0) (70 . 0) (50 . 0.0))
((-1 . <Nome entità: 7ffffb60d70>) (0 . VERTEX) (330 . <Nome entità: 7ffffb60d50>) (5 . AE8F) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (62 . 2) (100 . AcDbVertex) (100 . AcDb2dVertex) (10 1829.33 165.574 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0601886) (91 . 0) (70 . 0) (50 . 0.0))
...
((-1 . <Nome entità: 7ffffb60e50>) (0 . VERTEX) (330 . <Nome entità: 7ffffb60d50>) (5 . AE9D) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (62 . 2) (100 . AcDbVertex) (100 . AcDb2dVertex) (10 1954.41 267.061 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0465439) (91 . 0) (70 . 0) (50 . 4.25351))
((-1 . <Nome entità: 7ffffb60e60>) (0 . SEQEND) (330 . <Nome entità: 7ffffb60d50>) (5 . AE9E) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (62 . 2) (-2 . <Nome entità: 7ffffb60d50>))
((-1 . <Nome entità: 7ffffb44a40>) (0 . VIEWPORT) (330 . <Nome entità: 7ffffb44a20>) (5 . 94D4) (100 . AcDbEntity) (67 . 1) (410 . L2) (8 . 0) (100 . AcDbViewport) (10 975.889 259.916 0.0) (40 . 396.146) (41 . 286.588) (68 . 1) (69 . 1) (12 975.889 259.916 0.0) (13 0.0 0.0 0.0) (14 10.0 10.0 0.0) (15 10.0 10.0 0.0) (16 0.0 0.0 1.0) (17 0.0 0.0 0.0) (42 . 50.0) (43 . 0.0) (44 . 0.0) (45 . 286.588) (50 . 0.0) (51 . 0.0) (72 . 100) (90 . 819232) (281 . 0) (71 . 1) (74 . 0) (110 0.0 0.0 0.0) (111 1.0 0.0 0.0) (112 0.0 1.0 0.0) (79 . 0) (146 . 0.0) (170 . 0) (61 . 5) (348 . <Nome entità: 7ffffb06170>) (292 . 1) (282 . 1) (141 . 0.0) (142 . 0.0) (63 . 250) (421 . 3355443))
((-1 . <Nome entità: 7ffffbf7cc0>) (0 . CIRCLE) (330 . <Nome entità: 7ffffb44a20>) (5 . B08C) (100 . AcDbEntity) (67 . 1) (410 . L2) (8 . 0) (100 . AcDbCircle) (10 891.453 209.204 0.0) (40 . 33.0551) (210 0.0 0.0 1.0))
benchmark both function with (entnext (entnext)) as an argumentWhy?
I do not think so:it's a well known fact
I do not think so:it's a well known fact
if you want to test (ssget "_X")
create an empty drawing
draw a line
draw a circle
switch to Layout1
draw a polyline
draw a point
switch to Layout2
draw an arc
draw a text
then inspect (ssname "_X") in vlide
you will see that you line is the last element because http://www.theswamp.org/index.php?topic=45732.msg508993#msg508993 (http://www.theswamp.org/index.php?topic=45732.msg508993#msg508993)
Comando: (entget (entlast))
((-1 . <Nome entità: 7ffffbfb1a0>) (0 . "TEXT") (330 . <Nome entità: 7ffffbfb060>) (5 . "19C2") (100 . "AcDbEntity") (67 . 1) (410 . "Layout2") (8 . "$XP_COM_NORM") (100 . "AcDbText") (10 10.0 10.0 0.0) (40 . 2.0) (1 . "123") (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . "$STD_ISO") (71 . 0) (72 . 0) (11 0.0 0.0 0.0) (210 0.0 0.0 1.0) (100 . "AcDbText") (73 . 0))
Comando: <Passaggio a: Layout1>
Comando: (entget (entlast))
((-1 . <Nome entità: 7ffffbfb050>) (0 . "POINT") (330 . <Nome entità: 7ffffbfe8d0>) (5 . "19AD") (100 . "AcDbEntity") (67 . 1) (410 . "Layout1") (8 . "$XP_COM_NORM") (100 . "AcDbPoint") (10 0.0 0.0 0.0) (210 0.0 0.0 1.0) (50 . 0.0))
Comando: <Passaggio a: Layout2>
Comando: (entget (entlast))
((-1 . <Nome entità: 7ffffbfb1a0>) (0 . "TEXT") (330 . <Nome entità: 7ffffbfb060>) (5 . "19C2") (100 . "AcDbEntity") (67 . 1) (410 . "Layout2") (8 . "$XP_COM_NORM") (100 . "AcDbText") (10 10.0 10.0 0.0) (40 . 2.0) (1 . "123") (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . "$STD_ISO") (71 . 0) (72 . 0) (11 0.0 0.0 0.0) (210 0.0 0.0 1.0) (100 . "AcDbText") (73 . 0))
From MSpace:
Comando: _line
Specificare primo punto: 20,20
Specificare punto successivo o [Annulla]: 30,30
Specificare punto successivo o [Annulla]:
Comando: (entget (entlast))
((-1 . <Nome entità: 7ffffbfbb90>) (0 . "LINE") (330 . <Nome entità: 7ffffbfe820>) (5 . "1A59") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "$COM_NORM") (100 . "AcDbLine") (10 20.0 20.0 0.0) (11 30.0 30.0 0.0) (210 0.0 0.0 1.0))
Comando: <Passaggio a: Layout1>
Comando: (entget (entlast))
((-1 . <Nome entità: 7ffffbfb050>) (0 . "POINT") (330 . <Nome entità: 7ffffbfe8d0>) (5 . "19AD") (100 . "AcDbEntity") (67 . 1) (410 . "Layout1") (8 . "$XP_COM_NORM") (100 . "AcDbPoint") (10 0.0 0.0 0.0) (210 0.0 0.0 1.0) (50 . 0.0))
Comando: <Passaggio a: Layout2>
Comando: (entget (entlast))
((-1 . <Nome entità: 7ffffbfb1a0>) (0 . "TEXT") (330 . <Nome entità: 7ffffbfb060>) (5 . "19C2") (100 . "AcDbEntity") (67 . 1) (410 . "Layout2") (8 . "$XP_COM_NORM") (100 . "AcDbText") (10 10.0 10.0 0.0) (40 . 2.0) (1 . "123") (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . "$STD_ISO") (71 . 0) (72 . 0) (11 0.0 0.0 0.0) (210 0.0 0.0 1.0) (100 . "AcDbText") (73 . 0))
(entlast) > the result may change going from one Layout to another LayoutGrazie Marco, so che sarà difficile non partecipare...Hi Marco,Grazie a te, spero di ritrovarti ancora.
Thank you a lot for taking the time to run the tests and doing the benchmarking.... for me I guess it is all about my contribution on this thread, was fun but I do not use autolisp nor I work with objectarx anymore or even use AutoCAD nowadays. My sample code is there open, so anyone can use it and update it and make it better!!!.
Have fun!
:)
Gracias a ti, espero encontrarte de nuevo. :kewl:
Sorry new to this thread, but I would naturally assume ssget would select items in the same order as the draw order in ACAD essentially by their order in the DB. So not only would it be dependent on when they where created but also edited or modified,OK
you could also manipulate the order with the "draw order" command.
(defun C:PrintSS ( / Countr SelSet)
(setq SelSet (ssget "_X") Countr 0)
(repeat (sslength SelSet)
(princ "\n ") (princ (entget (ssname SelSet Countr)))
(setq Countr (1+ Countr))
)
(princ)
)
Comando: PRINTSS
((-1 . <Nome entità: 7ffffbfb050>) (0 . POINT) (330 . <Nome entità: 7ffffbfe8d0>) (5 . 19AD) (100 . AcDbEntity) (67 . 1) (410 . Layout1) (8 . $XP_COM_NORM) (100 . AcDbPoint) (10 0.0 0.0 0.0) (210 0.0 0.0 1.0) (50 . 0.0))
((-1 . <Nome entità: 7ffffbfb000>) (0 . POLYLINE) (330 . <Nome entità: 7ffffbfe8d0>) (5 . 19A8) (100 . AcDbEntity) (67 . 1) (410 . Layout1) (8 . $XP_COM_NORM) (100 . AcDb2dPolyline) (66 . 1) (10 0.0 0.0 0.0) (70 . 0) (40 . 0.0) (41 . 0.0) (210 0.0 0.0 1.0) (71 . 0) (72 . 0) (73 . 0) (74 . 0) (75 . 0))
((-1 . <Nome entità: 7ffffbfe8e0>) (0 . VIEWPORT) (330 . <Nome entità: 7ffffbfe8d0>) (5 . E) (100 . AcDbEntity) (67 . 1) (410 . Layout1) (8 . 0) (100 . AcDbViewport) (10 128.5 97.5 0.0) (40 . 958.196) (41 . 693.198) (68 . 1) (69 . 1) (12 128.5 97.5 0.0) (13 0.0 0.0 0.0) (14 10.0 10.0 0.0) (15 10.0 10.0 0.0) (16 0.0 0.0 1.0) (17 0.0 0.0 0.0) (42 . 50.0) (43 . 0.0) (44 . 0.0) (45 . 693.198) (50 . 0.0) (51 . 0.0) (72 . 100) (90 . 819232) (281 . 0) (71 . 1) (74 . 0) (110 0.0 0.0 0.0) (111 1.0 0.0 0.0) (112 0.0 1.0 0.0) (79 . 0) (146 . 0.0) (170 . 0) (61 . 5) (348 . <Nome entità: 7ffffbbc1f0>) (292 . 1) (282 . 1) (141 . 0.0) (142 . 0.0) (63 . 250) (421 . 3355443))
((-1 . <Nome entità: 7ffffbfb1a0>) (0 . TEXT) (330 . <Nome entità: 7ffffbfb060>) (5 . 19C2) (100 . AcDbEntity) (67 . 1) (410 . Layout2) (8 . $XP_COM_NORM) (100 . AcDbText) (10 10.0 10.0 0.0) (40 . 2.0) (1 . 123) (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . $STD_ISO) (71 . 0) (72 . 0) (11 0.0 0.0 0.0) (210 0.0 0.0 1.0) (100 . AcDbText) (73 . 0))
((-1 . <Nome entità: 7ffffbfb170>) (0 . ARC) (330 . <Nome entità: 7ffffbfb060>) (5 . 19BF) (100 . AcDbEntity) (67 . 1) (410 . Layout2) (8 . $XP_COM_NORM) (100 . AcDbCircle) (10 20.0 20.0 0.0) (40 . 14.1421) (210 0.0 0.0 1.0) (100 . AcDbArc) (50 . 3.92699) (51 . 4.45059))
((-1 . <Nome entità: 7ffffbfb140>) (0 . VIEWPORT) (5 . 19BC) (102 . {ACAD_XDICTIONARY) (360 . <Nome entità: 7ffffbfb150>) (102 . }) (330 . <Nome entità: 7ffffbfb060>) (100 . AcDbEntity) (67 . 1) (410 . Layout2) (8 . 0) (100 . AcDbViewport) (10 31.6168 40.5766 0.0) (40 . 96.4091) (41 . 69.7462) (68 . 1) (69 . 1) (12 31.6168 40.5766 0.0) (13 0.0 0.0 0.0) (14 10.0 10.0 0.0) (15 10.0 10.0 0.0) (16 0.0 0.0 1.0) (17 0.0 0.0 0.0) (42 . 50.0) (43 . 0.0) (44 . 0.0) (45 . 69.7462) (50 . 0.0) (51 . 0.0) (72 . 100) (90 . 819232) (281 . 0) (71 . 1) (74 . 0) (110 0.0 0.0 0.0) (111 1.0 0.0 0.0) (112 0.0 1.0 0.0) (79 . 0) (146 . 0.0) (170 . 0) (61 . 5) (348 . <Nome entità: 7ffffbbc1f0>) (292 . 1) (282 . 1) (141 . 0.0) (142 . 0.0) (63 . 250) (421 . 3355443))
((-1 . <Nome entità: 7ffffb05020>) (0 . LINE) (330 . <Nome entità: 7ffffbfe820>) (5 . 1A9A) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (100 . AcDbLine) (10 1.0 1.0 0.0) (11 5.0 5.0 0.0) (210 0.0 0.0 1.0))
((-1 . <Nome entità: 7ffffbbced0>) (0 . CIRCLE) (330 . <Nome entità: 7ffffbfe820>) (5 . 199D) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (100 . AcDbCircle) (10 10.0 10.0 0.0) (40 . 10.0) (210 0.0 0.0 1.0))
((-1 . <Nome entità: 7ffffbbcec0>) (0 . LINE) (330 . <Nome entità: 7ffffbfe820>) (5 . 199C) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (100 . AcDbLine) (10 0.0 0.0 0.0) (11 10.0 10.0 0.0) (210 0.0 0.0 1.0))
Comando: AI_DRAWORDER ... bla ... bla ...
Comando: PRINTSS
((-1 . <Nome entità: 7ffffbfb050>) (0 . POINT) (330 . <Nome entità: 7ffffbfe8d0>) (5 . 19AD) (100 . AcDbEntity) (67 . 1) (410 . Layout1) (8 . $XP_COM_NORM) (100 . AcDbPoint) (10 0.0 0.0 0.0) (210 0.0 0.0 1.0) (50 . 0.0))
((-1 . <Nome entità: 7ffffbfb000>) (0 . POLYLINE) (330 . <Nome entità: 7ffffbfe8d0>) (5 . 19A8) (100 . AcDbEntity) (67 . 1) (410 . Layout1) (8 . $XP_COM_NORM) (100 . AcDb2dPolyline) (66 . 1) (10 0.0 0.0 0.0) (70 . 0) (40 . 0.0) (41 . 0.0) (210 0.0 0.0 1.0) (71 . 0) (72 . 0) (73 . 0) (74 . 0) (75 . 0))
((-1 . <Nome entità: 7ffffbfe8e0>) (0 . VIEWPORT) (330 . <Nome entità: 7ffffbfe8d0>) (5 . E) (100 . AcDbEntity) (67 . 1) (410 . Layout1) (8 . 0) (100 . AcDbViewport) (10 128.5 97.5 0.0) (40 . 958.196) (41 . 693.198) (68 . 1) (69 . 1) (12 128.5 97.5 0.0) (13 0.0 0.0 0.0) (14 10.0 10.0 0.0) (15 10.0 10.0 0.0) (16 0.0 0.0 1.0) (17 0.0 0.0 0.0) (42 . 50.0) (43 . 0.0) (44 . 0.0) (45 . 693.198) (50 . 0.0) (51 . 0.0) (72 . 100) (90 . 819232) (281 . 0) (71 . 1) (74 . 0) (110 0.0 0.0 0.0) (111 1.0 0.0 0.0) (112 0.0 1.0 0.0) (79 . 0) (146 . 0.0) (170 . 0) (61 . 5) (348 . <Nome entità: 7ffffbbc1f0>) (292 . 1) (282 . 1) (141 . 0.0) (142 . 0.0) (63 . 250) (421 . 3355443))
((-1 . <Nome entità: 7ffffbfb1a0>) (0 . TEXT) (330 . <Nome entità: 7ffffbfb060>) (5 . 19C2) (100 . AcDbEntity) (67 . 1) (410 . Layout2) (8 . $XP_COM_NORM) (100 . AcDbText) (10 10.0 10.0 0.0) (40 . 2.0) (1 . 123) (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . $STD_ISO) (71 . 0) (72 . 0) (11 0.0 0.0 0.0) (210 0.0 0.0 1.0) (100 . AcDbText) (73 . 0))
((-1 . <Nome entità: 7ffffbfb170>) (0 . ARC) (330 . <Nome entità: 7ffffbfb060>) (5 . 19BF) (100 . AcDbEntity) (67 . 1) (410 . Layout2) (8 . $XP_COM_NORM) (100 . AcDbCircle) (10 20.0 20.0 0.0) (40 . 14.1421) (210 0.0 0.0 1.0) (100 . AcDbArc) (50 . 3.92699) (51 . 4.45059))
((-1 . <Nome entità: 7ffffbfb140>) (0 . VIEWPORT) (5 . 19BC) (102 . {ACAD_XDICTIONARY) (360 . <Nome entità: 7ffffbfb150>) (102 . }) (330 . <Nome entità: 7ffffbfb060>) (100 . AcDbEntity) (67 . 1) (410 . Layout2) (8 . 0) (100 . AcDbViewport) (10 31.6168 40.5766 0.0) (40 . 96.4091) (41 . 69.7462) (68 . 1) (69 . 1) (12 31.6168 40.5766 0.0) (13 0.0 0.0 0.0) (14 10.0 10.0 0.0) (15 10.0 10.0 0.0) (16 0.0 0.0 1.0) (17 0.0 0.0 0.0) (42 . 50.0) (43 . 0.0) (44 . 0.0) (45 . 69.7462) (50 . 0.0) (51 . 0.0) (72 . 100) (90 . 819232) (281 . 0) (71 . 1) (74 . 0) (110 0.0 0.0 0.0) (111 1.0 0.0 0.0) (112 0.0 1.0 0.0) (79 . 0) (146 . 0.0) (170 . 0) (61 . 5) (348 . <Nome entità: 7ffffbbc1f0>) (292 . 1) (282 . 1) (141 . 0.0) (142 . 0.0) (63 . 250) (421 . 3355443))
((-1 . <Nome entità: 7ffffb05020>) (0 . LINE) (330 . <Nome entità: 7ffffbfe820>) (5 . 1A9A) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (100 . AcDbLine) (10 1.0 1.0 0.0) (11 5.0 5.0 0.0) (210 0.0 0.0 1.0))
((-1 . <Nome entità: 7ffffbbced0>) (0 . CIRCLE) (330 . <Nome entità: 7ffffbfe820>) (5 . 199D) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (100 . AcDbCircle) (10 10.0 10.0 0.0) (40 . 10.0) (210 0.0 0.0 1.0))
((-1 . <Nome entità: 7ffffbbcec0>) (0 . LINE) (330 . <Nome entità: 7ffffbfe820>) (5 . 199C) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . $COM_NORM) (100 . AcDbLine) (10 0.0 0.0 0.0) (11 10.0 10.0 0.0) (210 0.0 0.0 1.0))
Command: (setq en (entnext))
<Entity name: 7ffffb95cc0>
Command: (while en (setq ed (entget en) en (entnext en)) (print (strcat (cdr (assoc 0 ed)) " on " (cdr (assoc 410 ed)))))
"CIRCLE on Model"
"LINE on Model"
"VIEWPORT on Layout1"
"MTEXT on Layout1"
"ARC on Model" "ARC on Model"
Command: (setq ed (entget (entlast)))
((-1 . <Entity name: 7ffffb961d0>) (0 . "ARC") (330 . <Entity name: 7ffffb929f0>) (5 . "28D") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbCircle") (10 4054.01 380.296 0.0) (40 . 1618.93) (210 0.0 0.0 1.0) (100 . "AcDbArc") (50 . 1.09233) (51 . 3.0848))
Then swap to a Layout tab and try againCommand: CTAB
Enter new value for CTAB <"Model">: Layout1
Restoring cached viewports - Regenerating layout.
Command: (setq en (entnext))
<Entity name: 7ffffb95cc0>
Command: (while en (setq ed (entget en) en (entnext en)) (print (strcat (cdr (assoc 0 ed)) " on " (cdr (assoc 410 ed)))))
"CIRCLE on Model"
"LINE on Model"
"VIEWPORT on Layout1"
"MTEXT on Layout1"
"ARC on Model" "ARC on Model"
Command: (setq ed (entget (entlast)))
((-1 . <Entity name: 7ffffb961d0>) (0 . "ARC") (330 . <Entity name: 7ffffb929f0>) (5 . "28D") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbCircle") (10 4054.01 380.296 0.0) (40 . 1618.93) (210 0.0 0.0 1.0) (100 . "AcDbArc") (50 . 1.09233) (51 . 3.0848))
Exact same result.
(entlast) > the result may change going from one Layout to another Layoutthat's an old bug
...
"CIRCLE on Model"
"LINE on Model"
"VIEWPORT on Layout1"
"MTEXT on Layout1"
"ARC on Model" "ARC on Model"
...
Comando: (setq en (entnext))
<Nome entità: 7ffffbca340>
Comando: (while en (setq ed (entget en) en (entnext en)) (print (strcat (cdr (assoc 0 ed)) " on " (cdr (assoc 410 ed)))))
"CIRCLE on Model"
"LINE on Model"
"VIEWPORT on Layout2"
"TEXT on Layout2"
"ARC on Model" "ARC on Model"
Comando: (setq ed (entget (entlast)))
((-1 . <Nome entità: 7ffffbca700>) (0 . "ARC") (330 . <Nome entità: 7ffffbaff10>) (5 . "E8") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbCircle") (10 577.904 218.872 0.0) (40 . 60.8391) (210 0.0 0.0 1.0) (100 . "AcDbArc") (50 . 1.47854) (51 . 2.12479))
Comando: CTAB
Digitare nuovo valore per CTAB <"Model">: Layout1
Ripristino finestre memorizzate nella cache in corso - Rigenerazione layout in corso.
Comando: (setq en (entnext))
<Nome entità: 7ffffbca340>
Comando: (while en (setq ed (entget en) en (entnext en)) (print (strcat (cdr (assoc 0 ed)) " on " (cdr (assoc 410 ed)))))
"CIRCLE on Model"
"LINE on Model"
"ARC on Model"
"VIEWPORT on Layout1"
"TEXT on Layout1" "TEXT on Layout1"
Comando: (setq ed (entget (entlast)))
((-1 . <Nome entità: 7ffffbca550>) (0 . "TEXT") (330 . <Nome entità: 7ffffbafed0>) (5 . "CD") (100 . "AcDbEntity") (67 . 1) (410 . "Layout1") (8 . "0") (100 . "AcDbText") (10 -203.743 43.1176 0.0) (40 . 23.0115) (1 . "123") (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . "Standard") (71 . 0) (72 . 0) (11 0.0 0.0 0.0) (210 0.0 0.0 1.0) (100 . "AcDbText") (73 . 0))
this is mine(entlast) > the result may change going from one Layout to another Layoutthat's an old bug
and i think it's somehow bugged because of this:
(http://i.piccy.info/i9/054ab6be2420d9f093ea985ab67733e2/1385563511/8062/407886/Clipboard_1_240.jpg) (http://piccy.info/view3/5504546/45bca6fbd10c3cf8c339f44c24ac1d33/)(http://i.piccy.info/a3/2013-11-27-14-45/i9-5504546/240x171-r/i.gif) (http://i.piccy.info/a3c/2013-11-27-14-45/i9-5504546/240x171-r)
...Remember that the code in VovKa-MR-entprev do not work if you select
So, please when benchmarking, take this code in consideration among others that are correct (I don't know much ab. arx and other languages)...
OP, M.R.
...Remember that the code in VovKa-MR-entprev do not work if you select
So, please when benchmarking, take this code in consideration among others that are correct (I don't know much ab. arx and other languages)...
OP, M.R.
a block (not the attribs).
Marc'Antonio, can you elaborate that... If I pick normal block in DWG made of normal blocks, it returns previous block of picked one... If I pick attributed block in DWG made of attributed blocks, it returns SEQUEND entity, and that is exactly previous entity of picked one - that is correct...Try with "Nentsel":
Try with "Nentsel":
(entnext (VovKa-MR-entprev (car (nentsel))))
(defun c:TestDxf360 ( / EntNam EntDat PrnEnt PrnDat)
(setq EntNam (car (nentsel))) ;select a block (not attribs)
(setq EntDat (entget EntNam))
(setq PrnEnt (cdr (assoc 330 EntDat)))
(setq PrnDat (entget (setq PrnEnt (cdr (assoc 330 EntDat)))))
(princ "\n ")
(entget (cdr (assoc 360 prndat)))
)
; >>>>>>>>>>>>>>>>>> Bricscad V14 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Seleziona entità:
;
; ----- LISP : Call Stack -----
; [0]...C:TESTDXF360 <<--
;
; ----- Error around expression -----
(ASSOC 360 PRNDAT)
;
; error : bad argument type <NIL> ; expected ENTITYNAME at [ENTGET]
; >>>>>>>>>>>>>>>>>> Bricscad V14 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
; >>>>>>>>>>>>>>>>>> AutoCAD 2013 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Selezionare oggetto:
((-1 . <Nome entità: 7ffffb579c0>) (0 . "BLOCK") (330 . <Nome entità: 7ffffb57990>) (5 . "AFEC") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbBlockBegin") (70 . 0) (10 0.0 0.0 0.0) (-2 . <Nome entità: 7ffffb579a0>) (2 . "ASSO010L") (1 . ""))
; >>>>>>>>>>>>>>>>>> AutoCAD 2013 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Marko, entnext works with nentselTry with "Nentsel":
(entnext (VovKa-MR-entprev (car (nentsel))))
Thats not the point... (entnext) won't work with (car (nentsel))... The function (entprev) should perform exactly the opposite than (entnext)... So (VovKa-MR-entprev) is correct function...
Hummm...Try with "Nentsel":
(entnext (VovKa-MR-entprev (car (nentsel))))
Thats not the point... (entnext) won't work with (car (nentsel))... The function (entprev) should perform exactly the opposite than (entnext)... So (VovKa-MR-entprev) is correct function...
...
anyway i suggest using this variant http://www.theswamp.org/index.php?topic=45732.msg508956#msg508956 (http://www.theswamp.org/index.php?topic=45732.msg508956#msg508956)
it's faster and works within nested objects if the argument supplied is a part of a complex entity
Marko, entnext works with nentsel
anyway i suggest using this variant http://www.theswamp.org/index.php?topic=45732.msg508956#msg508956
it's faster and works within nested objects if the argument supplied is a part of a complex entity
Regularly (entnext <block entity>) won't step inside that <block entity> and find very next nested entity... Only if (entnext <nested entity>) if will find next nested entity...entprev works the same way
Grazie Marco, so che sarà difficile non partecipare...Hi Marco,Grazie a te, spero di ritrovarti ancora.
Thank you a lot for taking the time to run the tests and doing the benchmarking.... for me I guess it is all about my contribution on this thread, was fun but I do not use autolisp nor I work with objectarx anymore or even use AutoCAD nowadays. My sample code is there open, so anyone can use it and update it and make it better!!!.
Have fun!
:)
Gracias a ti, espero encontrarte de nuevo. :kewl:
entprev works the same way
the main condition for entprev function is (eq (entnext (entprev e)) e)
No, VovKa, if I select with (car (nentsel)) second - next nested entity in block that contains more nested entities, (entprev) won't give that previous nested entity, but if I select that previous - first nested entity with (car (nentsel)), (entnext) returns second nested entity I previously picked... So (entnext) works in space of that block, but (entprev) can't enter that space, because (entnext <parent entity>) returns entity in space of parent entities and this is how (entprev) works, using only parent space...i think i can not fully understand your explanation.
(while (setq e (car (nentsel)))
(princ (if (eq (entnext (entprev e)) e)
"ok"
"error"
)
)
)
i think i can not fully understand your explanation.
can you test your drawing with this?Code: [Select](while (setq e (car (nentsel)))
(princ (if (eq (entnext (entprev e)) e)
"ok"
"error"
)
)
)
(while (setq e (car (nentsel)))
(princ (if (eq (entnext (entprev e)) e)
"ok"
"error"
)
)
)
(while (setq e (car (nentsel)))
(princ (if (eq (entprev (entnext e)) e)
"ok"
"error"
)
)
)
; Version 3.20 - 2013/11/27
(defun ALE_EntPrevious (EntNam / SelSet EntDat Countr EntOut PrnEnt)
(if
(and
(assoc 410 (setq EntDat (entget EntNam)))
(not (wcmatch (cdr (assoc 0 EntDat)) "ATTRIB,VERTEX"))
)
(progn
(setq SelSet (ssget "_X") Countr 0)
(while SelSet
(if (eq EntNam (ssname SelSet Countr))
(setq EntOut (ssname SelSet (1+ Countr)) PrnEnt EntOut SelSet nil)
(setq Countr (1+ Countr))
)
)
)
(setq
EntOut (entget (cdr (assoc 330 EntDat)))
EntOut (cdr (cond ((assoc 360 (reverse EntOut)))
((assoc -1 EntOut))
)
)
)
)
(while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
(setq EntOut PrnEnt)
)
EntOut
)
(defun entprev (e / e1 e2)
(setq e1 (entget (cdr (assoc 330 (entget e))))
e1 (cdr (cond ((assoc 360 (reverse e1)))
((assoc -1 e1))
)
)
)
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
: (entprev EntRef)
; ----- Error around expression -----
(ENTNEXT E1)
;
; error : Unknown Error in Lisp or CAD system or 'Stack Overflow'
...Luis, if I select a block ATTRIB I get an error:
OK I have to fix my code, here it is again -
...
(defun c:Test2 ( / EntRef EntPrv)
(setq EntRef (car (nentsel)))
(princ "\nEntRef ") (princ EntRef)
(princ "\nALE_EntPrevious") (princ (entnext (setq EntPrv (ALE_EntPrevious EntRef))))
(princ "\nentprev ") (princ (entnext (setq EntPrv (entprev EntRef))))
(princ "\nentpreviousFrom") (princ (entnext (setq EntPrv (entpreviousFrom EntRef)))) ; louis
(textpage)(princ)
)
Select object:
EntRef <Entity name: 7ffffb5fd20>
ALE_EntPrevious<Entity name: 7ffffb5fd20>
entprev <Entity name: 7ffffb5fd20>
entpreviousFrom; error: bad argument type: lentityp nil
Selection sets may be influenced by the Layouts, I don't truly know, but that's not the point of this thread is it?perhaps this thread may be interesting:
But I do know that entnext and entlast is not affected by them at all.
...
...and where is "TEXT on Layout2"?:? oops yes, you're correct! Only the last opened PS tab is iterated by entnext. So it's a situation of the model space object and the current paper space object.
Command: (ale_entprevious (entnext (entnext)))
<Entity name: 7ffffbfc330>
Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>
Command: CTAB
Enter new value for CTAB <"Layout2">: layout1
Restoring cached viewports - Regenerating layout.
Command: (ale_entprevious (entnext (entnext)))
nil
Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>
Command: (entnext)
<Entity name: 7ffffbfc330>
Command: CTAB
Enter new value for CTAB <"Layout1">: model
Restoring cached viewports.
Command: (ale_entprevious (entnext (entnext)))
nil
Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>
Command: (entnext)
<Entity name: 7ffffbfc330>
;;; switch to layout2 then to model
Command: CTAB
Enter new value for CTAB <"Model">: layout2
Restoring cached viewports - Regenerating layout.
Command: CTAB
Enter new value for CTAB <"Layout2">: model
Restoring cached viewports.
Command: (ale_entprevious (entnext (entnext)))
<Entity name: 7ffffbfc330>
Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>
This is the reason why entprev is very fast if there are many layout with many entities....and where is "TEXT on Layout2"?:? oops yes, you're correct! Only the last opened PS tab is iterated by entnext. So it's a situation of the model space object and the current paper space object.
Command: (ale_entprevious (entnext)) => nil
Command: (entprev (entnext)) => <Entity name: 7ffffbf9950>
"If entnext is called with no arguments, it returns the entity name of the first nondeleted entity in the database.Ah! But that's then not strictly true is it? E.g. blank drawing (all VP's deleted) with a circle on Layout2 with Layout1 open. (entnext) will give you the "Viewport" which is actually Layout1's page. But if you later draw a line in model space - that is considered the "1st" (not the VP, nor the circle).
[quote author=Marc'Antonio Alessi link=topic=45732.msg509089#msg509089 date=1385624054]
Luis, if I select a block ATTRIB I get an error:
entpreviousFrom; error: bad argument type: lentityp nil
[/quote]if (pObj->isKindOf(AcDb2dVertex::desc()))
[quote author=Marc'Antonio Alessi link=topic=45732.msg509089#msg509089 date=1385624054]
entpreviousFrom; error: bad argument type: lentityp nil
"If entnext is called with no arguments, it returns the entity name of the first nondeleted entity in the database.Ah! But that's then not strictly true is it? E.g. blank drawing (all VP's deleted) with a circle on Layout2 with Layout1 open. (entnext) will give you the "Viewport" which is actually Layout1's page. But if you later draw a line in model space - that is considered the "1st" (not the VP, nor the circle).
Thus it should rather read as: "If entnext is called with no arguments, it returns the entity name of the first nondeleted entity in either the model space or the current paperspace. If none found in model space, then the paperspace page (not viewport) is the 1st found. If the MS was blank before drawing anything in any PS, then any later entities in MS will be considered prior to the existing entities in the PS. Only after MS contains something is the order of entities constant. If you then delete the MS contents, the VP of PS becomes the 1st entity - even if you then draw something new in MS. When you then swap to a different PS the MS items are interpreted as previous to anything on the new PS (even if they were drawn earlier)"
It seems these edge cases might need lots of checks to get entprev working as an exact inverse of entnext.
Here it is my latest code:Sorry for late:
...
Let's see if works (arx attached).
TODO: Next task need to study AcDbDimension(s)... and being able to do the scan back.....the seek() works on the iterator but somehow the step back or something is not working... hmm need to install the arx wizard right since the debug does not work and can't step into each line..... :(
Benchmark.lsp | © 2005 Michael Puckett | All Rights Reserved
Elapsed milliseconds / relative speed for 16384 iteration(s):
> Old Polyline
(entpreviousfrom KKKK).....1607 / 1.31 <fastest>
(ALE_ENTPREVIOUS KKKK).....2106 / 1 <slowest>
> Entity in block
(entpreviousfrom KKKK)......2246 / 28.48 <fastest>
(ALE_ENTPREVIOUS KKKK).....63976 / 1 <slowest>
> Attrib in Block
(entpreviousfrom KKKK).....1092 / 1.53 <fastest>
(ALE_ENTPREVIOUS KKKK).....1669 / 1 <slowest>
> Line ********
(entpreviousfrom KKKK).......1029 / 167.57 <fastest>
(ALE_ENTPREVIOUS KKKK).....172428 / 1 <slowest>
Command: !entref
<Entity name: 7ffffbb3550>
Command: (entnext (ALE_EntPrevious EntRef))
<Entity name: 7ffffbb3550>
Command: (entnext (entprev EntRef))
<Entity name: 7ffffbb3550>
Command: (entnext (entpreviousFrom EntRef))
<Entity name: 7ffffbb32e0>
...
Yes, Irne, (entprev) will be very hard to implement doing exact inverse of (entnext)...
...
Yes, Irne, (entprev) will be very hard to implement doing exact inverse of (entnext)...
Do you know a condition for the last ALE_ENTPREVIOUS do not get the exact inverse of (entnext)?
Command: CTAB
Enter new value for CTAB <"Layout2">: layout1
Restoring cached viewports - Regenerating layout.
Command: (ale_entprevious (entnext (entnext)))
nil
Command: (entprev (entnext (entnext)))
<Entity name: 7ffffbfc330>
When I checked I get entity name of first imaginary VIEWPORT entity that is base entity of Layout TAB......Marko,
Marc' I think your version has even advantage in comparison to (entprev) my last version I posted... The only difference I see in obraining result is the case where you actually pick with (ale_entprevious (car (nentsel))) first nested entity in block - it then returns "BLOCK" entity - BlockBegin... And my version (entprev (car (nentsel))) with picked first nested entity returns nil - similar to picking last nested entity inside block or dimension with (entnext (car (nentsel)))... I've checked the cases with paper/model space entities and both version act the same (so I don't know how did you get these results stated in post 109) :
...
(defun entprevMR (e / e1 e2)
(if (eq (type e) 'ename)
(if (eq e (entnext))
nil
(progn
(if (not
(or
(eq (cdr (assoc 2 (entget (cdr (assoc 330 (entget e)))))) "*Model_Space")
(eq (cdr (assoc 2 (entget (cdr (assoc 330 (entget e)))))) "*Paper_Space")
)
)
(progn
(setq e1 (cdr (assoc -2 (entget (cdr (assoc 360 (entget (cdr (assoc 330 (entget e))))))))))
(if (eq e e1) nil
(progn
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
)
)
(progn
(setq e1 (entnext))
(while (and e1 (not (eq e (setq e2 (entnext e1)))))
(setq e1 e2)
)
e1
)
)
)
)
(entget e)
)
)
Test on my last DWG posted:; select line 1
Comando: (setq EntRef (car (nentsel)))
Selezionare oggetto: <Nome entità: 7ffffb600b0>
Comando: (entprevMR EntRef)
nil <<< NOT TRUE
; select line 2 in block
Comando: (setq EntRef (car (nentsel)))
Selezionare oggetto: <Nome entità: 7ffffb18770>
Comando: (entprevMR EntRef)
<Nome entità: 7ffffb18760>
Comando: (entnext (entprevMR EntRef))
<Nome entità: 7ffffb18770> <<< TRUE
; select OLD polyline 3
Comando: (setq EntRef (car (nentsel)))
Selezionare oggetto: <Nome entità: 7ffffb5fde0>
Comando: (entprevMR EntRef)
; errore: tipo di argomento errato: lentityp nil
(setq EntRef (car (nentsel)))
(setq EntPrv (ENTPREVMR EntRef))
(setq EntPrv (ENTPREVMR EntPrv)) ;;; repeat this until stop on the first entity that will be the last previous one.
Thanks, Luis for your tests, it was really small issue - I should have added SEQEND entity to (wcmatch) function... So I think that should fix it... Maybe I missed something else? Who knows, please inform me again if you find something strange like this issue...
M.R.
usage:
(EntPreviousFrom <ename> <container ename optional>)
returns: previous ename or nil or first ename on space
(setq e (car (nentsel)))
(setq e (EntPreviousFrom e))
or...
(setq e (car (entsel)))
(setq e (EntPreviousFrom e))
or...
(setq data (nentsel))
(setq e (EntPreviousFrom (car data) (car (last data))))
Marko,
I tried and still does the same - will give a try tomorrow. Thanks!
@Marko: your entpreMR seems ok, I have seen the problem with my ALE_EntPrevious and XREF, I'll see if I can solve. Thank you.
@Louis: do you know how do we get the same result of (ssget "_X"), equal to what you see in this window?
Hi Marc'Antonio,
Sorry, I do not understand your question, do you want to use some other function to get the same as using SSGET _X ? or if there is another way to get the same? and in that order?
edit: I see that image capture is taking from the VLIDE under View -> Browse drawing database -> Browse all entities
Here it is 5:30AM - I know in Italy it is 2:30PM --- let me get my first coffee.
Luis.
Yes. Take the coffee first!
My question: (ssget "_X") is very slow, is there another method in Visuallisp to obtain the same result?
That is a list of just main entities as can be seen also in Browse drawing database -> Browse all entities?
Ciao.
<INSERT> <Entity name: FFB06D40>
<LINE> <Entity name: FFB06E30>
<CIRCLE> <Entity name: FFB06E40>
<CIRCLE> <Entity name: FFB06E50>
<DIMENSION> <Entity name: FFB06ED0>
<CIRCLE> <Entity name: FFB04040>
<CIRCLE> <Entity name: FFB04050>
Yes. Take the coffee first!
My question: (ssget "_X") is very slow, is there another method in Visuallisp to obtain the same result?
That is a list of just main entities as can be seen also in Browse drawing database -> Browse all entities?
Ciao.
Not that I know or aware.
Command: 'VLIDE
#<VLA-OBJECT IAcadBlockReference 000000002a374448>
#<VLA-OBJECT IAcadLine 000000002a717b08>
#<VLA-OBJECT IAcadCircle 000000002a717bc8>
#<VLA-OBJECT IAcadCircle 000000002a717988>
#<VLA-OBJECT IAcadDimRotated 000000002a442da8>
#<VLA-OBJECT IAcadCircle 000000002a717a48>
#<VLA-OBJECT IAcadCircle 000000002a7178c8>
or:
<Entity name: 7ffffb06d40>
<Entity name: 7ffffb06e30>
<Entity name: 7ffffb06e40>
<Entity name: 7ffffb06e50>
<Entity name: 7ffffb06ed0>
<Entity name: 7ffffb04040>
<Entity name: 7ffffb04050>
To add something into my previous post, maybe something like this?I do not know if your code "...(setq ms (vla-get-modelspace db))..." is faster then (ssget "_X") because I have to iterate on ModelSpace and all layouts...Code - Auto/Visual Lisp: [Select]
;;; or...
; Version 3.30 - 2013/12/03 - not tested on xref
(defun ALE_EntPrevious (EntNam / EntObj SelSet EntDat Countr EntOut PrnEnt *AcAcDwg* *AcDataB* TrueFl)
(if
(and
(assoc 410 (setq EntDat (entget EntNam)))
(not (wcmatch (cdr (assoc 0 EntDat)) "ATTRIB,VERTEX"))
)
(progn
(setq
*AcAcDwg* (vla-get-ActiveDocument (vlax-get-acad-object))
*AcDataB* (vla-get-database *AcAcDwg*)
EntObj (vlax-ename->vla-object EntNam)
)
(vlax-for LayFor (vla-get-Layouts *AcDataB*)
(vlax-for ObjFor (vla-get-block LayFor)
(if (equal EntObj ObjFor)
(setq TrueFl T EntOut (vlax-vla-object->ename EntOut))
(or TrueFl (setq EntOut ObjFor))
)
)
)
)
(setq
EntOut (entget (cdr (assoc 330 EntDat)))
EntOut (cdr (cond ((assoc 360 (reverse EntOut)))
((assoc -1 EntOut))
)
)
)
)
(while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
(setq EntOut PrnEnt)
)
EntOut
)
I need a method to stop (vlax-for ObjFor (vla-get-block LayFor) ...
when find the (equal EntObj ObjFor) condition.
(vl-catch-all-apply
(function
(lambda ( )
(vlax-for l (vla-get-layouts *AcDataB*)
(vlax-for o (vla-get-block l)
(if (equal entobj o)
(progn
(setq entout (vlax-vla-object->ename entout))
(exit)
)
(setq entout o)
)
)
)
)
)
)
Thanks Lee, I thought (exit) or (quit) but the idea of putting it in a (vl-catch-all-apply ...) I would never come!I need a method to stop (vlax-for ObjFor (vla-get-block LayFor) ...
when find the (equal EntObj ObjFor) condition.
Not pretty, but should work: ...
;Benchmark.lsp | © 2005 Michael Puckett | All Rights Reserved
; On my entprev.dwg:
; select line 1
;Elapsed milliseconds / relative speed for 8192 iteration(s):
; (ALE_ENTPREVIOUS KKKK)......1076 / 67.53 <fastest>
; (ENTPREVMR KKKK)...........72665 / 1 <slowest>
; select line 2 in block
;Elapsed milliseconds / relative speed for 512 iteration(s):
; (ALE_ENTPREVIOUS KKKK).....2589 / 1.62 <fastest>
; (ENTPREVMR KKKK)...........4196 / 1 <slowest>
; select Attrib in block 2
;Elapsed milliseconds / relative speed for 16384 iteration(s):
; (ENTPREVMR KKKK)...........2028 / 1.27 <fastest>
; (ALE_ENTPREVIOUS KKKK).....2574 / 1 <slowest>
; select OLD polyline 3
;Elapsed milliseconds / relative speed for 16384 iteration(s):
; (ENTPREVMR KKKK)...........1404 / 1.03 <fastest>
; (ALE_ENTPREVIOUS KKKK).....1451 / 1 <slowest>
; select line 1
;Elapsed milliseconds / relative speed for 8192 iteration(s):
; (ALE_ENTPREVIOUS KKKK)................1498 / 10.85 <fastest>
; (ALE_ENTPREVIOUSBYSS KKKK #SSET).....16255 / 1 <slowest>
; Version 3.40 - 2013/12/04 - not tested on Xref
;(setq *AcDataB* (vla-get-database (vla-get-ActiveDocument (vlax-get-acad-object))))
;
(defun ALE_EntPrevious (EntNam / EntObj SelSet EntDat EntOut PrnEnt)
(if
(and
(assoc 410 (setq EntDat (entget EntNam)))
(not (wcmatch (cdr (assoc 0 EntDat)) "ATTRIB,VERTEX"))
)
(progn
(setq EntObj (vlax-ename->vla-object EntNam))
(vl-catch-all-apply ; Lee Mac idea
(function
(lambda ( )
(vlax-for l (vla-get-layouts *AcDataB*)
(vlax-for o (vla-get-block l)
(if (equal EntObj o)
(progn (setq EntOut (vlax-vla-object->ename EntOut)) (exit))
(setq EntOut o)
)
)
)
)
)
)
)
(setq
EntOut (entget (cdr (assoc 330 EntDat)))
EntOut (cdr (cond ((assoc 360 (reverse EntOut)))
((assoc -1 EntOut))
)
)
)
)
(while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
(setq EntOut PrnEnt)
)
EntOut
)
; Another attempt - Version 1.00 - 2013/12/04 - not tested on Xref
; (setq #SSet (ssget "_X"))
; (ALE_EntPreviousBySS (car (nentsel)) #SSet)
;
(defun ALE_EntPreviousBySS (EntNam SelSet / SelSet EntDat Countr EntOut PrnEnt)
(if
(and
(assoc 410 (setq EntDat (entget EntNam)))
(not (wcmatch (cdr (assoc 0 EntDat)) "ATTRIB,VERTEX"))
)
(progn
(setq Countr 0)
(while SelSet
(if (eq EntNam (ssname SelSet Countr))
(setq EntOut (ssname SelSet (1+ Countr)) PrnEnt EntOut SelSet nil)
(setq Countr (1+ Countr))
)
)
)
(setq
EntOut (entget (cdr (assoc 330 EntDat)))
EntOut (cdr (cond ((assoc 360 (reverse EntOut)))
((assoc -1 EntOut))
)
)
)
)
(while (and EntOut (not (eq EntNam (setq PrnEnt (entnext EntOut)))))
(setq EntOut PrnEnt)
)
EntOut
)
Marc', can you benchmark also this version... I think it's more optimized for entities near end of ss (ssname (ssget "_X") 0) or (entlast)... It would be nice to see if this version is actually faster than orig. (entprevMR)...Marko, I am doing tests, (ssget "_X") is very slow, this version use a selset as argument:
M.R.
; select line 1
;Elapsed milliseconds / relative speed for 8192 iteration(s):
; (ALE_ENTPREVIOUS KKKK)................1498 / 10.85 <fastest>
; (ALE_ENTPREVIOUSBYSS KKKK #SSET).....16255 / 1 <slowest>
Marc', can you benchmark also this version... I think it's more optimized for entities near end of ss (ssname (ssget "_X") 0) or (entlast)... It would be nice to see if this version is actually faster than orig. (entprevMR)...
M.R.
;Benchmark.lsp | © 2005 Michael Puckett | All Rights Reserved
; select line 1
;Elapsed milliseconds / relative speed for 8192 iteration(s):
; (ALE_ENTPREVIOUS KKKK).......1029 / 568.52 <fastest>
; (ENTPREVMR-SS KKKK)........585004 / 1 <slowest>
I can not do other tests, to much difference
; select line 1
;Elapsed milliseconds / relative speed for 128 iteration(s):
; (ENTPREVMR KKKK)........1092 / 8.73 <fastest>
; (ENTPREVMR-SS KKKK).....9531 / 1 <slowest>
I can not do other tests, to much difference; select line 1
Does this mean that you're testing functions on first line in DWG with plenty of them?Here are my results between (entprevMR) and (entprevMR-SS) :Marko,
...
(setq kkkk (car (nentsel)))
(Benchmark '(
(entprevMR kkkk) ;Marko Ribar
(ALE_EntPrevious kkkk)
) )
...Louis,
But anyway, my method that uses the acdbCurDwg()->currentSpaceId() or current space will work better since it will grab the entities on the desired location and also avoiding the use of COM or activex extensions as those from all the vlax-XXXX
...
(defun C:TestentpreviousFrom ( / SelSet Countr EntNam EntPrv Countr)
(setq EntNam (ssname (ssget "_X") 0) Countr 0)
(while EntNam
(if (setq EntPrv (entpreviousFrom EntNam))
(or
(eq EntNam (entnext EntPrv))
(progn (print (cdr (assoc 0 (entget EntNam)))) (princ " Not Eq "))
)
(progn (print (cdr (assoc 0 (entget EntNam))))(princ " nil "))
)
(setq EntNam (entnext EntNam) Countr (1+ Countr))
)
Countr
)
My fuction return nil only for seqend:...Louis,
But anyway, my method that uses the acdbCurDwg()->currentSpaceId() or current space will work better since it will grab the entities on the desired location and also avoiding the use of COM or activex extensions as those from all the vlax-XXXX
...
I have tested (in my entprev.dwg) your function again and:Code: [Select](defun C:TestentpreviousFrom ( / SelSet Countr EntNam EntPrv Countr)
My fuction return nil only for seqend:
(setq EntNam (ssname (ssget "_X") 0) Countr 0)
(while EntNam
(if (setq EntPrv (entpreviousFrom EntNam))
(or
(eq EntNam (entnext EntPrv))
(progn (print (cdr (assoc 0 (entget EntNam)))) (princ " Not Eq "))
)
(progn (print (cdr (assoc 0 (entget EntNam))))(princ " nil "))
)
(setq EntNam (entnext EntNam) Countr (1+ Countr))
)
Countr
)
...
"SEQEND" nil
"SEQEND" nil 6274
Your function:
....
"SEQEND" nil
"INSERT" nil
"SEQEND" nil
"LWPOLYLINE" nil
"SEQEND" nil
"POLYLINE" nil
"SEQEND" nil
"LWPOLYLINE" nil
...
and Not Eq in:
...
"INSERT" Not Eq
"INSERT" Not Eq
"INSERT" Not Eq
"INSERT" Not Eq
"INSERT" Not Eq
"INSERT" Not Eq
"INSERT" Not Eq
"LWPOLYLINE" Not Eq
"POLYLINE" Not Eq
"LWPOLYLINE" Not Eq
6274