;Jessica Rosenkrantz -- jrosenk @ mit.edu ;assignment 3 ;amazing line connecting device ;aka stairs ;the main function ;this function will be initiated by the user (arxload "geom3d") ;use decimal units (command "-units" "2" "4" "" "" "" "") ;(command "erase" "all" "") (command "osnap" "off") (command "ucs" "world") (command "-view" "_swiso") (defun c:device ( / topedge bottomedge) (setq topedge (get_a_line "Choose the first edge line of the device:")) (terpri) ; line feed in the prompt (setq bottomedge (get_a_line "Choose the second edge line of the device:")) (device-sub topedge bottomedge) ) ;a template for device-sub (defun device-sub (topedge bottomedge / pt_a1 pt_a2 pt_b1 pt_b2) (setq pt_a1 (get_data_for_group_code 10 topedge)) (setq pt_a2 (get_data_for_group_code 11 topedge)) (setq pt_b1 (get_data_for_group_code 10 bottomedge)) (setq pt_b2 (get_data_for_group_code 11 bottomedge)) ;Here, you will need to check the relationships of 2 lines ;by analyzing the topedges and bottomedges and ;compute values of the parameters of your device, or ask ;the user to specify the values of any additional parameters ;necessary. In this dummy program, I just print the coordinates. ; (print "Checking the parameters") (print (list pt_a1 pt_a2 pt_b1 pt_b2)) (draw-device pt_a1 pt_a2 pt_b1 pt_b2) ) ;this function lets user pick a line, and nothing else (no circle, box, etc) (defun get_a_line (prompt / entity) ; ask user to pick a line. ; it keeps asking until user picks a valid entity and it is a line (setq entity nil) (while (not (and (= (type entity) 'ENAME) (= (get_data_for_group_code 0 entity) "LINE"))) (setq entity (car (entsel prompt)))) entity) ; returns the entity ;this extracts data from entity data. ;use this to get endpoints of a line. (defun get_data_for_group_code (group_code entity / all_data pair_list the_data ) ; assumes that the given entity is a valid entity and no error check is performed. (setq all_data (entget entity)) (setq pair_list (assoc group_code all_data)) (setq the_data (cdr pair_list)) ) (defun draw-device (pt1 pt2 pt3 pt4) (cond ((= (find-relation pt1 pt2 pt3 pt4) 0) (print "parallel drawing commencing") (simple-stair pt1 pt2 pt3 pt4)) ((= (find-relation pt1 pt2 pt3 pt4 2)) (print "spiral code doesn't work yet") ;(simple-spiral pt1 pt2 pt3 pt4) ) (t (print "please choose again")) ) ) ;this takes 2 points of the form (x1, y1, z1) (x2, y2, z2) ; x= x1 + t(x2-x1) = x1 +ta = x2 + ta1 ; y= y1 + t(y2-y1) = y1 +tb ; z= z1 + t(z2-z1) = z1 +tc ; it returns the data ( (x1 a) (y1 b) (z1 c) ) (defun generate-param (pt1 pt2 / ln1) (setq ln1 (mapcar '- pt2 pt1)) (print ln1) ;returns list (list (list (car pt1) (car ln1)) (list (cadr pt1) (cadr ln1)) (list (cadr (cdr pt1)) (cadr (cdr ln1))) ) ) (defun intersect? (pt1 pt2 pt3 pt4 / v1 v2 v3 a1 a2 a3 b1 b2 b3 cprod dprod temp) ;this assumes we have already determined the lines are not parallel (setq v1 (mapcar '- pt1 pt2)) (setq v2 (mapcar '- pt1 pt4)) (setq v3 (mapcar '- pt1 pt3)) ;to find if two lines are coplanar ;make three vectors and see it a*(bxc)=0 ;cross product = ( (a2b3-a3b2) , (a3b1-a1b3) , (a1b2-a2b1) ) (setq a1 (nth 0 v1)) (setq a2 (nth 1 v1)) (setq a3 (nth 2 v1)) (setq b1 (nth 0 v2)) (setq b2 (nth 1 v2)) (setq b3 (nth 2 v2)) (print (list a1 a2 a3 b1 b2 b3)) (setq cprod (list (- (* a2 b3) (* a3 b2)) (- (* a3 b1) (* a1 b3)) (- (* a1 b2) (* a2 b1)) ) ) ;take the dot product (setq temp (mapcar '* v3 cprod)) (setq dprod (+ (nth 0 temp) (nth 1 temp) (nth 2 temp))) (if (= dprod 0) t nil) ) (defun parallel? (pt1 pt2 pt3 pt4 / ln1 ln2 temp) (setq ln1 (mapcar '- pt2 pt1)) (setq ln2 (mapcar '- pt4 pt3)) (print ln1) (print ln2) (print "parallel check") ;(if (= (car ln1) (car ln2)) ; (if (= (cadr ln1) (cadr ln2)) ; (= (nth 2 ln1) (nth 2 ln2)) ; nil ; ) (cond ((= (car ln1) (car ln2)) (if (= (cadr ln1) (cadr ln2)) (= (nth 2 ln1) (nth 2 ln2)) nil ) ) ((or (= (nth 1 ln1) 0) (= (nth 2 ln1) 0) (= (nth 1 ln2) 0) (= (nth 2 ln2) 0) ) nil) (t (print "second case") (setq temp (mapcar '/ ln1 ln2)) (= (nth 0 temp) (nth 1 temp) (nth 2 temp)) ) ) ) (defun find-relation (pt1 pt2 pt3 pt4) (cond ((parallel? pt1 pt2 pt3 pt4) 0) ((intersect? pt1 pt2 pt3 pt4) 1) (t 2) ) ) ;-->defun equal-height? (defun simple-stair (pt1 pt2 pt3 pt4 / tmp pt z y pt) ;for a case with parallel lines direction across from each other (cond ((> (nth 2 pt1) (nth 2 pt3)) (setq ln2 (list pt1 pt2)) (setq ln1 (list pt3 pt4)) ) (t (setq ln2 (list pt3 pt4)) (setq ln1 (list pt1 pt2)) ) ) (setq z (- (nth 2 (car ln2)) (nth 2 (car ln1)))) (setq y (- (nth 1 (car ln2)) (nth 1 (car ln1)))) (setq x (- (nth 0 (car ln2)) (nth 0 (car ln1)))) (if (= x 0) (setq b y) (setq b x)) ;should I add a platform every 35 rises? ;to do that -->look at the distance x and estimate number of landings needed based on optimal going 25cm = numLandings ;then subtract (.5m)*numLandings from x before you figure out the actual going, keep a counter and insert the landings ;after the 35 step (cond ((< b z) (double-run-alternate pt1 pt2 pt3 pt4 z b)) (t (setq tmp (/ (/ (+ (* 2 z) b) (/ (float 308) (float 1000))) 2)) (setq tmp (fix tmp)) (setq rise (/ z tmp)) (setq going (/ b tmp)) (print (list rise going tmp)) (setq pz (nth 2 (car ln1))) (setq py (nth 1 (car ln1))) (setq px (nth 0 (car ln1))) (print (list pz py px)) (repeat tmp (command "box" (list px py pz) "length" going "1" rise ) (setq pz (+ pz rise)) (setq px (+ px going)) )))) ;;IMPORTANT: the method is no longer use because it produces really horrible staircases ;;please refer to double-run-alternate (defun double-run (pt1 pt2 pt3 pt4 z x / a b c rise going pz py px) ;number of stairs (setq a (fix (/ z (/ (float 17) (float 100))))) (setq rise (/ z a)) ;b is number of times you turn (setq b (/ a 7)) ;c is z mod 7 (setq c (- a (* (/ a 7) 7))) (print (list a b c)) ;if b is even (if (= (* (/ b 2) 2) b) (setq going (/ x c)) (setq going (/ x (- 7 c))) ) (setq pz (nth 2 (car ln1))) (setq py (nth 1 (car ln1))) (setq px (nth 0 (car ln1))) ;(print (list pz py px)) (setq width 1) (repeat b (repeat 7 (command "box" (list px py pz) "length" going "1" rise ) (setq pz (+ pz rise)) (setq px (+ px going)) ) (setq going (- 0 going)) (setq py (+ py width)) (setq width (- 0 width)) ) (repeat c (command "box" (list px py pz) "length" going "1" rise ) (setq pz (+ pz rise)) (setq px (+ px going)) ) ) ;this function tells you if two parallel lines are the same line when projected in the xy plane (defun x-y-equation (pt1 pt2 pt3 pt4 / x m b) (setq x1 (- (nth 0 pt2) (nth 0 pt1))) (setq x2 (- (nth 0 pt4) (nth 0 pt3))) (cond ((and (= x1 0) (= x2 0)) (if (= (nth 0 pt1) (nth 0 pt3)) t nil ) ) ((= x1 0) nil) (t (setq m (/ (- (nth 1 pt2) (nth 1 pt1)) x1 )) (setq b (- (nth 1 pt1) (* (nth 0 pt1) m))) (= (nth 1 pt3) (+ (* m (nth 0 pt3)) b)) ) )) (defun double-run-alternate (pt1 pt2 pt3 pt4 z x / head numFlights bound1 bound2 part1 part2 going rise remaining numInFlight) (print "double-run-fun!") ;1) (# remaining steps)(rise)+(# of flights)(# in flight)(rise)=z ;2) 550mm< 2*rise+going < 700mm ;3) 2m < (# in flight)*rise < 5m --> (# in flight) = rise/3m ;4) (# remaining steps) = x/going OR (# in flight)*going - (# remaining steps)*going = x ;solution for 4a --> 550m< 2*(z - 3*(# of flights))/x < 700mm (setq bound1 (/ (float 550) 1000)) (setq bound2 (/ (float 700) 1000)) (cond ((x-y-equation pt1 pt2 pt3 pt4) ;simple double-run stair (setq head 3) (setq numFlights (fix (/ z head))) (setq actualHead (/ (float z) numFlights)) (setq rise (/ (float 17) 100)) (setq numInFlight (* (fix (/ (/ actualHead rise) 2)) 2)) (setq rise (/ actualHead numInFlight)) (setq going (/ (+ (- bound1 (* 2 rise)) (- bound2 (* 2 rise))) 2) ) ;(print (list numFlights numInFlight rise going px py pz)) (setq pz (nth 2 (car ln1))) (setq py (nth 1 (car ln1))) (setq px (nth 0 (car ln1))) (setq landing-width 1) (setq width 1) (repeat (* 2 numFlights) (repeat (- (/ numInFlight 2) 1) (command "box" (list px py pz) "length" going "1" rise ) (setq pz (+ pz rise)) (setq px (+ px going)) ) (if (> 0 landing-width) (setq pyBox (- py 1)) (setq pyBox py)) (command "box" (list px pyBox pz) "length" landing-width "2" rise ) (setq pz (+ pz rise)) (setq going (- 0 going)) (setq py (+ py width)) (setq width (- 0 width)) (setq landing-width (- 0 landing-width)) ) ) ;otherwise (t ;oh shit this isn't what i want (setq head 3) (setq numFlights (fix (/ z head))) (if (= (* numFlights head) z) (setq head (float 2.54))) (setq coeff (+ (/ (* 2 (- z (* (float head) numFlights))) x) 1)) (setq part1 (/ bound1 coeff)) (setq part2 (/ bound2 coeff)) (setq going (/ (+ part1 part2) 2)) (setq rise (/ (+ (/ (- bound1 going) 2) (/ (- bound2 going) 2) ) 2) ) (setq remaining (/ x going)) ;some adjustments to get whole numbers (setq numStairs (/ z rise)) (setq numStairs (fix numStairs)) (setq rise (/ z numStairs)) (setq numInFlight (/ head rise)) (setq numInFlight (fix numInFlight)) (setq remaining (- numStairs (* numInFlight numFlights))) (setq going (/ x remaining)) (setq pz (nth 2 (car ln1))) (setq py (nth 1 (car ln1))) (setq px (nth 0 (car ln1))) (setq width 1) (setq landing-width 1) (repeat (* 2 numFlights) (repeat (- (/ numInFlight 2) 1) (command "box" (list px py pz) "length" going "1" rise ) (setq pz (+ pz rise)) (setq px (+ px going)) ) (if (> 0 landing-width) (setq pyBox (- py 1)) (setq pyBox py)) (command "box" (list px pyBox pz) "length" landing-width "2" rise ) (print (list "pz is" pz)) (setq pz (+ pz rise)) (print (list "pz is now" pz)) (setq going (- 0 going)) (setq py (+ py width)) (setq width (- 0 width)) (setq landing-width (- 0 landing-width)) ) (repeat remaining (command "box" (list px py pz) "length" going "1" rise ) (setq pz (+ pz rise)) (setq px (+ px going)) ) (print (list numFlights numInFlight rise going remaining)) ) ) ) ;;;;IMPORTANT: the sprial code doesn't work yet (defun simple-spiral (pt1 pt2 pt3 pt4 / v1 v2 magnitude1 magnitude2 dotprod divisor head rise angle theta remaining numStairs numFlights) ;this procedure is used if we have skew lines that share a vertex when project in the xy plane ;figure out which line is the highest (cond ((> (nth 2 pt1) (nth 2 pt3)) (setq ln2 (list pt1 pt2)) (setq ln1 (list pt3 pt4)) ) (t (setq ln2 (list pt3 pt4)) (setq ln1 (list pt1 pt2)) ) ) (setq z (- (nth 2 (car ln2)) (nth 2 (car ln1)))) ;1) find which points are the corners and which are the legs (cond ((= (nth 0 pt1) (nth 0 pt3)) (setq center pt1) (setq leg1 pt2) (setq leg2 pt4) ) ((= (nth 0 pt1) (nth 0 pt4)) (setq center pt1) (setq leg1 pt2) (setq leg2 pt3)) ((= (nth 0 pt2) (nth 0 pt3)) (setq center pt2) (setq leg1 pt1) (setq leg2 pt4)) (t (setq center pt2) (setq leg1 pt1) (setq leg2 pt3))) ;2) find the angle between the legs (setq v1 (mapcar '- leg1 center)) (setq v1 (list (car v1) (cadr v1))) (setq v2 (mapcar '- leg2 center)) (setq v2 (list (car v2) (cadr v2))) (print (list "v1" v1 "v2" v2)) (setq dotprod (mapcar '* v1 v2)) (setq dotprod (+ (car dotprod) (cadr dotprod))) (setq magnitude1 (sqrt (+ (* (car v1) (car v1)) (* (cadr v1) (cadr v1))))) (setq magnitude2 (sqrt (+ (* (car v2) (car v2)) (* (cadr v2) (cadr v2))))) (setq divisor (* magnitude1 magnitude2)) (setq angle (/ dotprod divisor)) (setq angle (acos angle)) ;3) need the rise, angle between wedge edges = theta ;logical equations? ;numStairs*rise=z --> numFlights*(360/theta)+remaining=z ;theta*remaining= angle --> remaining= angle/theta ;numFlights*(360/theta)+(angle/theta)=z/R ;theta= R*(numFlights*360 + angle)/z ;theta*numInFlight= 360 --> numInFlight= 360/theta ;changable condition--> rise*numInFlight= 3 --> numInFlight=3/rise ;360/theta=3/rise --> rise = theta/120 (setq head 3) (setq numFlights (fix (/ z head))) ;(setq theta2 (/ .2 ;(setq theta (/ (+ (* numFlights 360) angle) z)) ;(if (> (* (sin (/ theta 2)) (float 1.5)) (float .4)) ;(setq half-going ( (setq rise (/ theta 120)) (setq remaining (/ angle theta)) (setq numStairs (+ (* (/ 360 theta) numFlights) remaining)) ;4) drawing time ;draw then translate?--> no use ucs to point origin at center? (setq radius (float 1.5)) (setq p1 (list 0 0 0)) (setq p2 (list 0 radius 0)) (command "line" (list 0 0 0) (list 0 radius 0) "") (setq line1 (entlast)) (command "ucs" "new" "z" theta) (command "line" (list 0 0 0) (list 0 radius 0) "") (setq line2 (entlast)) (command "circle" p1 radius) (setq circle (entlast)) (command "trim" line1 line2 "" circle "") (command "pedit" line1 "y" "join" line2 circle "" "") (setq closed (entlast)) (command "extrude" closed "" rise "") (setq wedge (entlast)) (print (list "this is the stuff" theta rise remaining numFlights numStairs)) ;(setq please (trans p2 0 1)) (setq pz 0) (print (list "stairs" numStairs)) (repeat numStairs (command "copy" wedge "" (list 0 0 pz) (list 0 0 (+ pz rise))) (setq pz (+ pz rise)) (setq wedge (entlast)) (command "rotate" wedge "" (list 0 0 pz) theta) ) ) ;concensus says I'm a jerk! (defun acos (cosine) (atan (sqrt (- 1 (* cosine cosine))) cosine))