Author Topic: (entprev)  (Read 56755 times)

0 Members and 2 Guests are viewing this topic.

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: (entprev)
« Reply #120 on: November 30, 2013, 12:06:43 PM »
According to my tests, now my version works (thanks to some of your excellent lines I've taken from your code) and on XREF's, but your version ALE_entprevious fails - my CAD doesn't finish test...

Of course, test it with (entprev (car (nentsel))) on nested entity from Xref...

M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: (entprev)
« Reply #121 on: December 01, 2013, 02:51:24 AM »
I've tested my code in various situations and it didn't fail... So if anyone have some spare time for testing, I just can produce situation where it should fail - tried combinations with nested blocks inside xrefs, with nested xrefs... So if it fails, please inform me...

The code for testing is here :
http://www.theswamp.org/index.php?topic=45732.msg509151#msg509151

M.R.
« Last Edit: December 01, 2013, 03:01:05 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

LE3

  • Guest
Re: (entprev)
« Reply #122 on: December 01, 2013, 12:04:56 PM »
ribarm,

try this one, select with nentsel the mtext from the dimension, then get the previous entity and then pass that previous entity until stop on the first entity (the block with the four attributes):

Sequence:
Quote
(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.

Does return the first one after all calls?

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: (entprev)
« Reply #123 on: December 01, 2013, 05:06:16 PM »
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.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

LE3

  • Guest
Re: (entprev)
« Reply #124 on: December 01, 2013, 09:36:48 PM »
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.

Marko,
I tried and still does the same - will give a try tomorrow. Thanks!

LE3

  • Guest
Re: (entprev)
« Reply #125 on: December 01, 2013, 09:50:11 PM »
This is the latest code on my try-out of using ObjectARX - why ARX? -- it is of what AutoLisp and Vlisp function are made of.

HTH and works.

Code - C++: [Select]
  1. void GetObjectIdFirstEntityOnCurrentSpace(AcDbObjectId& objIdFirst, AcDbObjectId spaceId = acdbCurDwg()->currentSpaceId())
  2. {
  3.         AcDbBlockTableRecordPointer blockTableRecordPointer(spaceId, AcDb::kForRead);
  4.         if (blockTableRecordPointer.openStatus() == Acad::eOk)
  5.         {
  6.                 AcDbBlockTableRecordIterator* it = NULL;
  7.                 if (blockTableRecordPointer->newIterator(it) == Acad::eOk)
  8.                 {
  9.                         it->start();
  10.                         AcDbObjectId objId;
  11.                         if (it->getEntityId(objId) == Acad::eOk) objIdFirst = objId;
  12.                         delete it;
  13.                 }
  14.         }
  15. }
  16.  
  17. void GetPreviousEntityObjectId(AcDbEntity* pObj, AcDbObjectId& objIdOut)
  18. {
  19.         AcDbBlockTableRecordPointer blockTableRecordPointer(pObj->ownerId(), AcDb::kForRead);
  20.         if (blockTableRecordPointer.openStatus() == Acad::eOk)
  21.         {
  22.                 AcDbBlockTableRecordIterator* it = NULL;
  23.                 if (blockTableRecordPointer->newIterator(it) == Acad::eOk)
  24.                 {
  25.                         if (it->seek(pObj->objectId()) == Acad::eOk)
  26.                         {
  27.                                 it->step(false, true);
  28.                                 AcDbObjectId objId;
  29.                                 if (it->getEntityId(objId) == Acad::eOk) objIdOut = objId;
  30.                         }
  31.                         delete it;
  32.                 }
  33.         }
  34. }
  35.  
  36. void GetPreviousEname(AcDbObjectId objIdFirst, AcDbObjectId& id, struct resbuf *rb, ads_name& objName)
  37. {
  38.         if (id.isValid() && objIdFirst != id)
  39.         {
  40.                 if (acdbGetAdsName(objName, id) != Acad::eOk) return;
  41.         }
  42.         else if (id.isValid() && objIdFirst == id)
  43.         {
  44.                 if (acdbGetAdsName(objName, objIdFirst) != Acad::eOk) return;
  45.         }
  46.         else if (id.isNull() && rb->rbnext && rb->rbnext->restype == RTENAME) // null id and has an optional argument?
  47.         {
  48.                 AcDbObjectId objId;
  49.                 if (acdbGetObjectId(objId, rb->rbnext->resval.rlname) != Acad::eOk) return;
  50.                 if (acdbGetAdsName(objName, objId) != Acad::eOk) return;
  51.                 id = objId; // make the id valid
  52.         }
  53. }
  54.  

Code - C++: [Select]
  1. static int ads_EntPreviousFrom(void)
  2. {
  3.         struct resbuf *rb = acedGetArgs();
  4.         if (!rb) return RSERR;
  5.        
  6.         AcDbObjectId objId;
  7.         ads_name objName;
  8.         AcDbObjectId objIdFirst;
  9.         if (rb && rb->restype != RTENAME) { acutPrintf(_T("\nError: function requires an ENAME argument. \n")); return RSERR; }
  10.         if (acdbGetObjectId(objId, rb->resval.rlname) != Acad::eOk) return RSERR;
  11.         AcDbObjectPointer<AcDbEntity> pObj(objId, AcDb::kForRead);
  12.         if (pObj.openStatus() != Acad::eOk) return RSERR;
  13.         GetObjectIdFirstEntityOnCurrentSpace(objIdFirst);
  14.         if (objIdFirst == objId && acdbGetAdsName(objName, objIdFirst) == Acad::eOk)
  15.         {
  16.                 acedRetName(objName, RTENAME);
  17.         }
  18.         else
  19.         {
  20.                 if (pObj->isKindOf(AcDb2dVertex::desc()))
  21.                 {
  22.                         AcDbObjectPointer<AcDb2dPolyline> pPline(pObj->ownerId(), AcDb::kForRead);
  23.                         if (pPline.openStatus() == Acad::eOk)
  24.                         {
  25.                                 AcDbObjectIterator* pVertIterator = pPline->vertexIterator();
  26.                                 pVertIterator->start();
  27.                                 pVertIterator->setPosition(pObj->objectId());
  28.                                 pVertIterator->step(true);
  29.                                 AcDbObjectPointer<AcDb2dVertex> pVertex(pVertIterator->objectId(), AcDb::kForRead);
  30.                                 if (pVertex.openStatus() == Acad::eOk && acdbGetAdsName(objName, pVertex->objectId()) == Acad::eOk)
  31.                                 {
  32.                                         acedRetName(objName, RTENAME);
  33.                                 }
  34.                                 else if (acdbGetAdsName(objName, pPline->objectId()) == Acad::eOk)
  35.                                 {
  36.                                         acedRetName(objName, RTENAME);
  37.                                 }
  38.                                 delete pVertIterator;
  39.                         }
  40.                 }
  41.                 else if (pObj->isKindOf(AcDbAttribute::desc()))
  42.                 {
  43.                         AcDbObjectPointer<AcDbBlockReference> pBlockReference(pObj->ownerId(), AcDb::kForRead);
  44.                         if (pBlockReference.openStatus() == Acad::eOk)
  45.                         {
  46.                                 AcDbObjectIterator* pAttributeIterator = pBlockReference->attributeIterator();
  47.                                 pAttributeIterator->start(true);
  48.                                 pAttributeIterator->setPosition(pObj->objectId());
  49.                                 pAttributeIterator->step(true);
  50.                                 AcDbObjectPointer<AcDbAttribute> pAttribute(pAttributeIterator->objectId(), AcDb::kForRead);
  51.                                 if (pAttribute.openStatus() == Acad::eOk && acdbGetAdsName(objName, pAttribute->objectId()) == Acad::eOk)
  52.                                 {
  53.                                         acedRetName(objName, RTENAME);
  54.                                 }
  55.                                 else if (acdbGetAdsName(objName, pBlockReference->objectId()) == Acad::eOk)
  56.                                 {
  57.                                         acedRetName(objName, RTENAME);
  58.                                 }
  59.                                 delete pAttributeIterator;
  60.                         }
  61.                 }
  62.                 else
  63.                 {
  64.                         AcDbObjectId id;
  65.                         GetPreviousEntityObjectId(pObj, id);
  66.                         if (id.isValid())
  67.                         {
  68.                                 GetPreviousEname(objIdFirst, id, rb, objName);
  69.                                 if (id.isValid())
  70.                                 {
  71.                                         acedRetName(objName, RTENAME);
  72.                                 }
  73.                         }
  74.                         else // use the optional argument if any
  75.                         {
  76.                                 GetPreviousEname(objIdFirst, id, rb, objName);
  77.                                 if (id.isValid())
  78.                                 {
  79.                                         acedRetName(objName, RTENAME);
  80.                                 }
  81.                                 else
  82.                                 {
  83.                                         // is part of a nest object?
  84.                                         // use the method with the optional argument:
  85.                                         // usage:
  86.                                         // (setq data (nentsel))
  87.                                         // (setq e (EntPreviousFrom (car data) (car (last data))))
  88.                                 }
  89.                         }
  90.                 }
  91.         }
  92.         return (RSRSLT);
  93. }
  94.  

Quote
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))))

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: (entprev)
« Reply #126 on: December 02, 2013, 10:02:32 AM »
Marko,
I tried and still does the same - will give a try tomorrow. Thanks!

If you're lazy, maybe this test function can help you... It should give the same results, both for (entnext) and (entprevMR)... Note that both functions won't step inside XREF entities - they will treat them parent entities...

Code - Auto/Visual Lisp: [Select]
  1. (defun entprevMR ( e / e1 e2 )
  2.   (if (eq (type e) 'ename)
  3.     (if (eq e (entnext))
  4.       nil
  5.       (if (wcmatch (cdr (assoc 0 (entget e))) "ATTRIB,VERTEX,SEQEND")
  6.         (progn
  7.           (setq e1 (cdr (assoc 330 (entget e))))
  8.           (while (and e1 (not (eq e (setq e2 (entnext e1)))))
  9.             (setq e1 e2)
  10.           )
  11.           e1
  12.         )
  13.         (if (wcmatch (cdr (assoc 2 (entget (cdr (assoc 330 (entget e)))))) "*Model_Space,*Paper_Space")
  14.           (progn
  15.             (setq e1 (cdr (assoc 360 (reverse (entget (cdr (assoc 330 (entget e))))))))
  16.             (if (eq (cdr (assoc 0 (entget e1))) "BLOCK") (setq e1 (entnext)))
  17.             (while (and e1 (not (eq e (setq e2 (entnext e1)))))
  18.               (setq e1 e2)
  19.             )
  20.             e1
  21.           )
  22.           (progn
  23.             (setq e1 (tblobjname "BLOCK" (vla-get-name (vlax-ename->vla-object (cdr (assoc 330 (entget e)))))))
  24.             (while (and e1 (not (eq e (setq e2 (entnext e1)))))
  25.               (setq e1 e2)
  26.             )
  27.             e1
  28.           )
  29.         )
  30.       )
  31.     )
  32.     (entget e)
  33.   )
  34. )
  35.  
  36. (defun c:test ( / e loop n )
  37.   ;;; last nested or parent entity - e ;;;
  38.   (setq e (entlast))
  39.   (setq loop t)
  40.   (while loop
  41.     (if (entnext e) (setq e (entnext e)) (setq loop nil))
  42.   )
  43.   ;;; test - entprev ;;;
  44.   (setq n 0)
  45.   (while e
  46.     (setq n (1+ n))
  47.     (setq e (entprevMR e))
  48.   )
  49.   (prompt "\nTesting entprev function; Total: ")
  50.   (if (= n 1)
  51.     (progn
  52.       (princ n) (prompt " nested/parent entity")
  53.     )
  54.     (progn
  55.       (princ n) (prompt " nested/parent entities")
  56.     )
  57.   )
  58.   ;;; first parent entity - e ;;;
  59.   (setq e (entnext))
  60.   ;;; test - entnext ;;;
  61.   (setq n 0)
  62.   (while e
  63.     (setq n (1+ n))
  64.     (setq e (entnext e))
  65.   )
  66.   (prompt "\nTesting entnext function; Total: ")
  67.   (if (= n 1)
  68.     (progn
  69.       (princ n) (prompt " nested/parent entity")
  70.     )
  71.     (progn
  72.       (princ n) (prompt " nested/parent entities")
  73.     )
  74.   )
  75.   (princ)
  76. )
  77.  

Marko R.
« Last Edit: December 02, 2013, 11:02:40 AM by ribarm »
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

ribarm

  • Gator
  • Posts: 3279
  • Marko Ribar, architect
Re: (entprev)
« Reply #127 on: December 02, 2013, 11:05:26 AM »
I had cutoff between different CTABs, so I've changed my function once more - look in my last post... Now (entprevMR) should be OK...

My testings passed... Please verify this...

M.R.
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

LE3

  • Guest
Re: (entprev)
« Reply #128 on: December 02, 2013, 11:58:48 AM »
Marko,
Got the chance to run another test and see the image capture below with the output - also using vovka entprev(this one will step to previous ones but after returning nil, it will rewind and return the entities again, yours and marco after returning nil will return an error, since the ename argument will be nil) and marco ALE_EntPrevious all with a call of (car (entsel)) - on the dimension.
The A it is what returns of all previous entities, but I see that the previous of a line it should be the block, but it first returns the attributes then the block (this being the first entity on the drawing).

Let's hope my explanation it is clear as mud.

Using my EntPreviousFrom it return entities on the B side.

Thanks,
Luis.

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • Marco
Re: (entprev)
« Reply #129 on: December 03, 2013, 08:15:41 AM »
@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?



 

LE3

  • Guest
Re: (entprev)
« Reply #130 on: December 03, 2013, 08:34:03 AM »
@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.
« Last Edit: December 03, 2013, 08:37:41 AM by LE »

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • Marco
Re: (entprev)
« Reply #131 on: December 03, 2013, 09:50:42 AM »
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.
 

LE3

  • Guest
Re: (entprev)
« Reply #132 on: December 03, 2013, 10:02:14 AM »
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.

I did a quick method in arx that access directly the database (as they did it for vlide):

Code - C++: [Select]
  1. static void BrowseAllEntities(void)
  2. {
  3.         AcDbBlockTableRecordPointer pBTR(acdbCurDwg()->currentSpaceId(), AcDb::kForRead);
  4.         if (pBTR.openStatus() != Acad::eOk) return;
  5.         AcDbBlockTableRecordIterator* it = NULL;
  6.         if (pBTR->newIterator(it) != Acad::eOk) return;
  7.         AcDbObjectId objId;
  8.         ads_name ename;
  9.         for (; !it->done(); it->step())
  10.         {
  11.                 if (it->getEntityId(objId) != Acad::eOk) continue;
  12.                 AcDbObjectPointer<AcDbEntity> pEnt(objId, AcDb::kForRead);
  13.                 if (pEnt.openStatus() != Acad::eOk) continue;
  14.                 if (acdbGetAdsName(ename, pEnt->objectId()) != Acad::eOk) continue;
  15.                 acutPrintf(_T("\n<%s> <Entity name: %8lx> \n"), pEnt->isA()->dxfName(), ename[0]);
  16.         }
  17.         delete it;
  18. }
  19.  

Then on the command line returns, similar to what the vlide does, did not added types:
Quote
<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>

I think that the best way is to create an objectarx solution and add your own methods to handle, this then send those to be use as autolisp functions - to do the work faster - I have no idea or have not tested this approach(es) on c# (thinking if by using c# could be much simpler and accessible since we can do autolisp function with c# btw) --- don't recall seeing a way to iterate the same as in arx....

LE3

  • Guest
Re: (entprev)
« Reply #133 on: December 03, 2013, 10:29:28 AM »
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.


To add something into my previous post, maybe something like this?

Code - Auto/Visual Lisp: [Select]
  1. (vlax-for item ms (print item))
  2. ;;; or...
  3. (vlax-for item ms (print (vlax-vla-object->ename item)))
  4.  

Quote
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>

Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1453
  • Marco
Re: (entprev)
« Reply #134 on: December 03, 2013, 11:36:47 AM »
To add something into my previous post, maybe something like this?
Code - Auto/Visual Lisp: [Select]
  1. (vlax-for item ms (print item))
  2. ;;; or...
  3. (vlax-for item ms (print (vlax-vla-object->ename item)))
  4.  
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...

In your DWG sample I have created two text one in Layout1  "ThisIsATextOnLayOut1" and one in Layout2 "ThisIsATextOnLayOut2" but I saw that "Browse drawing database -> Browse all entities" shows only the text in the active layout (Layout2 > "ThisIsATextOnLayOut2", see image).