Lsp polyline between block insertion point

Lsp polyline between block insertion point

Anonymous
Not applicable
4,737 Views
17 Replies
Message 1 of 18

Lsp polyline between block insertion point

Anonymous
Not applicable

Hi,

 

I would like to know how to writte the code for this lsp,

 

1- i want to know how to get a multipe insertions bolcks points list 

 

2- how to get them list by their attribute value, ( its always number and start by 1  .. ) 

 

The block is one point with an attribute, and the point is on the insertion point..

 

once i have this information list, i would like to have a line between point 1 to point 2,  and then a line point 2 to point 3,..

 

to last point,

 

i know you some of you like to give the code and it's really appreciated, but i also want to understand how so i could make lisp by myself after that,

 

Thank you in advance !  

 

 

0 Likes
Accepted solutions (1)
4,738 Views
17 Replies
Replies (17)
Message 2 of 18

Kent1Cooper
Consultant
Consultant
Accepted solution

Here's one way to do that.  It requires that all such Blocks be of the same name [edit the "YourBlockName" part accordingly], and that the Attribute with the number value is the only [or at least always the first] Attribute, and that its value always represents an integer.  Minimally tested.

 

(defun C:LBAS ; = Link Blocks in Attribute Sequence
  (/ ss blk att blkinslist)
  (prompt "\nTo Link Blocks with Lines in Attribute Sequence,")
  (if (setq ss (ssget '((0 . "INSERT") (66 . 1) (2 . "YourBlockName")))); could omit (66 . 1)*
    (progn ; then
      (repeat (setq n (sslength ss)); step through selection set
        (setq
          blk (ssname ss (setq n (1- n))); Block entity name
          att (entnext blk); Attribute entity name
          blkinslist ; list of integer equivalents of Attribute values paired with insertion points
            (cons
              (list (atoi (cdr (assoc 1 (entget att)))) (cdr (assoc 10 (entget blk))))
              blkinslist
            ); cons
        ); setq
      ); repeat
      (setq blkinslist ; replace former content
        (mapcar 'cadr ; keep only insertion points after:
          (vl-sort blkinslist '(lambda (a b) (< (car a) (car b)))); sorting in Attribute-value order
        ); mapcar
      ); setq
      (command "_.line"); consider Polyline instead, possibly with specified width
      (apply 'command blkinslist); feed points to Line command
      (command ""); end Line command
    ); progn
    (prompt "\nNo such Blocks selected."); else
  ); if
); defun

That asks the User to select the Blocks [and they can select a whole area -- it will "see" only Blocks having Attributes with that name].  It could be made to find all such Blocks without User selection.  It could be made to ask for the Block name rather than having it built in.  Or it could be made to accept multiple Block names [*the (66 . 1) in the (ssget) filter is to "see" only Blocks with Attributes, which is expendable if the "YourBlockName" Block always has one, but should be included if multiple Block names are allowed].  It could be made to ignore any Block whose Attribute value is not a string representing an integer, or to warn the User about that.  It could be made to work with multiple-Attribute Blocks and to find the right Attribute by its Tag.  It could be made to draw the Lines on a particular Layer [the above uses the current Layer].  And it could use all the usual enhancements [error handling, object-snap control, command-echo suppression, etc.].

Kent Cooper, AIA
Message 3 of 18

Anonymous
Not applicable

Wow it's worked really well ! 

 

and i put pline instead, 

 

now is there a way to make de polyline fit in the lsp 

 

is not a big deal to make by Pedit but if there a way i be glad to know, 

 

 

 

thank you ,

 

(defun C:plab ; = Link Blocks in Attribute Sequence

(/ *error* oldLayer layerName ss blk att blkinslist)

(defun *error* (errmsg)

(if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))

(princ (strcat "\nError: " errmsg)))

(setvar "CLAYER" oldLayer)

(princ)

); end *error*

(setq oldLayer (getvar "CLAYER"))

(if (not (tblsearch "LAYER" (setq layerName "POLYLINES"))) ;check if layer "POLYLINES" exists

(command "_.-LAYER" "_N" layerName "")) ;create layer if not

(setvar "CLAYER" layerName)

(prompt "\nTo Link Blocks with Lines in Attribute Sequence,")

(if (setq ss (ssget '((0 . "INSERT") (66 . 1) (2 . "POINT")))); could omit (66 . 1)*

(progn ; then

(repeat (setq n (sslength ss)); step through selection set

(setq

blk (ssname ss (setq n (1- n))); Block entity name

att (entnext blk); Attribute entity name

blkinslist ; list of integer equivalents of Attribute values paired with insertion points

(cons
(list (atoi (cdr (assoc 1 (entget att)))) (cdr (assoc 10 (entget blk))))
blkinslist

); consapp

); setq

); repeat

(setq blkinslist ; replace former content

(mapcar 'cadr ; keep only insertion points after:

(vl-sort blkinslist '(lambda (a b) (< (car a) (car b)))); sorting in Attribute-value order

); mapcar

); setq

(command "_.pline"); consider Polyline instead, possibly with specified width

(apply 'command blkinslist); feed points to Line command

(command ""); end Line command

(setvar "CLAYER" oldLayer)

); progn

(prompt "\nNo such Blocks selected."); else

); if

); defun

0 Likes
Message 4 of 18

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

Wow it's worked really well ! 

 

and i put pline instead, 

 

now is there a way to make de polyline fit in the lsp 

 

is not a big deal to make by Pedit but if there a way i be glad to know, 

....


Somehow I hadn't noticed the word Polyline in your Subject: line, but took the Lines approach based on your first description.  But I have what I think might be a better idea.  Fit-curving a Polyline can sometimes have weird results, depending on the relationship of the vertices.  To avoid that, and also because it can be done directly, without needing to do anything to the linking pathway after it's drawn, I suggest using a Spline instead.

 

And I did some nit-picking of a few little things --

 

 

(defun C:LPBSA ; = Link POINT Blocks with Spline in Attribute order
  (/ *error* oldLayer cmde osm ss blk att blkinslist)
  (defun *error* (errmsg)
    (if (not (wcmatch errmsg "Function cancelled,quit / exit abort,console break"))
      (princ (strcat "\nError: " errmsg))
    ); if
    (setvar "CLAYER" oldLayer)
    (setvar 'cmdecho cmde)
(setvar 'osmode osm) (princ) ); end *error* (setq oldLayer (getvar "CLAYER") cmde (getvar 'cmdecho)
osm (getvar 'osmode) ); setq (setvar 'cmdecho 0)
(setvar 'osmode 0) (command "_.LAYER" "_make" "POLYLINES" ""); create-&-set layer, or set current if it exists [no need to test for it] (prompt "\nTo Link POINT Blocks with Spline in Attribute Sequence,") (if (setq ss (ssget '((0 . "INSERT") (66 . 1) (2 . "POINT")))); could omit (66 . 1) (progn ; then (repeat (setq n (sslength ss)); step through selection set (setq blk (ssname ss (setq n (1- n))); Block entity name att (entnext blk); Attribute entity name blkinslist ; list of integer equiv.s of Attributes paired with insertion pts (cons (list (atoi (cdr (assoc 1 (entget att)))) (cdr (assoc 10 (entget blk)))) blkinslist ); cons & blkinslist ); setq ); repeat (setq blkinslist ; replace former content (mapcar 'cadr ; keep only insertion points after: (vl-sort blkinslist '(lambda (a b) (< (car a) (car b)))); sort -- Attribute order ); mapcar ); setq (command "_.spline") (apply 'command blkinslist); feed points to Spline command (command "" "" ""); end Spline command ); progn (prompt "\nNo POINT Blocks selected."); else ); if (setvar "CLAYER" oldLayer) (setvar 'cmdecho cmde)
(setvar 'osmode osm) (princ) ); defun

 

Kent Cooper, AIA
Message 5 of 18

Anonymous
Not applicable

gday,

 

I am a bit of a novice with autocad as I've only been using it for nearly 2 years and have only just upgraded to 2017 full version. I need help in laymans terms for me to understand, please. I know that can be frustrating so I apologize in advance.

 

My boss has suggested that in our drawings there is a way to link all blocks with a pline and it should number each block and produce a list of eastings/northings. I have been reading quite a few posts on this very thing but the answers given are all a bit above my understanding. I have tried to run some of the scripts that people have given but am getting nowhere fast. 

 

Any and all help is greatly appreciated.

 

Pete

 

0 Likes
Message 6 of 18

bobbyrubyii
Contributor
Contributor

having trouble with this just keeps telling me "nil" at the end.

 

I map utility poles and am looking for a solution where I can "connect" the dots.  I need a piece of code just like this to increase drafting time. 

 

I cannot seem to get it to work :/.  Literally only put the block name in.... and it is getting them.  Using ACAD MAP 3D 2016

 

Command: LBAS
To Link Blocks with Lines in Attribute Sequence,
Select objects: 1 found
Select objects: 1 found, 2 total
Select objects: _.pline
Specify start point:
Current line-width is 0.0
Specify next point or [Arc/Halfwidth/Length/Undo/Width]:
Specify next point or [Arc/Close/Halfwidth/Length/Undo/Width]:
Command: nil

 

 

Any assistance would be greatly appreciated.  See pasted code.

(defun C:LBAS ; = Link Blocks in Attribute Sequence
  (/ ss blk att blkinslist)
  (prompt "\nTo Link Blocks with Lines in Attribute Sequence,")
  (if (setq ss (ssget '((0 . "INSERT") (66 . 1) (2 . "ACMAP_ANN_TEMPLATE_JU_POLE")))); could omit (66 . 1)*
    (progn ; then
      (repeat (setq n (sslength ss)); step through selection set
        (setq
          blk (ssname ss (setq n (1- n))); Block entity name
          att (entnext blk); Attribute entity name
          blkinslist ; list of integer equivalents of Attribute values paired with insertion points
            (cons
              (list (atoi (cdr (assoc 1 (entget att)))) (cdr (assoc 10 (entget blk))))
              blkinslist
            ); cons
        ); setq
      ); repeat
      (setq blkinslist ; replace former content
        (mapcar 'cadr ; keep only insertion points after:
          (vl-sort blkinslist '(lambda (a b) (< (car a) (car b)))); sorting in Attribute-value order
        ); mapcar
      ); setq
      (command "_.pline"); consider Polyline instead, possibly with specified width
      (apply 'command blkinslist); feed points to Line command
      (command ""); end Line command
    ); progn
    (prompt "\nNo such Blocks selected."); else
  ); if
); defun
0 Likes
Message 7 of 18

Kent1Cooper
Consultant
Consultant

@bobbyrubyii wrote:

having trouble with this just keeps telling me "nil" at the end.

 

....

Is it drawing the connecting Polyline?  If so, don't worry about the nil returned at the end -- the (command) function always returns nil [read about it in Help].  You can suppress that, if you like, by adding a (princ) function with no arguments [read about that in Help, too -- it might be under (print) or (prin1) instead where it describes this as a way of "exiting quietly," but any of them work] just before the closing right parenthesis of the command definition:

 

....

  ); if

  (princ)

); defun

Kent Cooper, AIA
0 Likes
Message 8 of 18

bobbyrubyii
Contributor
Contributor

No it is not drawing the polyline... That is what is frustrating me so much.  Everyone else has it doing the deed but mine runs the command and does not draw me anything.... I even checked to ensure it was NOT drawing on a frozen layer :(.  Arg.

0 Likes
Message 9 of 18

Kent1Cooper
Consultant
Consultant

@bobbyrubyii wrote:

.... I even checked to ensure it was NOT drawing on a frozen layer ....


Could it be drawing on a Layer that's turned OFF?  The current Layer can't be Frozen, but it can  be turned Off.

Kent Cooper, AIA
0 Likes
Message 10 of 18

bobbyrubyii
Contributor
Contributor

Ok it is drawing a line but WAY off from the insertion point.... the insertion point is from the base point correct???

 

Would it have something to do with the fact that I am using annotation blocks?

 

I import the shapes files collected with my trimble to the drawing then, since it has data objects, I have to annotate them using the annotation blocks with attributes that are invisible... Like the "featid" attribute which is what I am using to order the blocks... 1 2 3 4... etc.

 

The polyline is being drawn but drawn miles away from the poles... It works and I am happy with it at present now as that I can zoom to extents then copy it back to where it goes.

 

And seriously thank you very much for helping me with this!  just wanted to add that bit.

0 Likes
Message 11 of 18

bobbyrubyii
Contributor
Contributor

Is there anyway to force a new polyline after every 2 points?  So that each polyline is a separate self contained polyline between the two objects in the chain of objects?

 

0 Likes
Message 12 of 18

Kent1Cooper
Consultant
Consultant

@bobbyrubyii wrote:

Ok it is drawing a line but WAY off from the insertion point.... the insertion point is from the base point correct???

....


Yes, but the way it's extracting it would be in World Coordinates -- this sounds a lot like there's an other-than-World UCS involved.  If so, try changing this part:

 

            (cons
              (list (atoi (cdr (assoc 1 (entget att)))) (cdr (assoc 10 (entget blk))))
              blkinslist
            ); cons

 

to this:

            (cons
              (list (atoi (cdr (assoc 1 (entget att)))) (trans (cdr (assoc 10 (entget blk))) 0 1))
              blkinslist
            ); cons

 

so that it gets the insertion points in terms of the current UCS.

Kent Cooper, AIA
0 Likes
Message 13 of 18

Kent1Cooper
Consultant
Consultant

@bobbyrubyii wrote:

Is there anyway to force a new polyline after every 2 points?  So that each polyline is a separate self contained polyline between the two objects in the chain of objects?

 


Will simple Lines do in that case?  If so, just change the "_.pline" command to "_.line" [i.e. go back to the accepted-Solution's approach].  That will be easier than making them separate Polylines, because it can still do it by feeding in the sequence of insertion points, once each, to a single Line command.

Kent Cooper, AIA
0 Likes
Message 14 of 18

bobbyrubyii
Contributor
Contributor

You are fantastic man.  Thank you so much!  It works perfectly!

0 Likes
Message 15 of 18

bobbyrubyii
Contributor
Contributor

How might I make this use a select order instead?

0 Likes
Message 16 of 18

Anonymous
Not applicable

Any possible way to use multiple block names?

0 Likes
Message 17 of 18

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

Any possible way to use multiple block names?


If you mean multiple specific  Block names that you want to build in, change this piece in the selection filter:

(2 . "YourBlockName")

to this, with a string of comma-separated names:

(2 . "YourBlockName1,YourBlockName2,YourBlockName3")

If you mean whatever  Block names, any  Block names, you should be able to just remove that (2 . "...") entry entirely, and it will "see" Blocks of any name that contain Attributes in your selection.

Kent Cooper, AIA
0 Likes
Message 18 of 18

Kent1Cooper
Consultant
Consultant

@bobbyrubyii wrote:

How might I make this use a select order instead?


[Didn't answer this back then -- sorry, but if you're still "listening"....]

 

Since the whole routine is about establishing the order by Attribute values, that's out the window in your case, and filtering for only those with Attributes shouldn't be necessary.  I would just set INSert as the one running Object Snap mode, and start a Polyline [or Line or Spline] command.  Since you need to pick on each one anyway, you may as well have the pick be the drawing of the path to the insertion points, directly, rather than selection of the Blocks.

Kent Cooper, AIA
0 Likes