;;; pursuit_apollonius.lsp ;;; Takaya Iwamoto Oct 17,2004 ;;; modified June 01,2005 added pursuit_test command ;;;Reference: Excursions in Geometry, C.Stanley Ogilvy Dover 1969 ;;;Test for Pursuit curve ;;;Suppose a ship leaves point B and steams in a fixed direction at a constant speed. ;;; A second ship,leaving point A at the same time,can go k times as fast as the first ship. ;;; Assuming a plane ocean,what course should the first ship steer in order to intercept ;;; the slow ship as quickly as possible ? ;;;The solution; ;;; find points C & D on the line connecting A & B such that AC = k * CB & AD = k * BD ;;; This means that points C & D divide AB harmonically,i.e AC/CB = AD/BD ;;; Then draw a circle with CD as a diameter. The point of intercept is on this circle. ;;; ;;; Letting the mid-point between A & B is O. ;;; The OC = r*(k-1)/(k+1) OD = r* (k+1)/(k-1) ;;; The diameter of the Apollonius circle is r * 4k/(k^2 -1) ;;; The distance of the center of the circle from point "O" is r*(k^2 + 1)/(k^2 - 1) ;;; ;;;The Geeek mathematician Apollonius discovered that a circle may be defined in a way quite ;;;different from the usual "all points equidistant from a fixed point." ;;;Apolloinius's defintion states that if a point moves in such a way that its distance from ;;;one fixed point is always a constant multiple of its distance from another fixed point, ;;;then its path is a circle. ;;; ;;; ;;;There are two demo scripts ;;; test_circle up to 7 pairs of circles drawn to show the intersections are on ;;; the Apolllonius circle ;;; Pursuit_test Harmonic division, explained by Ship chasing ;;; ;;; (defun c:test_circle() (setup_sysvar) (setup_pursuit_int) (ap_circles) (reset_sysvar) );;;TEST_CIRCLE ;;; (defun ap_circles() (setq col_id 0) (while (< col_id 7) (setq col_id (1+ col_id)) (command "_color" (itoa col_id)) (command "_circle" pnt_b PAUSE) (setq rad2 (* k (getvar "CIRCLERAD"))) (command "_.circle" pnt_a rad2) ) (command "_COLOR" "BYLAYER") ) ;;; ;;; (defun c:Pursuit_ap() (setup_sysvar) (setup_pursuit_ap) (pursuit_apollo_1) (reset_sysvar) );;;PURSUIT_AP ;;; ;;;Main routine for red boat chasing blue boat--PURSUIT_TEST ;;; (defun c:Pursuit_test() (setup_sysvar) (setup_pursuit_step1) ;;case (a) ;;;Define point C as internal (step1) (pursuit_apollo_1A) (make_pt "0" 0 pnt_c1) (mark_id pnt_c1 "C" 4 0.25) (alert "\nPoint C divides\nLine segment AB INTERNALLY to\nthe ratio K : 1\n\nAC : BC = K : 1") (entdel red_bt) (entdel blue_bt) ;;case (b) ;;;Define Point D as external (step2) (pursuit_apollo_1B) (make_pt "0" 0 pnt_c2) (mark_id pnt_c2 "D" 4 0.25) (alert "\nPoint D divides\nLine segment AB EXTERNALLY to\nthe ratio K : 1\n\nAD : BD = K : 1") (entdel red_bt) (entdel blue_bt) (alert "\nDraw a circle with a dimeter CD") ;;;General cases target point on the circle (make_circle_1 "0" 8 cir_cen ap_rad) (setq ap_circle (entlast)) (command "_.delay" 500) ;;case (c) (while (= (Yes_or_No "Want to try a general case ? ") "_Y") (general_ap) (command "_.delay" 1000) (entdel red_bt) (entdel blue_bt) ) ;;;end of while loop ;;;drawing aid for a proof (proof_ap) (reset_sysvar) );;;PURSUIT_TEST ;;; ;;; (defun c:Pursuit_test_1() (setup_sysvar) (setup_pursuit_step1) ;;case (a) ;;;Define point C as internal (step1) (pursuit_apollo_1A) (make_pt "0" 0 pnt_c1) (mark_id pnt_c1 "C" 4 0.25) (alert "\nPoint C divides\nLine segment AB INTERNALLY to\nthe ratio K : 1\n\nAC : BC = K : 1") ;(entdel red_bt); (entdel blue_bt) (reset_sysvar) );;;pursuit_test_1 ;;; (defun c:Pursuit_test_2() (setup_sysvar) (setup_pursuit_step1) ;;case (b) ;;;Define Point D as external (step2) (pursuit_apollo_1B) (make_pt "0" 0 pnt_c2) (mark_id pnt_c2 "D" 4 0.25) (alert "\nPoint D divides\nLine segment AB EXTERNALLY to\nthe ratio K : 1\n\nAD : BD = K : 1") ;(entdel red_bt) ;(entdel blue_bt) (reset_sysvar) );;;pursuit_test_2 ;;; ;;; (defun c:Pursuit_test_3() (setup_sysvar) (setup_pursuit_step1) (alert "\nDraw a circle with a dimeter CD") ;;;General cases target point on the circle (make_circle_1 "0" 8 cir_cen ap_rad) (setq ap_circle (entlast)) (command "_.delay" 500) ;;case (c) (while (= (Yes_or_No "Want to try a general case ? ") "_Y") (general_ap) (command "_.delay" 500) ;(entdel red_bt) ;(entdel blue_bt) ) ;;;end of while loop ;;;drawing aid for a proof ;(proof_ap) (reset_sysvar) );;;PURSUIT_TEST_3 ;;; ;;;PROOF_AP Proof for harmonic division (defun proof_ap() (make_line_1 "0" 8 pnt_c1 pnt_es) (make_line_1 "0" 8 pnt_es pnt_c2) (setq len_ap (distance pnt_1 pnt_es) len_bp (distance pnt_2 pnt_es) pnt_g (pld pnt_es pnt_1 len_bp) pnt_e (pld pnt_es pnt_1 (- len_bp)) pnt_h (inters pnt_c1 pnt_es pnt_2 pnt_g nil) pnt_f (inters pnt_c2 pnt_es pnt_2 pnt_e nil) ) (make_line_1 "0" 8 pnt_g pnt_2) (make_line_1 "0" 8 pnt_2 pnt_e) (make_line_1 "0" 8 pnt_es pnt_e) (mark_id pnt_e "E" 1 0.25) (mark_id pnt_f "F" 1 0.25) (mark_id pnt_g "G" 2 0.25) (mark_id pnt_h "H" 1 0.25) (setq mark_size 0.2) (mark_angle pnt_2 pnt_es pnt_f 0.3 "f" mark_size 4) (mark_angle pnt_f pnt_es pnt_e 0.4 "f" mark_size 1) (mark_angle pnt_g pnt_es pnt_h 0.6 "q" mark_size 3) (mark_angle pnt_h pnt_es pnt_2 0.7 "q" mark_size 3) );;;PROOF_AP ;;;GENERAL_AP any point on the Apollonius circle selected ;;; (defun general_ap() (alert "\nSelect a point on this circle\nto specify escape direction.") ;;;Set OSNAP to the NEAREST to pick a point on the circle (command "_.line" pnt_2 (setq pnt_es (getpoint pnt_2 "\nSpecify Escape direction")) "") (mark_id pnt_es "P" 2 0.25) (terpri) (command "_.delay" 500) (step3) (pursuit_apollo_1C) );;;GENERAL_AP ;;; (defun setup_pursuit_ap() (setq pnt_xl '(-2 0) pnt_xr '(5 0) pnt_o '(0 0) pnt_yu '(0 3) pnt_yl '(0 -3) ) (make_line_1 "0" 8 pnt_xl pnt_xr) (make_line_1 "0" 8 pnt_yl pnt_yu) (command "_.zoom" "_EXTENT") (command "_.regen") (setvar "OSMODE" 512) (setvar "PDMODE" 32) (command "_.point" (setq pnt_1 (getpoint "\nGet Point A:"))) (command "_.point" (setq pnt_2 (getpoint "\nGet Point B:"))) (command "_.line" pnt_2 (setq pnt_3 (getpoint pnt_2 "\nSpecify Escape direction")) "") (setq escape_line (entlast)) (setq k (getreal "\nRelative speed of the Pursuiter(>1.0)(def=2.0) = ")) (if (= k nil) (setq k 2.0)) (setq pnt_a pnt_1 pnt_b pnt_2 pnt_c pnt_3 ksq (* k k) ksqp1 (+ ksq 1) ksqm1 (- ksq 1) len_oc (/ (* 0.5 (distance pnt_a pnt_b) (- k 1)) (+ k 1)) ap_rad (/ (* (distance pnt_a pnt_b) k) ksqm1) cir_cen (shift_pnt (mid_point pnt_a pnt_b) (list (+ ap_rad len_oc) 0)) rel_speed k ) (make_circle_1 "0" 8 cir_cen ap_rad) (setq ap_circle (entlast)) (command "_.trim" (entlast) "" pnt_c "") (setq pnt_c (cdr (assoc 11 (entget escape_line))) ) ;;redefine pnt_c on a circle (setq rate (getreal "\nSpecify speed as a distance % of length AB:(def= 0.1 %) ")) (if (= rate nil) (setq rate 0.1)) (setq delta (* (distance pnt_b pnt_c) (/ rate 100.)) n_repeat (fix (/ 100 rate)) speed (getint "\nSpecify speed (1-100) 1:veryfast 100:very slow(def = 50)") ) (if (= speed nil) (setq speed 50)) (make_line_1 "0" 8 pnt_a pnt_c) ;set arrow at the starting points (setq theta_a (+ 180. (rtd (angle pnt_a pnt_c))) theta_b (+ 180. (rtd (angle pnt_b pnt_c))) ) (command "_.insert" "red_boat" pnt_a 0.5 0.5 theta_a ) (princ "after insert")(terpri) (setq red_bt (entlast)) (command "_.insert" "blue_boat" pnt_b 0.5 0.5 theta_b ) (setq blue_bt (entlast)) );;;SETUP ;;; ;;; (defun setup_pursuit_step1() (setq pnt_xl '(-2 0) pnt_xr '(5 0) pnt_o '(0 0) lower_left '(-2.4 -2.1) upper_right '(4.5 2.6) ) (make_line_1 "0" 8 pnt_xl pnt_xr) ;(make_line_1 "0" 8 pnt_yl pnt_yu) (command "_.zoom" "_Window" lower_left upper_right) (command "_.regen") (setvar "OSMODE" 512) (setvar "PDMODE" 32) ;(command "_.point" (setq pnt_1 (getpoint "\nGet Point A:"))) ;(command "_.point" (setq pnt_2 (getpoint "\nGet Point B:"))) (setq pnt_1 pnt_xl pnt_2 '(1.0 0) pnt_c1 '(0 0) pnt_c2 '(4 0) ;;;C1 & C2 are harmonic division points ) (make_pt "0" 0 pnt_1) (make_pt "0" 0 pnt_2) (mark_id pnt_1 "A" 4 0.25) (mark_id pnt_2 "B" 4 0.25) (setq k (getreal "\nRelative speed of the Pursuiter(>1.0)(def=2.0) = ")) (if (= k nil) (setq k 2.0)) (setq pnt_a pnt_1 pnt_b pnt_2 ksq (* k k) ksqp1 (+ ksq 1) ksqm1 (- ksq 1) len_oc (/ (* 0.5 (distance pnt_a pnt_b) (- k 1)) (+ k 1)) ap_rad (/ (* (distance pnt_a pnt_b) k) ksqm1) cir_cen (shift_pnt (mid_point pnt_a pnt_b) (list (+ ap_rad len_oc) 0)) rel_speed k ) ;(make_circle_1 "0" 8 cir_cen ap_rad) ; (setq ap_circle (entlast)) (setq rate 1. n_repeat (fix (/ 100 rate)) speed 50 ) );;;SETUP ;;; ;;;STEP1 ;;; (defun step1() (setq pnt_c pnt_c1 delta (* (distance pnt_b pnt_c) (/ rate 100.) ) ) ;set arrow at the starting points (command "_.insert" "red_boat" pnt_a 0.5 0.5 180. ) ;(princ "after insert")(terpri) (setq red_bt (entlast)) (command "_.insert" "blue_boat" pnt_b 0.5 0.5 0. ) (setq blue_bt (entlast)) );;;STEP1 ;;; ;;;STEP2 ;;; (defun step2() (setq pnt_c pnt_c2 pnt_a pnt_1 pnt_b pnt_2 delta (* (distance pnt_b pnt_c) (/ rate 100.) ) ) ;set arrow at the starting points (command "_.insert" "blue_boat" pnt_b 0.5 0.5 180. ) (setq blue_bt (entlast)) (command "_.insert" "red_boat" pnt_a 0.5 0.5 180. ) (setq red_bt (entlast)) );;;STEP2 ;;;STEP3 ;;; (defun step3() (setq pnt_c pnt_es pnt_a pnt_1 pnt_b pnt_2 delta (* (distance pnt_b pnt_c) (/ rate 100.) ) ) ;set arrow at the starting points (setq theta_a (+ 180. (rtd (angle pnt_a pnt_c))) theta_b (+ 180. (rtd (angle pnt_b pnt_c))) ) (command "_.insert" "red_boat" pnt_a 0.5 0.5 theta_a ) (setq red_bt (entlast)) (command "_.insert" "blue_boat" pnt_b 0.5 0.5 theta_b ) (setq blue_bt (entlast)) );;;STEP3 ;;; ;;;PURSUIT for a straight line case ;;; The case of dog and rabbit running at the independetn pre-destined target points ;;; initial points pnt_rs for rabbit, pnt_ds for dog ;;; target points pnt_rt for rabbit, pnt_dt for dog ;;; rel_speed dog's speed/ rabbit's speed ;;; The following code must be updated in the future (June 3,2005) ;;;PURSUIT_APOLLO_1 ;;; (defun pursuit_apollo_1() ;(setup_sysvar) (if (= (Yes_or_No "Start ?") "_Y") (repeat n_repeat (setq pnt_bc (pld pnt_b pnt_c delta) pnt_ac (pld pnt_a pnt_c (* rel_speed delta)) ) (slow_line speed "0" 1 pnt_a pnt_ac) (slow_line speed "0" 5 pnt_b pnt_bc) (command "_.move" blue_bt "" pnt_b pnt_bc ) (command "_.move" red_bt "" pnt_a pnt_ac) (setq pnt_a pnt_ac pnt_b pnt_bc ) ) ;;;end of repeat loop ) ;;;end of if loop );;;PURSUIT_apollo_1 ;;; ;;;PURSUIT_APOLLO_1A ;;; (defun pursuit_apollo_1A() (setq nstep 0) (make_jpg) ;;apollo_1a jpg file (if (= (Yes_or_No "Start ?") "_Y") (repeat n_repeat (setq pnt_bc (pld pnt_b pnt_c delta) pnt_ac (pld pnt_a pnt_c (* rel_speed delta)) ) (slow_line speed "0" 1 pnt_a pnt_ac) (slow_line speed "0" 5 pnt_b pnt_bc) (command "_.move" blue_bt "" pnt_b pnt_bc ) (command "_.move" red_bt "" pnt_a pnt_ac) (setq pnt_a pnt_ac pnt_b pnt_bc nstep (1+ nstep)) (if (= (rem nstep 10) 0) (make_jpg)) ) ;;;end of repeat loop ) ;;;end of if loop );;;PURSUIT_apollo_1A ;;; ;;;PURSUIT_APOLLO_1B ;;; (defun pursuit_apollo_1B() (setq nstep 0) (make_jpg) ;;apollo_1b jpg file (if (= (Yes_or_No "Start ?") "_Y") (repeat n_repeat (setq pnt_bc (pld pnt_b pnt_c delta) pnt_ac (pld pnt_a pnt_c (* rel_speed delta)) ) (slow_line speed "0" 1 pnt_a pnt_ac) (slow_line speed "0" 5 pnt_b pnt_bc) (command "_.move" blue_bt "" pnt_b pnt_bc ) (command "_.move" red_bt "" pnt_a pnt_ac) (setq pnt_a pnt_ac pnt_b pnt_bc nstep (1+ nstep)) (if (= (rem nstep 10) 0) (make_jpg) ) ) ;;;end of repeat loop ) ;;;end of if loop );;;PURSUIT_apollo_1B ;;; ;;; ;;;PURSUIT_APOLLO_1C ;;; (defun pursuit_apollo_1C() (setq nstep 0) (make_jpg) ;apollo_1c jpg file (if (= (Yes_or_No "Start ?") "_Y") (repeat n_repeat (setq pnt_bc (pld pnt_b pnt_c delta) pnt_ac (pld pnt_a pnt_c (* rel_speed delta)) ) (slow_line speed "0" 1 pnt_a pnt_ac) (slow_line speed "0" 5 pnt_b pnt_bc) (command "_.move" blue_bt "" pnt_b pnt_bc ) (command "_.move" red_bt "" pnt_a pnt_ac) (setq pnt_a pnt_ac pnt_b pnt_bc nstep (1+ nstep)) (if (= (rem nstep 10) 0) (make_jpg) ) ) ;;;end of repeat loop ) ;;;end of if loop );;;PURSUIT_apollo_1C ;;; ;;; (defun setup_pursuit_int() (setq pnt_xl '(-2 0) pnt_xr '(5 0) pnt_o '(0 0) pnt_yu '(0 3) pnt_yl '(0 -3) ) (make_line_1 "0" 8 pnt_xl pnt_xr) (make_line_1 "0" 8 pnt_yl pnt_yu) (command "_.zoom" "_EXTENT") (command "_.regen") (setvar "OSMODE" 512) (setvar "PDMODE" 32) (command "_.point" (setq pnt_1 (getpoint "\nGet Point A:"))) (command "_.point" (setq pnt_2 (getpoint "\nGet Point B:"))) ;(command "_.line" pnt_2 (setq pnt_3 (getpoint pnt_2 "\nSpecify Escape direction")) "") (setq k (getreal "\nRatio of distance from A & B(>1.0) = ")) (setq pnt_a pnt_1 pnt_b pnt_2 pnt_c pnt_3 d_ref 1.e10 ksq (* k k) ksqp1 (+ ksq 1) ksqm1 (- ksq 1) len_oc (/ (* 0.5 (distance pnt_a pnt_b) (- k 1)) (+ k 1)) ap_rad (/ (* (distance pnt_a pnt_b) k) ksqm1) cir_cen (shift_pnt (mid_point pnt_a pnt_b) (list (+ ap_rad len_oc) 0)) ) (setq d_ab (distance pnt_a pnt_b)) ;set arrow at the starting points (command "_.insert" "red_arrow" pnt_a 0.5 0.5 -90.) (princ "after insert")(terpri) (setq red_arw (entlast)) (mark_id pnt_a "A" 2 0.25) (command "_.insert" "blue_arrow" pnt_b 0.5 0.5 -90. ) (setq blue_arw (entlast)) (mark_id pnt_b "B" 2 0.25) (setvar "OSMODE" 32) (alert "draw 5 pairs of circles") );;; ;;;PURSUIT for a straight line case ;;;