bditty Posted March 10 Posted March 10 On 3/27/2014 at 5:24 AM, Madruga_SP said: This is really good stuff, thank you. It works great, but for me, we use quadrant bearings, so can the code first ask for a quadrant (1-4) and then the bearing (89.5050) then the distance (125.50) Where is the tip jar? happy to pay for this, I've wanted to find this shortcut for years! On 3/27/2014 at 6:23 AM, ymg3 said: Madruga_SP, There you go. (defun C:AZI (/ point ds a d m s dec_deg osm) (vl-load-com) ;;; Error Handler by ElpanovEvgenyi ; (defun *error* (msg) (mapcar 'eval errl) (if (and msg (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*"))) (princ (strcat "\nError: " msg)) ) (and *AcadDoc* (vla-endundomark *AcadDoc*)) (princ) ) (setq errl '("OSMODE" "CMDECHO" "ANGDIR" "ANGBASE") errl (mapcar (function (lambda (a) (list 'setvar a (getvar a)))) errl) ) (or *AcadDoc* (setq *AcadDoc* (vla-get-activedocument (vlax-get-acad-object))) ) (vla-startundomark *AcadDoc*) (setvar "cmdecho" 0) (setvar 'ANGDIR 1) (setvar 'ANGBASE (/ pi 2)) (setvar 'OSMODE 0) (if (setq POINT (getpoint "\nSeleciona o ponto de início:")) (progn (vla-startundomark *AcadDoc*) (setvar "cmdecho" 0) (setvar 'ANGDIR 1) (setvar 'ANGBASE (/ pi 2)) (setvar 'OSMODE 0) (command "_Pline" point) (while (> (getvar "CMDACTIVE") 0) (if (and (setq ds (getdist (getvar 'Lastpoint) "\nDigita a distância: ")) (setq a (getreal "\nDigita o Azimute [GG.MMSS] : "))) (progn (setq d (fix a)) (setq m (fix (* 100 (- a d)))) (setq s (* 100 (- (* 100 (- a d)) m))) (setq dec_deg (+ d (/ m 60.0) (/ s 3600.0))) (command (strcat "@" (rtos ds) "<" (angtos (angtof (rtos dec_deg 2 4) 0) 1 4))) ) (command "") ) ) ) ) (*error* nil) ) We could also modify bd and say you would enter add.mmssd 120.369, it could interpret it as an azimut. ymg Quote
ymg3 Posted March 17 Posted March 17 (edited) Here's one that will accept either Quadrant, Bearing or Azimut: ; dmsin by ymg ; ; ; ; Interpret a real number as an angle ; ; Calculator style ->dd.mmss ; ; Returns the angle in radians ; (defun dmsin (a / d m s) (setq d (fix a) m (* (- a d) 100) s (* (- m (fix m)) 100) m (fix m) ) (* pi (/ (+ d (/ (+ m (/ s 60)) 60)) 180)) ) ;; parse by CAB ; ;; ; ;; Creates a list from a string and a delimiter. ; ;; ; (defun parse (str delim / ptr lst) (while (setq ptr (vl-string-search delim str)) (setq lst (cons (substr str 1 ptr) lst)) (setq str (substr str (+ ptr 2))) ) (reverse (cons str lst)) ) ; bdin by ymg ; ; ; ; Let you enter Bearing and Distance as a ; ; single string Calculator style. ; ; (Ndd.mmssE 120.365) ; ;also accept quadrant angle distance ; ; (Q dd.mm.ss distance ; ;azimut from north can also be entered ; ; Add.mmss distance ; ; ; ; Returns a list (Angle Distance) where, ; ; the angle is in radians. ; ; ; ; Requires subroutine dmsin ; (defun bdin (s / a d lst) (setq s (strcase (vl-string-trim " " s)) ; Required so that E is not interpreted as an exponent ; s (vl-string-subst "Z" "E" s) s (vl-string-subst " " "," s) lst (parse s " ") ) (if (> (length lst) 2) (cond ((= (car lst) "1") (setq a (dmsin (atof (cadr lst))))) ;; Northeast ; ((= (car lst) "2") (setq a (- pi (dmsin (atof (cadr lst)))))) ;; Southeast ; ((= (car lst) "3") (setq a (+ pi (dmsin (atof (cadr lst)))))) ;; Southwest ; ((= (car lst) "4") (setq a (- pi pi (dmsin (atof (cadr lst)))))) ;; Nortwest ; ) (cond ((= (substr (car lst) 1 1) "A") (setq a (dmsin (atof (substr (car lst) 2))))) ((= (substr (car lst) 1 1) "N") (if (= (substr (car lst) (strlen (car lst))) "Z") (setq a (dmsin (atof (substr (car lst) 2)))) (setq a (- pi pi (dmsin (atof (substr (car lst) 2))))) )) ((= (substr (car lst) 1 1) "S") (if (= (substr (car lst) (strlen (car lst))) "Z") (setq a (- pi (dmsin (atof (substr (car lst) 2))))) (setq a (+ pi (dmsin (atof (substr (car lst) 2))))) )) ) ) (setq d (atof (last lst))) (if (and a d) (list a d)) ) ;; angbd function to respect ANGBASE / ANGDIR by ymg ; ;; Modified from Lee Mac's _angle function ; (defun angbd (a) (rem (+ pi pi ((if (zerop (getvar 'ANGDIR)) + -) (- a (getvar 'ANGBASE)))) (+ pi pi) ) ) ;;bd by ymg ; ;; ; ;;Draw polyline by entering segments under various format ; ;; ; ;; Segment can be: ; ;; bearing/distance Ex. S30.3030W 120.567 ; ;; Quadrant /Angle/Distance Ex. 3 30.3030 120.567 ; ;; Azimut distance Ex. A210.3030 120.567 ; ;; : ;; Entering C will close the current polyline. ; ;; Entering U will remove the last segment entered ; ;; Just Pressing ENTER will send you back to pick a new starting ; ;; point and start a new polyline. ; ;; ; ;; All angle are entered in DD.MMSS Calculator style ; ;; ; (defun c:bd ( / bd sp p1) (vl-load-com) ;;; Error Handler by ElpanovEvgenyi ; (defun *error* (msg) (mapcar 'eval errl) (if (and msg (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*"))) (princ (strcat "\nError: " msg)) ) (and *AcadDoc* (vla-endundomark *AcadDoc*)) (princ) ) (setq errl '("OSMODE" "CMDECHO" "ANGDIR" "ANGBASE") errl (mapcar (function (lambda (a) (list 'setvar a (getvar a)))) errl) ) (or *AcadDoc* (setq *AcadDoc* (vla-get-activedocument (vlax-get-acad-object))) ) (vla-startundomark *AcadDoc*) (setvar 'ANGDIR 1) (setvar 'ANGBASE (/ pi 2)) (setvar 'OSMODE 0) (while (setq sp (getpoint "\nSelect a Starting Point: ")) (command "_PLINE" sp) (while (and (not (equal p1 sp 0.01)) (not (equal "" (setq bd (strcase (getstring T "\nEnter a Segment: "))))) ) (if (not p1) (setq p1 sp)) (cond ((equal bd "C") (command (setq p1 sp)));;Close the polyline and exit ; ((equal bd "U") (command "U") ;;Undo the last segment of the polyline ; (setq p1 (getvar 'LASTPOINT)) (if (equal p1 sp) (setq p1 nil)) ) ((equal bd "" ) (command "")(setq sp nil)) (t (if (setq bd (bdin bd)) (command (setq p1 (polar p1 (angbd (car bd)) (cadr bd)))) (alert "Invalid Input...!") ) ) ) ) ) (command "") (*error* nil) ) (princ "Press bd to start") (c:bd) bd.lsp Edited March 20 by ymg3 attach the file and modified code Quote
ymg3 Posted March 23 Posted March 23 So following a request by bditty, I modified bd.lsp and renamed it qbd.lsp. Instead of having a single prompt for entering each segment of the polyline separating item with space, you now have different prompt for each item of the line segment. It's a bit of a hack as there is not much validating of the inputs. Here's the code: ;;qbd by ymg ; ;; ; ;;Draw polyline by entering segments under various format. ; ;; ; ;;First prompt you to Pick a Starting Point: ; ;; ; ;; Then prompt to Enter Quadrant or Bearing or Azzimut of Line Segment: ; ;; Here you can Enter a Quadrant (Integer between 1 and 4) ; ;; or Enter a Bearing Ex. S30.3030W ; ;; or Enter an Azimut Ex. A210.3030 ; ;; or Enter "C" Will close the polyline. ; ;; or Enter "U" Will remove last segment ; ;; or Enter "" Will send you to Pick a Starting Point: ; ;; ; ;; If you entered a Quadrant next prompt will be: ; ;; Enter angle (dd.mmss): 30.3030 ; ;; otherwise next prompt will be: ; ;; Enter Distance: ; ;; ; (defun c:qbd ( / bd sp p1 str pr) (vl-load-com) ;;; Error Handler by ElpanovEvgenyi ; (defun *error* (msg) (mapcar 'eval errl) (if (and msg (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*"))) (princ (strcat "\nError: " msg)) ) (and *AcadDoc* (vla-endundomark *AcadDoc*)) (princ) ) (setq errl '("OSMODE" "CMDECHO" "ANGDIR" "ANGBASE") errl (mapcar (function (lambda (a) (list 'setvar a (getvar a)))) errl) ) (or *AcadDoc* (setq *AcadDoc* (vla-get-activedocument (vlax-get-acad-object))) ) (vla-startundomark *AcadDoc*) (setvar 'ANGDIR 1) (setvar 'ANGBASE (/ pi 2)) (while (setq sp (getpoint "\nPick a Starting Point: ")) (setq p1 nil) (command "_PLINE" sp) (setq str "" pr "\nEnter Quadrant or Bearing or Azzimut of Line Segment: ") (while (and sp (setq bd (strcase (getstring pr)))) (cond ((equal bd "C") (command "C" )(setq sp nil)) ;;Close the polyline and exit ; ((equal bd "U") (command "U") ;;Undo the last segment of the polyline ; (setq p1 (getvar 'LASTPOINT)) (if (equal p1 sp) (setq p1 nil)) ) ((equal bd "" ) (command "")(setq sp nil p1 nil)) ((equal bd "1") (setq str "1 " pr "\nEnter angle (dd.mmss): " )) ((equal bd "2") (setq str "2 " pr "\nEnter angle (dd.mmss): ")) ((equal bd "3") (setq str "3 " pr "\nEnter angle (dd.mmss): ")) ((equal bd "4") (setq str "4 " pr "\nEnter angle (dd.mmss): ")) ((equal (substr bd 1 1) "A") (setq str (strcat str bd) pr "\nEnter Distance: ")) ((equal (substr bd 1 1) "N") (setq str (strcat str bd) pr "\nEnter Distance: ")) ((equal (substr bd 1 1) "S") (setq str (strcat str bd) pr "\nEnter Distance: ")) ((equal pr "\nEnter angle (dd.mmss): ") (setq str (strcat str bd) pr "\nEnter Distance: ")) ((equal pr "\nEnter Distance: ") (setq str (strcat str " " bd) pr "\nEnter next Line Segment: ")) ) (if (and (equal pr "\nEnter next Line Segment: ") (setq bd (bdin str))) (progn (if (not p1) (setq p1 sp)) (command (setq p1 (polar p1 (angbd (car bd)) (cadr bd)))) (setq str "") ) ;(alert "Invalid Input...!") ) (if (equal p1 sp 0.001)(progn (setq sp nil)(command "c"))) ) ) (*error* nil) ) ; dmsin by ymg ; ; ; ; Interpret a real number as an angle ; ; Calculator style ->dd.mmss ; ; Returns the angle in radians ; (defun dmsin (a / d m s) (setq d (fix a) m (* (- a d) 100) s (* (- m (fix m)) 100) m (fix m) ) (* pi (/ (+ d (/ (+ m (/ s 60)) 60)) 180)) ) ;; parse by CAB ; ;; ; ;; Creates a list from a string and a delimiter. ; ;; ; (defun parse (str delim / ptr lst) (while (setq ptr (vl-string-search delim str)) (setq lst (cons (substr str 1 ptr) lst)) (setq str (substr str (+ ptr 2))) ) (reverse (cons str lst)) ) ; bdin by ymg ; ; ; ; Let you enter Bearing and Distance as a ; ; single string Calculator style. ; ; (Ndd.mmssE 120.365) ; ;also accept quadrant angle distance ; ; (Q dd.mm.ss distance ; ;azimut from north can also be entered ; ; Add.mmss distance ; ; ; ; Returns a list (Angle Distance) where, ; ; the angle is in radians. ; ; ; ; Requires subroutine dmsin ; (defun bdin (s / a d lst) (setq s (strcase (vl-string-trim " " s)) ; Required so that E is not interpreted as an exponent ; s (vl-string-subst "Z" "E" s) s (vl-string-subst " " "," s) lst (parse s " ") ) (if (> (length lst) 2) (cond ((= (car lst) "1") (setq a (dmsin (atof (cadr lst))))) ;; Northeast ; ((= (car lst) "2") (setq a (- pi (dmsin (atof (cadr lst)))))) ;; Southeast ; ((= (car lst) "3") (setq a (+ pi (dmsin (atof (cadr lst)))))) ;; Southwest ; ((= (car lst) "4") (setq a (- pi pi (dmsin (atof (cadr lst)))))) ;; Nortwest ; ) (cond ((= (substr (car lst) 1 1) "A") (setq a (dmsin (atof (substr (car lst) 2))))) ((= (substr (car lst) 1 1) "N") (if (= (substr (car lst) (strlen (car lst))) "Z") (setq a (dmsin (atof (substr (car lst) 2)))) (setq a (- pi pi (dmsin (atof (substr (car lst) 2))))) )) ((= (substr (car lst) 1 1) "S") (if (= (substr (car lst) (strlen (car lst))) "Z") (setq a (- pi (dmsin (atof (substr (car lst) 2))))) (setq a (+ pi (dmsin (atof (substr (car lst) 2))))) )) ) ) (setq d (atof (last lst))) (if (and a d) (list a d)) ) ;; angbd function to respect ANGBASE / ANGDIR by ymg ; ;; Modified from Lee Mac's _angle function ; (defun angbd (a) (rem (+ pi pi ((if (zerop (getvar 'ANGDIR)) + -) (- a (getvar 'ANGBASE)))) (+ pi pi) ) ) ;; Start the program upon loading ; (princ "Press qbd to start") (c:qbd) qbd.lsp Quote
ymg3 Posted April 10 Posted April 10 (edited) bditty signaled that when entering angle or bearing in the form S54.3E conversion would be not correct. This should be interpreted as 54d30'00" further the use of fix in the dmsin routine would lead to improper rounding down. So I changed the dms routine to operate with string instead of floating number to prevent this. Added a last minute change to account for decimals of seconds. So revised the code: ;;qbd by ymg ; ;; ; ;;Draw polyline by entering segments under various format. ; ;; ; ;;First prompt you to Pick a Starting Point: ; ;; ; ;; Then prompt to Enter Quadrant or Bearing or Azzimut of Line Segment: ; ;; Here you can Enter a Quadrant (Integer between 1 and 4) ; ;; or Enter a Bearing Ex. S30.3030W ; ;; or Enter an Azimut Ex. A210.3030 ; ;; or Enter "C" Will close the polyline. ; ;; or Enter "U" Will remove last segment ; ;; or Enter "" Will send you to Pick a Starting Point: ; ;; ; ;; If you entered a Quadrant next prompt will be: ; ;; Enter angle (dd.mmss): 30.3030 ; ;; otherwise next prompt will be: ; ;; Enter Distance: ; ;; ; (defun c:qbd ( / bd sp p1 str pr) (vl-load-com) ;;; Error Handler by ElpanovEvgenyi ; (defun *error* (msg) (mapcar 'eval errl) (if (and msg (not (wcmatch (strcase msg) "*BREAK*,*CANCEL*,*EXIT*"))) (princ (strcat "\nError: " msg)) ) (and *AcadDoc* (vla-endundomark *AcadDoc*)) (princ) ) (setq errl '("OSMODE" "CMDECHO" "ANGDIR" "ANGBASE") errl (mapcar (function (lambda (a) (list 'setvar a (getvar a)))) errl) ) (or *AcadDoc* (setq *AcadDoc* (vla-get-activedocument (vlax-get-acad-object))) ) (vla-startundomark *AcadDoc*) (setvar 'ANGDIR 1) (setvar 'ANGBASE (/ pi 2)) (while (setq sp (getpoint "\nPick a Starting Point: ")) (setq p1 nil) (command "_PLINE" sp) (setq str "" pr "\nEnter Quadrant or Bearing or Azzimut of Line Segment: ") (while (and sp (setq bd (strcase (getstring pr)))) (cond ((equal bd "C") (command "C" )(setq sp nil)) ;;Close the polyline and exit ; ((equal bd "U") (command "U") ;;Undo the last segment of the polyline ; (setq p1 (getvar 'LASTPOINT)) (if (equal p1 sp) (setq p1 nil)) ) ((equal bd "" ) (command "")(setq sp nil p1 nil)) ((equal bd "1") (setq str "1 " pr "\nEnter angle (dd.mmss): " )) ((equal bd "2") (setq str "2 " pr "\nEnter angle (dd.mmss): ")) ((equal bd "3") (setq str "3 " pr "\nEnter angle (dd.mmss): ")) ((equal bd "4") (setq str "4 " pr "\nEnter angle (dd.mmss): ")) ((equal (substr bd 1 1) "A") (setq str (strcat str bd) pr "\nEnter Distance: ")) ((equal (substr bd 1 1) "N") (setq str (strcat str bd) pr "\nEnter Distance: ")) ((equal (substr bd 1 1) "S") (setq str (strcat str bd) pr "\nEnter Distance: ")) ((equal pr "\nEnter angle (dd.mmss): ") (setq str (strcat str bd) pr "\nEnter Distance: ")) ((equal pr "\nEnter Distance: ") (setq str (strcat str " " bd) pr "\nEnter next Line Segment: ")) ) (if (and (equal pr "\nEnter next Line Segment: ") (setq bd (bdin str))) (progn (if (not p1) (setq p1 sp)) (command (setq p1 (polar p1 (angbd (car bd)) (cadr bd)))) (setq str "") ) ;(alert "Invalid Input...!") ) (if (equal p1 sp 0.001)(progn (setq sp nil)(command "c"))) ) ) (*error* nil) ) ; dmsin by ymg ; ; ; ; Interpret a string as an angle ; ; Calculator style ->dd.mmss ; ; ; ; Returns the angle in radians ; (defun dmsin (a / d m s) (setq a (vl-string-subst "" "N" a) a (vl-string-subst "" "Z" a) a (vl-string-subst "" "S" a) a (vl-string-subst "" "W" a) a (vl-string-subst "" "E" a) ) (if (< (length (parse a ".")) 2) (setq a (strcat a ".0000"))) (while (< (strlen (cadr (parse a "."))) 4) (setq a (strcat a "0"))) (setq a (parse a ".")) (setq d (atof (substr (car a) 1)) m (atof (substr (cadr a) 1 2)) s (atof (strcat (substr (cadr a) 3 2) "." (substr (cadr a) 5))) ) (* pi (/ (+ d (/ (+ m (/ s 60.0)) 60.0)) 180.0)) ) ;; parse by CAB ; ;; ; ;; Creates a list from a string and a delimiter. ; ;; ; (defun parse (str delim / ptr lst) (while (setq ptr (vl-string-search delim str)) (setq lst (cons (substr str 1 ptr) lst)) (setq str (substr str (+ ptr 2))) ) (reverse (cons str lst)) ) ; bdin by ymg ; ; ; ; Let you enter Bearing and Distance as a ; ; single string Calculator style. ; ; (Ndd.mmssE 120.365) ; ;also accept quadrant angle distance ; ; (Q dd.mm.ss distance ; ;azimut from north can also be entered ; ; Add.mmss distance ; ; ; ; Returns a list (Angle Distance) where, ; ; the angle is in radians. ; ; ; ; Requires subroutine dmsin ; (defun bdin (s / a d lst) (princ s) (setq s (strcase (vl-string-trim " " s)) ; Required so that E is not interpreted as an exponent ; s (vl-string-subst "Z" "E" s) s (vl-string-subst " " "," s) lst (parse s " ") ) (if (> (length lst) 2) (cond ((= (car lst) "1") (setq a (dmsin (cadr lst)))) ;; Northeast ; ((= (car lst) "2") (setq a (- pi (dmsin (cadr lst))))) ;; Southeast ; ((= (car lst) "3") (setq a (+ pi (dmsin (cadr lst))))) ;; Southwest ; ((= (car lst) "4") (setq a (- pi pi (dmsin (cadr lst))))) ;; Nortwest ; ) (cond ((= (substr (car lst) 1 1) "A") (setq a (dmsin (substr (car lst) 2)))) ((= (substr (car lst) 1 1) "N") (if (= (substr (car lst) (strlen (car lst))) "Z") (setq a (dmsin (substr (car lst) 2))) (setq a (- pi pi (dmsin (substr (car lst) 2)))) )) ((= (substr (car lst) 1 1) "S") (if (= (substr (car lst) (strlen (car lst))) "Z") (setq a (- pi (dmsin (substr (car lst) 2)))) (setq a (+ pi (dmsin (substr (car lst) 2)))) )) ) ) (setq d (atof (last lst))) (if (and a d) (list a d)) ) ;; angbd function to respect ANGBASE / ANGDIR by ymg ; ;; Modified from Lee Mac's _angle function ; (defun angbd (a) (rem (+ pi pi ((if (zerop (getvar 'ANGDIR)) + -) (- a (getvar 'ANGBASE)))) (+ pi pi) ) ) ;; Radian to decimal degree ; (defun rtd (a) (/ (* a 180.0) pi)) ;; Start the program upon loading ; (princ "Press qbd to start") (c:qbd) qbdrev.lsp Edited April 10 by ymg3 Added decimal of seconds Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.