Emmanuel Delay 发表于 2022-7-5 17:54:40

I added an attribute "BACK" to the panel.
 
The back ballasts come 200 mm from the bottom; the top ballasts come 600 mm from the bottom.
You can change this with these commands:
(+ 200.0 y_value) and (+ 600.0 y_value)
 
The code is now this:

;; @file: draw ballasts on solar panels, depending on the properties of the roof regions;; @author: Emmanuel Delay - emmanueldelay@gmail.com; load extra recources(vl-load-com)(defun ballast ( / blocks x_values sorted_indexes block spacing x_pointer x_pointer_back lft rgt width_panel y_value)(princ "\nSelect the solar panel blocks (cross select)") (setq    i 0   spacing 0.0   x_pointer 0.0                                                       ;; x_pointer is like the needle of a turn table.We set it to the x of the left panel block, then it only increases untill we get to the right panel    x_pointer_back 0.0   x_values (list)   blocks (ssget ":N"   ;; client makes a cross select   (list      (cons 0 "INSERT")   )   ) ) ;; we read the y-value of the first panel (setq y_value (nth 2 (assoc 10 (entget (ssname blocks 0)))));; we make an array (list) containing the x-value of the insert point(repeat (sslength blocks)   (setq x_values (append x_values (list   (cadr (assoc 10 (entget (ssname blocks i))));; returns the insert point, x-value   )))   (setq i (+ i 1)) );; we sort this last list, from left to right.sorted_indexes contains the index (to be used in the "nth" and "ssname" function) (setq sorted_indexes (vl-sort-i x_values    (function (lambda (e1 e2) (< e1 e2))) )) ;; we set x_pointer to the x-value of the left panel (setq x_pointer (nth (nth 0 sorted_indexes) x_values)) (setq x_pointer_back (nth (nth 0 sorted_indexes) x_values));; same for the back pointer;; calculate the width of the panel(setq width_panel (- (nth (nth 1 sorted_indexes) x_values) (nth (nth 0 sorted_indexes) x_values) ));; we loop over sorted_indexes. (setq i 0) (repeat (length sorted_indexes)   (setq block (VLAX-ENAME->VLA-OBJECT (ssname blocks (nth i sorted_indexes))))   ;; set left and right point of the panel   (setq      lft (nth (nth i sorted_indexes) x_values)   rgt (+ lft width_panel)   )    ;; we look for the "SPACING" attribute   (foreach Attribute (vlax-invoke Block "GetAttributes")   (if (= (vla-get-TagString Attribute) "SPACING")       (progn         (setq spacing (atof (vla-get-TextString Attribute)))         ;;         (while (< x_pointer rgt)         (progn             (AT:InsertBlock "ballast" (list x_pointer (+ 600.0 y_value)) 1.0 1.0 0.0)             (setq x_pointer (+ x_pointer spacing))         )         )         (princ "\n")       )   )   )   ;; we look for the "BACK" attribute   (foreach Attribute (vlax-invoke Block "GetAttributes")   (if (= (vla-get-TagString Attribute) "BACK")       (progn         (setq spacing (atof (vla-get-TextString Attribute)))         ;;         (while (< x_pointer_back rgt)         (progn             (AT:InsertBlock "ballast" (list x_pointer_back (+ 200.0 y_value)) 1.0 1.0 0.0)             (setq x_pointer_back (+ x_pointer_back spacing))         )         )         (princ "\n")       )   )   )      (setq i (+ i 1)) ));;; Insert block into drawing;;; #Name - name of block;;; #InsPt - insert point;;; #XScale - block X scale;;; #YScale - block Y scale;;; #Rot - block rotation;;; Alan J. Thompson, 04.21.09(defun AT:InsertBlock (#Name #InsPt #XScale #YScale #Rot) (if (or (tblsearch "block" #Name)         (findfile #Name)   ) ;_ or   (vla-insertblock   ((if (eq (getvar "cvport") 1)      vla-get-paperspace      vla-get-modelspace      ) ;_ if       (vla-get-ActiveDocument         (vlax-get-acad-object)       ) ;_ vla-get-ActiveDocument   )   (vlax-3d-point #InsPt)   #Name   #XScale   #YScale   #XScale   #Rot   ) ;_ vla-insert-block ) ;_ if) ;_ defun;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;(defun c:ballast ( / ) (ballast) (princ))
spacing.dwg

drew4748 发表于 2022-7-5 17:58:45

One more issue than I'm sure this is solved. When I changed the name ofthe ballast block to "Ballast Block" which is the name of the block weuse, I get an "invalid table function argument(s): "Ballast Block""Ballast Block". When i changed the name in the first lsp you sent me,it works fine with my block, but not with the routine which has bothrear and front spacing. Could you please shed some light on this. I attached both of the files. Maybe you can see something I cannot. Sorry I have never really done lsp routines before. Im sure this is an easy fix which I just can not see.Thankyou.ballast.lsp
ballast2.lsp

Emmanuel Delay 发表于 2022-7-5 18:00:27

No problem.
 
It's line 101 (of ballast2.lsp).
 

(if (or      (tblsearch "Ballast Block" #Name)   (findfile #Name)   ) ;_ or
should be
 

(if (or      (tblsearch "BLOCK" #Name)   (findfile #Name)   ) ;_ or

drew4748 发表于 2022-7-5 18:06:19

 
So that last line where it says BLOCK is basically telling it to insert a block correct? Just trying to understand this better.
 
This works perfectly now that I have changed it. It will reduce my drafting time, and more importantly user errors significantly. Thank you.

Emmanuel Delay 发表于 2022-7-5 18:08:06

Autocad has a list (a table) of all the blocks, layers ... that are available.
They might or might not have an instance drawn on the dwg, but they are available.
 
tblsearch searches in that list.So, that would also be the function you need to see if you can set a layer
(tblsearch "LAYER" "MyLayer")
 
------
Let me tell you a a few things about LISP.
 
LISP has no operators.
 
Most programming languages do something like this:
 
a = b + 15
LISP does
(setq a (+ b 15))
 
- Opening a "(" means you start a function
"=" and "+" are just functions; in other languages they are operators; so they don't look like functions.
 
----
LISP looks most like javascript.
That is to say: javascript was written to behave like LISP, but look like JAVA or C.
 
You can pass anything to any function.You can pass the definition of a function to another function;
you have anonimous functions: lambda.
 
example

(setq sorted_indexes (vl-sort-i x_values    (function (lambda (e1 e2) (< e1 e2))) ))
 
In javascript this would be something like

sorted_indexes.sort(function(a, b) { return (a < b);});
 
So you can pass an anonimous function, each pair that is evaluated passes through that function.
In (most) other languages you can't do that.
 
Both in LISP and javascript there are no classes, no interfaces ... the function does it all.

drew4748 发表于 2022-7-5 18:11:48

Let me just say I am very happy with this routine it works perfect, however I am having some troubles trying to update it. I cannot, and do not know how, to change where the routine inserts the blocks via the x coordinate. Also I am wondering as to why the block is grabbing the attribute from the next area as opposed to the area its in. Thanks in advance.

Chemra 发表于 2022-7-5 18:15:01

Hi Experts,
 
I am looking for a LISP routine which user defines an area (rectangle) and a block and 2 numbers x & y (array dimension) and the the routine place the amount of blocks inside the rectangle.
NB: the distance of block-edge of rectangle shall be distance of block-block divided by 2.
I need to use it to place an amount of lighting fixtures. lights must be away from walls half distance of light to light.
 
Thank you all.

Emmanuel Delay 发表于 2022-7-5 18:17:37

@Chemra
 
 
I'm not 100% sure what exactly you want, this is how I understand it:
 
Let's say you have a room: 12m (x-axis), 6m (y-axis), and you want 3 lamps along the x-axis, 2 lamps along the y-axis
This results in 6 lamps, inserted at (2.01.5), (2.04.5), (6.01.5), (6.04.5), (10.01.5), (10.04.5)
my idea is: I divide the room in 6 equal rectangles, each rectangle has a lamp in the middle of it.
 
 
 
Is that what you have in mind?
 
-----
 
Anyway, here is what I guess you want.
 
Included: 2 test functions, commands: "TEST" & "TEST2" (requires a block called "LAMP", feel free to change this value)
 
 

;; @see http://www.cadtutor.net/forum/showthread.php?88364-block-spacing-lisp&p=667173&viewfull=1#post667173;; I am looking for a LISP routine which user defines an area (rectangle) and a block and 2 numbers x & y (array dimension) ;;   and the the routine place the amount of blocks inside the rectangle.;; NB: the distance of block-edge of rectangle shall be distance of block-block divided by 2.;; I need to use it to place an amount of lighting fixtures. lights must be away from walls half distance of light to light.(vl-load-com);;; Insert block into drawing;;; #Name - name of block;;; #InsPt - insert point;;; #XScale - block X scale;;; #YScale - block Y scale;;; #Rot - block rotation;;; Alan J. Thompson, 04.21.09(defun AT:InsertBlock (#Name #InsPt #XScale #YScale #Rot) (if (or (tblsearch "block" #Name)         (findfile #Name)   ) ;_ or   (vla-insertblock   ((if (eq (getvar "cvport") 1)      vla-get-paperspace      vla-get-modelspace      ) ;_ if       (vla-get-ActiveDocument         (vlax-get-acad-object)       ) ;_ vla-get-ActiveDocument   )   (vlax-3d-point #InsPt)   #Name   #XScale   #YScale   #XScale   #Rot   ) ;_ vla-insert-block ) ;_ if) ;_ defun;; inserts a block.This might be a function where you perform extra stuff, like fill attributes(defun insert_block (blockname x y / ) (AT:InsertBlock blockname (list x y) 1.0 1.0 0.0));; main function(defun fill_rectangle ( p1 p2 blockname cols rows / segment_x segment_y x y) (setq segment_x                ;; (x2 - x1) / cols   (/ (- (nth 0 p2) (nth 0 p1)) cols) ) (setq segment_y   (/ (- (nth 1 p2) (nth 1 p1)) rows) ) (setq    x 0   y 0 ) (repeat cols   (setq y 0)   (repeat rows   (insert_block         blockname      (+ (nth 0 p1) (/ segment_x 2 ) (* segment_x x ));; insert point (x) + half segment length + X number full segment lengths       (+ (nth 1 p1) (/ segment_y 2 ) (* segment_y y ))   )   (setq y (+ y 1))   )   (setq x (+ x 1)) ));;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; test function with hardcoded values, as example.;; This requires a block "LAMP"(defun c:test2 ( / p1 p2) (fill_rectangle   (list 0.0 0.0)   (list 12.0 6.0)   "LAMP"   3   2 ) (princ));; test function with user selected values.(defun c:test ( / p1 p2) (fill_rectangle      ;; user defines an area (rectangle)   (setq p1 (getpoint   "\nPoint 1, bottom-left: "))   (setq p2 (getcorner p1 "\nPoint 2, top-right: "))      ;; and a block   (getstring "\nBlock name: ")      ;; and 2 numbers x & y (array dimension)   (getint "\nX (number of colums) ")   (getint "\nY (number of rows) ")    ) (princ))

Chemra 发表于 2022-7-5 18:22:11

Brilliant thanks, You made my day

Chemra 发表于 2022-7-5 18:22:16

Hi Emmanuel,
 
I was trying to change the way of getting the block. I tried entsel, however, i still getting error, too many arguments. Any advice?
Thanks
 
页: 1 [2]
查看完整版本: 块间距lisp