Lisp to center text

Discussion in 'AutoCAD' started by Martin Shoemaker, Feb 22, 2005.

  1. I'm working on a routine to clean up equipment schedules we get from
    other consultants. The schedules tend to be a mixture of MTEXT and
    TEXT. The goal is to convert each entity to TEXT that is middle center
    justified in the cell.

    The TEXT side is working OK. I'm having a problem with MTEXT. The
    (command "_explode" ...) works, but the entity in the selection set
    isn't updated, so the entity that was just converted to TEXT isn't
    handled by the "(if (= "TEXT" ...) routine. I'm looking for suggestions
    on how to either force an update of the selection set after the explode,
    or to add the converted entity to the selection set so the TEXT entity
    will be handled later in the loop. I've tried everything I can think of
    but I can't get either to work. Probably really simple, but after a 14
    hour day....

    All suggestions appreciated.

    Martin


    (defun C:AT (/ selset box1 box2)

    (defun get_center ( lstPtIn / entity_boundary entity3 index3
    vertices temp num_vertices x_min

    y_min x_max y_max x_avg
    y_avg z_avg centroid
    )

    (command "_.boundary" "a" "o" "p" "" lstPtIn "")
    (setq entity_boundary (entlast))
    (setq entity3 (entget (entlast)))
    (entdel entity_boundary)
    (setq vertices (list)) ; create an empty list to

    ; store the vertices in.
    (foreach temp entity3 ; step through each sub-list
    (if (= 10 (car temp)) ; if the first item in the
    ; sub-list equals 10 then ...
    (setq vertices ; reset vertices to the old
    ; list plus the new point
    (append vertices
    (list
    (cdr temp)
    )
    )
    )
    )
    )
    (setq num_vertices (length vertices))
    (setq x_min (apply 'min (mapcar 'car vertices)))
    (setq y_min (apply 'min (mapcar 'cadr vertices)))
    (setq x_max (apply 'max (mapcar 'car vertices)))
    (setq y_max (apply 'max (mapcar 'cadr vertices)))
    (setq index3 0)
    (setq z_avg nil)
    (setq x_avg (/ (apply '+ (mapcar 'car vertices)) num_vertices))
    (setq y_avg (/ (apply '+ (mapcar 'cadr vertices)) num_vertices))
    (setq centroid (list x_avg y_avg))
    (setq box1 (list x_min y_min 0.0))
    (setq box2 (list x_max y_max 0.0))
    centroid
    )

    (defun dxf (1code 1ent) (cdr (assoc 1code 1ent)))

    (setvar "CMDECHO" 0)
    (setq selset (ssget))
    (if selset
    (progn
    (setq index 0)
    (while (< index (sslength selset))
    (setq entity (entget (ssname selset index)))
    (if (= "MTEXT" (dxf 0 entity))
    (progn
    (setq ins_point (dxf 10 entity))
    ;>>>>>>>>
    (command "_.explode" (ssname selset index))
    )
    )
    ;>>>>>>>>
    (if (= "TEXT" (dxf 0 entity))
    (progn
    (setq center_point (get_center (dxf 10 entity)))
    (if (= (cddr center_point) nil)
    (setq center_point (list (car center_point)
    (cadr center_point) 0.0))
    )
    (setq selset3 (ssget "_C" box1 box2 '((0 . "TEXT"))))
    (if (= 1 (sslength selset3))
    (progn
    (setq entity (entget (ssname selset3 0)))
    (setq hjus (assoc '72 entity))
    (setq vjus (assoc '73 entity))
    (setq apoi (cons 11 center_point))
    (setq hnew (cons 72 1))
    (setq vnew (cons 73 2))
    (setq entity (subst hnew hjus entity))
    (setq entity (subst vnew vjus entity))
    (setq entity (subst apoi (assoc '11 entity) entity))
    (entmod entity)
    )
    )
    )
    )
    (setq index (1+ index))
    )
    )
    )
    )
     
    Martin Shoemaker, Feb 22, 2005
    #1
  2. Martin Shoemaker

    Walt Engle Guest

    Can you insert the routine below into your lsp?

    ;CHANGES MTEXT TO REGULAR TEXT
    (defun C:MTT (/ en ent nent lyr ipt tsz txt sty elv spc ts pt pty
    npty ptx ptz npt)
    (setq en (car (entsel "\nSelect MTEXT to change to regular text "))
    ent (entget en)
    nent (car ent)
    )
    (setq lyr (assoc 8 ent)
    ipt (assoc 10 ent)
    tsz (assoc 40 ent)
    txt (assoc 1 ent)
    sty (assoc 7 ent)
    elv (assoc 210 ent)
    spc (assoc 67 ent)
    )
    (setq ts (cdr tsz)
    pt (cdr ipt)
    pty (cadr pt)
    npty (- pty ts)
    ptx (car pt)
    ptz (caddr pt)
    npt (list ptx npty ptz)
    ipt (cons 10 npt)
    )
    (setq nent
    (list nent (cons 0 "TEXT")
    (cons 100 "AcDbEntity")
    spc
    lyr
    (cons 100 "AcDbText")
    ipt
    tsz
    txt
    (cons 50 0.0)
    (cons 41 1.0)
    (cons 51 0.0)
    sty
    (cons 71 0)
    (cons 72 0)
    (cons 11 (list 0.0 0.0 0.0))
    elv
    (cons 73 0)
    ))
    (entdel en)
    (entmake nent)
    (princ)
    )
     
    Walt Engle, Feb 22, 2005
    #2
  3. Walt,

    Thanks for the suggestion. This function was one of the things I had
    tried. I have two problems with this approach. First, much of the
    MTEXT I'm working with has formatting codes that would have to be
    stripped, and some has multiple lines in a cell, which would have to be
    split out. Not a big thing, just a nuisance to resolve. Second, in
    most cases the string shifts location, which moves the insertion point
    outside the cell. That's fixable, too, but both fixes add a lot of
    complexity. The explode function takes care of both -- there's just the
    problem of getting the new entity into the selection set so it can be
    processed.

    Martin
     
    Martin Shoemaker, Feb 22, 2005
    #3
  4. Martin Shoemaker

    Joe Burke Guest

    Martin,

    I think using explode is a good idea. But I also think your code structure is flawed
    after (if selest... For instance, (if (= "MTEXT" has no effect on (if (= "TEXT" as
    you seem to imply.

    In general this seems a good example of why nested ifs are hard to follow and should
    be avoided when more straightforward methods are available.

    Regards
    Joe Burke
     
    Joe Burke, Feb 22, 2005
    #4
  5. Joe,

    Thanks for the comment. The code is still very much in development and
    there may be structural issues. It will probably look much different in
    its final form. I probably posted too much code so that the problem
    wasn't clear.

    I'm an engineer, not a programmer, but I'm not sure there's a viable
    alternate on the structure. The '(if (selset' is a necessary test to
    assure the selection set is not empty. The '(if (= "MTEXT"' and '(if (=
    "TEXT"' are sequential by design. The intended program sequence in this
    section is:

    1. Check if the entity in the selection set is MTEXT. If so,
    convert the entity to a TEXT entity. The resulting TEXT entity
    must be placed in 'selset'. [the (if (= "MTEXT" ]

    2. If the current entity is TEXT (whether it was originally a TEXT
    entity or was converted from MTEXT in step 1) center the text in
    the associated cell in the schedule. [the (if (= "TEXT" ]

    (Side note: This sequence should work whether the exploded
    entity replaces the original entity in the selection set and
    can be processed immediately, or the exploded entity is added
    to the end of the selection set [the immediate (if (= "TEXT"
    will fail, but the exploded entity will still eventually be
    reached by the WHILE loop]. An alternate approach would be
    to
    process the exploded MTEXT entity directly, but if I can't
    select it to add to the selection set I probably can't select
    it to directly process.)


    What I haven't found a way to do is to get the entity that's exploded
    from MTEXT to TEXT back in the selection set as a TEXT entity so that it
    can be processed. I've spent over three hours trying to get the
    exploded entity back in the selection set and haven't found anything
    that works. I've been through every example file I can find, searched
    the usual web sites, etc. I'm thinking that referencing the exploded
    entity so I can do a (ssadd should be easy, but I'm missing it.

    Martin
     
    Martin Shoemaker, Feb 22, 2005
    #5
  6. Martin Shoemaker

    Jeff Mishler Guest

    How about a function that can be called that does the text adjusting, then
    you could do something like this:
    Code:
    ;untested, and just for a rough idea!
    (setq idx -1)
    (if (setq ss (ssget '((0 . "TEXT,MTEXT"))))
    (while (< (setq idx (1+ idx))(sslength ss))
    (setq ent (ssname ss 0))
    (if (eq (cdr (assoc 0 (entget ent))) "MTEXT")
    (progn ;it's mtext so reduce it to text
    (command "explode" ent "")
    (setq newss (ssget "p")
    cnt -1)
    (while (< (setq cnt (1+ cnt))(sslength newss))
    (center_txt (ssname newss cnt))
    )
    )
    (center_txt (ssname ss idx))
    )
    )
    )
    ;;funtion to adjust the text
    (defun center_txt (txtent)
    ;;do your centering on the txtent here
    )
    
     
    Jeff Mishler, Feb 22, 2005
    #6
  7. (setq newss (ssget "p"))

    Problem solved. I knew I was missing something simple. Thanks for the
    help.

    Martin
     
    Martin Shoemaker, Feb 22, 2005
    #7
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.