Entmaking XDATA

Discussion in 'AutoCAD' started by David Bethel, May 5, 2004.

  1. David Bethel

    David Bethel Guest

    Greetings,

    I can't find the right combination for entmaking a entity ( a line in
    this case ) in the following code if XDATA is not present: R12 -> A2K

    (defun c:cline (/ en ed)

    (setq *error* nil)

    (setq en (car (entsel "\nSelect Line: "))
    ed (entget en '("*")))

    (foreach g '(-3 0 6 8 10 11 39 62 67 210)
    (set (read (strcat "g" (itoa g)))
    (cdr (assoc g ed))))

    (entmake (list (cons 0 g0)
    (cons 8 g8)
    (cons 10 g10)
    (cons 11 g11)
    (cons 210 g210)
    ; (cons -3 (if g-3 g-3 '("")))
    ; (cons -3 (if g-3 g-3 nil))
    ; (cons -3 (if g-3 g-3 '()))
    ; (if g-3 (cons -3 g-3))
    (cons 6 (if g6 g6 "BYLAYER"))
    (cons 39 (if g39 g39 0))
    (cons 62 (if g62 g62 256))
    (cons 67 (if g67 g67 0))))

    (entdel en)
    (redraw (entlast))

    ; (foreach g '(-3 0 6 8 10 11 39 62 67 210)
    ; (set (read (strcat "g" (itoa g))) nil))

    (prin1))


    The routine crashes in all of the commented instances. No so, if say g62
    color is nil.

    Any suggestions? TIA -David
     
    David Bethel, May 5, 2004
    #1
  2. David Bethel

    Rudy Tovar Guest

    Try this...

    ;(Xdata-add Data App String Appname Layer Handle 3D Real Int)

    (defun Xdata-add (Data Part String Appname Layer Handle 3D Real Int /)
    (if (not (tblsearch "appid" Part))
    (regapp (strcat "Your_" Part))
    )
    (setq XDlist (list (strcat "Your_" Part)))
    (if String (setq XDlist (append XDlist (list (cons 1000 String)))))
    (if Appname (setq XDlist (append XDlist (list (cons 1001 Appname)))))
    (if Layer (setq XDlist (append XDlist (list (cons 1003 Layer)))))
    (if Handle (setq XDlist (append XDlist (list (cons 1005 Handle)))))
    (if 3D (setq XDlist (append XDlist (list (cons 1010 3D)))))
    (if Real (setq XDlist (append XDlist (list (cons 1040 Real)))))
    (if Int (setq XDlist (append XDlist (list (cons 1070 Int)))))
    (entmod (append Data (list (list -3 Xdlist))))
    )

    (defun xdata? (ename Part /)
    (assoc -3 (entget ename (list Part)))
    )
    --

    AUTODESK
    Authorized Developer
    http://www.Cadentity.com
    MASi
     
    Rudy Tovar, May 5, 2004
    #2
  3. Just lookin' quick ...

    Do you really want entdel/entmake and not entmod?

    and perhaps <hint>

    (append
    '("this")
    nil
    '("and")
    nil
    '("that")
    )

    returns

    ("this" "and" "that")

    </hint>

    When I do this I typically delegate the task of creating
    the xdata construct to a separate function which either
    returns the formatted data or nil, which then the calling
    function can then deal with. For example, as suggested
    above, by using append.

    HTH.

    Michael.

    Greetings,

    I can't find the right combination for entmaking a entity ( a line in
    this case ) in the following code if XDATA is not present: R12 -> A2K

    (defun c:cline (/ en ed)

    (setq *error* nil)

    (setq en (car (entsel "\nSelect Line: "))
    ed (entget en '("*")))

    (foreach g '(-3 0 6 8 10 11 39 62 67 210)
    (set (read (strcat "g" (itoa g)))
    (cdr (assoc g ed))))

    (entmake (list (cons 0 g0)
    (cons 8 g8)
    (cons 10 g10)
    (cons 11 g11)
    (cons 210 g210)
    ; (cons -3 (if g-3 g-3 '("")))
    ; (cons -3 (if g-3 g-3 nil))
    ; (cons -3 (if g-3 g-3 '()))
    ; (if g-3 (cons -3 g-3))
    (cons 6 (if g6 g6 "BYLAYER"))
    (cons 39 (if g39 g39 0))
    (cons 62 (if g62 g62 256))
    (cons 67 (if g67 g67 0))))

    (entdel en)
    (redraw (entlast))

    ; (foreach g '(-3 0 6 8 10 11 39 62 67 210)
    ; (set (read (strcat "g" (itoa g))) nil))

    (prin1))


    The routine crashes in all of the commented instances. No so, if say g62
    color is nil.

    Any suggestions? TIA -David
     
    michael puckett, May 5, 2004
    #3
  4. David Bethel

    David Bethel Guest

    Yes, I really want to entmake / entdel. I trying to strip out unwanted
    DXF codes that the existing entiy has. So I want just the basic DXF
    data including XDATA and just remake the thing.

    My best attempt so far:

    (setq ml (list (cons 0 g0)
    (cons 8 g8)
    (cons 10 g10)
    (cons 11 g11)
    (cons 210 g210)
    (cons 6 (if g6 g6 "BYLAYER"))
    (cons 39 (if g39 g39 0))
    (cons 62 (if g62 g62 256))
    (cons 67 (if g67 g67 0))))

    (if g-3 (setq ml (append ml (list (cons -3 g-3)))))

    (entmake ml)

    I just think entmake should be able to handle it in-line. -David
     
    David Bethel, May 5, 2004
    #4
  5. David Bethel

    David Bethel Guest

    Rudy,

    I don't know what kind of XDATA it is, I just need to duplicate it.

    If only a string were to be added, I take it you would call this by:

    (xdata-add ent_def_list "APPID" "String" nil nil nil nil nil nil)

    ? -David
     
    David Bethel, May 5, 2004
    #5
  6. Haven't tried this; I don't have your data loaded up, but perhaps ...

    (setq ml
    (append
    (list
    (cons 0 g0)
    (cons 8 g8)
    (cons 10 g10)
    (cons 11 g11)
    (cons 210 g210)
    (cons 6 (if g6 g6 "BYLAYER"))
    (cons 39 (if g39 g39 0))
    (cons 62 (if g62 g62 256))
    (cons 67 (if g67 g67 0))
    )
    (if g-3 (setq ml (append ml (list (cons -3 g-3)))))
    )
    )


    Yes, I really want to entmake / entdel. I trying to strip out unwanted
    DXF codes that the existing entiy has. So I want just the basic DXF
    data including XDATA and just remake the thing.

    My best attempt so far:

    (setq ml (list (cons 0 g0)
    (cons 8 g8)
    (cons 10 g10)
    (cons 11 g11)
    (cons 210 g210)
    (cons 6 (if g6 g6 "BYLAYER"))
    (cons 39 (if g39 g39 0))
    (cons 62 (if g62 g62 256))
    (cons 67 (if g67 g67 0))))

    (if g-3 (setq ml (append ml (list (cons -3 g-3)))))

    (entmake ml)

    I just think entmake should be able to handle it in-line. -David
     
    michael puckett, May 5, 2004
    #6
  7. David Bethel

    Doug Broad Guest

    David,
    I suggest you make the line and then add the xdata

    ;;untested.
    (and
    (setq newinfo (entmake '((cons 0 "line").....))
    (setq oldxdata (entget <enname> '("*")))
    (entmake (list (assoc -1 newinfo) oldxdata))
    )

    You may have to add the xdata for each application
    separately (uncertain).

    The copy command also carries the all the xdata to the new
    entitiy.
     
    Doug Broad, May 5, 2004
    #7
  8. David Bethel

    David Bethel Guest

    Yes,

    That works as well, just looks a little funny. -David
     
    David Bethel, May 5, 2004
    #8
  9. <scrap my other responses, perhaps this too>

    Let me understand the problem ...

    In essence, you are deleting and then re-creating an
    entity in order to remove a bunch of crud (not described)
    you don't want?

    If that is the case then maybe, just maybe this will help,
    though I don't have anything to test it on, so it was blind
    coding.

    <Since you spec'd r12 I won't use vl-remove>.

    Code:
    
    (defun c:cline ( / keepkeys ename data xdata )
    
    ;;  local defun
    
    (defun keepkeys ( lst keylist / result )
    ;;  not robust, just quick
    (foreach item (reverse lst)
    (if (member (car item) keylist)
    (setq result (cons item result))
    )
    )
    result
    )
    
    ;; "main"
    
    (cond
    (   (setq ename (car (entsel)))
    (setq data
    (keepkeys
    (entget ename '("*"))
    ;; presumably 100 groups aren't needed
    ;; because lines are "old school" entities
    '(-3 0 6 8 10 11 39 62 67 210)
    )
    )
    (entdel ename)
    (entmake data)
    )
    (   (princ "Fancy error message here.")  )
    )
    (princ)
    )
    
    
    Greetings,

    I can't find the right combination for entmaking a entity ( a line in
    this case ) in the following code if XDATA is not present: R12 -> A2K

    (defun c:cline (/ en ed)

    (setq *error* nil)

    (setq en (car (entsel "\nSelect Line: "))
    ed (entget en '("*")))

    (foreach g '(-3 0 6 8 10 11 39 62 67 210)
    (set (read (strcat "g" (itoa g)))
    (cdr (assoc g ed))))

    (entmake (list (cons 0 g0)
    (cons 8 g8)
    (cons 10 g10)
    (cons 11 g11)
    (cons 210 g210)
    ; (cons -3 (if g-3 g-3 '("")))
    ; (cons -3 (if g-3 g-3 nil))
    ; (cons -3 (if g-3 g-3 '()))
    ; (if g-3 (cons -3 g-3))
    (cons 6 (if g6 g6 "BYLAYER"))
    (cons 39 (if g39 g39 0))
    (cons 62 (if g62 g62 256))
    (cons 67 (if g67 g67 0))))

    (entdel en)
    (redraw (entlast))

    ; (foreach g '(-3 0 6 8 10 11 39 62 67 210)
    ; (set (read (strcat "g" (itoa g))) nil))

    (prin1))


    The routine crashes in all of the commented instances. No so, if say g62
    color is nil.

    Any suggestions? TIA -David
     
    michael puckett, May 5, 2004
    #9
  10. David Bethel

    Rudy Tovar Guest

    YES

     
    Rudy Tovar, May 5, 2004
    #10
  11. Excuse me if this comes off like a sermon, but.....

    If your intention is to replace an existing entity with
    another one, you should keep in mind that AutoCAD and/or
    other applications may have data associated with the entity
    via its extension dictionary, or may have references to the
    existing entity via its handle or object id. This approach
    will discard the original entity's extension dictionary,
    and break any references to it as well.

    For example, draworder stores references to entities in the
    model space's extension dictionary, which would be broken
    by replacing the existing entity, rather than modifying it.

    The general practice of modifying one logical entity in a
    drawing by erasing and replacing it with another, new entity
    is highly flawed. That's simply because doing that undermines
    references and attached data in ways that are beyond a user's
    understanding. To an end user, it looks like you modified an
    existing entity but in reality, you didn't.

    Another for-instance: What if entity that's replaced was a
    member of one or more groups? Since the user perceives the
    operation as a modification of an existing entity, wouldn't
    they expect the 'modified' entity to remain a member of the
    groups they assigned it to? Well, what do we do about that?

    In fact, many AutoCAD operations do precisely this (the BREAK
    command for example, replaces a circle with an arc), but they
    also take the mandatory step of swapping the xdata; extension
    dictionaries; entity handles; and object ids of the existing and
    'replacement' entities (effectively swapping their 'identities'),
    in order to 'make things right'. AutoLISP/ActiveX applications
    don't have this luxury, however.

    One area where I've had problems with my own application's
    data being discarded, is when a user replaces an existing
    entity with a new one that was created by OFFSETting the
    existing entity, and then erasing it. The user didn't know
    that they were trashing the application data on the existing
    entity, and the OFFSET command (which isn't really an editing
    command, but an entity creation command) does not do any of
    the aforementioned swapping of object ids or application data
    (it can't because it doesn't erase the original offset entity).

    So, what I ended up doing was making a new command, called
    'INFLATE' which is essentially offset + delete-the-original
    entity. It replaces the existing entities with new ones it
    creates by offsetting the existing ones, before it erases the
    original. And, it also does the aforementioned swapping of
    identities and application data. That solution isn't the best,
    but had to be done to cater to end user idiosyncrasies, which
    is something we must do.

    There is a very good reason why AutoCAD performs this swapping
    of xdata; extension dictionaries; and identities, and my mission
    here, is to try to help everyone better understand it, so they
    may also understand how to build robust applications that play
    nice with, and don't stomp all over each other, or AutoCAD.
     
    Tony Tanzillo, May 5, 2004
    #11
  12. David Bethel

    Rudy Tovar Guest

    Excuse me for questioning, but would he be the one determining the
    information that being stored, and would he have to address how that
    information is passed?

    Or are you perhaps associating that some other object within his drawing
    file or application is processing information within his objects?

    Just curious.
     
    Rudy Tovar, May 5, 2004
    #12
  13. David Bethel

    David Bethel Guest

    michael,

    Yes, you have basic premise. Matching the groups to the data is good.
    I do need to add back in 6, 39, 62 & 67 codes as entmake defaults to
    the current settings store in the respective sysvar. 67 was 1 for
    paperspace and missing for model space in R12. 48 & 60 are after R12.

    You can't entmake a viewport, so those codes would be useless anyway.

    The next step in the process is PLINEs and attributed INSERT so 66 will
    have to be included as well as VERTICEs and ATTRIBs and the SEQENDs

    The final list will probably look like this:

    '(-3 -1 0 2 3 6 7 8 10 11 12 13 14 15 16 39 40 41 42 43 44 45 48 50 51
    52 53 60 62 66 67 70 71 72 73 74 75 210)

    Thanks for another approach. -David


     
    David Bethel, May 5, 2004
    #13
  14. David Bethel

    Doug Broad Guest

    Excellent points!


    <snip>
     
    Doug Broad, May 5, 2004
    #14
  15. David Bethel

    David Bethel Guest

    Doug,

    I'll have to check, but I think all XDATA is listed in (1) -3 group.

    The copy command also carries over the crud I'm trying to get rid of.
    -David
     
    David Bethel, May 5, 2004
    #15
  16. I'm not sure I understand your question worded that way.

    An entity's extension dicationary is a communal affair,
    e.g., any number of applications can hang data on it.

    Manual duplication of everything in an extension dictionary
    is not always possible, because it may contain custom objects
    that have their own formally-defined 'copying' methods that
    are only invoked when an entity is deep-cloned as part of
    operations like WBLOCK, INSERT, EXPLODE, BLOCK, COPY, etc.
     
    Tony Tanzillo, May 5, 2004
    #16
  17. Notwithstanding Tony's advice (which you would be
    well advised to pay heed) given the size of that
    list of "keepers", it may be easier to identify
    the codes you wish to eliminate; '(-1 5 330 ...).

    Code:
    
    (defun removekeys ( lst keylist / result )
    ;;  not robust, just penned quick
    (foreach item (reverse lst)
    (if (null (member (car item) keylist))
    (setq result (cons item result))
    )
    )
    result
    )
    
    
    Cheers :)

    michael,

    Yes, you have basic premise. Matching the groups to the data is good.
    I do need to add back in 6, 39, 62 & 67 codes as entmake defaults to
    the current settings store in the respective sysvar. 67 was 1 for
    paperspace and missing for model space in R12. 48 & 60 are after R12.

    You can't entmake a viewport, so those codes would be useless anyway.

    The next step in the process is PLINEs and attributed INSERT so 66 will
    have to be included as well as VERTICEs and ATTRIBs and the SEQENDs

    The final list will probably look like this:

    '(-3 -1 0 2 3 6 7 8 10 11 12 13 14 15 16 39 40 41 42 43 44 45 48 50 51
    52 53 60 62 66 67 70 71 72 73 74 75 210)

    Thanks for another approach. -David
     
    michael puckett, May 5, 2004
    #17
  18. David Bethel

    Doug Broad Guest

    What kind of stuff are you trying to get rid of?

    I would agree with Tony that modifying an entity would
    be better than deleting and recreating the entity. If
    those things aren't of concern, then something like Michael's
    would be good. I don't think a single keyword sequence
    would work for all types of entities however. You might
    need to use a branch that would allow more flexibility for
    the order of the keys.

    Code:
    (setq keys
    (cond
    ((= etype "LINE" '(0 10 11 ....))
    ((= etype "CIRCLE" '(0 10 .....))
    ))
    
    
     
    Doug Broad, May 5, 2004
    #18
  19. David Bethel

    David Bethel Guest

    Tony,

    That's pretty much what I am doing. Trashing all of the extemporaneous
    data. I even turn HANDLEs off in R12. This is so that when the client
    gets the DWG file back ( he supplied the back ground ) that we have
    worked on, none of the entities that I give back to them will conflict
    with any of their existing ones. XDATA excluded.

    example:

    You supply me with an interior wall layout. You have all of this fancy
    stuff attached. I add my stuff to it. I send it back with just the
    most basic info. You overlay, insert, xref, whatever, no way my stuff
    will conflict with yours. And mine can still be used as stand alone dwg.

    Does that make sense? -David
     
    David Bethel, May 5, 2004
    #19
  20. Not only is this sound advice, it would be the norm
    rather than the exception. A failure to code accordingly
    could render a drawing mortally lobotomized. Thank you
    for the heads up.


    Excuse me if this comes off like a sermon, but.....

    If your intention is to replace an existing entity with
    another one, you should keep in mind that AutoCAD and/or
    other applications may have data associated with the entity
    via its extension dictionary, or may have references to the
    existing entity via its handle or object id. This approach
    will discard the original entity's extension dictionary,
    and break any references to it as well.

    [snip ...]
     
    michael puckett, May 5, 2004
    #20
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.