Jump to content

Recommended Posts

Posted

I have an old lisp routine that we've been using to create the correct linespacing between lines of DTEXT. This routine is used primarily in coping the notes from old drawings to create a revision. For whatever reason the notes on most of these drawings are single lines of DTEXT instead of MTEXT. To make matters worse, the line spacing is kind of all over the place (i.e. varies between line to line) and being the **** person needing order that I am, this is totally unacceptable :oops:.

 

Anyways there are several problems with this routine that hurts its functionality. First, the user must select each line of text in sequential order to order the note correctly. When you have a full F-size sheet of notes and you have to manually select each line of text sequentially, it can get pretty tedius.

 

Secondly, the user must manually enter the spacing between lines. This is not that bad but I'd rather not leave it up to the user. Instead I'd rather have two options, single or double spacing and let the user either select the spacing from a dialog box or just by typing 'S' for single or 'D' for double (i.e., the command line would look something like this: Command: Select spacing option (Single/Double) : )

 

Finally, after the command is run, the first piece of text still looks like it is selected. See picture below.

 

 

bad.jpg

 

Hitting the ESCAPE key doesn't do anything. The user has to select something else on the screen then hit ESCAPE to clear it. I realize this is trivial but it just bugs me :roll:.

 

In another post a while back someone mentioned to me to just combine the DTEXT lines into an MTEXT entity with the Express command TXT2MTXT which would create the correct line spacing between the lines within one note. Then all we would have to do is adjust the spacing between notes. I passed this tidbit along to our team and this is how we've been doing it recently.

 

However, as I delve deeper into learning lisp, I've decided I want to modify the existing line spacing lisp routine to incorporate the ideas I list above. The problem is I just don't know how to work with selection sets. I found the bit of code below here (from Alanjt) that I think can help:

(if (setq ss (ssget '((0 . "TEXT"))))
 (vl-sort
   ((lambda (i / lst)
      (while (setq e (ssname ss (setq i (1+ i))))
        (setq lst (cons e lst))
      )
    )
     -1
   )
   (function (lambda (a b) (> (caddr (assoc 10 (entget a))) (caddr (assoc 10 (entget b))))))
 )
)

 

 

Here is the code from our line spacing lisp:

; TXTSPC command is for adjusting the spacing between existing TEXT
; By G. Ramesh, NPCC, Abu Dhabi.
(defun C:TXTSPC (/ d e1 elist fpt el1 el2 sp1 sp2 r-ang dis dif i)
 (setvar "highlight" 1)
 (command ".undo" "g")
 (setq d (getdist "\nSpacing required between lines: "))
 (prompt
   "\nSelect the TEXT entities one by one starting from the top . . ."
 )
 (setq e1    (entsel "\nSelect first TEXT: ")
elist '()
i     0
 )
 (while e1
   (redraw (car e1) 3)
   (setq elist (append elist (list (car e1)))
  e1 (entsel "\nSelect next TEXT: ")
   )
 )
 (foreach n elist (redraw n 1))
 (setq el1 (entget (nth 0 elist)))
 (if (/= (cdr (assoc 72 el1)) 0)
   (setq code 11)
   (setq code 10)
 )
 (setq fpt (cdr (assoc code el1)))
 (repeat (1- (length elist))
   (setq el1 (entget (nth i elist))
  el2 (entget (nth (1+ i) elist))
  sp1 (cdr (assoc code el1))
  sp2 (cdr (assoc code el2))
  r-ang (cdr (assoc 50 el1))
  dis (- (cadr sp1) (cadr sp2))
  dif (- d dis)
  sp2 (polar fpt (- r-ang (/ pi 2)) (* (1+ i) d))
  el2 (subst (append (list code) sp2) (assoc code el2) el2)
  i (1+ i)
   )
   (entmod el2)
 )
 (foreach n elist (redraw n 1))
 (command ".undo" "end")
 (prin1)
)

 

 

Can I get some pointers about how I can incorporate a selection set where the entities are processed according to their vertical location with the above code? I know this is a long post so if you've read this far, I appreciate it.

 

Lonnie

  • Replies 25
  • Created
  • Last Reply

Top Posters In This Topic

  • lfe011969

    11

  • Lee Mac

    7

  • alanjt

    6

  • David Bethel

    2

Popular Days

Top Posters In This Topic

Posted Images

Posted

Assumptions:

 

all of the text have the same justifications, text height, font, etc

you want to have all text LH X axis aligned

you want to adjust the Y axis values only

spacing of 1.5 X the text height is somewhat of a standard,

you want either single or double this value

 

-David

Posted

David,

 

All of your assumptions are correct. I know there are many more robust text align and spacing routines out there. Lee Mac's Dynamic Text Alignment tool is a great program, it's just more than we need for our needs. Plus I'm trying to learn lisp so figuring out how to modify an existing real world problem would help be become a better coder.

 

Lonnie

Posted

You've actually picked a very difficult 1 to take on

 

the logic needs to follow:

  • Select "TEXT" only entities
  • Step thru the set
  • Find the maximum Y value
  • Record all Y values and it's respective entity's name
  • Sort the Y values and record the entity names
  • Step thru the sorted set
  • entmod each sorted entity's point values by the preset X and Descending Y axis values

 

Not a real simple procedure.

 

Modifying existing code can be a real challnge. It's sometimes better to start from scratch

 

 

Here's is how I would start an approach to this 1

 

 [b][color=BLACK]([/color][/b]initget 1 [color=#2f4f4f]"Single Double"[/color][b][color=BLACK])[/color][/b]
 [b][color=BLACK]([/color][/b]setq ys [b][color=FUCHSIA]([/color][/b]getkword [color=#2f4f4f]"\nSpacing Style - Single/Double:   "[/color][b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b]

 [b][color=BLACK]([/color][/b]and [b][color=FUCHSIA]([/color][/b]setq i -1
           ss [b][color=NAVY]([/color][/b]ssget '[b][color=MAROON]([/color][/b][b][color=GREEN]([/color][/b]0 . [color=#2f4f4f]"TEXT"[/color][b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b]
      [b][color=FUCHSIA]([/color][/b]while [b][color=NAVY]([/color][/b]setq en [b][color=MAROON]([/color][/b]ssname ss [b][color=GREEN]([/color][/b]setq i [b][color=BLUE]([/color][/b]1+ i[b][color=BLUE])[/color][/b][b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
             [b][color=NAVY]([/color][/b]setq ed [b][color=MAROON]([/color][/b]entget en[b][color=MAROON])[/color][/b]
                  p10 [b][color=MAROON]([/color][/b]cdr [b][color=GREEN]([/color][/b]assoc 10 ed[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
             [b][color=NAVY]([/color][/b]cond [b][color=MAROON]([/color][/b][b][color=GREEN]([/color][/b]not maxy[b][color=GREEN])[/color][/b]
                    [b][color=GREEN]([/color][/b]setq maxy [b][color=BLUE]([/color][/b]cadr p10[b][color=BLUE])[/color][/b]
                          maxe en[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b]
                   [b][color=MAROON]([/color][/b][b][color=GREEN]([/color][/b]> [b][color=BLUE]([/color][/b]cadr p10[b][color=BLUE])[/color][/b] maxy[b][color=GREEN])[/color][/b]
                    [b][color=GREEN]([/color][/b]setq maxy [b][color=BLUE]([/color][/b]cadr p10[b][color=BLUE])[/color][/b]
                          maxe en[b][color=GREEN])[/color][/b][b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
             [b][color=NAVY]([/color][/b]setq yl [b][color=MAROON]([/color][/b]cons [b][color=GREEN]([/color][/b]cons [b][color=BLUE]([/color][/b]cadr p10[b][color=BLUE])[/color][/b] en[b][color=GREEN])[/color][/b] yl[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b]
      [b][color=FUCHSIA]([/color][/b]setq fd [b][color=NAVY]([/color][/b]entget maxe[b][color=NAVY])[/color][/b]
            xp [b][color=NAVY]([/color][/b]car [b][color=MAROON]([/color][/b]assoc 10 fd[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b]
            yp [b][color=NAVY]([/color][/b]cadr [b][color=MAROON]([/color][/b]assoc 10 fd[b][color=MAROON])[/color][/b][b][color=NAVY])[/color][/b][b][color=FUCHSIA])[/color][/b][b][color=BLACK])[/color][/b]

 

 

This would give the starting X and Y values xp yp

and the entity list yl

 

It would take a good bit of work to flush this out. -David

Posted

Well I wouldn't want it to be too easy now would I? :wink:

 

Thanks for getting me started.

 

Lonnie

Posted

IMO, I would be inclined to approach this solution using VL, as it makes for a more concise solution - this is how I might approach it.

 

 

I don't want to just give you the solution, so perhaps scroll down after you have attempted it.

 

< Scroll down to see solution >


























(defun c:test ( / ss )
 (vl-load-com)
 ;; © Lee Mac 2010

 (if (setq ss (ssget "_:L" '((0 . "TEXT"))))
   (
     (lambda ( i / e l p h a )
       (while (setq e (ssname ss (setq i (1+ i))))
         (setq l (cons (entget e) l ))
       )
       (setq l
         (vl-sort l
           (function
             (lambda ( a b )
               (> (cadr (LM:GetTextInsertion a)) (cadr (LM:GetTextInsertion b)))
             )
           )
         )
       )
       (setq p (LM:GetTextInsertion (car l)) h (* 1.5 (dxf 40 (car l))) a (/ (* 3 pi) 2.))
       (
         (lambda ( j )
           (while (setq l (cdr l))
             (LM:PutTextInsertion (car l) (polar p a (* (setq j (1+ j)) h)))
           )
         )
         0
       )
     )
     -1
   )
 )

 (princ)
)

(defun dxf ( code lst ) (cdr (assoc code lst)))

(defun LM:GetTextInsertion ( eList )
 ;; © Lee Mac 2010
 (dxf
   (if (vl-every 'zerop
         (mapcar 'dxf '(72 73) (list elist elist))
       )
     10 11
   )
   eList
 )
)

(defun LM:PutTextInsertion ( eList point / code )
 ;; © Lee Mac 2010
 (setq code
   (if (vl-every 'zerop
         (mapcar 'dxf '(72 73) (list elist elist))
       )
     10 11
   )
 )
 (entupd
   (cdr
     (assoc -1
       (entmod
         (subst (cons code point) (assoc code elist) elist
         )
       )
     )
   )
 )
)

Posted

Lee has posted a nice solution, but since I already coded it, I'll share anyway. I went the boundingbox route.

 

BTW, cool stuff Lee. :)

 

<Scroll to see>

































(defun c:ALT (/ foo lst)
 ;; Align TEXT objects
 ;; Alan J. Thomspon, 08.02.10

 (vl-load-com)

 (defun foo (o / a b)
   (vla-getboundingbox o 'a 'b)
   (vlax-safearray->list a)
 )

 (if (and (setq lst (vl-sort ((lambda (/ ss l)
                                (if (setq ss (ssget "_:L" '((0 . "TEXT"))))
                                  (progn
                                    (vlax-for x (setq ss (vla-get-activeselectionset
                                                           (cond (*AcadDoc*)
                                                                 ((setq *AcadDoc*
                                                                         (vla-get-activedocument (vlax-get-acad-object))
                                                                  )
                                                                 )
                                                           )
                                                         )
                                                )
                                      ;; (XYZ, height, object)
                                      (setq l (cons (list (foo x) (vla-get-height x) x) l))
                                    )
                                    (vla-delete ss)
                                    l
                                  )
                                )
                              )
                             )
                             (function (lambda (a b) (> (cadar a) (cadar b))))
                    )
          )
          (not (initget 0 "Single Double"))
          (setq *ALT:Space*
                 (cond ((getkword (strcat "\nSpecify spacing [single/Double] <"
                                          (cond (*ALT:Space*)
                                                ((setq *ALT:Space* "Single"))
                                          )
                                          ">: "
                                  )
                        )
                       )
                       (*ALT:Space*)
                 )
          )
     )
   ((lambda (d m)
      (foreach x (cdr lst)
        (vla-move (caddr x)
                  (vlax-3d-point (car x))
                  (vlax-3d-point (polar (caar lst) (* pi 1.5) (setq d (+ d (* m (cadr x))))))
        )
      )
    )
     0.
     (if (eq *ALT:Space* "Single")
       1.5
       3.
     )
   )
 )
 (princ)
)

Posted

Cheers dude - some nice code from you also. I wouldn't have thought to approach it that way :thumbsup:

 

I suppose the advantage of your code is that it will position text with equal spacing irrelevant of justification, whereas mine will equally space the insertion points. - I suppose it depends on the desired result of the OP.

 

:)

Posted

Great! I will try both out guys. Thanks.

 

 

During my planning for this routine earlier today, I was thinking along the lines of this logic:

  • Get the spacing (single or double) and store in the variable 'sp'
  • Get the selection set
  • Put the set into a list to be processed called 'list1'
  • Process the list according to the largest 'Y' coordinate value to the smallest and put into a new list 'list2'
  • Get the first entity of the new list (thus the one with the largest 'Y' coordinate value) and store the 'Y' value into variable 'ybase'
  • Do a FOREACH evaluation with a forumla that would come up with new Y values for each entity in the list where each value would increase by a factor of the specified spacing and then be placed in new list 'list3'
  • Move entities to new 'Y' locations per 'list3' in relation to 'ybase'

Without looking deeply at either of your example codes, does this sound about right as far as the logic is concerned?

Posted

The problem you face by avoiding the VL route is that you don't have access to a sort function and so must implement your own sorting algorithm, which, most likely, will be the bubble sort.

 

The vl-sort function is faster in this respect as it would implement, most probably, a form of quicksort algorithm, using arx to do so.

 

Lee

Posted
I suppose the advantage of your code is that it will position text with equal spacing irrelevant of justification, whereas mine will equally space the insertion points. - I suppose it depends on the desired result of the OP.

 

:)

 

Unfortunately we usually deal with old drawings and I would be extremely lucky to copy the notes from one to a new drawing and find they all have uniform insertion points. I'm pretty sure most of our go-by drawings have been converted from some other CAD program which could explain why insertion points, line spacing and justification are all over the place. But thanks for your code nonetheless as it gives me more food for thought.

 

Lonnie

Posted
The problem you face by avoiding the VL route is that you don't have access to a sort function and so must implement your own sorting algorithm, which, most likely, will be the bubble sort.

 

The vl-sort function is faster in this respect as it would implement, most probably, a form of quicksort algorithm, using arx to do so.

 

Lee

 

The only reference material I have for using LISP is a book titled, "Customizing AutoCAD 2009" by Sham Tickoo and unfortunately only about 3 chapters concern Lisp or Visual Lisp. I've seen a lot of material on the net concerning VL coding but nothing along the lines of a "How-to" code with VL.

 

Lonnie

Posted

Perhaps I may have caused a misunderstanding using the term 'insertion point' - I meant 'alignment point' - i.e. dependent on text justification.

Posted
The only reference material I have for using LISP is a book titled, "Customizing AutoCAD 2009" by Sham Tickoo and unfortunately only about 3 chapters concern Lisp or Visual Lisp. I've seen a lot of material on the net concerning VL coding but nothing along the lines of a "How-to" code with VL.

 

Lonnie

 

For sure, your best reference are the VLIDE Help Files provided with AutoCAD - the vla-* functions are equivalent to VBA properties and methods as derived from the ActiveX COM Model, however the argument order and type apply to Visual LISP so it is no trouble to put 2 and 2 together in such cases.

 

And, of course, if you get stuck, just give us a shout :)

Posted

I guess I really didn't know there was a difference between the two. I guess I just assumed the insertion point was the point about which the text would be moved if the justification were to be changed.

Posted
Cheers dude - some nice code from you also. I wouldn't have thought to approach it that way :thumbsup:

 

I suppose the advantage of your code is that it will position text with equal spacing irrelevant of justification, whereas mine will equally space the insertion points. - I suppose it depends on the desired result of the OP.

 

:)

Thanks. :)

I used this method a while back to neatly sort about 200 GPR (ground penetrating radar) images. The fun part was having it also draw a profile with full labels. I coded the whole thing in 15-20 minutes, set my images and went home for the day, billing the remaining day to the project.

Posted
I guess I really didn't know there was a difference between the two. I guess I just assumed the insertion point was the point about which the text would be moved if the justification were to be changed.

 

The insertion point only plays a part if the text is left-justified, else the alignment point takes over.

Posted
The insertion point only plays a part if the text is left-justified, else the alignment point takes over.

 

Well like my grandfather used to say, "You learn something new every day. The day you don't learn something is the day you should just hang it up." :thumbsup:

 

Thanks for the clarification and the coding help and tips.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...