Repeat Insert a Block at a given spacing?

Repeat Insert a Block at a given spacing?

Anonymous
Not applicable
1,801 Views
14 Replies
Message 1 of 15

Repeat Insert a Block at a given spacing?

Anonymous
Not applicable

I have been working on a lisp that should insert an arrow block "PT STRAND" on a line at a predetermined spacing "tendon" although when running the lisp it does not seem to want to auto insert each block at the predetermined spacing from the last. The code does not have an issue inserting the first arrow at 6" from the first end point selected but no matter what I try, it will not insert the other blocks. The blocks should be inserted until the point they are being inserted on is greater than or equal to the second endpoint selected, after which the code should end. 

(The first endpoint selected should be the right most or top most point on the line)

Any help would be appreciated!

The code I have so far is below:

 

(defun c:GL()

(setq ep1 (getpoint "\nSelect First End Point: "))
(setq x1 (car ep1))
(setq y1 (cadr ep1))
(setq ep2 (getpoint "\nSelect Second End Point: "))
(setq x2 (car ep2))
(setq y2 (cadr ep2))
(cond
((setq xe(= x1 x2))
(cond
((= x1 x2)
(setq hy (-(cadr ep1)6))
(setq hlp (list x1 hy 0.0))
(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" hlp)
(cond
((while (<= hy y2))
((setq hp (-(hy)tendon)))
(setq hlp2 (list x1 hp 0.0))
(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" hlp2))))))
((setq ye(= y1 y2))
(cond
((= y1 y2)
(setq vx (-(car ep1)6))
(setq vlp (list vx y1 0.0))
(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 90 "_none" vlp)
(cond
((while (<= vx x2))
((setq vp (-(vx)tendon)))
(setq vlp2 (list vp y1 0.0))
(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 90 "_none" vlp2)
)))))))

0 Likes
Accepted solutions (1)
1,802 Views
14 Replies
Replies (14)
Message 2 of 15

dlanorh
Advisor
Advisor

The attached lisp does almost what you want, but is rather advanced. It relies on the direction the line was constructed and works for lines, lwpolylines, polylines and splines. The first block is inserted at the entered distance from the selecteded start point, then every "x" distance until the end point or there is insufficient distance to fit another block. Blocks are rotated parallel with the line and there is an option to rotate them by 180 degrees.

 

You're welcome to study the code and make changes to suit your need. If you need help pop back here and ask, and I'm sure someone will lend a hand.

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

0 Likes
Message 3 of 15

ВeekeeCZ
Consultant
Consultant

Would you comment your intentions to the code? This part:

 

(cond
    ((setq xe(= x1 x2)) 
     (cond
       ((= x1 x2)
	(setq hy (-(cadr ep1)6))
	(setq hlp (list x1 hy 0.0))
	(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" hlp)
	(cond
	  ((while (<= hy y2))
	   ((setq hp (-(hy)tendon)))
	   (setq hlp2 (list x1 hp 0.0))
	   (command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" hlp2))))))
    ((setq ye(= y1 y2))
     (cond
       ((= y1 y2)
	(setq vx (-(car ep1)6))
	(setq vlp (list vx y1 0.0))
	(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 90 "_none" vlp)
	(cond
	  ((while (<= vx x2))
	   ((setq vp (-(vx)tendon)))
	   (setq vlp2 (list vp y1 0.0))
	   (command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 90 "_none" vlp2)
	   ))))))

Why so many conds? If does not work?

 

This is wrong syntax: ((setq vp (-(vx)tendon)))... should be: (setq vp (- vx tendon)). Where you tendon get from?

 

What this suppose to mean?

((setq xe(= x1 x2))

 

Here is my example of such a loop.

(setq x x1) ; initial x
(while (<= (setq x (+ x x1) tendon) x2)  ; add step distance to x
  
  (setq y y1) ; initial y
  (while (<= (setq y (+ y y2) tendon) y2) ; add step distance to y
    (command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 90 "_none" (list (- x 6) (- y 6)))))  ; add offset 6 to x and y

 

0 Likes
Message 4 of 15

Anonymous
Not applicable

This is the code of that part with notes on what each line should be doing if it makes any more sense, I apologize if it is jumbled this is my first attempt at coding with lisp. If does not seem to be working either I have tried replacing cond with if but it does not seem to work any better.


(cond
((setq xe(= x1 x2)) ;Evaluates if the line connecting the end points is verticle
(cond
((= x1 x2) ;If line is verticle:
(setq hy (-(cadr ep1)6)) ;Subtract 6 from y value of ep1
(setq hlp (list x1 hy 0.0)) ;Create point using new y value and x1
(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" hlp) ;Insert Arrow on point hlp
(cond
((while (<= hy y2))
(setq hp (- hy tendon)) ;Set hp: hy subtract predetermined spacing
(setq hlp2 (list x1 hp 0.0)) ;Create point using new y value and x1
(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" hlp2)))))) ;Insert arrow "predetermined spacing below the 1st arrow"
((setq ye(= y1 y2)) ;Evaluates if the line connecting the end points is horizontal
(cond
((= y1 y2) ;If line is Horizontal:
(setq vx (-(car ep1)6)) ;Subtract 6 from x value of ep1
(setq vlp (list vx y1 0.0)) ;Create point using new x value and y1
(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 90 "_none" vlp) ;Insert arrow on point vlp
(cond
((while (<= vx x2))
(setq vp (- vx tendon)) ;Set vp: vx subtract predetermined spacing
(setq vlp2 (list vp y1 0.0)) ;Create point using new x value and y1
(command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 90 "_none" vlp2) ;Insert aroow "predetermined spacing to the left of the 1st arrow"
)))))))

0 Likes
Message 5 of 15

ВeekeeCZ
Consultant
Consultant

Consider using something like this to get a value of tendon :

http://www.lee-mac.com/listtiledependency.html

0 Likes
Message 6 of 15

Anonymous
Not applicable

I actually already have a code for finding tendon spacing that goes with the code above but I appreciate it!

0 Likes
Message 7 of 15

ВeekeeCZ
Consultant
Consultant

This works. Not sure about the math, but that's up to you to fix.

 

(defun c:test ()

  (setq tendon 0.5)

  (setq ep1 (getpoint "\nSelect First End Point: "))
  (setq x1 (car ep1))
  (setq y1 (cadr ep1))
  (setq ep2 (getpoint "\nSelect Second End Point: "))
  (setq x2 (car ep2))
  (setq y2 (cadr ep2))

(cond
  ((equal x1 x2 1e-6) ;It's vertical

   (setq hy (- y1 6)) ;Subtract 6 from y value of ep1
   (setq hlp (list x1 hy)) ;Create point using new y value and x1
   (command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" hlp) ;Insert Arrow on point hlp

   (while (<= hy y2)
     (setq hy (+ hy tendon)) ;Set hp: hy subtract predetermined spacing
     (setq hlp2 (list x1 hy)) ;Create point using new y value and x1
     (command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" hlp2)))   ;Insert arrow "predetermined spacing below the 1st arrow"
  ))

 

Or rewriten to the fashion i've recommend.

(cond ((equal x1 x2 1e-6) 
       (setq y (- y1 6 tendon))
       (while (<= (setq y (+ y tendon)) y2)
	 (command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" (list x y))))

      ((equal y1 y2 1e-6)
       (setq x (- x1 6 tendon)) 
       (while (<= (setq x (+ x tendon)) x2)
	 (command "_.insert" "PT STRAND" "_scale" 1 "_rotate" 0 "_none" (list x y)))))

 

But if that's your first code... thumps up! Not that bad attempt.

0 Likes
Message 8 of 15

Anonymous
Not applicable

Thank you very much I appreciate the help, what is the meaning of the "1e-6" piece of code, what role does this play?

0 Likes
Message 9 of 15

dlanorh
Advisor
Advisor

@Anonymous wrote:

Thank you very much I appreciate the help, what is the meaning of the "1e-6" piece of code, what role does this play?


It equates to 0.000001 and is the number expressed in scientific notation. It is the fuzz factor for the equals function. What this means is that if the two values are not the same to 20 significant decimal places consider them equal if the difference is less than the fuzz factor.

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

Message 10 of 15

Anonymous
Not applicable

This code looks like it should work but it still does not seem to be repeat inserting the blocks, did it work when you attempted to run the code? Am I running it incorrectly? 

0 Likes
Message 11 of 15

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... The blocks should be inserted until the point they are being inserted on is greater than or equal to the second endpoint selected, after which the code should end. 

(The first endpoint selected should be the right most or top most point on the line)

....


 

Maybe I'm assuming too much, but if the second endpoint selected is, in fact, an endpoint, i.e. the other end of a Line, then MEASURE should be able to do this for you without any code, provided you define your Block in such a way that its orientation will be as you want it in relation to the Line's direction.  If MEASURE puts the Blocks in from the "wrong end," you can Undo it, REVERSE the Line, and do it again.

Kent Cooper, AIA
0 Likes
Message 12 of 15

ВeekeeCZ
Consultant
Consultant

@Anonymous wrote:

Thank you very much I appreciate the help, what is the meaning of the "1e-6" piece of code, what role does this play?


When comparing real numbers never use a (= ) function. Real number has limited precision (see WIKI), so even seemingly same numbers can be different in 0.0000000000000000000x digit. So limit the comparison to something reasonable (let's say 10^-6). 

0 Likes
Message 13 of 15

Anonymous
Not applicable

Thank you for your help, I am new to coding autolisp though so im not 100% sure how to integrate the measure command into my existing code and alter the measure command so it is equal to my predetermined "tendon" spacing (how far the blocks should be placed from one another). If you have time would you mind explaining further or creating an example code for me, I would very much appreciate it!

0 Likes
Message 14 of 15

ВeekeeCZ
Consultant
Consultant
Accepted solution

@Anonymous wrote:

This code looks like it should work but it still does not seem to be repeat inserting the blocks, did it work when you attempted to run the code? Am I running it incorrectly? 


 

Sorry for late answer. The logic is other way around, 1st point is the lower one. I was hoping that you are able to adjust the code to your needs. See the screencast HERE 

0 Likes
Message 15 of 15

Kent1Cooper
Consultant
Consultant

@Anonymous wrote:

.... how to integrate the measure command into my existing code and alter the measure command so it is equal to my predetermined "tendon" spacing (how far the blocks should be placed from one another). ....


 

Try something like this [very lightly tested]:

(defun C:GL (/ esel ent dir adj)
  (setq
    esel (entsel "\nSelect horizontal or vertical Line: ")
    ent (car esel)
    dir (angle (vlax-curve-getStartPoint ent) (vlax-curve-getEndPoint ent))
    adj (- tendon 6); for Lengthen command Delta option
  ); setq
  (if
    (and
      (member '(0 . "LINE") (entget ent)); it's a Line
      (or ; it's horizontal or vertical
        (equal (rem dir (/ pi 2)) 0.0 1e-4)
        (equal (rem dir (/ pi 2)) (/ pi 2) 1e-4)
      ); or
    ); and
    (progn ; then -- proceed
      (if ; runs rightward or upward?
        (or (equal dir 0.0 1e-4) (equal dir (* pi 2) 1e-4) (equal dir (/ pi 2) 1e-4))
        (command "_.reverse" ent "" "_.regen"); then -- turn it around
          ;; REGEN seems to be needed to re-establish 'ent' and where it starts and ends
      ); if
      (command
        "_.lengthen" "_delta" adj (list ent (vlax-curve-getStartPoint ent)) ""
          ;; so that first instance will be 6 units from original start
        "_.regen" ;; as above
        "_.measure" (list ent (vlax-curve-getStartPoint ent)) "_block" "PT STRAND" "_yes" tendon
        "_.lengthen" "_delta" (- adj) (list ent (vlax-curve-getStartPoint ent)) ""
;; back to original length ); command ); progn (prompt "\nNot a Line, or not vertical or horizontal.") ); if (princ) ); defun (vl-load-com)

 

It has the advantage that you don't need to pick both ends, but simply pick a Line anywhere on it [under the assumptions in my previous Reply].

 

BUT be aware that MEASURE, when using Blocks and aligning them with the object, puts their rotation angle in the drawn direction of the object.  Since your process is leftward  or downward, and the routine ensures that the Line's drawn direction is one of those in order for MEASURE to start at the correct end, the Blocks will therefore not be at 0 or 90 degrees, but at 180 or 270.  So if your Block "aims" in some non-symmetrical way, you will probably want to spin the contents in the Block definition 180 degrees around the insertion point.

 

Kent Cooper, AIA
0 Likes