AutoLISP: Add a Calendar To Your Drawing

I don’t know how useful this is. I just think it is cool because I tend to not know what the date is and now I can have a date and calendar in my drawing…

Here’s how:

  • CALENDAR <enter> to start
  • Specify year
  • Pick 2 points like a rectangle. This is where the calendar page will fit
  • Specify month (numeric) or ALL <enter>  to place the whole whole year calendar in the rectangle. But to be honest, I can’t get the ALL (whole year) function to work correctly….

;calendar.lsp
;James Tunstall
;Autodesk Australia
;28-08-91
;draws calenders of any year
;in several arrangements
;at any scale
;AutoCAD Release 11 or greater is required
;Z direction of the current UCS.
(defun zdir
(
/ xdir ydir
a1 a2 a3
b1 b2 b3
)
(setq xdir (getvar "UCSXDIR")) ;X direction of the current UCS
(setq ydir (getvar "UCSYDIR")) ;Y direction of the current UCS
(setq a1 (car xdir) a2 (cadr xdir) a3 (caddr xdir))
(setq b1 (car ydir) b2 (cadr ydir) b3 (caddr ydir))
;return UCS Z axis direction
(list
(- (* a2 b3) (* a3 b2))
(- (* a3 b1) (* a1 b3))
(- (* a1 b2) (* a2 b1))
)
)
;xdir of ECS
;requires (zdir)
(defun xdir
(
/ normal factor b1 b2 b3 a1 a2 a3
)
(setq normal (zdir))
(setq factor (/ 1.0 64.0))
(setq b1 (car normal))
(setq b2 (cadr normal))
(setq b3 (caddr normal))
(if
(and
(< (abs b1) factor)
(< (abs b2) factor)
)
(progn
(setq a1 0.0 a2 1.0 a3 0.0)
)
(progn
(setq a1 0.0 a2 0.0 a3 1.0)
)
)
;return ECS X axis direction
(list
(- (* a2 b3) (* a3 b2))
(- (* a3 b1) (* a1 b3))
(- (* a1 b2) (* a2 b1))
)
)
;base angle of UCS in terms of ECS
;requires (xdir) & (zdir)
(defun ucs_base_angle ( / ecs_xdir )
(setq ecs_xdir
(mapcar
(quote +)
(trans (xdir) 0 1)
(trans (getvar "UCSORG") 0 1 T)
)
)
(-
0.0
(atan (cadr ecs_xdir) (car ecs_xdir))
)
)
;Modulo division
(defun % (x y)
(- (fix x) (* (/ (fix x) (fix y)) (fix y)))
)
;Returns T if year is a leap year
(defun LeapYear ( year )
(cond
(
(/= (% year 4) 0)
nil
)
(
(and
(= (% year 100) 0)
(/= (% year 400) 0)
)
nil
)
(
T
T
)
)
)
;returns day of week for 1st January for year
(defun JanOne
( year
/ LastYear LotsOf400 LotsOf100 LotsOfOne LeapYears DaysAhead
)
(if (> year 0)
(progn
(setq LastYear (- (fix year) 1))
(setq LotsOf400 (/ LastYear 400))
(setq LotsOf100 (/ (% LastYear 400) 100))
(setq LotsOfOne (% LastYear 100))
(setq LeapYears
(+
(* LotsOf400 97)
(* LotsOf100 24)
(/ LotsOfOne 4)
)
)
(setq DaysAhead (+ (fix year) LeapYears))
;return day of week for 1st January
;0 Sunday 6 Saturday
(% DaysAhead 7)
)
nil
)
)
;returns a list of 12 calender months
;each month is made up of 5 weeks
;each week is made up of 7 days
;the value of the day indicates the date
;a value of zero(0) indicates a blank
(defun cal
(
year
/ week month StartOfMonth DaysInMonth date day calender
)
(setq StartOfMonth (JanOne year))
(setq DaysInMonth
(if (LeapYear year)
(list 31 29 31 30 31 30 31 31 30 31 30 31)
(list 31 28 31 30 31 30 31 31 30 31 30 31)
)
)
(setq calender nil)
(foreach NoOfDays DaysInMonth
(setq month nil)
(setq week nil)
(cond
(
(and (= StartOfMonth 5) (= NoOfDays 31))
(progn
(setq week (list 31 0 0 0 0 1 2))
(setq date 3)
(setq StartOfMonth 1)
)
)
(
(and (= StartOfMonth 6) (= NoOfDays 31))
(progn
(setq week (list 30 31 0 0 0 0 1))
(setq date 2)
(setq StartOfMonth 2)
)
)
(
(and (= StartOfMonth 6) (= NoOfDays 30))
(progn
(setq week (list 30 0 0 0 0 0 1))
(setq date 2)
(setq StartOfMonth 1)
)
)
(
T
(progn
(setq day 0)
(while (< day StartOfMonth)
(setq week (append week (list 0)))
(setq day (1+ day))
)
(setq date 1)
(while (< day 7)
(setq week (append week (list date)))
(setq date (1+ date))
(setq day (1+ day))
)
)
)
)
(setq month (append month (list week)))
(repeat 4
(setq week nil)
(setq day 0)
(while (< day 7)
(if (= date NoOfDays)
(setq StartOfMonth (% (1+ day) 7))
)
(if (<= date NoOfDays)
(setq week (append week (list date)))
(setq week (append week (list 0)))
)
(setq date (1+ date))
(setq day (1+ day))
)
(setq month (append month (list week)))
)
(setq calender (append calender (list month)))
)
)
;draws a box
(defun box (pt0 pt1)
(command)
(command
".PLINE"
(list (car pt0) (cadr pt0))
(list (car pt1) (cadr pt0))
(list (car pt1) (cadr pt1))
(list (car pt0) (cadr pt1))
"C"
)
)
;draws text
(defun text
(
string pt height xscale
/ extdir base_angle
)
;current extrusion direction
(setq extdir (zdir))
;base angle of UCS in terms of ECS
(setq base_angle (ucs_base_angle))
(entmake
(list
(cons 0 "TEXT")
(append (list 10) (trans pt 1 extdir))
(cons 40 height)
(cons 1 string)
(cons 50 base_angle)
(cons 41 xscale)
(cons 51 0.0)
(cons 7 (getvar "TEXTSTYLE"))
(cons 71 0)
(append (list 210) extdir)
)
)
)
;draws a calender month
;given corner points,which month,a list of dates
(defun draw_month
(
pt0 pt1 month dates
/ months days xdist ydist m n height width_factor
)
(setq months
(list
"January"
"February"
"March"
"April"
"May"
"June"
"July"
"August"
"September"
"October"
"November"
"December"
)
)
(setq days
(list
"Sunday"
"Monday"
"Tuesday"
"Wednesday"
"Thursday"
"Friday"
"Saturday"
)
)
(setq xdist (- (car pt1) (car pt0)))
(setq ydist (- (cadr pt1) (cadr pt0)))
(setq height (/ ydist 16.0))
(setq width_factor (/ xdist ydist 2.0))
(box pt0 pt1)
(text
(nth month months)
(list
(+
(car pt0)
(/ xdist 2.0)
(* (strlen (nth month months)) -0.5 height width_factor)
)
(+
(cadr pt0)
(* 7.0 (/ ydist 8.0))
)
)
height
width_factor
)
(setq m 1.0)
(foreach day days
(text
(strcase (substr day 1 3))
(list
(+
(car pt0)
(* m (/ xdist 28.0))
)
(+
(cadr pt0)
(* 6.0 (/ ydist 8.0))
)
)
height
width_factor
)
(setq m (+ m 4.0))
)
(setq n 5)
(foreach week dates
(setq m 1.0)
(foreach date week
(if (/= date 0)
(text
(itoa date)
(list
(+
(car pt0)
(* m (/ xdist 28.0))
)
(+
(cadr pt0)
(* n (/ ydist 8.0))
)
)
height
width_factor
)
)
(setq m (+ m 4.0))
)
(setq n (1- n))
)
)
;main function
(defun C:calendar
(
/ echo ortho year calender pt0 pt1 pta ptb
columns rows xdist ydist month i j m n x y option
)
;store system variables
(setq echo (getvar "CMDECHO"))
(setq ortho (getvar "ORTHOMODE"))
;set system variables
(setvar "CMDECHO" 0)
(setvar "ORTHOMODE" 1)
(command)
(command ".UNDO" "GROUP")
;calender year
(initget 7)
(setq year (getint "\nYear :"))
;calculate calender for year
(setq calender (cal year))
;get points for lower left month position
(setq pta (getpoint "\nFirst corner :"))
(setq ptb (getcorner pta "\nOther corner :"))
(setq pt0
(list
(apply (quote min) (list (car pta) (car ptb)))
(apply (quote min) (list (cadr pta) (cadr ptb)))
)
)
(setq pt1
(list
(apply (quote max) (list (car pta) (car ptb)))
(apply (quote max) (list (cadr pta) (cadr ptb)))
)
)
(setq xdist (- (car pt1) (car pt0)))
(setq ydist (- (cadr pt1) (cadr pt0)))
(initget 7 "All")
(setq option 13)
(while (> option 12)
(setq option (getint "\nWhich month [1-12] / All :"))
(if (= option "All")
(setq option 0)
)
(if (> option 12)
(prompt "\nMonth month between [1-12]")
)
)
(if (= option 0)
(progn
;determine calender layout
(setq columns (getint "\nNumber of columns [1 2 3 4 6 12] :"))
(while (or (<= columns 0) (/= (% 12 columns) 0))
(prompt "\nNumber of columns must divide into 12")
(setq columns (getint "\nNumber of columns [1 2 3 4 6 12] :"))
)
(setq rows (/ 12 columns))
(setq x 0.0)
(if (/= columns 1)
(while (< (abs x) xdist)
(setq x (getdist pt0 "\nDistance between columns ||| :"))
(if (< (abs x) xdist)
(prompt "\nDistance must be > than box width")
)
)
)
(setq y 0.0)
(if (/= rows 1)
(while (< (abs y) ydist)
(setq y (getdist pt0 "\nDistance between rows --- :"))
(if (< (abs y) ydist)
(prompt "\nDistance must be > than box height")
)
)
)
;draw calender
(setq month 0)
(setq j (1- rows))
(while (>= j 0)
(setq n (+ (cadr pt0) (* j y)))
(setq i 0)
(while (< i columns)
(setq m (+ (car pt0) (* i x)))
(draw_month
(list m n)
(list
(+ m xdist)
(+ n ydist)
)
month
(nth month calender)
)
(setq i (1+ i))
(setq month (1+ month))
)
(setq j (1- j))
)
)
(progn
(setq month (1- option))
(draw_month
pt0
pt1
month
(nth month calender)
)
)
)
(command ".UNDO" "END")
;restore system variables
(setvar "CMDECHO" echo)
(setvar "ORTHOMODE" ortho)
(princ)
)

Posted in AutoLISP, Text, TIPS | 1 Comment

AutoLISP: Dim Text OverRide

Although you do not really need a LISP routine to accomplish this task (as seen in THIS post). This particular routine is great because it also has an extra option to clear existing text overrides.

I use this routine to easily add text to show underneath dimensions and also to remove text overrides from dimensions.

Here’s how:

  • DTOR <enter> to start
  • Select Dimensions to have the text overrides applied to (can be multiple)
  • Enter the text that you’d like to show: in this example, I used <>\XTYP. to show “TYP.” underneath the dimension.
  • <> lets you keep the actual measured dimension
  • \X starts a new line of text underneath the actual dimension
  • TYP. that is right next to the “\X” is the text to be displayed in the new line

The below animation shows how to add text:

The below animation shows how to remove text overrides:

I do not remember where this routine came from or who wrote it. I think that Alan Thompson wrote it but I am not certain.

(defun c:DTOR () (c:DimTextOverride))

(defun c:DimTextOverride ( / ss textString)

(princ "\rDIMENSION TEXT OVERRIDE ")

(vl-load-com)

(if (and (setq ss (ssget '((0 . "DIMENSION"))))

(setq textString

(getstring

T

"\nEnter override text, <Enter> to remove override: ")))

(progn

(vla-startundomark

(cond (*activeDoc*)

((setq *activeDoc*

(vla-get-activedocument

(vlax-get-acad-object))))))

(vlax-for oDim

(setq ss (vla-get-activeselectionset *activeDoc*))

(vla-put-textoverride oDim textString))

(vla-delete ss)

(vla-endundomark *activeDoc*))

(prompt "\n** Nothing selected ** "))

(princ))
Posted in AutoLISP, Dimensions, Modifying, Text, TIPS | 8 Comments

AutoLISP: Fillet Match Radius

This is my 101st post. I missed the 100th post. I am proud that this blog was only started in November and yet has so many posts. Hopefully I can continue to find helpful stuff for you to make your daily CAD use a little easier. So thanks everyone.

Here’s is a great routine by Kent Cooper found at the AutoCAD forums. It will let you select either a circle, arc or even an ellipse and use the radius of one of these objects and set that as the fillet radius.

Here’s how:

  • FMR <enter> to start (Fillet Match Radius0
  • Select either a Circle, Arc or Ellipse to set your fillet radius
  • Select objects to be filleted

; by Kent Cooper

(defun C:FMR (/ aper pt); = Fillet Match Radius [of existing curve]

; to apply the radius of a selected curved object in the Fillet command

; Kent Cooper, June 2011

(setq aper (getvar 'aperture))

(while

(not (setq pt (cadr (entsel "Select curve to set Fillet Radius: "))))

(prompt "\nNothing selected -- ")

); end while

(setvar 'aperture (getvar 'pickbox)); ensures Osnap won't "see" wrong thing

(if (osnap pt "cen")

(setvar 'filletrad (distance (osnap pt "nea") (osnap pt "cen"))); then

(progn ; else

(prompt "\nNo radius for that object.")

(setvar 'aperture aper)

(exit)

); end progn

); end if

(setvar 'aperture aper)

(command "_.fillet" "_mUltiple")

(princ)

)
Posted in AutoLISP, Modifying, TIPS | 4 Comments

Hatch To Back

I use the command HATCHTOBACK all of the time and I am surprised at how little known or used it is. Sometimes when you have hatches in your drawing and you continue working, the hatches tend to work their way to the front and end up covering your linework. Here’s how to fix this:

  • HB <enter> or HATCHTOBACK <enter>

The command does all of the work and searches the entire drawing and sends all hatches to the back of the draw order.

Posted in BASICS, Modifying, TIPS | 10 Comments

Quick (Ghetto) Way To Scale Text

So I not proud of this method but there have been a couple of times when the recipients of what I was drawing were not going to receive or need the AutoCAD file so this method has  saved me a couple of times when deadlines loomed and impatient people were waiting for my drawing….

Even after setting up a text style, I needed to make some unique text labels and so what I did instead of creating a new text style is use an existing style to create a new text onject and then scale that object. This only affects that one text object so there is no harm done.

The great things about his is that if the text size looks incorrect in a given setting, it is easily adjustable.

Here’s how:

SCALE or SC <enter> to start the scale command

Select the text object(s)

<enter> when finished selecting

Click to specify a base point

move your cursor away from the base point to scale the text up in size.

When the text looks correct, click to end the scale command.

Note: If you want to double the size of the text, after picking a base point, enter 2 at the command line and hit <enter>. Numbers greater than 1 will increase the size of the object being scaled and numbers less then 1 will decrease the size of the objects. SO if you wanted to shrink the object to half of its size, enter .5 at the command line and hit <enter>.

Posted in BASICS, Modifying, Text, TIPS | Leave a comment

Erase Individual Wipeouts with TFRAMES

If you need to erase an individual wipeout, there is a command that is a “toggle” which means that once the command is entered, it either turns this function on or off. The command is TFRAMES. there is no button for it on the ribbon or on a toolbar so you have to use the command. This command makes the wipeout frames (outlines) visible and thus selectable so that you can erase them.

To start:

  • TFRAMES <enter>
  • (make sure to check the command line as it will tell you whether you are in fact turning them on or off)
  • With “Selection Cycling” turned on, it is easy to select the wipeout (as seen below)
  • After selecting the wipeout, hit the delete button or use the ERASE command

 

 

Posted in AutoLISP, BASICS, Modifying, TIPS | Leave a comment

AutoLISP: Erase all Wipeouts

I sometimes get drawings that have wipeouts in them. And to be honest, I don’t think that the person who made them knew what they were when they made them because the wipeouts are not hiding anything. So I use this little Lisp routine to erase all of the wipeouts before I begin working.

To start:

  • GOWIPE <enter> to start
  • The routine does everything from there…

 

 

 

(defun c:gowipe (/ b)

(setvar "pickstyle" 0)

(setq b (ssget "x" '((0 . "wipeout"))))

(command "._erase" b "")

)
Posted in AutoLISP, Modifying, TIPS, Wipeouts | 3 Comments

AutoLISP: Objects 2 Wipeout

If you’ve ever used wipeouts in order to mask something in your drawing, you already know that you cant used curved objects. This great routine allows you to select an existing object that is curved and turn it into a wipeout. It also gives you an option to erase the existing object after it makes the wipeout. It will work on olylines, circles and ellipses.

  • OB2WO <enter> to start
  • Select object to turn into wipeout (Circle, Ellipse, Polyline)
  • select “Yes” or “No” to erase the existing object

;;; OB2WO (gile) -Gilles Chanteau- 10/03/07
;;; Creates a "Wipeout" from an object (circle, ellipse, or polyline with arcs)
;;; Works whatever the current ucs and object OCS

(defun c:ob2wo (/ ent lst nor)
  (vl-load-com)
  (if (and (setq ent (car (entsel)))
	   (member (cdr (assoc 0 (entget ent)))
		   '("CIRCLE" "ELLIPSE" "LWPOLYLINE")
	   )
	   (setq lst (ent2ptlst ent))
	   (setq nor (cdr (assoc 210 (entget ent))))
      )
    (progn
      (vla-StartundoMark
	(vla-get-ActiveDocument (vlax-get-acad-object))
      )
      (makeWipeout lst nor)
      (initget "Yes No")
      (if
	(= (getkword "\nDelete source object? [Yes/No] <No>: ")
	   "Yes"
	)
	 (entdel ent)
      )
      (vla-EndundoMark
	(vla-get-ActiveDocument (vlax-get-acad-object))
      )
    )
  )
)


;;; ENT2PTLST
;;; Returns the vertices list of the polygon figuring the curve object
;;; Coordinates defined in OCS

(defun ent2ptlst (ent / obj dist n lst p_lst prec)
  (vl-load-com)
  (if (= (type ent) 'ENAME)
    (setq obj (vlax-ename->vla-object ent))
  )
  (cond
    ((member (cdr (assoc 0 (entget ent))) '("CIRCLE" "ELLIPSE"))
     (setq dist	(/ (vlax-curve-getDistAtParam
		     obj
		     (vlax-curve-getEndParam obj)
		   )
		   50
		)
	   n	0
     )
     (repeat 50
       (setq
	 lst
	  (cons
	    (trans
	      (vlax-curve-getPointAtDist obj (* dist (setq n (1+ n))))
	      0
	      (vlax-get obj 'Normal)
	    )
	    lst
	  )
       )
     )
    )
    (T
     (setq p_lst (vl-remove-if-not
		   '(lambda (x)
		      (or (= (car x) 10)
			  (= (car x) 42)
		      )
		    )
		   (entget ent)
		 )
     )
     (while p_lst
       (setq
	 lst
	  (cons
	    (append (cdr (assoc 10 p_lst))
		    (list (cdr (assoc 38 (entget ent))))
	    )
	    lst
	  )
       )
       (if (/= 0 (cdadr p_lst))
	 (progn
	   (setq prec (1+ (fix (* 25 (sqrt (abs (cdadr p_lst))))))
		 dist (/ (- (if	(cdaddr p_lst)
			      (vlax-curve-getDistAtPoint
				obj
				(trans (cdaddr p_lst) ent 0)
			      )
			      (vlax-curve-getDistAtParam
				obj
				(vlax-curve-getEndParam obj)
			      )
			    )
			    (vlax-curve-getDistAtPoint
			      obj
			      (trans (cdar p_lst) ent 0)
			    )
			 )
			 prec
		      )
		 n    0
	   )
	   (repeat (1- prec)
	     (setq
	       lst (cons
		     (trans
		       (vlax-curve-getPointAtDist
			 obj
			 (+ (vlax-curve-getDistAtPoint
			      obj
			      (trans (cdar p_lst) ent 0)
			    )
			    (* dist (setq n (1+ n)))
			 )
		       )
		       0
		       ent
		     )
		     lst
		   )
	     )
	   )
	 )
       )
       (setq p_lst (cddr p_lst))
     )
    )
  )
  lst
)


;;; MakeWipeout creates a "wipeout" from a points list and the normal vector of the object

(defun MakeWipeout (pt_lst nor / dxf10 max_dist cen dxf_14)

  (setq	dxf10 (list (apply 'min (mapcar 'car pt_lst))
		    (apply 'min (mapcar 'cadr pt_lst))
		    (caddar pt_lst)
	      )
  )
  (setq
    max_dist
     (float
       (apply 'max
	      (mapcar '- (apply 'mapcar (cons 'max pt_lst)) dxf10)
       )
     )
  )
  (setq cen (mapcar '+ dxf10 (list (/ max_dist 2) (/ max_dist 2) 0.0)))
  (setq
    dxf14 (mapcar
	    '(lambda (p)
	       (mapcar '/
		       (mapcar '- p cen)
		       (list max_dist (- max_dist) 1.0)
	       )
	     )
	    pt_lst
	  )
  )
  (setq dxf14 (reverse (cons (car dxf14) (reverse dxf14))))
  (entmake (append (list '(0 . "WIPEOUT")
			 '(100 . "AcDbEntity")
			 '(100 . "AcDbWipeout")
			 '(90 . 0)
			 (cons 10 (trans dxf10 nor 0))
			 (cons 11 (trans (list max_dist 0.0 0.0) nor 0))
			 (cons 12 (trans (list 0.0 max_dist 0.0) nor 0))
			 '(13 1.0 1.0 0.0)
			 '(70 . 7)
			 '(280 . 1)
			 '(71 . 2)
			 (cons 91 (length dxf14))
		   )
		   (mapcar '(lambda (p) (cons 14 p)) dxf14)
	   )
  )
)
Posted in AutoLISP, Modifying, TIPS, Wipeouts | 30 Comments

Fast Pan

Here is crazy way to pan across your drawing. It will take some practice to get used to but if you are having to pan across a large drawing, this can be a useful tip.

  • Hold CTRL
  • Press and hold the mouse scroll-wheel
  • Move  the mouse away from the direction that you want to go in. This is similar to how you normally pan except that you press and hold the scroll wheel.

The further away you move the cursor, the faster it pans.

You can also change directions in the middle of this method.

Enough describing – check it out for yourself!!!!

Posted in BASICS, Settling In, TIPS | Leave a comment

Quick Way to Join Using PEDIT

If you have ever joined lines into a polyline this tip is really helpful. Usually when you want to join lines into a polyline you have to select the lines that are going to be joined in a sequential order. The picture below describes this process. You start with the first line and then select accordingly. And if you dont pick in the correct order, your polyline may only partially turn out the way that you wanted it to.

That method may come in use for some instances, but check this out:

  • PE <enter> or PEDIT <enter>
  • Select one line that is going to be part of the joined objects
  • Y <enter> to respond to the prompt, “Do you want to turn it into one?”
  • J <enter> to “Join” these objects
  • Select all of the other lines (including the first)
  • <enter> when finished selecting the objects
  • <enter> again to exit the PEDIT command

Posted in BASICS, Modifying, TIPS | 7 Comments