Mass move block to nearest polyline

Mass move block to nearest polyline

eoconnor95662
Enthusiast Enthusiast
7,816 Views
50 Replies
Message 1 of 51

Mass move block to nearest polyline

eoconnor95662
Enthusiast
Enthusiast

As noted in title I would like a LISP command to mass move blocks to nearest polyline. I've researched and found commands like lee mac's move block to polyline but it doesn't work in mass. Any feedback or existing AutoCAD functions would be much appreciated.

0 Likes
Accepted solutions (3)
7,817 Views
50 Replies
Replies (50)
Message 2 of 51

dlanorh
Advisor
Advisor
Define MASS? Is it all blocks in the drawing, blocks you select, blocks on a certain layer, blocks with a specific name?

I am not one of the robots you're looking for

0 Likes
Message 3 of 51

eoconnor95662
Enthusiast
Enthusiast

Blocks that I can select would be the easiest for me as I only would want to select a couple different blocks that repeat with different attributes. A name(s) for blocks would also work.

0 Likes
Message 4 of 51

pendean
Community Legend
Community Legend
Move the block from where, the nearest point to the Pline, or the block's Insertion point, or something else?
Are you trying to control spacing between the blocks once at the Pline, or it does not matter?

Are you just trying to align blocks in general? Or is the Pline of significance?

0 Likes
Message 5 of 51

eoconnor95662
Enthusiast
Enthusiast

Move the block from current distance (dist= "1-7" away) to the nearest Pline (not nearest vertex of Pline) from block's Insertion point or nearest block edge.


Are you trying to control spacing between the blocks once at the Pline, or it does not matter?

Block should be touching the Pline

 

Are you just trying to align blocks in general? Or is the Pline of significance?

All blocks to be moved are circular, Pline is significant because it is not a Line and can bend away from the block to be moved.

0 Likes
Message 6 of 51

eoconnor95662
Enthusiast
Enthusiast

Block should be touching the Pline and need to keep relative distance between other blocks (can't stack all blocks on 1 spot on PLINE)

 

All blocks to be moved are circular - and need to be aligned to PLINE.

 

I would like a LISP routine that takes specific block(s) from a drag window, targets the nearest Pline (or Pline vertex? as long as its not too far away) and moves it to touch the line.

 

Thank you for the help!

0 Likes
Message 7 of 51

eoconnor95662
Enthusiast
Enthusiast

Using the attached code from post - https://www.cadtutor.net/forum/topic/59757-mass-move-blocks-to-nearest-line/ - (looks reasonable for what I want) I get the following description/error in cmd prompt:

 

Select objects: Specify opposite corner: 0 found, 2 total

Select objects:
; error: bad argument type: lselsetp nil

 

What am I doing wrong?

0 Likes
Message 8 of 51

dlanorh
Advisor
Advisor
Accepted solution

 

One of the selection sets has nothing in it, probably the line selection set as this is restricting the line entities selection to a single layer "A-WALL-INTR"

 

If this layer is not in your drawing, or there are no ARC's ,CIRCLE's ,ELLIPSE's ,LINE's ,LWPOLYLINE's ,POLYLINE's or SPLINE's on this layer then you will get a nil selection set.

 

Remove this line near the top of the lisp, or just comment it out with a ; in front of it as shown below.

;(cons 8 "A-WALL-INTR")

I am not one of the robots you're looking for

0 Likes
Message 9 of 51

eoconnor95662
Enthusiast
Enthusiast

IN this code, is there a way to determine how far away the block is placed from the line? This code works fine but I would like a way to set distance from the line (so blocks are touching on side not completely centered)

0 Likes
Message 10 of 51

dlanorh
Advisor
Advisor

That is possible, but it is better to do it after the block is moved provide the circle radius is obtainable. 

I am not one of the robots you're looking for

0 Likes
Message 11 of 51

eoconnor95662
Enthusiast
Enthusiast

RADIUS 5.000

0 Likes
Message 12 of 51

dlanorh
Advisor
Advisor
Accepted solution

Try this. I've not tested it as I don't have the blocks

 

(defun c:m2l ( / l_ss b_ss b_cnt b_ent i_pt min_dist m_pt l_cnt l_ent c_pt md m_ang)

  (prompt "\nSelect Lines : ")
  (setq l_ss (ssget "_X" '((0 . "ARC,CIRCLE,ELLIPSE,LINE,LWPOLYLINE,POLYLINE,SPLINE"))))

  (prompt "\nSelect Blocks : ")
  (setq b_ss (ssget '((0 . "INSERT"))))  
 
  (repeat (setq b_cnt (sslength b_ss))
    (setq b_ent (ssname b_ss (setq b_cnt (1- b_cnt)))
          i_pt (cdr (assoc 10 (entget b_ent)))
          min_dist 1000000
          m_pt nil
    )
    (repeat (setq l_cnt (sslength l_ss))
      (setq l_ent (ssname l_ss (setq l_cnt (1- l_cnt)))
            c_pt (vlax-curve-getclosestpointto l_ent i_pt)
      )
      (cond ( (< (setq md (distance i_pt c_pt)) min_dist)
              (setq min_dist md
                    m_pt c_pt
              )
            )
      )
    )
    (setq m_ang (angle i_pt m_pt)
          m_pt (polar i_pt m_ang (- min_dist 5.0));;5.0 = radius of circle in block
    )
    (vla-move (vlax-ename->vla-object b_ent) (vlax-3d-point i_pt) (vlax-3d-point m_pt))
  )
  (princ)
)

I am not one of the robots you're looking for

Message 13 of 51

eoconnor95662
Enthusiast
Enthusiast

Thanks for the useful code. I was wondering if you could make 2 small modifications to it.

 

One is to have it move to a specific line layer (SPPC-E-EL) , the other is to have it only select certain block type names (552-2, 551-1, and 552-0-CO).

 

Thanks again,

0 Likes
Message 14 of 51

dlanorh
Advisor
Advisor
(defun c:m2l ( / l_ss b_ss b_cnt b_ent i_pt min_dist m_pt l_cnt l_ent c_pt md m_ang)

  (prompt "\nSelect Lines : ")
  (setq l_ss (ssget "_X" '((0 . "ARC,CIRCLE,ELLIPSE,LINE,LWPOLYLINE,POLYLINE,SPLINE"))))

  (prompt "\nSelect Blocks : ")
  (setq b_ss (ssget '((0 . "INSERT") (2 . "552-2,551-1,552-0-CO"))))  
 
  (repeat (setq b_cnt (sslength b_ss))
    (setq b_ent (ssname b_ss (setq b_cnt (1- b_cnt)))
          i_pt (cdr (assoc 10 (entget b_ent)))
          min_dist 1000000
          m_pt nil
    )
    (repeat (setq l_cnt (sslength l_ss))
      (setq l_ent (ssname l_ss (setq l_cnt (1- l_cnt)))
            c_pt (vlax-curve-getclosestpointto l_ent i_pt)
      )
      (cond ( (< (setq md (distance i_pt c_pt)) min_dist)
              (setq min_dist md
                    m_pt c_pt
              )
            )
      )
    )
    (setq m_ang (angle i_pt m_pt)
          m_pt (polar i_pt m_ang (- min_dist 5.0));;5.0 = radius of circle in block
    )
    (vla-move (vlax-ename->vla-object b_ent) (vlax-3d-point i_pt) (vlax-3d-point m_pt))
  )
  (princ)
)

The above will only allow the selection of  blocks named 552-2, 551-1, and 552-0-CO

 

Sorry but I'm a bit brain dead at the moment. Move what to the specific line layer "SPPC-E-EL", the lines or the blocks?

I am not one of the robots you're looking for

0 Likes
Message 15 of 51

eoconnor95662
Enthusiast
Enthusiast

Move the aforementioned blocks to the line, which happens to be on layer SPPC-E-EL. The blocks are not on this layer. This is done mainly done to avoid it jumping to nearby lines that are not the desired line.

 

This seems to do the trick, let me know if I errored.

0 Likes
Message 16 of 51

dlanorh
Advisor
Advisor
Accepted solution

OK. I think this does what you want. It only selects lines on layer "SPPC-E-EL", and only the named blocks.

 

(defun c:m2l ( / l_ss b_ss b_cnt b_ent i_pt min_dist m_pt l_cnt l_ent c_pt md m_ang)

  (prompt "\nSelect Lines : ")
  (setq l_ss (ssget "_X" '((0 . "ARC,CIRCLE,ELLIPSE,LINE,LWPOLYLINE,POLYLINE,SPLINE") (8 . "SPPC-E-EL"))))

  (prompt "\nSelect Blocks : ")
  (setq b_ss (ssget '((0 . "INSERT") (2 . "552-2,551-1,552-0-CO"))))  
 
  (repeat (setq b_cnt (sslength b_ss))
    (setq b_ent (ssname b_ss (setq b_cnt (1- b_cnt)))
          i_pt (cdr (assoc 10 (entget b_ent)))
          min_dist 1000000
          m_pt nil
    )
    (repeat (setq l_cnt (sslength l_ss))
      (setq l_ent (ssname l_ss (setq l_cnt (1- l_cnt)))
            c_pt (vlax-curve-getclosestpointto l_ent i_pt)
      )
      (cond ( (< (setq md (distance i_pt c_pt)) min_dist)
              (setq min_dist md
                    m_pt c_pt
              )
            )
      )
    )
    (setq m_ang (angle i_pt m_pt)
          m_pt (polar i_pt m_ang (- min_dist 5.0));;5.0 = radius of circle in block
    )
    (vla-move (vlax-ename->vla-object b_ent) (vlax-3d-point i_pt) (vlax-3d-point m_pt))
  )
  (princ)
)

I am not one of the robots you're looking for

0 Likes
Message 17 of 51

jtm2020hyo
Collaborator
Collaborator

awesome code, thanks for your contribution.

0 Likes
Message 18 of 51

mbaxterB9TKM
Participant
Participant

This is my first post, so sorry if this is in the wrong place but it seemed like this thread was the closest thing I could find to what I am looking for. I slightly adjusted the lisp routine mentioned above to work for selected polylines instead of blocks. I thought it did exactly what I wanted until I realized that the perpendicular distance between my polylines was not maintained. Is there a way to maintain the perpendicular distance between the polylines? We set up our drawings with DVIEW's instead of UCS views because we like to leave the drawing in world view. I only make that distinction because I think it makes everything a little more complicated for the lisp.

 

I have attached an image of what I am looking to do. We have a crosswalk who's stripes need to be 2' apart from each other. The stripes are always parallel to the curb. I have a line from the center of one ADA ramp to another. I would like all the stripes to be along this line as shown in the image on the right. Again I need the perpendicular 2' spacing maintained. Please let me know if this is possible with a lisp. I am a total newbie with lisps so please speak in layman's terms 🙂

 

Thank you!

0 Likes
Message 19 of 51

dlanorh
Advisor
Advisor

Try this.

 

(defun c:m2l2 ( / ent s1 e1 ss cnt lent el mpt ipt)

  (setq ent (car (entsel "\nSelect Centreline : "))
        s1 (cdr (assoc 10 (entget ent)))
        e1 (cdr (assoc 11 (entget ent)))
  );end_setq

  (prompt "\nSelect Lines to Move : ")
  (setq ss (ssget ":L" '((0 . "LINE"))))

  (cond (ss 
          (repeat (setq cnt (sslength ss))
            (setq el (entget (setq lent (ssname ss (setq cnt (1- cnt)))))
                  mpt (mapcar '(lambda (x y) (/ (+ x y) 2.0)) (setq s2 (cdr (assoc 10 el))) (setq e2 (cdr (assoc 11 el))))
                  ipt (inters s1 e1 s2 e2 nil)
            );end_setq
            (cond (ipt (vlax-invoke (vlax-ename->vla-object lent) 'move mpt ipt)))
          );end_repeat
        )
  );end_cond
  (princ)
);end_defun

 Once loaded type M2L2 to run.

I am not one of the robots you're looking for

0 Likes
Message 20 of 51

mbaxterB9TKM
Participant
Participant

I tried the lisp above and got the following error:

 

; error: bad argument type: 2D/3D point: nil

0 Likes