3D distance and angle.

Discussion in 'AutoCAD' started by BillZ, Jun 9, 2004.

  1. BillZ

    BillZ Guest

    If I have a basepoint at a 3d coordinate and I have another point in 3D space set to variables.
    Then I use:

    Command: (mapcar '- (nth 1 ptlist)(nth 0 ptlist))
    (0.224654 -0.270677 1.01018)

    to get the differences in xyz coordinates.

    What formulas do I use to get the 3d distance and angles from the base point to the point? Like the list command returns.

    TIA

    Bill
     
    BillZ, Jun 9, 2004
    #1
  2. BillZ

    BillZ Guest

    Got it:

    (setq p1 (mapcar '- (nth cnt ptlist) basepoint)
    ds1 (sqrt (+ (expt (car p1) 2)(expt (cadr p1) 2)))
    ds2 (sqrt (+ (expt ds1 2)(expt (caddr p1) 2))))

    Bill
     
    BillZ, Jun 9, 2004
    #2
  3. BillZ

    Devin Guest

    BillZ,

    The angle is something that's up to need, as there are three angles
    actually:

    1. from x plane
    2. from y plane
    3. from z plane

    Devin
     
    Devin, Jun 9, 2004
    #3
  4. BillZ

    BillZ Guest

    Hi Devin,
    Thanks.
    I was about to come looking for you. :)
    Looking at your axial_rotate program. Not sure I understand it completely.
    What I am trying to do is flatten a simple 3d mesh and keep the original shape and area of the segments..
    Thinking I can take some code from axial_rotate to bring each side of polygons flat, sort of like an unfld, but not having much luck.
    What I'm saying is, take a 3D mesh created with edgesurf and flatten but keep the integrity.
    Do you have anything like that?

    Thanks

    Bill
     
    BillZ, Jun 9, 2004
    #4
  5. BillZ

    Devin Guest

    BillZ,

    The axial_rotate was actually written by Domenico Maria Pisano. Quite
    brilliant too!

    The axial rotate is good if your actually rotating points along an arbitrary
    axis. What might be more efficient is a 3d rotation matrix transformation
    and translation.

    Let me get this straight. You've got a mesh (of any shape) and you simply
    want to rotate it to be generally oriented to the x-y plane?

    If the 3d mesh is bumpy and you want to flatten it like taking a crumpled up
    piece of foil and flattening it out to a flat sheet, then that's beyond what
    I've done (not that it can't be done and if that's the case perhaps I can
    help).

    But if it's a simple 3d rotation then that's pretty easy, please elaborate a
    little more so I can help with the procedural recommendations and code
    required.

    Is it a mesh enitity or a list of pts? and in what form?

    Devin
     
    Devin, Jun 9, 2004
    #5
  6. BillZ

    BillZ Guest

    Let me get this straight. You've got a mesh (of any shape) >>and you simply
    Devin,
    Let's start in the basement on this one. Just for starts, take a couple of triangles that exist in 3d space. They share one common side and 2 corner points but lay on two different planes.
    The question: How does one take all the points (vertices) of the 2 triangles and transform/orientate them to lay on the same plane and still define the same geometrical shape of the 2 triangles. This may not work for the "crumpled" piece of paper because I believe that then there would have to be a separating of sides in some cases (like a 3 sided pyrimid) to get it to flatten out. Eventually restaints would have to be built in as to what type of mesh would work but for now I would be satisfied with working out a formula that would work on a simple 2 or 3 sections of mesh.
    I have a program already that sets a variable to the points in the mesh. It also tells me the number of points in the m & n directions (these are controlled by the surftab1 & 2 variables during mesh creation).
    Yes, any shape of mesh but particularly a mesh of fours or so sides.
    I know there are some commercial programs out there that will do this unfolding to one extent or the other. I already have made one that works on simple flat sided (like a box) items.
    I want to do this in Autolisp/Vlisp so we can continue to develop this ourselves as time goes on.

    Thanks

    Bill
     
    BillZ, Jun 9, 2004
    #6
  7. BillZ

    Devin Guest

    BillZ,

    OK, we can do that (take two triangles and orient them on the same plane.
    What I have is a series of routines that create and work with ucs matrices.
    That would be the easiest way to do it. I do a similar thing myself.

    triangle delta = triangle you wish to change
    trangle base = trangle on desired plane

    1. First create a matrix aligned with the plane of triangle delta and the
    base edge along the line connecting both triangles
    2. transform triangle delta's points to the newly created matrix, just like
    (trans pt 0 1).
    3. now create a matrix aligned with the plane of triangle base and the base
    edge the same as before.
    4. transform triangle delta's points from the second newly created matrix,
    just like (trans pt 1 0)

    I use a program called (3pxa_matrix <origin> <xvector> <yvector> <angle>) to
    setup the matrix. Notice it's got an origin and an x direction and a y
    direction and also an angle along the origin-xvector edge. That angle is
    for tilting the plane up or down. Somply tilt it 180degrees to invert the
    plane. The origin and xvector should be the shared edge of the triangles
    and the yvector is always behind the edge.

    That procedure will pass the triangle, kinda like passing it through a
    dimensional door, from the plane of itself to the desired plane. Here are
    some routines to do that and I'll spell out just how later, but I have to
    leave for the day...

    (defun identity->matrix ( pt mat /
    px py pz #0 #1 #2
    #00 #01 #02 #03
    #10 #11 #12 #13
    #20 #21 #22 #23
    )
    (setq;extract pt
    px (car pt)
    py (cadr pt)
    pz (caddr pt)
    )
    (setq;extract matrix
    #0 (nth 0 mat) #1 (nth 1 mat) #2 (nth 2 mat)
    #00 (nth 0 #0) #01 (nth 1 #0) #02 (nth 2 #0) #03 (nth 3 #0)
    #10 (nth 0 #1) #11 (nth 1 #1) #12 (nth 2 #1) #13 (nth 3 #1)
    #20 (nth 0 #2) #21 (nth 1 #2) #22 (nth 2 #2) #23 (nth 3 #2)
    )
    (list;rotate pt
    (+ (* px #00) (* py #01) (* pz #02) #03)
    (+ (* px #10) (* py #11) (* pz #12) #13)
    (+ (* px #20) (* py #21) (* pz #22) #23)
    )
    )

    (defun matrix->identity ( pt mat /
    px py pz #0 #1 #2
    #00 #01 #02 #03
    #10 #11 #12 #13
    #20 #21 #22 #23
    )
    (setq;extract pt
    px (car pt)
    py (cadr pt)
    pz (caddr pt)
    )
    (setq;extract matrix
    #0 (nth 0 mat) #1 (nth 1 mat) #2 (nth 2 mat)
    #00 (nth 0 #0) #01 (nth 1 #0) #02 (nth 2 #0) #03 (nth 3 #0)
    #10 (nth 0 #1) #11 (nth 1 #1) #12 (nth 2 #1) #13 (nth 3 #1)
    #20 (nth 0 #2) #21 (nth 1 #2) #22 (nth 2 #2) #23 (nth 3 #2)
    )
    (setq;translate pt
    px (- px #03)
    py (- py #13)
    pz (- pz #23)
    )
    (list;rotate pt
    (+ (* px #00) (* py #10) (* pz #20))
    (+ (* px #01) (* py #11) (* pz #21))
    (+ (* px #02) (* py #12) (* pz #22))
    )
    )

    (defun mtrans ( pt from to / )
    (if
    ucs_matrix
    (cond
    (
    (and (= from 1) (= to 0))
    (identity->matrix pt ucs_matrix)
    )
    (
    (and (= from 0) (= to 1))
    (matrix->identity pt ucs_matrix)
    )
    (t nil)
    )
    pt
    )
    )

    (defun 3pxa_matrix ( origin xvector yvector xangle
    /
    -x org -y -z xo yo zo xx yx zx xy yy zy xz yz zz numx
    numy numz v a
    )
    (setq
    ;create new axis
    xangle (dtor (sign xangle))
    v (mapcar;magnify vector a factor of 100
    '(lambda (a)
    (* a 100.0)
    )
    (vector origin xvector)
    )
    yvector (vector_translate yvector v)
    -y (axial_rotate yvector 180d origin xvector)
    -x (axial_rotate origin 180d yvector -y)
    org (midpoint yvector -y)
    -y (axial_rotate -y xangle origin xvector)
    -z (axial_rotate -y 90d origin xvector)
    )
    (setq
    xo (car org)
    yo (cadr org)
    zo (caddr org)
    xx (car -x)
    yx (cadr -x)
    zx (caddr -x)
    xy (car -y)
    yy (cadr -y)
    zy (caddr -y)
    xz (car -z)
    yz (cadr -z)
    zz (caddr -z)
    numx (sqrt (+ (sqr (- xx xo)) (sqr (- yx yo)) (sqr (- zx zo))))
    numy (sqrt (+ (sqr (- xy xo)) (sqr (- yy yo)) (sqr (- zy zo))))
    numz (sqrt (+ (sqr (- xz xo)) (sqr (- yz yo)) (sqr (- zz zo))))
    v (vector (list 0.0 0.0 0.0) origin)
    ucs_matrix
    (list
    (list (/ (- xx xo) numx) (/ (- xy xo) numy) (/ (- xz xo) numz) (car
    v))
    (list (/ (- yx yo) numx) (/ (- yy yo) numy) (/ (- yz yo) numz) (cadr
    v))
    (list (/ (- zx zo) numx) (/ (- zy zo) numy) (/ (- zz zo) numz) (caddr
    v))
    (list 0.0 0.0 0.0 1.0)
    )
    ucs_matrix_array (vlax-tmatrix ucs_matrix)
    )
    ucs_matrix
    )

    (defun vector (v1 v2)
    (if
    (equal v1 v2 1e-10)
    (list 0.0 0.0 0.0)
    (mapcar '- v2 v1)
    )
    )

    (defun vector_translate (pt vec)
    (mapcar '+ pt vec)
    )

    (defun :VECTOR_2P (pt1 pt2 / )
    (if(equal pt1 pt2 1e-10)
    nil
    (mapcar (function (lambda (i j) (- j i))) pt1 pt2)
    )
    )



    (defun :ACOS (x1)
    ;
    (cond
    ((equal x1 -1.0 1e-06) (setq x1 -1.0) )
    ((equal x1 1.0 1e-06) (setq x1 1.0) )
    ((> x1 1.0) (setq x1 nil ) )
    ((< x1 -1.0) (setq x1 nil ) )
    )
    (if x1
    (atan (sqrt (- 1.0 (expt x1 2.0))) x1)
    nil
    )
    )


    (defun :VECTOR_SCALAR_PRODUCT (v1 v2)
    (+ (* (car v1)(car v2)) (* (cadr v1)(cadr v2)) (* (caddr v1)(caddr
    v2)) )
    )


    (defun :VECTOR_MODULE (v / X1 Y1 Z1)
    (setq x1 (car v) y1 (cadr v) z1 (caddr v) )
    (if (not z1) (setq z1 0.0))
    (sqrt (+ (* z1 z1) (* x1 x1) (* y1 y1) ) )
    )


    ; returns intenal angle (radiants) for 3 3d points
    (defun deflection ( p1 p2 p3 / )
    (rtod (- pi (angle3d p1 p2 p3)))
    )

    (defun angle3d (p1 px p3 / V1 V3)
    (setq v1 :)VECTOR_2P px p1))
    (if v1
    (setq v3 :)VECTOR_2P px p3))
    )
    (if v3
    (if (not (equal v1 v3 1e-12))
    :)ACOS
    (/
    :)VECTOR_SCALAR_PRODUCT v1 v3)
    (* :)VECTOR_MODULE v1) :)VECTOR_MODULE v3) )
    )
    )
    0.0
    )
    nil
    )
    )

    (defun :SQR (n)
    (if (> n 46340)
    (* (float n) n)
    (* n n)
    )
    )

    (defun list_axial_rotate ( pts angx p1 p2
    /
    CADDRP CADRP CARP COSA COSB COSC LEN LENXY
    N P PZ SINA SINB SINC oldpt
    )

    (setq
    *EPS10* 1.0e-010
    n :)VECTOR_2P p1 p2)
    lenxy (sqrt (+ :)SQR (car n)) :)SQR (cadr n))))
    )
    (if (> lenxy *EPS10*)
    (setq cosa (/ (car n) lenxy) sina (/ (cadr n) lenxy) )
    (setq cosa 1.0 sina 0.0 )
    )
    (setq
    len :)VECTOR_MODULE n)
    cosb (/ (caddr n) len)
    sinb (/ lenxy len)
    cosc (cos angx)
    sinc (sin angx)
    )
    (mapcar
    '(lambda (px)
    (setq
    p :)VECTOR_2P p1 px)
    carp (car p)
    cadrp (cadr p)
    caddrp (caddr p)
    px (+ (* cosa carp) (* sina cadrp))
    cadrp (+ (* sina -1.0 carp) (* cosa cadrp))
    carp px
    pz (+ (* cosb caddrp)(* sinb carp) )
    carp (+(* -1.0 sinb caddrp)(* cosb carp))
    caddrp pz
    px (-(* cosc carp) (* sinc cadrp))
    cadrp (+(* sinc carp) (* cosc cadrp))
    carp px
    pz (-(* cosb caddrp)(* sinb carp))
    carp (+(* sinb caddrp)(* cosb carp))
    caddrp pz
    px (-(* cosa carp)(* sina cadrp))
    cadrp (+(* sina carp)(* cosa cadrp))
    carp px
    )
    (list
    (+ carp (car p1))
    (+ cadrp (cadr p1))
    (+ caddrp (caddr p1))
    )
    )
    pts
    )
    )

    (defun axial_rotate ( px angx p1 p2
    /
    CADDRP CADRP CARP COSA COSB COSC LEN LENXY
    N P PZ SINA SINB SINC oldpt
    )

    (setq
    *EPS10* 1.0e-010
    n :)VECTOR_2P p1 p2)
    lenxy (sqrt (+ :)SQR (car n)) :)SQR (cadr n))))
    )
    (if (> lenxy *EPS10*)
    (setq cosa (/ (car n) lenxy) sina (/ (cadr n) lenxy) )
    (setq cosa 1.0 sina 0.0 )
    )
    (setq
    len :)VECTOR_MODULE n)
    cosb (/ (caddr n) len)
    sinb (/ lenxy len)
    cosc (cos angx)
    sinc (sin angx)

    p :)VECTOR_2P p1 px)
    carp (car p)
    cadrp (cadr p)
    caddrp (caddr p)
    px (+ (* cosa carp) (* sina cadrp))
    cadrp (+ (* sina -1.0 carp) (* cosa cadrp))
    carp px
    pz (+ (* cosb caddrp)(* sinb carp) )
    carp (+(* -1.0 sinb caddrp)(* cosb carp))
    caddrp pz
    px (-(* cosc carp) (* sinc cadrp))
    cadrp (+(* sinc carp) (* cosc cadrp))
    carp px
    pz (-(* cosb caddrp)(* sinb carp))
    carp (+(* sinb caddrp)(* cosb carp))
    caddrp pz
    px (-(* cosa carp)(* sina cadrp))
    cadrp (+(* sina carp)(* cosa cadrp))
    carp px
    )
    (list
    (+ carp (car p1))
    (+ cadrp (cadr p1))
    (+ caddrp (caddr p1))
    )
    )

    (defun midpoint ( p1 p2 / )
    (cond
    (
    (and
    (= (length p1) 3)
    (= (length p2) 3)
    )
    (list
    (/ (+ (car p1) (car p2)) 2.0)
    (/ (+ (cadr p1) (cadr p2)) 2.0)
    (/ (+ (caddr p1) (caddr p2)) 2.0)
    )
    )
    (
    (or
    (= (length p1) 2)
    (= (length p2) 2)
    )
    (list
    (/ (+ (car p1) (car p2)) 2.0)
    (/ (+ (cadr p1) (cadr p2)) 2.0)
    )
    )
    )
    )
     
    Devin, Jun 9, 2004
    #7
  8. BillZ

    Devin Guest

    BillZ,

    Let me know if some of the routines don't work. Some have internal
    functions used in them, I think I provided all the functions but I could be
    wrong. Anyways here's the actual code to do one triangle rotation...

    The following applies:
    1. triangle delta has pts list triang1 = '(a1 b1 c1)
    2. trangle base has pts list triang2 = '(a2 b2 c2)
    3. the common edge between both triangles is a-b

    ;align ucs to triangle delta but flip plane right side up 180 degrees
    (3pxa_ucs a1 b1 c1 180.0)
    ;translate triangle delta to new plane
    (setq triang1 (mapcar '(lambda (pt) (mtrans pt 0 1)) triang1))
    ;align ucs to triangle base with same origin as before
    (3pxa_ucs a2 b2 c2 0.0)
    ;translate triangle delta to WCS from new plane
    (setq triang1 (mapcar '(lambda (pt) (mtrans pt 1 0)) triang1))

    That should put triangle delta onto the same plane as triangle base.

    Let me know if you have any questions.

    Devin
     
    Devin, Jun 10, 2004
    #8
  9. BillZ

    BillZ Guest

    Devin,
    Thanks!
    It'll take me a while to chew through this.
    Are both triangles defined merely by a list of points?

    Bill
     
    BillZ, Jun 10, 2004
    #9
  10. BillZ

    Devin Guest

    BillZ,

    you'll also need two other internal functions I believe...

    (defun rtod ( ed_arg / )
    (*(/ (float ed_arg) pi) 180.0)
    )
    (defun dtor ( ed_arg / )
    (*(/ (float ed_arg) 180.0) pi)
    )

    The triangles should be points. Although if you have activex objects you
    could simply bypass the point manipulation and use (vla-transformby obj
    ucs_matrix_array) and that would simply replace the mtrans portion of the
    code. ucs_matrix_array is a global variable that is assigned an activex
    rotation matrix durring the function (3pxa_matrix).

    HTH,

    Devin
     
    Devin, Jun 10, 2004
    #10
  11. BillZ

    Devin Guest

    Sorry Bill,

    Please replace (3pxa_ucs) with (3pxa_matrix). I forgot I changed the
    function name.
     
    Devin, Jun 10, 2004
    #11
  12. BillZ

    BillZ Guest

    Devin,

    I take it 90d and 180d are variables set to angles in radians?

    I don't see them defined anywhere.

    Bill
     
    BillZ, Jun 10, 2004
    #12
  13. BillZ

    Devin Guest

    BillZ,

    Good catch, yes I have globally assigned the following...

    (setq
    0d 0.0
    45d (/ pi 4.0)
    90d (/ pi 2.0)
    180d pi
    270d (+ pi (/ pi 2.0))
    360d (* pi 2.0)
    2pi 360d
    )

    Devin
     
    Devin, Jun 10, 2004
    #13
  14. BillZ

    BillZ Guest

    Devin,

    I need a subr call SIGN

    Thanks

    Bill
     
    BillZ, Jun 10, 2004
    #14
  15. BillZ

    Devin Guest

    Here ya go...

    (defun sign ( arg_num / )
    (- 0.0 arg_num)
    )
     
    Devin, Jun 10, 2004
    #15
  16. BillZ

    BillZ Guest

    Devin,
    Seem like it's working.

    Basically you are getting the matrix of the base item and passing to the target item?

    I'll need to write some code now for putting entities into objects so they can be modified and then do some testing.

    Thanks Again.

    Bill
     
    BillZ, Jun 10, 2004
    #16
  17. BillZ

    BillZ Guest

    Thanks Devin,

    I also was missing another subr called SQR, is that the same as the :SQR subr used in axial_rotate?

    Bill
     
    BillZ, Jun 10, 2004
    #17
  18. BillZ

    Devin Guest

    it's simply...

    (defun sqr ( num ) (* num num))

    Sorry I'm just to lazy to write everything out like (* 2.45 2.45)

    :)
     
    Devin, Jun 10, 2004
    #18
  19. BillZ

    Devin Guest

    Bill.

    I'm glad I could help!

    Devin
     
    Devin, Jun 10, 2004
    #19
  20. BillZ

    BillZ Guest

    The following applies:
    Devin,
    I just want to clarify the steps in this proceedure.
    I have triangle "Base", drawn in WCS with corners defined as points '(a1 b1 c1).
    I also have triangle "Delta", drawn in another UCS but sharing one side with triangle Base and corners defined as '(a2 b2 c2).
    At this point I am in the WCS looking at the 2connected triangles that are drawn in 2 different UCS's. I have the coordinate lists of both triangles set to separate variables.
    Now if I feed the list of points of Base triangle to the function:
    (3pxa_matrix a1 b1 c1 180.0)
    I get a return of:
    ((0.866025 0.5 1.26319e-014 22.529) (0.5 -0.866025 0.0 12.0148) (1.21933e-016
    6.12303e-017 -1.0 0.0) (0.0 0.0 0.0 1.0))
    And when I feed the second set of points from triangle Delta I get:
    (3pxa_matrix a2 b21 c21 0.0)
    ((0.866025 0.247193 -0.434621 22.529) (0.5 -0.428151 0.752786 12.0148)
    (4.90169e-015 -0.869242 -0.494386 -2.77556e-015) (0.0 0.0 0.0 1.0))
    In the point lists: a1= a2 and b1= b2. but they are in different coordinate system.
    (I have tired it both ways converting the point list of Delta with the trans function to convert the points to the WCS.)
    I am confused on what to do next. I tried taking the second return list (same as ucs_matrix) and:
    (setq newmat (vlax-tmatrix return_from_delta))
    (vla-transformby rec_2 newmat) ;rec_2 is vlaobj of delta
    but is just moves delta to another location on the screen.
    I think I am missing something because it that is all there is too it, why did I get the first return from (3pxa_matrix a1 b1 c1 180.0)?
    Thanks for any help.

    Bill
     
    BillZ, Jun 11, 2004
    #20
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.