Author Topic: Breaking unhandy entities  (Read 7426 times)

0 Members and 1 Guest are viewing this topic.

S.Langhammer

  • Guest
Breaking unhandy entities
« on: July 03, 2013, 10:59:18 AM »
Once again hello to you all!

I've been on hiatus with this whole read entities via BricsCAD-LISP project for a while now.
The last thing i was working on was a function to explode all entities, which are unhandy for reading on the Delphi side of the interface.

Now my problem is, that i have to go through all Blocks and explode the unhandy entites there. Practicly I have to use the "REFEDIT" command, since BricsCAD doesn't seem to have a command, which would give me a direct acces to the blocklist.

Now here's the buggy function:

Code - Auto/Visual Lisp: [Select]
  1. (defun breakUnhandyEntities (/ entName entity entTyp explode)
  2.         (foreach entName (Blk_ENameLstNstd "*Model_Space")
  3.                 (if (setq entity(entget entName))
  4.                         (if (setq entTyp(cdr(assoc 0 entity)))
  5.                                 (if(wcmatch entTyp "INSERT,3DSOLID,REGION,SURFACE,BODY,MTEXT,DIMENSION,POLYLINE")
  6.                                         (cond
  7.                                                 ((= entTyp "INSERT")
  8.                                                         (command "._REFEDIT" (list entName (trans(cdr(assoc 10 entity))(cdr(assoc 210 entity)) 0)) "_ok" "_all" "_yes")
  9.                                                         (explodeByObject(list '((100 . "ACDBMODELERGEOMETRY"))'((100 . "ACDBMODELERGEOMETRY"))'((100 . "ACDBMODELERGEOMETRY"))'((100 . "ACDBMODELERGEOMETRY"))'((100 . "ACDBPOLYLINE"))'((100 . "ACDBPOLYGONMESH"))'((100 . "ACDBMLINE"))'((100 . "ACDBDIMENSION"))'((100 . "ACDB2DPOLYLINE"))'((100 . "ACDB3DPOLYLINE"))'((100 . "ACDBMTEXT"))))
  10.                                                         (command "._REFCLOSE" "")
  11.                                                         ;(return)       ;;;?
  12.                                                 )
  13.                                                 ((wcmatch entTyp "3DSOLID,BODY,SURFACE,REGION")                                                                                
  14.                                                         (explodeByObject(list '((100 . "ACDBMODELERGEOMETRY"))'((100 . "ACDBMODELERGEOMETRY"))'((100 . "ACDBMODELERGEOMETRY"))'((100 . "ACDBMODELERGEOMETRY"))))
  15.                                                         ; (return)
  16.                                                 )
  17.                                                 ((wcmatch entTyp "MTEXT,DIMENSION,POLYLINE")
  18.                                                         (command "._EXPLODE" entName)
  19.                                                         ; (return)
  20.                                                 )
  21.                                         )
  22.                                
  23.                                 )
  24.                         )
  25.                 )
  26.         )
  27. )       ;;; ende breakUnhandyEntities
  28. ;;; -
  29. (defun explodeByObject (objLst / explode)
  30.         (foreach explode objLst
  31.                 (if (setq insSet (ssget "x" explode))
  32.                         (command "._EXPLODE" insSet)
  33.                 )
  34.         )
  35. );;; ende explodeByObject
  36. ;;; -
  37.  

I've tracked the error down to be somewhere in the (= entTyp "INSERT") case.  I'm propably using refedit the wrong way. Would be nice of you, if you could grabb me by the back of my head, and slamm my face into my misstake.
Sorry for the lack of professionality there. It's a little bit frustrating, when you come back to a project, you assumed to work, after a long time and find yourself confronted with a rather critical error.

As always: Thanks in advance!

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Breaking unhandy entities
« Reply #1 on: July 04, 2013, 03:29:57 AM »
The use of the refedit command is very problematic. Your code makes two assumptions:
  • Every insert has a clickable entity going through its insertion point.
  • The current UCS is always the WCS.
Why not use this code already suggested to you?:
http://www.theswamp.org/index.php?topic=44630.msg498648#msg498648

S.Langhammer

  • Guest
Re: Breaking unhandy entities
« Reply #2 on: July 04, 2013, 07:20:24 AM »
Well about point 1: as far as I understand it, all entities, that are visible in the modelspace, do have somehow a insertion Point, assuming you can click what you can see. I'm not interrested in invisible entities at all. I'm exporting entities so they can be drawed in glScene.
About point 2: I don't see how that is relevant, at this Point. Maybe I lack of knoledge here.

And about your Suggestion: I'd have to make it check for ACDBMODELERGEOMETRY multiple times, since the more complx ones (e.g. Bodies) explode to less complex ACDBMODELERGEOMETRY, if you explode them only once. Yet while I'm writing this I think I get an idea, how to work around that. Also like I sayed, I've been on hiatus for this project for quite a while. Vocational School/college (whatever the correct term is) other tasks at work and this whole flood Thing over here kept my mind kinda occupied, so I didn't quite remember that post at frst.

S.Langhammer

  • Guest
Re: Breaking unhandy entities
« Reply #3 on: July 04, 2013, 10:23:58 AM »
Ok so now I'm using roy's code in my main function:

-I step though every block in the block list
-I check each block if it's not an anonymus block (starting with a "*")
-then I take a list of object types I want to explode and run roy's explode code for every item in the list

Code - Auto/Visual Lisp: [Select]
  1. (while (setq LstBlk (tblnext "BLOCK" (not LstBlk)))
  2.         (if (/=(substr(cdr(assoc 2 LstBlk))1 1)"*")(progn
  3.                 (foreach a '("ACDBMODELERGEOMETRY" "ACDBMODELERGEOMETRY" "ACDBMODELERGEOMETRY" "ACDBMODELERGEOMETRY" "ACDBPOLYLINE" "ACDBPOLYGONMESH" "ACDBMLINE" "ACDBDIMENSION" "ACDB2DPOLYLINE" "ACDB3DPOLYLINE")
  4.                         (mapcar
  5.                                 '(lambda (object)
  6.                                         (if (= (strcase (vla-get-objectname object)) a)(progn
  7.                                                 (vla-explode object)
  8.                                                 (vla-erase object) ; (vla-explode) does not erase the original object.
  9.                                         ))
  10.                                 )
  11.                                 (vla-collection->list ; BricsCAD function.
  12.                                         (vla-item
  13.                                                 (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
  14.                                                 (cdr(assoc 2 LstBlk))
  15.                                         )
  16.                                 )
  17.                         )
  18.                 )      
  19.         ))
  20. )
  21.  

I wrote ACDBMODELERGEOMETRY three times to the list, to ensure I break down the more complex modeler geometry to something I can actually read out and hand over, since a BODY would only explode to SURFACEs. But yea... It seams to ignore them.
« Last Edit: July 04, 2013, 10:43:08 AM by S.Langhammer »

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Breaking unhandy entities
« Reply #4 on: July 04, 2013, 11:07:24 AM »
Well about point 1: as far as I understand it, all entities, that are visible in the modelspace, do have somehow a insertion Point, assuming you can click what you can see. I'm not interrested in invisible entities at all. I'm exporting entities so they can be drawed in glScene.
The problem is that the refedit command requires you to pick a point that is on a visible entity in the insert. A lot of inserts do not have a visible entity going through their insertion point.

About point 2: I don't see how that is relevant, at this Point. Maybe I lack of knoledge here.
In your code you use the trans function to translate the insertion point of inserts to the WCS. You then use this point for the refedit command. But all commands expect points in the current UCS. So your code will fail if the current UCS does not match the WCS.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Breaking unhandy entities
« Reply #5 on: July 04, 2013, 12:05:33 PM »
Regarding your last code:
Your code:           Is it a valid object name?  Does it support the explode method?
ACDBMODELERGEOMETRY  No                     
ACDBPOLYLINE         Yes                         Yes
ACDBPOLYGONMESH      Yes                         Yes
ACDBMLINE            Yes                         No
ACDBDIMENSION        No
ACDB2DPOLYLINE       No
ACDB3DPOLYLINE       Yes                         Yes


Sadly at least one more 'complex' object does not support the explode method:
ACDBPOLYFACEMESH

So for some complex objects using the explode command seems to be the only option.
I suggest using this approach:
  • Store the ename of the last modelspace entity.
  • Use vla-copyobjects to make a temporary copy of all 'complex' entities from the block definition to modelspace.
  • Delete these entities from the block definition.
  • Use the explode command on the temporary entities in modelspace until all complex entities are gone.
  • Using the stored ename from step 1, select all new entities in modelspace, use vla-copyobjects to copy them to the block definition and then delete them from modelspace.

Alternative 1:
Explode all inserts containing 'complex' entities. And then keep on using the explode command... This would be a lot easier of course.

Alternative 2:
Use the SAVEASR12 command. I know you have already rejected this (http://www.theswamp.org/index.php?topic=44640.msg498834#msg498834), but it is the easiest solution by far.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Breaking unhandy entities
« Reply #6 on: July 05, 2013, 01:13:46 AM »
Well about point 1: as far as I understand it, all entities, that are visible in the modelspace, do have somehow a insertion Point, assuming you can click what you can see. I'm not interrested in invisible entities at all. I'm exporting entities so they can be drawed in glScene.
Why then not use ACad's 3dsOut command. Or BricsCad's addon.

Especially seeing as glScene can import 3DS files including even materials: http://glscene.sourceforge.net/oldsite/faq.htm#120502-3
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Re: Breaking unhandy entities
« Reply #7 on: July 05, 2013, 01:33:26 AM »
Another alternative for you would be to write an import filter for glScene using OpenDwg's libraries. You should be able to link dynamically to the DLL/SO files from Delphi/Kylix/Lazarus (the IDE's used to create glScene). I know OpenDWG offers an ActiveX, DotNet and direct C++ libs. This way, you'd not even need AC/BC to open the DWG directly in glScene.
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

irneb

  • Water Moccasin
  • Posts: 1794
  • ACad R9-2016, Revit Arch 6-2016
Common sense - the curse in disguise. Because if you have it, you have to live with those that don't.

S.Langhammer

  • Guest
Re: Breaking unhandy entities
« Reply #9 on: July 05, 2013, 03:15:55 AM »
@roy:

Once I have the time, I'll try your routine, also the good thing is the Delphi side of the iterface can handle polyfacemeshes quite well and I manage to read them rather fast, so there's no need to explode them. (I guess I DO have luck sometimes.)

alternative 1 was rejected by my supervisor: We'll definetly need the whole block structure from the original, otherwhise I would just explode everything to the most basic entities and read then.

@irneb: We sell a BricsCAD licence along with the company software, not ACad (that would make things A LOT easier for me.) and sadly as it seems this addon is commercial and I don't think I'd get the ok for that, since I'm just a trainee and all.

I'll look through your suggestions once I have the time. Thank you to you all.

S.Langhammer

  • Guest
Re: Breaking unhandy entities
« Reply #10 on: July 05, 2013, 03:46:03 AM »
Ok an issue came to my mind now. It's propably a noob question:
Up until now i thought, that the information stored in the dxf groop code 100 (aka the subclass marker) would be the object name, this seems to be true for polyline polygon mesh and 3d polyline, but not for things like modeler geometry or dimensions. So where exactly is the object name stored in the groop dxf code? Is it stored there at all? I assume it should be, since you can read it somehow individually for every entity.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Breaking unhandy entities
« Reply #11 on: July 05, 2013, 04:01:06 AM »
Group code 100 can occur more than once:
Code: [Select]
(
  ...
  (0 . "DIMENSION")
  ...
  (100 . "AcDbEntity")
  ...
  (100 . "AcDbDimension")
  ...
  (100 . "AcDbAlignedDimension")
  ...
  (100 . "AcDbRotatedDimension") ; << The last one is the object name.
)

(
  ...
  (0 . "3DSOLID")
  ...
  (100 . "AcDbEntity")
  ...
  (100 . "AcDbModelerGeometry")
  ...
  (100 . "AcDb3dSolid") ; << The last one is the object name.
)

S.Langhammer

  • Guest
Re: Breaking unhandy entities
« Reply #12 on: July 10, 2013, 10:26:29 AM »
Thanks for the explenation roy!
And also thank you for helping me, even tho my posts tend to become more and more frustrated.
The further I dive into this whole LISP thing, the more I start to believe, that I cant completly accomplish the task, that was given to me.
Example: I finally understood (halfway) how to explode objects with vla commands based function you gave me. Woohoo, right? Well I tend to be oversceptical and in this case for a reason, since it's not able to explode hatches, surfaces, dimensions [...].  Please don't get me wrong, I don't want to criticize. Just after I checked the new function into the repository, the first question was: "Why don't you explode hatches, dimensions, surfaces and all other entities as well now to?"
I feel a little like a hamster in a wheel. Every time I make a step foreward in understanding how LISP and CAD-entities work or make some progress with my script, I seem to find something I can't do and that's what's being pointed out to me.
Another point, that doesn't make this whole thing easier is, that the boss of my company keeps asking the same questions: "Why isn't this finished yet?" "Why can't I see everything yet?" "Why isn't this fast yet?"
I'm not that much responsible for the total speed of the interface or for the visualisation but if these don't work the way they are supposed to, the whole project is going to be cancelled as a dead end and I wasted a lot of time.

Sorry for the wall of text here, I just needed to blow of some steam.
If anyone's actually reading this: thanks for that!

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Breaking unhandy entities
« Reply #13 on: July 11, 2013, 07:46:11 AM »
AutoLISP is not exactly kept up to date with all the features of the .dwg format, there are some strange omissions and many things are sorely missed. 'BricsCAD Lisp' will in most cases have the same issues. This is the downside of striving for compatibility.

FWIW:
Alternative 3:
Wblock blocks with 'complex' entities using the R12 SaveFormat. And then reinsert these blocks.

S.Langhammer

  • Guest
Re: Breaking unhandy entities
« Reply #14 on: July 11, 2013, 09:59:58 AM »
The last statement considering save format is a big no. : ( The interface is supposed wo work on future versions of BricsCAD as well and they might not have the R12 Format anymore. So I have to think of something else.

Now I'm using roy's method to break unhandy stuff. Works perfectly fine within all blocks, yet I filter anonymus blocks out.
Since the model space isn't anything else than an anonymus block (named "*Model_Space") I have to crash through that to.
Right now I do it like this:


Code - Auto/Visual Lisp: [Select]
  1. (while (setq LstBlk (tblnext "BLOCK" (not LstBlk)))
  2.         (if (/=(substr(cdr(assoc 2 LstBlk))1 1)"*")
  3.                 (foreach a '("ACDB3DSOLID" "ACDBBODY" "ACDBREGION" "ACDBPOLYLINE" "ACDBPOLYGONMESH" "ACDB3DPOLYLINE")
  4.                         (mapcar
  5.                                 '(lambda (object)
  6.                                         (if (= (strcase (vla-get-objectname object)) a)(progn
  7.                                                 (vla-explode object)
  8.                                                 (vla-erase object)
  9.                                         ))
  10.                                 )
  11.                                 (vla-collection->list
  12.                                         (vla-item
  13.                                                 (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
  14.                                                 (cdr(assoc 2 LstBlk))
  15.                                         )
  16.                                 )
  17.                         )
  18.                 )      
  19.         )
  20. )
  21. ;;; this is supposed to work in the model space
  22. (while (setq LstBlk (tblnext "BLOCK" (not LstBlk)))
  23.         (if (= (cdr(assoc 2 LstBlk)) "*Model_Space") ;; this should only let you into the model space block
  24.                 ;;; buit I never get there
  25.                 (foreach a '("ACDB3DSOLID" "ACDBBODY" "ACDBREGION" "ACDBPOLYLINE" "ACDBPOLYGONMESH" "ACDB3DPOLYLINE")
  26.                         (mapcar
  27.                                 '(lambda (object)
  28.                                         (if (= (strcase (vla-get-objectname object)) a)(progn
  29.                                                 (vla-explode object)
  30.                                                 (vla-erase object)
  31.                                         ))
  32.                                 )
  33.                                 (vla-collection->list
  34.                                         (vla-item
  35.                                                 (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
  36.                                                 "*Model_Space"
  37.                                         )
  38.                                 )
  39.                         )
  40.                 )
  41.         )
  42. )
  43.  

But as the comments Show to, I never get into the model space case.
Any suggestions, what I could do?

Lee Mac

  • Seagull
  • Posts: 12924
  • London, England
Re: Breaking unhandy entities
« Reply #15 on: July 11, 2013, 10:36:15 AM »
Right now I do it like this:
Code - Auto/Visual Lisp: [Select]
  1. (while (setq LstBlk (tblnext "BLOCK" (not LstBlk)))
  2.         (if (/=(substr(cdr(assoc 2 LstBlk))1 1)"*")
  3.                 (foreach a '("ACDB3DSOLID" "ACDBBODY" "ACDBREGION" "ACDBPOLYLINE" "ACDBPOLYGONMESH" "ACDB3DPOLYLINE")
  4.                         (mapcar
  5.                                 '(lambda (object)
  6.                                         (if (= (strcase (vla-get-objectname object)) a)(progn
  7.                                                 (vla-explode object)
  8.                                                 (vla-erase object)
  9.                                         ))
  10.                                 )
  11.                                 (vla-collection->list
  12.                                         (vla-item
  13.                                                 (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
  14.                                                 (cdr(assoc 2 LstBlk))
  15.                                         )
  16.                                 )
  17.                         )
  18.                 )      
  19.         )
  20. )
  21. ;;; this is supposed to work in the model space
  22. (while (setq LstBlk (tblnext "BLOCK" (not LstBlk)))
  23.         (if (= (cdr(assoc 2 LstBlk)) "*Model_Space") ;; this should only let you into the model space block
  24.                 ;;; buit I never get there
  25.                 (foreach a '("ACDB3DSOLID" "ACDBBODY" "ACDBREGION" "ACDBPOLYLINE" "ACDBPOLYGONMESH" "ACDB3DPOLYLINE")
  26.                         (mapcar
  27.                                 '(lambda (object)
  28.                                         (if (= (strcase (vla-get-objectname object)) a)(progn
  29.                                                 (vla-explode object)
  30.                                                 (vla-erase object)
  31.                                         ))
  32.                                 )
  33.                                 (vla-collection->list
  34.                                         (vla-item
  35.                                                 (vla-get-blocks (vla-get-activedocument (vlax-get-acad-object)))
  36.                                                 "*Model_Space"
  37.                                         )
  38.                                 )
  39.                         )
  40.                 )
  41.         )
  42. )
  43.  

Sorry, but I cannot stress strongly enough how terribly inefficient your code is.

Here is what your code is currently doing (pseudo-code):
Code - Text: [Select]
  1. For every block in the block table
  2.     If the block is not an anonymous block
  3.         For every objectname in the list
  4.             Convert the collection of block components into a list
  5.             Iterate over the list of block components
  6.             If the objectname of the component matches the item currently processed
  7.                 Explode the object
  8.                 Erase the original object
  9.             end if
  10.         end foreach
  11.     end if
  12. end foreach
  13. For every block in the block table (again)
  14.     If the block is the Modelspace block
  15.         For every objectname in the list
  16.             Convert the collection of all objects in Modelspace into a list
  17.             Iterate over the list of every object in Modelspace
  18.             If the objectname of the component matches the item currently processed
  19.                 Explode the object
  20.                 Erase the original object
  21.             end if
  22.         end foreach
  23.     end if
  24. end foreach

Think about what the code is doing for each block processed:
Code - Text: [Select]
  1. Process first block in block table
  2.     Block is not anonymous
  3.         Process "ACDB3DSOLID"
  4.             Convert the collection of every object in the block into a list
  5.             Iterate over this list
  6.             If objectname = "ACDB3DSOLID"
  7.                 Explode object
  8.                 Erase object
  9.             end if
  10.         Process "ACDBBODY"
  11.             Convert the collection of every object in the block into a list (again)
  12.             Iterate over this list (the same list)
  13.             If objectname = "ACDBBODY"
  14.                 Explode object
  15.                 Erase object
  16.             end if
  17.         Process "ACDBREGION"
  18.             Convert the collection of every object in the block into a list (and again)
  19.             Iterate over this list (the same list again)
  20.             If objectname = "ACDBREGION"
  21.                 Explode object
  22.                 Erase object
  23.             end if
  24.         ...
  25.     ...
  26. Process second block in block table...
  27. ...
  28.  

Notice that, for every block, the collection of objects in each block definition (which could potentially be hundreds, if not thousands of objects) is being converted to a list and iterated over... 6 times!

And that's before you do the same thing and iterate over EVERY object in Modelspace another 6 times!  :-o

Furthermore, you are needlessly retrieving the AutoCAD Application object & Block Collection object (an inefficient & slow process in itself) 6 times for EVERY block processed, and another 6 times for the Modelspace block!

Note also that your code will not account for nested blocks (or other explodable nested objects) - if a block reference or block definition were to contain a nested block or explodable object (such as a polyline), or even perhaps multiple blocks nested within each other several levels deep, when the parent block is exploded, the nested blocks & objects will now be present within the containing object (Modelspace / Block Definition) and will remain in the drawing since the code will have already iterated over the block definition.

Consider the following alternative:
Code - Auto/Visual Lisp: [Select]
  1. (defun explodeall ( )
  2.         (vlax-map-collection blk 'explode)
  3.     )
  4.     (princ)
  5. )
  6.  
  7. (defun explode ( obj / lst )
  8.     (if (vlax-method-applicable-p obj 'explode)
  9.         (if (not (vl-catch-all-error-p (setq lst (vl-catch-all-apply 'vlax-invoke (list obj 'explode)))))
  10.             (progn
  11.                 (vla-delete obj)
  12.                 (foreach obj lst (explode obj))
  13.             )
  14.         )
  15.     )
  16. )

The above will iterate over all objects in all block definitions (including all drawing layouts), and will attempt to explode every object. To account for the possibility of nested blocks & other nested explodable objects, the function will recursively iterate over the set of exploded objects, repeating the process to ensure every explodable object is exploded.
« Last Edit: July 11, 2013, 10:47:45 AM by Lee Mac »

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Breaking unhandy entities
« Reply #16 on: July 11, 2013, 10:57:02 AM »
I never get into the model space case.
Your problem is caused by the second use of:
Code: [Select]
(tblnext "BLOCK" (not LstBlk))at that point (not LstBlk) returns nil instead of T.

I suggest using this approach:
  • Store the ename of the last modelspace entity.
  • Use vla-copyobjects to make a temporary copy of all 'complex' entities from the block definition to modelspace.
  • Delete these entities from the block definition.
  • Use the explode command on the temporary entities in modelspace until all complex entities are gone.
  • Using the stored ename from step 1, select all new entities in modelspace, use vla-copyobjects to copy them to the block definition and then delete them from modelspace.
Here is a function using this approach:
Code - Auto/Visual Lisp: [Select]
  1. ; Argument:     Object in block definition as vla-object or ename.
  2. ;               The function does not check if the object can be exploded.
  3. ; Return value: List of new objects in the block definition as list of vla-objects.
  4. (defun ExplodeObjectInBlock (object / N_ExplodeCommand N_ExplodeMethod)
  5.  
  6.   (defun N_ExplodeCommand (object / docObject lastEname newEnameList newObjectList ownerObject tempObject)
  7.     (setq ownerObject (vla-objectidtoobject docObject (vla-get-ownerid object)))
  8.     ; Store the ename of the last object in modelspace:
  9.     (setq lastEname (entlast))
  10.     ; Required for 'SEQEND situations':
  11.     (while (entnext lastEname)
  12.       (setq lastEname (entnext lastEname))
  13.     )
  14.     ; Make a temporary copy of the object from the block definition to modelspace:
  15.     (setq tempObject
  16.       (car
  17.         (vlax-invoke
  18.           docObject
  19.           'copyobjects
  20.           (list object)
  21.           (vla-get-modelspace docObject)
  22.         )
  23.       )
  24.     )
  25.     ; Delete the object from the block definition:
  26.     (vla-delete object)
  27.     ; Use the explode command:
  28.     (setvar 'cmdecho 0)
  29.     (command "_.explode" (vlax-vla-object->ename tempObject))
  30.     (setvar 'cmdecho 1)
  31.     ; Get the enames of all new objects in modelspace:
  32.     (while (setq lastEname (entnext lastEname))
  33.       (setq newEnameList (cons lastEname newEnameList))
  34.     )
  35.     ; Copy the new objects to the block definition:
  36.     (if newEnameList
  37.       (setq newObjectList
  38.         (vlax-invoke
  39.           docObject
  40.           'copyobjects
  41.           (mapcar 'vlax-ename->vla-object newEnameList)
  42.           ownerObject
  43.         )
  44.       )
  45.     )
  46.     ; Delete the new entities from modelspace:
  47.     (mapcar 'entdel newEnameList)
  48.     ; Return the new objects in the block definition:
  49.     newObjectList
  50.   )
  51.  
  52.   (defun N_ExplodeMethod (object / newObjectList)
  53.     (setq newObjectList (vlax-invoke object 'explode))
  54.     (vla-delete object)
  55.     ; Return the new objects in the block definition:
  56.     newObjectList
  57.   )
  58.  
  59.   (if (= (type object) 'ename) (setq object (vlax-ename->vla-object object)))
  60.   (if (vlax-method-applicable-p object 'explode)
  61.     (N_ExplodeMethod object)
  62.     (N_ExplodeCommand object)
  63.   )
  64. )

@ Lee: you make a good point. But the OP does not want to explode ALL objects.

Lee Mac

  • Seagull
  • Posts: 12924
  • London, England
Re: Breaking unhandy entities
« Reply #17 on: July 11, 2013, 11:04:49 AM »
@ Lee: you make a good point. But the OP does not want to explode ALL objects.

I see - a conditional could quite easily be added to control which objects are exploded  :-)
BTW, good idea to enable use of the explode command for block components roy.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Re: Breaking unhandy entities
« Reply #18 on: July 11, 2013, 01:10:01 PM »
Your code:           Is it a valid object name?  Does it support the explode method?
ACDB2DPOLYLINE       No

I have to correct this:
Your code:           Is it a valid object name?  Does it support the explode method?
ACDB2DPOLYLINE       Yes                         Yes


Here is an improved version of the function in my previous post:
Code - Auto/Visual Lisp: [Select]
  1. ;;; Argument:     Object in a block definition (can be modelspace) as vla-object or ename.
  2. ;;;               The function does not check if the object can be exploded.
  3. ;;; Return value: List of new objects in the block definition as list of vla-objects.
  4. (defun ExplodeObject  (object
  5.                         / N_ExplodeCommandModelSpace
  6.                           N_ExplodeCommandOther
  7.                           N_ExplodeMethod
  8.                           docObject modelSpaceObject ownerObject
  9.                       )
  10.  
  11.   (defun N_ExplodeCommandModelSpace (object / lastEname newEnameList)
  12.     ; Store the ename of the last object in modelspace:
  13.     (setq lastEname (entlast))
  14.     ; Required for 'SEQEND situations':
  15.     (while (entnext lastEname)
  16.       (setq lastEname (entnext lastEname))
  17.     )
  18.     ; Use the explode command:
  19.     (setvar 'cmdecho 0)
  20.     (command "_.explode" (vlax-vla-object->ename object))
  21.     (setvar 'cmdecho 1)
  22.     ; Get the enames of all new objects in modelspace:
  23.     (while (setq lastEname (entnext lastEname))
  24.       (setq newEnameList (cons lastEname newEnameList))
  25.     )
  26.     (mapcar 'vlax-ename->vla-object newEnameList)
  27.   )
  28.  
  29.   ;; The function uses the following variables from the main function:
  30.   ;;   docObject
  31.   ;;   modelSpaceObject
  32.   ;;   ownerObject
  33.   (defun N_ExplodeCommandOther (object / lastEname newEnameList newObjectList tempObject)
  34.     ; Store the ename of the last object in modelspace:
  35.     (setq lastEname (entlast))
  36.     ; Required for 'SEQEND situations':
  37.     (while (entnext lastEname)
  38.       (setq lastEname (entnext lastEname))
  39.     )
  40.     ; Make a temporary copy of the object from the block definition in modelspace:
  41.     (setq tempObject
  42.       (car
  43.         (vlax-invoke
  44.           docObject
  45.           'copyobjects
  46.           (list object)
  47.           modelSpaceObject
  48.         )
  49.       )
  50.     )
  51.     ; Delete the object from the block definition:
  52.     (vla-delete object)
  53.     ; Use the explode command:
  54.     (setvar 'cmdecho 0)
  55.     (command "_.explode" (vlax-vla-object->ename tempObject))
  56.     (setvar 'cmdecho 1)
  57.     ; Get the enames of all new objects in modelspace:
  58.     (while (setq lastEname (entnext lastEname))
  59.       (setq newEnameList (cons lastEname newEnameList))
  60.     )
  61.     ; Copy the new objects to the block definition:
  62.     (if newEnameList
  63.       (setq newObjectList
  64.         (vlax-invoke
  65.           docObject
  66.           'copyobjects
  67.           (mapcar 'vlax-ename->vla-object newEnameList)
  68.           ownerObject
  69.         )
  70.       )
  71.     )
  72.     ; Delete the new entities from modelspace:
  73.     (mapcar 'entdel newEnameList)
  74.     ; Return the new objects in the block definition:
  75.     newObjectList
  76.   )
  77.  
  78.   (defun N_ExplodeMethod (object / newObjectList)
  79.     (setq newObjectList (vlax-invoke object 'explode))
  80.     (vla-delete object)
  81.     ; Return the new objects in the block definition:
  82.     newObjectList
  83.   )
  84.  
  85.   (if (= (type object) 'ename) (setq object (vlax-ename->vla-object object)))
  86.   (if (vlax-method-applicable-p object 'explode)
  87.     (N_ExplodeMethod object)
  88.     (progn
  89.       ; Make sure that modelspace is current:
  90.       (setvar 'tilemode 1)
  91.       (setq modelSpaceObject (vla-get-modelspace docObject))
  92.       (setq ownerObject (vla-objectidtoobject docObject (vla-get-ownerid object)))
  93.       (if (= ownerObject modelSpaceObject)
  94.         (N_ExplodeCommandModelSpace object)
  95.         (N_ExplodeCommandOther object)
  96.       )
  97.     )
  98.   )
  99. )