First of all, let me start off by saying that I was reluctant to post this code here for a number of reasons. First, and foremost, I'm certain that there is a better way, a more effecient way, and a cleaner way to accomplish what this code accomplishes. Second, I threw this code together one afternoon in frustration and I haven't even had an opportunity to comment it all correctly. It's embarrasing.
So, having said all of that, here it is. Someone asked a few days ago about a routine for drawing acoustical ceiling tile grids for a lighting layout and this is what I use. Quite often we get drawings from the architect and the layout that they have for the ceiling grid is so
horribly bad that we end up having to draw it all anyway.
What this code doesThis is two routines that do, essentially, the same thing. They could be combined into one routine, I know, but, like I said, this was a 'quick-n-dirty' bit of code. The only difference between the two routines is that one of them draws the grid at an angle (for rooms situated at an angle, obviously) and one of them does not.
You have the option of drawing a 'frame' around the room (a rectangle on the same layer as the grid) or not, and the routine centers the 24" X 24" grid in the room (much like the guy who will actually be installing the tiles will do).
That's all well and good until you realise that not all rooms are square or rectangular shaped. And that's why the option is there for the frame.
Normally, when we draw these 'by hand' we draw a polygon frame (in the case of a non-rectangular room) around the room, draw a line across the room vertically and horizontally, then copy or offset those lines by 24 inches. Then we center the grid and trim off the excess. That process goes much quicker if the room is rectangular or square in shape, but it's still a very time consuming bit of work. For example, the project that prompted me to write this was a middle school with somewhere in the neighborhood of 60 rooms and corridors that our loving architect revised on a daily basis. Every day we had to 'clean up' the architects drawings so that we could use them. The process of drawing the ceiling grids, alone, took most of the day.
These routines, believe it or not, save us countless
hours of work because the most tedious of the above mentioned tasks are eliminated. The only thing left for the user to do is trim off the excess of a non-rectangular room.
How I use these routinesFor a square or rectangular room (not at an angle), in the words of the band Saliva: click, click, BOOM!
Done.
For a square or rectangular room (at an angle): click, click, click, BOOM!
I use the routine with the argument
e_frame set to TRUE and it does all of the work.
For a non-rectangular room I draw a polygon frame around the limits of the room and I run the routine with the argument
e_frame set to FALSE. It draws the grid, centered in the room, then I trim the excess using my frame as the boundary.
For a real world example of how that works consider the middle school I mentioned above. I can do the whole school in about an hour compared to all day doing it 'by hand'.
What I have listed is, first, the format that I use to call these routines from our menu. The routines are stored in our MNL file along with the little bitty routine
elecLayers that I included (it's used in these routines).
Where these routines could goOne of the things I plan to do one of these days when I have time (HA!) is to try to combine this all into one nice little routine that does everything like this:
The user is first prompted for what type of frame they want to draw, polygon or rectangle. If they choose rectangle, run the routine pretty much as is. If they choose polygon, prompt for each point around the frame and, when the user us finished, draw the grid then use the polygon they created to trim the excess, if any.
Why it doesn't do that alreadyLike I said, quick-n-dirty. Compared to what we used to do, this is
heaven as it is right now. I'm not given much time to actually write code at work, I have to sneak it in. On those rare occasions where I do get time, I end up having only enough time to throw together something quick-n-dirty.
Most of my coding happens on my personal time, like during lunch or after work. Right now this works better than anything my users have ever had so there isn't a valid reason (in my boss' eyes) for me to spend anymore time on it. None of the users here really appreciate the code I write anyway, so it's difficult for me to care how easy I can make things on them.
I know, bad attitude and all...
Anyway, here it is, ask any questions if you like, hack away at it if you want, critique it to it's last bit if you like, copy it, put your name on it, tell everyone else you wrote it and sell it for a million dollars if it makes you happy.
;;==========================================================================================
;; Commands, as they appear in the menu
;;==========================================================================================
ID_EGridF [EGrid with Frame]^C^C(setq e_frame T);egrid;
ID_EGrid [EGrid w/o Frame]^C^C(setq e_frame F);egrid;
ID_EGridA [Angled EGrid with Frame]^C^C(setq e_frame T);a_egrid;
ID_EGridAx [Angled EGrid w/o Frame]^C^C(setq e_frame F);a_egrid;
;;==========================================================================================
;; elecLayers
;;==========================================================================================
(defun elecLayers (x)
(and (tblsearch "layer" x))
)
;;==========================================================================================
;; EGRID
;;==========================================================================================
(defun c:egrid (/ pt_1 pt_2 h_dist h_count
h_pt_1 h_pt_a h_diff v_dist v_count
v_pt_1 v_pt_a v_diff user_osnap user_layer
)
(setq pt_1 (getpoint "\nSelect LOWER-LEFT corner of room"))
(setq pt_2 (getcorner pt_1 "\nSelect UPPER-RIGHT corner of room"))
(setq h_dist (- (car pt_2) (car pt_1)))
;; horizontal length of the rectangle
(setq v_dist (- (cadr pt_2) (cadr pt_1)))
;; vertical length of the rectangle
(setq h_count (atoi (rtos (/ h_dist 24.0) 2)))
;; the number of 24 inch spaces, horizontally
(setq v_count (atoi (rtos (/ v_dist 24.0) 2)))
;; the number of 24 inch spaces, vertically
(if (= 24 (/ h_dist h_count))
;; alright, here is where we check to see if the number of spaces that we came up with
;; is divisible by 24. Because, if it isn't, we need to adjust our starting points to
;; begin the drawing of our grid. If it is, then we need to subtract 1 from the total
;; because, if not, a line will be drawn on the far wall (vertically or horizontally)
;; where it is equally divisible and we want to eliminate that clutter.
(progn
(setq h_count (1- h_count))
(setq v_pt_1 pt_1)
)
;; okay, everything is equally divisible by 24 so subtract 1 off of the count total and
;; our VERTICAL grid lines will be centered, horizontally.
(progn
;; Oops, not so good now. Since our distance isn't divisible by 24 our grid needs to
;; be centered, horizontally, for us.
(setq h_diff (- 24 (/ (- h_dist (* h_count 24)) 2)))
;; set a variable for the difference by multiplying our count by 24, subtracting that
;; number from our overall distance, taking the number we come up with, and dividing
;; it by two. Then, subtract that number from 24 so that we know where to actually
;; start drawing our VERTICAL lines.
(if (< 12 h_diff)
(progn
(setq h_diff (+ 12 h_diff))
(setq h_count (1- h_count))
)
(progn)
)
;; if the number we came up with above is less than 12 it is most likely not going to
;; look all that great as a finished product. A 2 inch sliver of ceiling tile is not
;; only ugly, it's difficult to install. Therefore, we can add 12 inches (oddly enough
;; that's half the distance across a 2 foot square of tile) and add it to our starting
;; point. If we're gonna do that, however, we need to draw 1 less line, overall.
(setq h_count (1+ h_count))
(setq v_pt_1 (subst (+ 24 (- (car pt_1) h_diff)) (car pt_1) pt_1))
)
)
(if (= 24 (/ v_dist v_count))
(progn
(setq v_count (1- v_count))
(setq h_pt_1 pt_1)
)
(progn
(setq v_diff (- 24 (/ (- v_dist (* v_count 24)) 2)))
(if (< 12 v_diff)
(progn
(setq v_diff (+ 12 v_diff))
(setq v_count (1- v_count))
)
(progn)
)
(setq v_count (1+ v_count))
(setq
h_pt_1 (subst (+ 24 (- (cadr pt_1) v_diff)) (cadr pt_1) pt_1)
)
)
)
(setq user_osnap (getvar "osmode"))
(setq user_layer (getvar "clayer"))
(setvar "osmode" 0)
(if (/= (elecLayers "egrid") T)
(command "-layer" "n" "egrid" "c" "41" "egrid" "")
)
(setvar "clayer" "egrid")
(repeat v_count
(setq h_pt_a (subst (+ 24.0 (cadr h_pt_1)) (cadr h_pt_1) h_pt_1))
(setq h_pt_b (subst (+ h_dist (car h_pt_a)) (car h_pt_a) h_pt_a))
(command "line" h_pt_a h_pt_b "")
(setq h_pt_1 h_pt_a)
)
(repeat h_count
(setq v_pt_a (subst (+ 24.0 (car v_pt_1)) (car v_pt_1) v_pt_1))
(setq v_pt_b (subst (+ v_dist (cadr v_pt_a)) (cadr v_pt_a) v_pt_a))
(command "line" v_pt_a v_pt_b "")
(setq v_pt_1 v_pt_a)
)
(if (= e_frame T)
(command "rectangle" pt_1 pt_2))
(setvar "osmode" user_osnap)
(setvar "clayer" user_layer)
)
;;==========================================================================================
;; A_EGRID
;;==========================================================================================
(defun c:a_egrid (/ pt_1 pt_2 pt_3
h_dist h_count h_pt_1 h_pt_a
h_diff v_dist v_count h_ang
v_pt_1 v_pt_a v_diff user_osnap
user_layer user_units egrid_ss
)
(setq user_units (getvar "lunits"))
(setvar "lunits" 2)
(setq pt_1 (getpoint "\nSelect LOWER-LEFT corner of room"))
(setq pt_2 (getpoint pt_1 "\nSelect LOWER-RIGHT corner of room"))
(setq pt_3 (getpoint pt_2 "\nSelect UPPER-RIGHT corner of room"))
(setq h_dist (distance pt_1 pt_2))
(setq v_dist (distance pt_2 pt_3))
(setq h_ang (rtd (angle pt_1 pt_2)))
(setq h_count (atoi (rtos (/ h_dist 24.0) 2)))
(setq v_count (atoi (rtos (/ v_dist 24.0) 2)))
(if (= 24 (/ h_dist h_count))
(progn
(setq h_count (1- h_count))
(setq v_pt_1 pt_1)
)
(progn
(setq h_diff (- 24 (/ (- h_dist (* h_count 24)) 2)))
(if (< 12 h_diff)
(progn
(setq h_diff (+ 12 h_diff))
(setq h_count (1- h_count))
)
(progn)
)
(setq h_count (1+ h_count))
(setq v_pt_1 (subst (+ 24 (- (car pt_1) h_diff)) (car pt_1) pt_1))
)
)
(if (= 24 (/ v_dist v_count))
(progn
(setq v_count (1- v_count))
(setq h_pt_1 pt_1)
)
(progn
(setq v_diff (- 24 (/ (- v_dist (* v_count 24)) 2)))
(if (< 12 v_diff)
(progn
(setq v_diff (+ 12 v_diff))
(setq v_count (1- v_count))
)
(progn)
)
(setq v_count (1+ v_count))
(setq
h_pt_1 (subst (+ 24 (- (cadr pt_1) v_diff)) (cadr pt_1) pt_1)
)
)
)
(setq user_osnap (getvar "osmode"))
(setq user_layer (getvar "clayer"))
(setvar "osmode" 0)
(if (/= (elecLayers "egrid") T)
(command "-layer" "n" "egrid" "c" "41" "egrid" "")
)
(setvar "clayer" "egrid")
(setq egrid_ss (ssadd))
(repeat v_count
(setq h_pt_a (subst (+ 24.0 (cadr h_pt_1)) (cadr h_pt_1) h_pt_1))
(setq h_pt_b (subst (+ h_dist (car h_pt_a)) (car h_pt_a) h_pt_a))
(command "line" h_pt_a h_pt_b "")
(ssadd (entlast) egrid_ss)
(setq h_pt_1 h_pt_a)
)
(repeat h_count
(setq v_pt_a (subst (+ 24.0 (car v_pt_1)) (car v_pt_1) v_pt_1))
(setq v_pt_b (subst (+ v_dist (cadr v_pt_a)) (cadr v_pt_a) v_pt_a))
(command "line" v_pt_a v_pt_b "")
(ssadd (entlast) egrid_ss)
(setq v_pt_1 v_pt_a)
)
(command "rotate" egrid_ss "" pt_1 "r" pt_1 "@1<0" pt_2)
(if (= e_frame T)
(progn
(command "pline"
pt_1
(strcat "@" (rtos h_dist) "<0")
(strcat "@" (rtos v_dist) "<90")
(strcat "@" (rtos h_dist) "<180")
"c"
)
(command "rotate" "l" "" pt_1 "r" pt_1 "@1<0" pt_2)
)
)
(setvar "lunits" user_units)
(setvar "osmode" user_osnap)
(setvar "clayer" user_layer)
)
;;===================================================================