How to add point to a surface and detect Z coordinates?

How to add point to a surface and detect Z coordinates?

jiahao.billy
Participant Participant
1,208 Views
13 Replies
Message 1 of 14

How to add point to a surface and detect Z coordinates?

jiahao.billy
Participant
Participant

Hello,

I have surveyor drawings come back to me with a modelled topography in AutoCAD. They do give me some points to show the level of the ground (height above sea). 

jiahaobilly_0-1670902997019.png

jiahaobilly_1-1670903023033.png

jiahaobilly_2-1670903193045.png

 

 

The numbers in white are the levels done by the surveyor. The green Web is the 3D topography done accurately by the surveyor. The point they plot are EXACTLY the Z coordinates, eg, 24.05m above sea level on site is exactly Z = 24.05

 

Is there a way for me to plot directly onto the topo surface and get the exact Z coordinate?

I have tried multiple methods, including making/using Z coordinate annotation blocks. They fail me when I use them on other projects.

 

Is there a .lisp available for these type of situations? 

 

Thanks in advance.

 

0 Likes
Accepted solutions (1)
1,209 Views
13 Replies
Replies (13)
Message 2 of 14

imadHabash
Mentor
Mentor

Hi,

Honestly i did not catch your point !! Would you please clarify more your exact need ?

 

Imad Habash

EESignature

0 Likes
Message 3 of 14

Pointdump
Consultant
Consultant

Hi Billy,
If I understand you correctly, what you want is spot elevation labels. Or do you just want to see elevations as you hover your mouse over the surface? That is exactly what Civil 3D is designed to do. What version of AutoCAD do you have?
Dave

 

Z_Hover_1.png

 

Dave Stoll
Las Vegas, Nevada

EESignature

64GB DDR4 2400MHz ECC SoDIMM / 1TB SSD
NVIDIA Quadro P5000 16GB
Windows 10 Pro 64 / Civil 3D 2025
0 Likes
Message 4 of 14

tramber
Advisor
Advisor

I would make a tool in the tool palette :

tramber_0-1670918791009.png

 

And i would use this old fashion CAL, may i say 'CAL

5 clics to go dans it is done.

NB : you don't see the osnaps but it works 😉

 

'cal;ilp(end,end,end,end,end);

 

 

tramber_1-1670919001845.png

 

tramber_2-1670919009472.png

 

tramber_3-1670919019933.png

 

You can build modern surface, transforming a 3Dface (easy) and finding an interference, etc, but i like those old tools, it is strongeur than me.

Have a look on CAL function and its ilp(p1,p2,p3,p4,p5) option 😎

 


EESignature

0 Likes
Message 5 of 14

tramber
Advisor
Advisor

OUPSSS !

Sorry... replace EXT with END, English version ! I did it in the message. Should be possible with _END too.

I am checking


EESignature

0 Likes
Message 6 of 14

jiahao.billy
Participant
Participant

Hello, sorry for the bad English, not my strong language 😞

So in short, I want to find the Z coordinate on any point of the 3D surface. How am I able to plot this point on the surface with annotations suggesting the Z coordinates?

Thank you

0 Likes
Message 7 of 14

jiahao.billy
Participant
Participant
Hi,
I would want both functions if possible so I can share around the information.
We only have AutoCAD 2020 from the company.
0 Likes
Message 8 of 14

jiahao.billy
Participant
Participant
Hi thanks for the help!
Sorry I am a bit new to AutoCAD and is confused on where I could create this tool in the tool palette. Do I select the 3D face when creating the tool?
0 Likes
Message 9 of 14

tramber
Advisor
Advisor

You will see for the button when you will be able to understand !

 

You need to invoque a command like LINE or whatever asking for a point.

Then call 'CAL (' allows what we call the "transparency", write 'CAL and not CAL)

And write your own ILP

https://knowledge.autodesk.com/support/autocad/learn-explore/caas/CloudHelp/cloudhelp/2019/ENU/AutoC...

So you see if it works and if it is convenient. It is an old fashioned solution with no lisp or construction.

ilp(end,end,end,end,end);

 

Then you will help you making a button 😉

(My variable INPUTHISTORYMODE is set to 0 so that i can call and call again what was written by me with the up arrow of the keyboard. In other words i can test this formula easily many times be "re"-calling it several times.)


EESignature

0 Likes
Message 10 of 14

leeminardi
Mentor
Mentor
Accepted solution

@jiahao.billy   I thought I would try to reproduce with VLISP the Civil 3D program feature of being able to pick points on  a TIN and get the spot elevation.

 

The following program enables you to add points and elevation values at picked locations on a collection of 3DFACEs.   The program prompts you to select a collection of 3DFACEs and then the user can pick any point to add a point on a 3DFACE with text that notes its elevation. 

 

In writing the program I needed a routine to determine if a point was within the bounds of a triangle. I could not find any that I liked so I wrote my own.  At first I thought it necessary to determine if a point was outside, on a triangle vertex, triangle edge, or fully within the bounds of the triangle.  I later determined that the point on an edge distinction was not necessary.  As a result there are unnecessary elements still in the code related to edge detection.  The program could be more made more efficient but some testing indicates that it is very reliable.  One major assumption that could affect results is  that the first three vertices of a 3DFACE are used to determine its geometry. The code could be modified to look at all four 3DFACE vertices to determine which three form a true triangle.

 

Here's a sample of the output.

 

leeminardi_0-1671376889376.png

; Working in the top view, a user specifies a point location which is then
; projected to a 3DFACE above it. A point, and text of the z value, is added
; on the 3DFACE. One or more 3DFACES may be used to define the surface.
;
; L. Minardi 12/18/2022
		
(defun c:SpotElev (/ ss numsel i pt ed pt1 pt2 pt3 w ElevText )
(setup)
(princ "\nSelect one or more 3DFaces.")
(setq ss (ssget '((0 . "3dface"))))
(setq numsel (sslength ss))  
(setq i 0)
(setq pt (getpoint "\nEnter a point from the top view."))  
(while (< i numsel)
  (setq	ed  (entget (ssname ss i))
	pt1 (cdr (assoc 10 ed))		;get points of 3DFACE from entity data
	pt2 (cdr (assoc 11 ed))
	pt3 (cdr (assoc 12 ed))
	;  pt4  (cdr (assoc 13 ed))
  )
  (setq w (PtInTriangle pt1 pt2 pt3 pt)) ; Determine if point is inside current 3DFACE
  (cond
    ((= w 0) (setq i (1+ i)))		; point outside triangle
    ((= w 1) (setq PtOnFace (FullyInside)))
    ((= (car w) 2) (setq PtOnFace (cadr w))) ; point at 3DFACE vertex
    ((= (car w) 3) (setq PtOnFace (FullyInside)))
  )					; end cond
  (if (and (= w 0) (= i numsel))
    (progn
      (princ "\nNo intersection with a 3DFACE.")
      (setq pt (getpoint "\nEnter another point over a 3DFACE or [ENter] to exit.")
            i	 0
      )
  )
  )
  (if (/= w 0)
    (progn
      (setq ElevText (rtos (caddr PtOnFace)))
      (command "_point" ptOnFace)
      (command "_text" "J" "BL" ptOnFace "" "" ElevText)
      (setq pt (getpoint "\nEnter another point or [Enter] to exit.")
            i   0
      )
      (if (= pt nil) (setq i numsel))  ; quit
    )
 )
) ; end while
  (cleanup)
  (princ)
)					;end qq

(defun FullyInside ( / )
      (setq v12	(mapcar '- pt2 pt1)
	    b	(distance '(0. 0. 0.) v12)
      )
      (if (equal b 0.0 0.00001)
	(setq u12 '(0. 0. 0.))
	(setq u12 (mapcar '/ v12 (list b b b)))
					; unit vector from pt1 to pt2
      )
      (setq vn	(cross u12 (mapcar '- pt3 pt1))
	    b	(distance '(0 0 0) vn)
	    uvn	(mapcar '/ vn (list b b b))
					; unit normal vector to face
      )
      (if (< (dot uvn '(0 0 1)) 0)
	(setq uvn (mapcar '* uvn '(-1 -1 -1)))
					; make sure normal vector z component points up
      )
      (setq d (dot (mapcar '- pt1 pt) uvn))
      (setq magvz (/ d (caddr uvn)))	; z coordinate of point on face
      (setq
	ptOnFace (mapcar '+ pt (mapcar '* '(0 0 1) (list 0 0 magvz)))
      )					; point on face
)

; Determine if point pt is inside triangle defined by
; points pt1 pt2 pt3
; Returns
; 0 : if point outside triangle
; 1 : if point fully inside triangle
; 2 and point  ; if point at triangle  vertex
; 3 and two points ; if point on edge between the two points  
; L. Minardi 12/14/2022
(defun PtInTriangle (pt1 pt2 pt3 pt / ptfarright ptfarleft i j )
(setq i	0 j 0 )
(setq ptfarright (list 1000000.0 (cadr pt))
      ptfarleft	 (list -1000000.0 (cadr pt))
)
(if (inters PT ptfarright PT1 PT2)
  (setq i (1+ i))
)
(if (inters PT ptfarright PT2 PT3)
  (setq i (1+ i))
)
(if (inters PT ptfarright PT3 PT1)
  (setq i (1+ i))
)
(if (inters PT ptfarleft PT1 PT2)
  (setq j (1+ j))
)
(if (inters PT ptfarleft PT2 PT3)
  (setq j (1+ j))
)
(if (inters PT ptfarleft PT3 PT1)
  (setq j (1+ j))
)

(cond ((or				; if outside set w = 0
	 (and (= i 0) (= j 0))
	 (and (= i 2) (= j 0))
	 (and (= i 0) (= j 2))
       )
       (setq w 0)  ; point is OUTSIDE
      )					

      ((equal pt1 pt 0.01)		; if at vertex set w = 2 and point
       (setq w (list 2 pt1))
      )
      ((equal pt2 pt 0.01)
       (setq w (list 2 pt2))
      )
      ((equal pt3 pt 0.01)
       (setq w (list 2 pt3))
      )
      (setq w 1)
;;;;;;      ((PtsInLine pt1 pt2 pt)  ; if on edge set w = 3 and two points
;;;;;;       (setq w (list 3 pt1 pt2)))
;;;;;;      ((PtsInLine pt2 pt3 pt)
;;;;;;       (setq w (list 3 pt2 pt3)))
;;;;;;      ((PtsInLine pt3 pt1 pt)
;;;;;;       (setq w (list 3 pt3 pt1)))
;;;;;;      ((or (= i 1) (= j 1)) (setq w 1)) ; if interior set w = 1
)
  )

(defun setup (/)
  (setq osm (getvar "osmode"))
  (setvar "osmode" 0)
  (setvar "cmdecho" 0)
  (command "UCS" "W")
)					;end setup

(defun cleanup (/)
  (setvar "osmode" osm)
  (setvar "cmdecho" 1)
  (princ)
)					;end cleanup

; cross product
(defun cross (a b / crs)
  (setq	crs (list
	      (- (* (nth 1 a) (nth 2 b))
		 (* (nth 1 b) (nth 2 a))
	      )
	      (- (* (nth 0 b) (nth 2 a))
		 (* (nth 0 a) (nth 2 b))
	      )
	      (- (* (nth 0 a) (nth 1 b))
		 (* (nth 0 b) (nth 1 a))
	      )
	    )				;end list
  )					;end setq c
)					;end cross

; dot product
(defun dot (a b / dd)
  (setq dd (mapcar '* a b))
  (setq dd (+ (nth 0 dd) (nth 1 dd) (nth 2 dd)))
)					

;  unit vector
(defun unitv (v / d)
  (setq d (distance '(0 0 0) v))
  (if (equal d 0.0 1e-9) nil (mapcar '/ v (list d d d)))
)

; Determines if 3 points are in a line, nil if not
(defun PtsInLine (p1 p2 p3 / a)
 (setq ans (abs (dot (unitv (mapcar '- p1 p2)) (unitv (mapcar '- p1 p3)))))
  (if (equal (abs (dot (unitv (mapcar '- p1 p2)) (unitv (mapcar '- p1 p3)))) 1.0 1e-9)
    (setq a 1)
    (setq a nil)
  )
)


lee.minardi
0 Likes
Message 11 of 14

jiahao.billy
Participant
Participant

Thank you! 

This worked perfectly!

 

I would first have to EXPLODE my topo plans before I could detect the faces.

I had a look at the code and I couldn't fully understand the magic behind it. Hopefully I'll learn it in the years to come 🙂 

 

0 Likes
Message 12 of 14

jiahao.billy
Participant
Participant

Thank you!

 

Sorry for the late reply, was away on holiday 🙂

I have tested this this morning, seems to be working but requires me to be in 3D View.

 

@leeminardi has made a VLISP which reproduces the Civil 3D program feature of being able to pick points on a TIN and get the spot elevation.

 

Thanks again for the help!

 

 

 

0 Likes
Message 13 of 14

leeminardi
Mentor
Mentor

@jiahao.billy you are welcome.

 

You said "...but requires me to be in 3D View".   It works fine for me when picking points in the top view and the WCS is acrive.   I don't know what you mean by "3D View".

lee.minardi
0 Likes
Message 14 of 14

jiahao.billy
Participant
Participant

Ah sorry, I was replying to @tramber about his method of plotting the points for Z axis.

His method requires me to be in a 3D view instead of 'top view'

 

Apologies for confusion, I come from Rhino so my head isn't getting around AutoCAD terminology 

0 Likes