Author Topic: SOLVED_Calculate endpoint of line given initial point, azi, incli, distance  (Read 1903 times)

0 Members and 1 Guest are viewing this topic.

nekonihonjin

  • Newt
  • Posts: 103
Hi guys,

Is there something like the Polar function, but for a point in 3D?

Given an initial point, distance, inclination and azimuth; calculate the point where a line would reach in that direction.
I was using the command _line -> initial pt ->  @dist<azim<inclination 
but I think it the lisp would be faster if I avoid using the command line and create the line with entmake


Found this in a topic here a the forum, but need some modification:
Code: [Select]
(defun polar3D-incl (pt dist inclination azimuth /)
  (mapcar '+
          pt
          (list (* dist (sin inclination) (cos azimuth))
                (* dist (sin inclination) (sin azimuth))
                (* dist (cos inclination))
          )
  )
)

the main problem is that the azimuth I have is the one used in topography/geology, which starts from 0° in the north (y-axis) and from there clockwise.
while autocad handles 0° to the east (a line to the positive x-axis), and increases the angle counterclockwise.
So my CVS file has an azimuth of 10°, for autocad it would be 80°, while an azimuth of 135° in my file would be 315° in autocad.


« Last Edit: November 05, 2022, 10:51:20 AM by nekonihonjin »

Jim2018

  • Mosquito
  • Posts: 16
The easy way: change autocad to start count angles from north and clockwise!


nekonihonjin

  • Newt
  • Posts: 103
See ANGDIR and ANGBASE (System Variable)
The easy way: change autocad to start count angles from north and clockwise!


It's a way to solve it, but it's meant for other people to use it, and I wouldn't like an error to occur while running the lisp and leave those variables changed to the user, but it will do for now

Thank you both







VovKa

  • Water Moccasin
  • Posts: 1631
  • Ukraine
isn't it just (- (/ pi 2) azimuth) ?

57gmc

  • Bull Frog
  • Posts: 366
See ANGDIR and ANGBASE (System Variable)
The easy way: change autocad to start count angles from north and clockwise!

It's a way to solve it, but it's meant for other people to use it, and I wouldn't like an error to occur while running the lisp and leave those variables changed to the user, but it will do for now

Thank you both
In addition to VovKa's suggestion and for future reference, it's good programming practice when you want to change a program's setting to create a new variable, store the current setting's value, and then make your change. At the end of your code, you can then reset the setting using the value stored in your variable. For example:
Code - Auto/Visual Lisp: [Select]
  1. (setq "vAngDir" (getvar "ANGDIR"))
  2. (setvar "ANGDIR" 90)
  3. **do your thing
  4. (setvar "ANGDIR" vAngDir)

**what language name do you use to format the code tag for lisp?
« Last Edit: November 03, 2022, 03:41:00 PM by 57gmc »

nekonihonjin

  • Newt
  • Posts: 103
isn't it just (- (/ pi 2) azimuth) ?

since I'm a noob, had to do this:

Code: [Select]
(defun aztocad (ang /)
  (if (<= ang 90)
      (- 90 ang)
      (- 450 ang)
  )
)

(setq az (dtr (aztocad (getreal "\nEnter azimuth: "))))

but every piece of advice is for learning and is appreciated

now I just need to reduce this code with the help of mapcar:

Code: [Select]
(defun pol3d (pt az incl dist / )
(setq x (car pt))
(setq y (car (cdr pt)))
(setq z (car (cdr (cdr pt))))


(setq dx (* dist (* (cos az) (cos incl))))
(setq dy (* dist (* (sin az) (cos incl))))
(setq dz (* dist (sin incl)))

(list (+ x dx) (+ y dy) (+ z dz) )

)


nekonihonjin

  • Newt
  • Posts: 103
See ANGDIR and ANGBASE (System Variable)
The easy way: change autocad to start count angles from north and clockwise!

It's a way to solve it, but it's meant for other people to use it, and I wouldn't like an error to occur while running the lisp and leave those variables changed to the user, but it will do for now

Thank you both
In addition to VovKa's suggestion and for future reference, it's good programming practice when you want to change a program's setting to create a new variable, store the current setting's value, and then make your change. At the end of your code, you can then reset the setting using the value stored in your variable. For example:
Code - Text: [Select]
  1. (setq "vAngDir" (getvar "ANGDIR"))
  2. (setvar "ANGDIR" 90)
  3. **do your thing
  4. (setvar "ANGDIR" vAngDir)

That's good advice GMC, I'm still not good with error handling, I prefer not to risk that something happens in the middle of the **do your thing, but before the (setvar "ANGDIR" vAngDir).
I see how advanced users convert a code that would take 5 lines, into 30 just to deal with whether the right object was selected, if the function has the necessary arguments or if there was missclick. between AND, NOT, IF, OR strings.
I still have a way to go to get there.


efernal

  • Bull Frog
  • Posts: 206
I have made something about this, long time ago...

https://www.gr-acad.com.br/pac/gr-pack-001.gif

(forgive me for my bad site, no time to improve it...)
e.fernal

kirby

  • Newt
  • Posts: 131
Or just build all the cases of AngBase and AngDir into your solution.

And don't get hung up on shortening or 'mapcar lambda apply'-ifying your code for the sake of brevity or elegance, lots of comments and avoiding shortcut steps will help you debug and understand in  the future.

Code - Auto/Visual Lisp: [Select]
  1. (defun C:TestPolar3D ( /
  2.                         StartPoint k MyAzimuth MyInclination MyDist NextPoint Cancel
  3.                         )
  4. ; Test function for 'Polar3D'
  5. ; KJM - Nov 2022
  6.  
  7. (setvar "CMDECHO" 0)
  8.  
  9. ; Report angle settings
  10. (prompt "\n  AUnits = ")(princ (getvar "AUNITS"))
  11. (prompt "  AngDir = ")(princ (getvar "ANGDIR"))
  12. (prompt "  AngBase = ")(princ (getvar "ANGBASE"))
  13.  
  14. ; Starting point
  15. (setq StartPoint (getpoint "\nSelect starting point..."))
  16. (prompt "\n  Starting Point = ")(princ StartPoint)(princ)
  17. (command ".POINT" StartPoint)
  18.  
  19. ; Loop for repeat entry of segments
  20. (setq k 1)
  21.  
  22.         ; Get segment details
  23.         (setq MyAzimuth (getreal "\nEnter azimuth angle in decimal degrees (0.0 = north, measured CW)..."))
  24.         (setq MyInclination (getreal "\nEnter inclination angle from horizontal in decimal degrees..."))
  25.         (setq MyDist (getreal "\nEnter length of 3D line segment..."))
  26.  
  27.         (if (and MyAzimuth MyInclination MyDist (not (zerop MyDist)))
  28.           (progn
  29.  
  30.                 ; Get 3d point using custom function.  Assumes AngBase = 0.0 (east) and AngDir = 0 (CCW)
  31.                 (setq NextPoint (Polar3D StartPoint MyAzimuth MyInclination MyDist 1 270.0 1))
  32.                 (prompt "\n  Next Point = ")(princ NextPoint)(princ)
  33.        
  34.                 ; Draw the line segment
  35.                 (command ".LINE" StartPoint NextPoint "")
  36.  
  37.                 ; Update starting point
  38.                 (setq StartPoint NextPoint)
  39.           )
  40.         ) ; close if  
  41.        
  42.         ; continue to quit
  43.         (setq Cancel (strcase (substr (getstring "\nE to end or any key to continue entering segments...") 1 1)))
  44.         (if (= Cancel "E")
  45.           (progn
  46.                 (setq k nil)
  47.                 (prompt "\nTerminating...")(princ)
  48.           )    
  49.         ) ; close if
  50.  
  51. ) ; close while loop
  52.  
  53. )      
  54.  
  55.  
  56.  
  57.  
  58.  
  59. (defun Polar3D (BasePoint Azimuth Inclination Dist AngUnits ZeroAngle PosAngDir /
  60.                         Verbose NewAzimuth DistH DistV NewPoint2D NewPoint3D
  61.                         )
  62. ; Compute a 3D point given a basepoint, azimuth, inclination, distance and angle measurement properties
  63. ; KJM - Nov 2022
  64. ; Input:
  65. ;       BasePoint - (point) base point for measurment
  66. ;       Azimuth - (real) Horizontal azimuth angle (degrees or radians)
  67. ;       Inclination - (real) Vertical inclination / declination angle (degrees or radians)
  68. ;       Dist - (real) 3D length of line segment
  69. ;       AngUnits - (integer) code indicating units for angles 0=radians, 1=degrees, nil = 0 (radians).  Note: differs from sysvar 'AUNITS'
  70. ;                       (Surveyors, etc -> use 1)
  71. ;       ZeroAngle - (real) zero angle in degrees or radians.  nil = use AngBase
  72. ;               if PosAngDir = 0 (CCW), east = 0.0, north = 90.0 / hpi, west = 180.0 / pi, and south = 270.0 / 1.5pi
  73. ;               if PosAngDir = 1 (CW), east = 0.0, north = 270.0 / 1.5pi, west = 180.0 / pi, and south = 90.0 / hpi
  74. ;                       (Surveyors, etc -> use 270.0)
  75. ;       PosAngDir - (integer) code matching AngDir.  0 = counterclockwise, 1 = clockwise,  nil = use AngDir
  76. ;                       (Surveyors, etc -> use 1)
  77. ; Returns:
  78. ;       point
  79. ; Notes:
  80. ;       does not consider UCS
  81. ; Uses custom functions:
  82. ;       dtr
  83.  
  84. (setq Verbose 1)        ; set to 0 to supress comments
  85.  
  86. ; defaults
  87. (if (not AngUnits) (setq AngUnits 0))                   ; default is radians
  88.  
  89. (if (not ZeroAngle)
  90.         (setq ZeroAngle (getvar "ANGBASE"))             ; default uses ANGBASE
  91.         (if (eq AngUnits 1)
  92.                 (setq ZeroAngle (dtr ZeroAngle))        ; Convert entered value to radians
  93.         )      
  94. )
  95.  
  96. (if (not PosAngDir) (setq PosAngDir (getvar "ANGDIR"))) ; default uses ANGDIR
  97.  
  98. ; Convert entered angles to radians
  99. (if (eq AngUnits 1)
  100.   (progn
  101.         (setq Azimuth (dtr Azimuth))
  102.         (setq Inclination (dtr Inclination))
  103.   )
  104. )
  105.  
  106. ; Convert azimuth angle to current
  107. (if (eq PosAngDir 0)
  108.         (setq NewAzimuth (- Azimuth ZeroAngle))                         ; Angles provided in CCW units (Acad standard / cartesian)
  109.         (setq NewAzimuth (- (- (+ pi pi) ZeroAngle) Azimuth))           ; Angles provided in CW units
  110. )      
  111.  
  112. (if (eq Verbose 1)
  113.   (progn
  114.         (prompt "\n  PosAngDir = ")(princ PosAngDir)
  115.         (prompt "  ZeroAngle = ")(princ ZeroAngle)(prompt " (")(princ (rtd ZeroAngle))(prompt " d)")
  116.         (prompt "  Azimuth = ")(princ Azimuth)(prompt " (")(princ (rtd Azimuth))(prompt " d)")
  117.         (prompt "  NewAzimuth = ")(princ NewAzimuth)(prompt " (")(princ (rtd NewAzimuth))(prompt " d)")
  118.         (princ)
  119.   )
  120. ) ; close if  
  121.  
  122. ; Get horizontal and vertica components of distance
  123. (setq DistH (* Dist (cos Inclination)))
  124. (setq DistV (* Dist (sin Inclination)))
  125.  
  126. ; Get point on plane, then add elevation
  127. (setq NewPoint2D (polar BasePoint NewAzimuth DistH))                                            ; Note: polar always used CCW and east=0.0 cartesian angles
  128. (setq NewPoint3D (list (car NewPoint2D) (cadr NewPoint2D) (+ (caddr NewPoint2D) DistV)))       
  129.  
  130. NewPoint3D
  131. )
  132.  
  133.  
  134. (defun RTD (A)
  135. ; Radians to Degrees
  136.         (* 180.0 (/ A pi))
  137. )
  138.  
  139. (defun DTR (A)
  140. ; Degrees to Radians
  141.         (* pi (/ A 180.0))
  142. )
  143.  
  144.  

57gmc

  • Bull Frog
  • Posts: 366
That's good advice GMC, I'm still not good with error handling, I prefer not to risk that something happens in the middle of the **do your thing, but before the (setvar "ANGDIR" vAngDir).
I see how advanced users convert a code that would take 5 lines, into 30 just to deal with whether the right object was selected, if the function has the necessary arguments or if there was missclick. between AND, NOT, IF, OR strings.
I still have a way to go to get there.

My name is Ed, GMC is my truck. ;)
You bring up a good point. The trick to handling mishaps like that is to implement UNDO functionality. That way if something goes wrong, the user can just undo. To do this all you have to do is start an undo mark at the beginning and then create an undo mark at the end of your code. See this help topic.

nekonihonjin

  • Newt
  • Posts: 103
That's good advice GMC, I'm still not good with error handling, I prefer not to risk that something happens in the middle of the **do your thing, but before the (setvar "ANGDIR" vAngDir).
I see how advanced users convert a code that would take 5 lines, into 30 just to deal with whether the right object was selected, if the function has the necessary arguments or if there was missclick. between AND, NOT, IF, OR strings.
I still have a way to go to get there.

My name is Ed, GMC is my truck. ;)
You bring up a good point. The trick to handling mishaps like that is to implement UNDO functionality. That way if something goes wrong, the user can just undo. To do this all you have to do is start an undo mark at the beginning and then create an undo mark at the end of your code. See this help topic.

I had used the undomark when the lisp creates many objects and does many actions and if you want to go back is step by step delete one by one the objects, with the undomark you delete everything, but I did not know that it also returned the variables to the value they had before the mark. one more reason to use it.

Thanks again Ed,



Or just build all the cases of AngBase and AngDir into your solution.

And don't get hung up on shortening or 'mapcar lambda apply'-ifying your code for the sake of brevity or elegance, lots of comments and avoiding shortcut steps will help you debug and understand in  the future.

Code - Auto/Visual Lisp: [Select]
  1. (defun C:TestPolar3D ( /
  2.                         StartPoint k MyAzimuth MyInclination MyDist NextPoint Cancel
  3.                         )
  4. ; Test function for 'Polar3D'
  5. ; KJM - Nov 2022
  6.  
  7. (setvar "CMDECHO" 0)
  8.  
  9. ; Report angle settings
  10. (prompt "\n  AUnits = ")(princ (getvar "AUNITS"))
  11. (prompt "  AngDir = ")(princ (getvar "ANGDIR"))
  12. (prompt "  AngBase = ")(princ (getvar "ANGBASE"))
  13.  
  14. ; Starting point
  15. (setq StartPoint (getpoint "\nSelect starting point..."))
  16. (prompt "\n  Starting Point = ")(princ StartPoint)(princ)
  17. (command ".POINT" StartPoint)
  18.  
  19. ; Loop for repeat entry of segments
  20. (setq k 1)
  21.  
  22.         ; Get segment details
  23.         (setq MyAzimuth (getreal "\nEnter azimuth angle in decimal degrees (0.0 = north, measured CW)..."))
  24.         (setq MyInclination (getreal "\nEnter inclination angle from horizontal in decimal degrees..."))
  25.         (setq MyDist (getreal "\nEnter length of 3D line segment..."))
  26.  
  27.         (if (and MyAzimuth MyInclination MyDist (not (zerop MyDist)))
  28.           (progn
  29.  
  30.                 ; Get 3d point using custom function.  Assumes AngBase = 0.0 (east) and AngDir = 0 (CCW)
  31.                 (setq NextPoint (Polar3D StartPoint MyAzimuth MyInclination MyDist 1 270.0 1))
  32.                 (prompt "\n  Next Point = ")(princ NextPoint)(princ)
  33.        
  34.                 ; Draw the line segment
  35.                 (command ".LINE" StartPoint NextPoint "")
  36.  
  37.                 ; Update starting point
  38.                 (setq StartPoint NextPoint)
  39.           )
  40.         ) ; close if  
  41.        
  42.         ; continue to quit
  43.         (setq Cancel (strcase (substr (getstring "\nE to end or any key to continue entering segments...") 1 1)))
  44.         (if (= Cancel "E")
  45.           (progn
  46.                 (setq k nil)
  47.                 (prompt "\nTerminating...")(princ)
  48.           )    
  49.         ) ; close if
  50.  
  51. ) ; close while loop
  52.  
  53. )      
  54.  
  55.  
  56.  
  57.  
  58.  
  59. (defun Polar3D (BasePoint Azimuth Inclination Dist AngUnits ZeroAngle PosAngDir /
  60.                         Verbose NewAzimuth DistH DistV NewPoint2D NewPoint3D
  61.                         )
  62. ; Compute a 3D point given a basepoint, azimuth, inclination, distance and angle measurement properties
  63. ; KJM - Nov 2022
  64. ; Input:
  65. ;       BasePoint - (point) base point for measurment
  66. ;       Azimuth - (real) Horizontal azimuth angle (degrees or radians)
  67. ;       Inclination - (real) Vertical inclination / declination angle (degrees or radians)
  68. ;       Dist - (real) 3D length of line segment
  69. ;       AngUnits - (integer) code indicating units for angles 0=radians, 1=degrees, nil = 0 (radians).  Note: differs from sysvar 'AUNITS'
  70. ;                       (Surveyors, etc -> use 1)
  71. ;       ZeroAngle - (real) zero angle in degrees or radians.  nil = use AngBase
  72. ;               if PosAngDir = 0 (CCW), east = 0.0, north = 90.0 / hpi, west = 180.0 / pi, and south = 270.0 / 1.5pi
  73. ;               if PosAngDir = 1 (CW), east = 0.0, north = 270.0 / 1.5pi, west = 180.0 / pi, and south = 90.0 / hpi
  74. ;                       (Surveyors, etc -> use 270.0)
  75. ;       PosAngDir - (integer) code matching AngDir.  0 = counterclockwise, 1 = clockwise,  nil = use AngDir
  76. ;                       (Surveyors, etc -> use 1)
  77. ; Returns:
  78. ;       point
  79. ; Notes:
  80. ;       does not consider UCS
  81. ; Uses custom functions:
  82. ;       dtr
  83.  
  84. (setq Verbose 1)        ; set to 0 to supress comments
  85.  
  86. ; defaults
  87. (if (not AngUnits) (setq AngUnits 0))                   ; default is radians
  88.  
  89. (if (not ZeroAngle)
  90.         (setq ZeroAngle (getvar "ANGBASE"))             ; default uses ANGBASE
  91.         (if (eq AngUnits 1)
  92.                 (setq ZeroAngle (dtr ZeroAngle))        ; Convert entered value to radians
  93.         )      
  94. )
  95.  
  96. (if (not PosAngDir) (setq PosAngDir (getvar "ANGDIR"))) ; default uses ANGDIR
  97.  
  98. ; Convert entered angles to radians
  99. (if (eq AngUnits 1)
  100.   (progn
  101.         (setq Azimuth (dtr Azimuth))
  102.         (setq Inclination (dtr Inclination))
  103.   )
  104. )
  105.  
  106. ; Convert azimuth angle to current
  107. (if (eq PosAngDir 0)
  108.         (setq NewAzimuth (- Azimuth ZeroAngle))                         ; Angles provided in CCW units (Acad standard / cartesian)
  109.         (setq NewAzimuth (- (- (+ pi pi) ZeroAngle) Azimuth))           ; Angles provided in CW units
  110. )      
  111.  
  112. (if (eq Verbose 1)
  113.   (progn
  114.         (prompt "\n  PosAngDir = ")(princ PosAngDir)
  115.         (prompt "  ZeroAngle = ")(princ ZeroAngle)(prompt " (")(princ (rtd ZeroAngle))(prompt " d)")
  116.         (prompt "  Azimuth = ")(princ Azimuth)(prompt " (")(princ (rtd Azimuth))(prompt " d)")
  117.         (prompt "  NewAzimuth = ")(princ NewAzimuth)(prompt " (")(princ (rtd NewAzimuth))(prompt " d)")
  118.         (princ)
  119.   )
  120. ) ; close if  
  121.  
  122. ; Get horizontal and vertica components of distance
  123. (setq DistH (* Dist (cos Inclination)))
  124. (setq DistV (* Dist (sin Inclination)))
  125.  
  126. ; Get point on plane, then add elevation
  127. (setq NewPoint2D (polar BasePoint NewAzimuth DistH))                                            ; Note: polar always used CCW and east=0.0 cartesian angles
  128. (setq NewPoint3D (list (car NewPoint2D) (cadr NewPoint2D) (+ (caddr NewPoint2D) DistV)))       
  129.  
  130. NewPoint3D
  131. )
  132.  
  133.  
  134. (defun RTD (A)
  135. ; Radians to Degrees
  136.         (* 180.0 (/ A pi))
  137. )
  138.  
  139. (defun DTR (A)
  140. ; Degrees to Radians
  141.         (* pi (/ A 180.0))
  142. )
  143.  
  144.  

Kirby, that's a good routine, and with all the comments and explanations it's gold for me, thanks man.



I have made something about this, long time ago...

https://www.gr-acad.com.br/pac/gr-pack-001.gif

(forgive me for my bad site, no time to improve it...)

that's pretty interesting, although my field is underground topography.

kirby

  • Newt
  • Posts: 131
Comments are over the top, but better more than less to help understand flow.