Copy block x time between 2 points (with orientation) (CM2P adaptation)

Copy block x time between 2 points (with orientation) (CM2P adaptation)

m.lharidon
Enthusiast Enthusiast
1,950 Views
24 Replies
Message 1 of 25

Copy block x time between 2 points (with orientation) (CM2P adaptation)

m.lharidon
Enthusiast
Enthusiast

Hello,

 

I tried to modified the attached LSP to add fonctionnalities:

 

- automatically select the base point of my block

- keep the orientation of my block (for instance if my block is looking up, then when it copy along the line it stay normal to this line)

 

Here is my try:

 

(defun c:CM2PM nil (c:CopyMultipleArrayBetween2point))
(defun c:CopyMultipleArrayBetween2point
       (/ *error* ss p p1 p2 pt n l d c lst)
  ;; Author : Tharwat ~ 15. Jan. 2014	;;
  (defun *error* (pm)
    (if c
      (setvar 'CMDECHO c)
    )
    (princ "\n *Cancel*")
  )
  (if (and       
	   (setq e (car (entsel "\Select block: ")))
           (setq p (cdr (assoc 10 (entget e)))
           (setq p1 (getpoint "\n Specify first point :"))
           (setq p2 (getpoint "\n Next point :" p1))
           (setq n (getint "\n Number of EQ spaces :"))
	   (setq rad (angle p1 p2)
		 dau (angtos rad (getvar 'AUNITS) 12))
      )
    (progn
      (setq l (distance p1 p2)
            d (/ l n)
            c (getvar 'CMDECHO)
      )
      (setvar 'CMDECHO 0)
      (foreach x (list p1 p2)
        (command "_.copy" ss "" "_none" p "_none" x)
	(command "_.INSERT" p e "_Scale" 1 "_Rotate" dau "_none" x)
      )
      (repeat (1- n)
        (command "_.copy"
                 ss
                 ""
                 "_none"
                 p
                 "_none"
                 (setq pt (polar p1 (angle p1 p2) d))
        )
        (setq p1 pt)
      )
      (setvar 'CMDECHO c)
    )
  )
  (princ)
)

If anyone can help, it could be so great.

 

Thanks 🙂

 

ML

0 Likes
Accepted solutions (4)
1,951 Views
24 Replies
Replies (24)
Message 2 of 25

Kent1Cooper
Consultant
Consultant

A few things I notice, quickly....

 

Your selected Block is in the 'e' variable where selected, but you seem to be meaning the same thing by the 'ss' variable, which is never created.

 

The first thing after the INSERT command name needs to be the Block name  [the (assoc 2) entry in entity data], not 'p' which is its insertion point.

 

There are some other efficiencies I could suggest, but first straighten those out, and see whether you can get it to work.

Kent Cooper, AIA
0 Likes
Message 3 of 25

m.lharidon
Enthusiast
Enthusiast

Hello,

 

Thanks a lot for your feedback.

 

Your are right I actually wanted to replace the copy fonction by the insert fonction. so I erase had to erase the copy line.

About the ss name of object I forgot to change it in the copy command so I did it.

I changed the original "copy" command by an "insert", is that correct?

(defun c:CM2PM nil (c:CopyMultipleArrayBetween2point))
(defun c:CopyMultipleArrayBetween2point
       (/ *error* ss p p1 p2 pt n l d c lst)
  ;; Author : Tharwat ~ 15. Jan. 2014	;;
  (defun *error* (pm)
    (if c
      (setvar 'CMDECHO c)
    )
    (princ "\n *Cancel*")
  )
  (if (and       
	   (setq e (car (entsel "\Select block: ")))
           (setq p (cdr (assoc 10 (entget e)))
           (setq p1 (getpoint "\n Specify first point :"))
           (setq p2 (getpoint "\n Next point :" p1))
           (setq n (getint "\n Number of EQ spaces :"))
	   (setq rad (angle p1 p2)
		 dau (angtos rad (getvar 'AUNITS) 12))
      )
    (progn
      (setq l (distance p1 p2)
            d (/ l n)
            c (getvar 'CMDECHO)
      )
      (setvar 'CMDECHO 0)
      (foreach x (list p1 p2)
       (command "_.INSERT" e "_Scale" 1 "_Rotate" dau "_none" x)
      )
      (repeat (1- n)
        (command "_.copy"
                 e
                 ""
                 "_none"
                 p
                 "_none"
                 (setq pt (polar p1 (angle p1 p2) d))
        )
        (setq p1 pt)
      )
      (setvar 'CMDECHO c)
    )
  )
  (princ)
)

Is that better?

 

Thanks again.

 

ML

 

0 Likes
Message 4 of 25

dbhunia
Advisor
Advisor
Accepted solution

Try this....... 

 

 

 


Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 5 of 25

Kent1Cooper
Consultant
Consultant

@m.lharidon wrote:

...

Is that better?

....


 

[You tell us....]  The thing I noticed first is that the INSERT command is given 'e' [which is the entity name of a Block insertion  or reference ] where it wants to be given a Block name.  @dbhunia has corrected that in his suggestion.

 

But I have a question:  Would the selected Block ever be at a scale other than 1?  And might it ever be of unequal  scale factors?  The code appears to Insert one at a scale of 1, regardless of the scale of the selected one.  It matches only the rotation of the original.  And it puts it on the current Layer, regardless of what Layer the selected one is on.  Is that what you want?  If the spaced ones should be the same as the selected one, in Layer and scale(s) as well as rotation, I would think it could be done with one Copy command with a Multiple option, rather than with two Insert commands and a series of Copy commands.

Kent Cooper, AIA
0 Likes
Message 6 of 25

m.lharidon
Enthusiast
Enthusiast

Hello,

 

Thanks a lot for your answer.

 

Yes this is exactly what I want. There is just one point:

It keeps the latest orientation of the block, when i selectr if in my drawing. When I draw my line i would like the block to be always normal to it.

Is there a way to do this?

 

Once again, thanks a lot!

 

ML

0 Likes
Message 7 of 25

dbhunia
Advisor
Advisor

Try this.......

 

 

(defun c:CM2PM (/ *error* ss p p1 p2 p3 pt n l d c lst)
  (defun *error* (pm)
    (if c
      (setvar 'CMDECHO c)
    )
    (princ "\n *Cancel*")
  )
  (if (and       
	   (setq e (car (entsel "\n Select block: ")))
	   (setq p (cdr (assoc 10 (entget e))))
           (setq p1 (getpoint "\n Specify first point :"))
           (setq p2 (getpoint "\n Next point :" p1))
           (setq n (getint "\n Number of EQ spaces :"))
	   (setq rad (angle p1 p2))
	   (setq dau (angtos rad (getvar 'AUNITS) 12))
      )
    (progn
      (setq l (distance p1 p2)
            d (/ l n)
            c (getvar 'CMDECHO)
      )
      (setvar 'CMDECHO 0)
      (command "_.copy" e "" "_none" p "_none" p1)
      (command "_.rotate" (setq e (entlast)) "" (setq p3 (cdr (assoc 10 (entget e)))) dau)
      (repeat n
	(setq p1 (polar p1 rad d))
        (command "_.copy" e "" "_none" p3 "_none" p1)
      )
      (setvar 'CMDECHO c)
    )
  )
  (princ)
)

 

 

 


Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 8 of 25

m.lharidon
Enthusiast
Enthusiast

Hello,

 

Thanks for your answer.

 

Except my mistake I see no difference in this lips behavior. The result looks the same a the previous.

 

ML

0 Likes
Message 9 of 25

dbhunia
Advisor
Advisor

@m.lharidon wrote:

Hello,

 

Thanks for your answer.

 

Except my mistake I see no difference in this lips behavior. The result looks the same a the previous.

 

ML


 

What is the Basic difference between INSERT a Block & COPY a Block?

 

When you INSERT a block it ask for "insertion point" "scale factor" and "rotation angle".....

 

But whenever you COPY an Object it ask for "base point" and "second point".... and it creates an Object with the same property of the parent Object at "second point"....... For Block the "scale factor" , "rotation angle" and the other properties will be same as  the parent Block.....

 


Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 10 of 25

m.lharidon
Enthusiast
Enthusiast

Hello,

 

Ok, I understand for the copy/insert difference. But when i use the fonction (copy oer insert) I would like (whatever the block or his actual orientation) to have it always normal to the P1/P2 line i draw.

 

I can't find how to achieve it.

 

ML

0 Likes
Message 11 of 25

dbhunia
Advisor
Advisor

Try this.......

 

 

(defun c:CM2PM (/ *error* e p p1 p2 n rad l d c blk_ent p3)
  (defun *error* (pm)
    (if c
      (setvar 'CMDECHO c)
    )
    (princ "\n *Cancel*")
  )
  (if (and       
	   (setq e (car (entsel "\n Select block: ")))
	   (setq p (cdr (assoc 10 (entget e))))
           (setq p1 (getpoint "\n Specify first point :"))
           (setq p2 (getpoint "\n Next point :" p1))
           (setq n (getint "\n Number of EQ spaces :"))
	   (setq rad (angle p1 p2))
      )
    (progn
      (setq l (distance p1 p2)
            d (/ l n)
            c (getvar 'CMDECHO)
      )
      (setvar 'CMDECHO 0)
      (command "_.copy" e "" "_none" p "_none" p1)
      (setq blk_ent (entget (entlast)))
      (entmod (subst (cons 50 rad)(assoc 50 blk_ent)blk_ent))
      (setq e (entlast))
      (setq p3 (cdr (assoc 10 (entget e))))
      (repeat n
	(setq p1 (polar p1 rad d))
        (command "_.copy" e "" "_none" p3 "_none" p1)
      )
      (setvar 'CMDECHO c)
    )
  )
  (princ)
)

 

 

 


Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 12 of 25

m.lharidon
Enthusiast
Enthusiast

Oh! So great! It almost that. My block is actually parrallele to the line (Unfortunatly I cant change the block himself, I need it this way to other reasons) . I look to have it at 90°. I suppose we can play with this parameter to change it?

 (entmod (subst (cons 50 rad)(assoc 50 blk_ent)blk_ent))

 ML

0 Likes
Message 13 of 25

dbhunia
Advisor
Advisor

Absolutely right......  Manipulate "rad" for your desire rotation.......


Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 14 of 25

m.lharidon
Enthusiast
Enthusiast

ok, but how. I can't find out the link between 50rad and my orientation... Sorry my skills are really poor...

0 Likes
Message 15 of 25

Kent1Cooper
Consultant
Consultant

Add half of pi radians to the angle:

 

(entmod (subst (cons 50 (+ rad (/ pi 2))) (assoc 50 blk_ent) blk_ent))

 

[or subtract it from the angle, if that's the direction you need].

Kent Cooper, AIA
0 Likes
Message 16 of 25

dbhunia
Advisor
Advisor
Accepted solution

@m.lharidon wrote:

ok, but how. I can't find out the link between 50rad and my orientation... Sorry my skills are really poor...


 

Here 50 is the DXF Group code stores the "Angle" of rotation in Radians ......

 

Check this for more details.....

https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2018/ENU/AutoCAD-DXF/files/GUI...

 

And follow as @Kent1Cooper  said ...... that is only play with "rad" value

 

That is like (setq rad (+ rad (/ pi 2)))  or (setq rad (- rad (/ pi 2))) or (setq rad (+ rad (/ pi 4))) etc.......

 

 

 


Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 17 of 25

m.lharidon
Enthusiast
Enthusiast

Top! thanks a lot. It also gave my solution to fix other of my lisp.

Once again thanks for the support.

 

ML

0 Likes
Message 18 of 25

m.lharidon
Enthusiast
Enthusiast

Hello,

I tried to use in input of this lisp the number of copied block instead of number of division 

(setq n (getint "\nNumber of copies :"))
(setq m (1 - n)) ;;;number of equal space

Then I used M instead than N in the code:

    (progn
      (setq l (distance p1 p2)
            d (/ l m)
            c (getvar 'CMDECHO)
      )
      (setvar 'CMDECHO 0)
      (command "_.copy" e "" "_none" p "_none" p1)
      (setq blk_ent (entget (entlast)))
      (entmod (subst (cons 50 (+ rad (/ pi 2))) (assoc 50 blk_ent) blk_ent))
      (setq e (entlast))
      (setq p3 (cdr (assoc 10 (entget e))))
      (repeat m
	(setq p1 (polar p1 rad d))
        (command "_.copy" e "" "_none" p3 "_none" p1)
      )
      (setvar 'CMDECHO c)
    )
  )
  (princ)
)

But nothing happends.

 

In the same logic I wanted to create an alternative lisp by redefine the starting point of copy att half distance of P1

(setq l (distance p1 p2))
(setq d (/ l n))
(setq dd (/ d 2))
(setq p4 (polar p1 rad dd))

Once again no result, In quite sure I mess up in my variable set up.

 

Thanks.

 

ML

 

0 Likes
Message 19 of 25

dbhunia
Advisor
Advisor

For this.......

 


@m.lharidon wrote:

Hello,

I tried to use in input of this lisp the number of copied block instead of number of division 

(setq n (getint "\nNumber of copies :"))
(setq m (1 - n)) ;;;number of equal space

 

use.......

 

(setq m (1- n)); No space between "1" & "-".
OR
(setq m (- n 1))

 

 

In the same logic I wanted to create an alternative lisp by redefine the starting point of copy att half distance of P1 ;;;; what do you mean by att half distance of P1

 



 


Debashis Bhunia
Co-Founder of Geometrifying Trigonometry(C)
________________________________________________
Walking is the First step of Running, Technique comes Next....
0 Likes
Message 20 of 25

m.lharidon
Enthusiast
Enthusiast

Hello,

 

Attached a layout describing what i want to do.

LISP 1 :  I just have to correct and set my number of division according to my number of copy

LISP 2 :  I wanted to set a P4  (setq p4 (polar p1 rad dd)) ///dd is half d then copy my block from here.

 

ML

0 Likes