Jump to content

find maximum slop in 3d face


motee-z

Recommended Posts

Hello friends

i want to find the maximum slope in a 3d face (this 3d face) consist of 3 points with different z value

is this possible 

thanks

Link to comment
Share on other sites

The slope of of the plan defined by 3 distinct, non collinear points.

(defun 3dface_slope (p1 p2 p3 / n)
  (setq n (v*v
            (v-v p1 p2)
            (v-v p1 p3)
          )
  )
  (atan
    (distance '(0 0) n)
    (abs (caddr n))
  )
)

 ;Vectors and matrices function
 ;Stefan M. 17.11.2013
 (defun v-v (u v) (mapcar '- u v))                    ;subtract 2 vectors
 (defun v*v (a b)                                     ;cross product
    (list
      (- (* (cadr  a) (caddr b)) (* (caddr a) (cadr  b)))
      (- (* (caddr a) (car   b)) (* (car   a) (caddr b)))
      (- (* (car   a) (cadr  b)) (* (cadr  a) (car   b)))
    )
  )

 

Edited by Stefan BMR
small simplification
Link to comment
Share on other sites

Here's my primitive attempt.

(defun c:FaceSlope (/)
  (princ "\nPlease select 3DFACE and press ENTER.")
  (setq	ss    (ssget)
	en    (ssname ss 0)
	edata (entget en)
  )
  (if (= (cdr (assoc 0 edata)) "3DFACE")
    (progn
      (setq p1 (cdr (assoc 10 edata))	;set p1, p2, p3 to the three vertices of the 3DFACE
	    p2 (cdr (assoc 11 edata))
	    p3 (cdr (assoc 12 edata))
      )
      (setq normal (cross (mapcar '- p2 p1) (mapcar '- p3 p1)))
      (setq v1 (cross '(0.0 0.0 1.0) normal))
      (setq sv (cross v1 normal))
      (setq a (expt (+ (expt (car sv) 2) (expt (cadr sv) 2)) 0.5))
      ;; check if a = 0
      (if (< (abs a) 0.00001 )
	(setq slope "Vertical")
	(setq slope (/ (caddr sv) a))
      )
      (princ "\nThe slope is: ")
      (princ slope)
    )					;end true if
  )					; end if
  (princ)
)

;;; Compute the cross product of 2 vectors a and b
(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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

Link to comment
Share on other sites

The other way is to take P1 and get closestpoint P4 to P2-P3 then get slope of P1-P4.

 

Repeat for P2 & P3 keeping answer compare a abs of slope. This way if -ve is ok.

 

As its faces will need a line or ray to be calculated.

 

Cal(p1,p2,p3) maybe ? 

 

>> Expression: nor(p1,p2,p3)
0.707106781,-0.707106781,0
 

Edited by BIGAL
Link to comment
Share on other sites

  • 2 weeks later...

Hello  friends 

sorry for delaying 

thank you for replying 

i did't get what i want exactly 

Mr Irm

can you add a vector in the direction of maximum slope on the 3dface

because you calculate the value but in unknown place

thanks

 

Link to comment
Share on other sites

Here's a revised version of the program. It outputs a unit vector of the maximum slope and draws a line from the center of the face in the direction of the maximum slope.  The length of the line is the average length of the sides of the face.

 

;; Determine the maximum slope of a 3dface.
;; 7/11/2020
(defun c:FaceSlope (/ ss en edata p1 p2 p3 v1 sv a slope midpt s endpt)
  (setq oldsnap (getvar "osmode"))
  (setvar "osmode" 0)

  (princ "\nPlease select 3DFACE and press ENTER.")
  (setq	ss    (ssget)
	en    (ssname ss 0)
	edata (entget en)
  )
  (setvar "cmdecho" 0)
  (if (= (cdr (assoc 0 edata)) "3DFACE")
    (progn
      (setq p1 (cdr (assoc 10 edata))	;set p1, p2, p3 to the three vertices of the 3DFACE
	    p2 (cdr (assoc 11 edata))
	    p3 (cdr (assoc 12 edata))
      )
      (setq normal (cross (mapcar '- p2 p1) (mapcar '- p3 p1)))
      (setq v1 (cross '(0.0 0.0 1.0) normal))
      (setq sv (cross v1 normal))
      (setq a (distance '(0 0 0) sv))
      (setq sv (mapcar '/ sv (list a a a)))
      (setq a (expt (+ (expt (car sv) 2) (expt (cadr sv) 2)) 0.5))
      ;; check if a = 0
      (if (< (abs a) 0.00001)
	(setq slope "Vertical")
	(setq slope (/ (caddr sv) a))
      )
      (princ "\nThe slope is: ")
      (princ slope)
      (princ "\nThe slope vector is: ")
      (princ sv)

      (setq midpt (mapcar '/ (mapcar '+ p1 p2 p3) '(3.0 3.0 3.0)))
      (setq s (+ (distance p1 p2) (distance p2 p3) (distance p1 p3)))
      (setq endpt (mapcar '+ midpt (mapcar '* sv (list s s s))))
      (command "_line" midpt endpt "")  ;; draw line showing maximum slope
    )					;end true if
    (princ "\nSelected object must be a face.")
  )					; end if
  (setvar "osmode" oldsnap)
  (setvar "cmdecho" 1)
  (princ)
)
;;; Compute the cross product of 2 vectors a and b
(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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 

Link to comment
Share on other sites

Thank you Mr Irm for your routine 

it is excellent but if you print slop value on the line that indicates the direction

 

Link to comment
Share on other sites

@motee-z

You are welcome.

Are you asking for text to be added to the drawing that contains the numerical value of the slope or do you want the unit vector values? Should the text align with the slope line or the XY world plane or something else?  The more specific you are in specifying what you want the more likely the results will meet your needs.

 

Link to comment
Share on other sites

i want the numerical  value text of the slope to be aligned with the slope line drawn by the lisp.

thanks

 

Edited by motee-z
Link to comment
Share on other sites

lrm, a 3dface has always 4 points, even if it looks like a  triangle. In this case, 2 points are coincidental and the 4th point is not necessary one of them. So the points you need are not always dxf 10, 11 and 12.

Try it on this object:

(entmakex
  '((0 . "3DFACE")
    (10 0.0 0.0 0.0)
    (11 2.0 0.0 0.0)
    (12 2.0 0.0 0.0)
    (13 1.0 2.0 2.0)
   )
)

 

Edited by Stefan BMR
Link to comment
Share on other sites

@Stefan BMR yes, I realize that a face has 4 points.  It is likely, but not guaranteed,  that the first three are the ones that are being used to define the flat plane of interest to the user. I did not idiot proof the code (not a good idea) and assumed the first three points are the ones to use.  My main goal was to find the maximum slope and simplify the coding with some basic assumptions.  Feel free to edit my code to handle invalid faces.

Link to comment
Share on other sites

@motee-z

"i want the numerical  value of the slope to be aligned with the slope line drawn by the lisp."

 

That reduces the orientation to an infinity of choices as the text could be rotated about the slope line and still be aligned with it!  Should I assume you do not care which one is used?

Link to comment
Share on other sites

24 minutes ago, lrm said:

.... Feel free to edit my code to handle invalid faces.

No, thanks, I don't need it.. I just wanted to point out that you will get an error eventually.

It's your decision, and your time, if you want to add it to your code or not.

Link to comment
Share on other sites

Whilst civ3d has slope arrow I dont think you can add a slope text as a surface style. But it is useful to test against a series of 3dfaces can compare result lisp versus arrow. I still think the nor (p1,p2,p3) is useful just not sure how to interpret the x y z compared to (0 0 0)  

 ang1=nor(p1,p2,p3)

(angle '(0. 0. 0.) ang1)

 

Link to comment
Share on other sites

@motee-z

 

Here's a revised version that adds text to the face with the slope value.  It also checks that the firsts 3 vertices of the face are not duplicates.  It does not check to see if they are collinear.

 

;; Determine the maximum slope of a 3dface.
;; 7/13/2020
(defun c:FaceSlope (/ ss en edata p1 p2 p3 v1 sv a slope midpt s endpt)
  (setq oldsnap (getvar "osmode"))
  (setvar "osmode" 0)
  (princ "\nPlease select 3DFACE and press ENTER.")
  (setq	ss    (ssget)
	en    (ssname ss 0)
	edata (entget en)
  )
  (setvar "cmdecho" 0)
  (if (= (cdr (assoc 0 edata)) "3DFACE")
    (progn
      (setq p1 (cdr (assoc 10 edata))	;set p1, p2, p3 to the three vertices of the 3DFACE
	    p2 (cdr (assoc 11 edata))
	    p3 (cdr (assoc 12 edata))
      )
      (if (or (equal p1 p2 0.0001)
	      (equal p1 p3 0.0001)
	      (equal p3 p2 0.0001)
	  )
	(princ "\nThe first 3 vertices of the face are not unique.")
	(progn
	  (setq normal (cross (mapcar '- p2 p1) (mapcar '- p3 p1)))
	  (setq v1 (cross '(0.0 0.0 1.0) normal))
	  (setq sv (cross v1 normal))
	  (setq a (distance '(0 0 0) sv))
	  (setq sv (mapcar '/ sv (list a a a)))
	  (setq a (expt (+ (expt (car sv) 2) (expt (cadr sv) 2)) 0.5))
	  ;; check if a = 0
	  (if (< (abs a) 0.00001)
	    (setq slope "Vertical")
	    (setq slope (/ (caddr sv) a))
	  )
	  (princ "\nThe slope is: ")
	  (princ slope)
	  (princ "\nThe slope vector is: ")
	  (princ sv)

	  (setq midpt (mapcar '/ (mapcar '+ p1 p2 p3) '(3.0 3.0 3.0)))
	  (setq
	    s (/ (+ (distance p1 p2) (distance p2 p3) (distance p1 p3)) 3.0)
	  )
	  (setq endpt (mapcar '+ midpt (mapcar '* sv (list s s s))))
	  (command "_line" midpt endpt "")
	  ;; draw line showing maximum slope

	  (setq slope (LM:roundto slope 3))
	  (command "text" midpt "" "" slope "")
	)				; end if false, no duplicates
      )					;end true, is face 
    )					; end if duplicate
       (princ "\nSelected object must be a face.")
 )					; end if face
  (setvar "osmode" oldsnap)
  (setvar "cmdecho" 1)
  (princ)
)
;;; Compute the cross product of 2 vectors a and b
(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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Round Multiple  -  Lee Mac
;; Rounds 'n' to the nearest multiple of 'm'
(defun LM:roundm (n m)
  (* m (atoi (rtos (/ n (float m)) 2 0)))
)
;; Round To  -  Lee Mac
;; Rounds 'n' to 'p' decimal places
(defun LM:roundto (n p)
  (LM:roundm n (expt 10.0 (- p)))
)

 

  • Thanks 1
Link to comment
Share on other sites

Had a look in CIV3d the display slope and your code look like they match, well done. The slope in CIV3d has a rainbow as its variation in slope.

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...