Author Topic: Breaking unhandy entities  (Read 7442 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?