scale point list

Discussion in 'AutoCAD' started by Joe Burke, Jun 1, 2004.

  1. Joe Burke

    Joe Burke Guest

    There's probably an easier method... ?

    Joe Burke

    ;; arguments:
    ;; ptlst - point list
    ;; bp - base point
    ;; scale - scale factor
    (defun ScalePts (ptlst bp scale / veclst sclst)
    ;if single point passed
    (if (atom (car ptlst))
    (setq ptlst (list ptlst))
    )
    ;subtract base point from each point in ptlst
    ;return list of vectors
    (setq veclst
    (mapcar '(lambda (p) (mapcar '- p bp)) ptlst)
    )
    ;multiply each vector by scale
    ;return list of scaled vectors
    (setq sclst
    (mapcar '(lambda (v) (mapcar '(lambda (x) (* scale x)) v)) veclst)
    )
    ;add base point to each scaled vector
    ;return scaled point list
    (mapcar '(lambda (v) (mapcar '+ v bp)) sclst)
    ) ;end

    ;; example
    Command: (ScalePts '((20 20 0) (30 30 0) (25 5 2)) '(2 2 0) 3)
    ((56 56 0) (86 86 0) (71 11 6))
     
    Joe Burke, Jun 1, 2004
    #1
  2. Joe Burke

    ECCAD Guest

    Joe,
    I don't know where you are going here..but you could gather
    the 'points' with ssget and pick windows, filtering 'POINT'..then feed this list in as ptlst, rather than type it in ?

    Bob
     
    ECCAD, Jun 1, 2004
    #2
  3. Joe Burke

    Joe Burke Guest

    Hi Bob,

    It assumes a point list in-hand by whatever means. The example just demonstrates the
    function works as is.

    You know, sometimes you have a gut feeling you've taken the long way around solving
    something. Can't see the forest for the trees. I'm just wondering if there's a more
    elegant solution.

    Thanks
    Joe Burke


    as ptlst, rather than type it in ?
     
    Joe Burke, Jun 1, 2004
    #3
  4. There's no easier method, but I'll guess that this
    might be a tad more efficient on larger lists, as
    it avoids intermediate assignment/copying.

    (defun scalePoints (plist bp scale / scalar)
    (setq scalar (list scale scale scale))
    (mapcar
    '(lambda (pt)
    (mapcar '+ bp
    (mapcar '* scalar
    (mapcar '- pt bp)
    )
    )
    )
    (if (atom (car plist))
    (list plist)
    plist
    )
    )
    )


    --
    http://www.caddzone.com

    AutoCAD based Security Planning Solutions:
    http://www.caddzone.com/securityplanning

    AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005
    http://www.acadxtabs.com
     
    Tony Tanzillo, Jun 1, 2004
    #4
  5. Joe Burke

    Joe Burke Guest

    Hi Devin,

    Thanks for the compliment and suggestion.

    Polar would work when all points have the same Z value.
    Command: (Scalepts '(2 2 0) 3 '((20 20 0) (30 30 0) (25 5 0)))
    ((56.0 56.0 0.0) (86.0 86.0 0.0) (71.0 11.0 0.0))

    But with the original example:
    Command: (Scalepts '(2 2 0) 3 '((20 20 0) (30 30 0) (25 5 2))) ;Z value
    ((56.0 56.0 0.0) (86.0 86.0 0.0) (71.256 11.0334 0.0))

    Should be: ((56 56 0) (86 86 0) (71 11 6))

    Of course you knew that. :)

    Joe Burke
     
    Joe Burke, Jun 2, 2004
    #5
  6. Joe Burke

    Joe Burke Guest

    Tony,

    Thanks for the lesson. I tried to do something like that, but couldn't figure it out.

    Joe Burke
     
    Joe Burke, Jun 2, 2004
    #6

  7. I'd do this another way:

    (defun plus (v1 v2)
    (mapcar (function +) v1 v2))

    (defun minus (v1 v2)
    (mapcar (function -) v1 v2))

    (defun scale-vector (vector scale)
    (mapcar (function (lambda (x) (* scale x)))
    vector))

    (defun scale-points (points base scale)
    (if (atom (car points))
    (setq points (list points)))

    (mapcar
    (function
    (lambda (point)
    (plus base (scale-vector (minus point base)
    scale))))
    points))


    Not necessarily any easier, but the low-level tools would be usable
    elsewhere, too.

    --
     
    Martti Halminen, Jun 2, 2004
    #7
  8. <IMHO>

    This is fine, but I don't think we can call
    these 'low-level' tools.

    They're really just abstractions of what are
    already relatively simple expressions. They
    do serve to make code more self-descriptive,
    which is not a bad thing, but I don't think
    they serve the goal of well-structured code
    modularity all that well.

    In fact, if this degree of abstraction were
    applied universally on a larger scale, there
    could be some penalty from so many additional
    layers of function calls.

    I've always tried to strike a reasonable
    balance in my code, serving modularity;
    clarity; and performance. To that end, I
    generally don't carry abstraction to this
    extent but of course, to each his own.

    I've long since chosen to go the C++ or Object
    Pascal route for performance-critical code,
    which is the great thing about AutoCAD. You
    have many levels on which to operate, each
    having its own strengths and drawbacks.

    </IMHO>

    --
    http://www.caddzone.com

    AutoCAD based Security Planning Solutions:
    http://www.caddzone.com/securityplanning

    AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005
    http://www.acadxtabs.com
     
    Tony Tanzillo, Jun 2, 2004
    #8
  9. Joe Burke

    Steve Doman Guest

    Looks good Joe. Nice use of Atom and Mapcar. Easy to read too.

    Steve Doman
     
    Steve Doman, Jun 2, 2004
    #9
  10. Joe Burke

    Devin Guest

    Right, yours is the mathematically correct method. I guess it depends on if
    your doing 3d with it or not, most of my functions are 2d into 3d so I don't
    usually think that way. I work on a 2d plane then transform the plane into
    3d. Your method reminds me of the methods used in rotating points along an
    arbitrary axis in 3d. It's got the same type of method.

    Devin
     
    Devin, Jun 2, 2004
    #10
  11. Joe Burke

    Joe Burke Guest

    Hi Steve,

    Tony's solution blows me away. So what else is new? ;-)

    BTW, thanks for your help back when. I guess you know what I mean.

    Joe
     
    Joe Burke, Jun 2, 2004
    #11
  12. Joe Burke

    Joe Burke Guest

    Devin,

    I know you are into this kind of stuff. How about an example of how you would do it?
    I'm more interested in theory than efficient code.

    Thanks
    Joe Burke
     
    Joe Burke, Jun 2, 2004
    #12
  13. Joe Burke

    Devin Guest

    Joe,

    I build sheet metal and panelling fabrication design systems. I orient a
    ucs onto a plane and then I perform operations into that plane. Then when
    I'm done I transform my modifications back to the WCS and store them in a
    panel database system. I find that it's easier to work with UCS
    construction planes than with arbitrary coordinates.

    I'm certainly open to discuss further. I can't share all of my code though
    as it's proprietary to my company. But I can surely discuss theory with you
    and it would be my pleasure.

    Devin
     
    Devin, Jun 2, 2004
    #13
  14. Joe Burke

    Joe Burke Guest

    Devin,

    I need to think on this a bit. I'll get back to you soon.

    Joe Burke
     
    Joe Burke, Jun 3, 2004
    #14
  15. Joe Burke

    Joe Burke Guest

    Hi Devin,

    Thinking on it didn't help much.

    I'll just ask this. Given my example point list in the first message. Would you
    prefer to align a UCS to the three points (one has a Z value other than zero) and
    then use the polar based function you posted to scale the point list? If so, then you
    would trans the UCS points returned back to WCS?

    I've never tried to deal with these kinds of issues that way. So I'm trying to
    understand what the advantages might be. My gut feeling is it seems like the long way
    around. For instance you mentioned, "arbitrary coordinates". Seem to me that's what a
    UCS is, compared to WCS. And you can't directly feed the result of a UCS based
    calculation to entmake or some Add object method.

    Please know, I don't mean to imply one method is better than the other. But I do
    think, and I might be wrong, that all operations similar to this example can be done
    using WCS coordinates. Which in turn results in less trans complexity.

    Thanks for any thoughts... :)
    Joe
     
    Joe Burke, Jun 3, 2004
    #15
  16. Joe Burke

    Devin Guest

    Joe,

    We can talk further, but I think I found a better solution to your problem.
    Try working on the vector elements themselves instead of the vector as a
    whole, that should be the most efficient method, ie:

    (defun scalepts (plst bp scl / )
    (if
    (atom (car plst))
    (setq plst (list plst))
    )
    (mapcar
    '(lambda (pt)
    (mapcar
    '(lambda (ptelem orelem)
    (+ (* (- ptelem orelem) scl) orelem)
    )
    pt bp
    )
    )
    plst
    )
    )

    And excuse me if someone's already posted this solution. But try it out and
    let me know, as I haven't tested it yet.

    HTH,

    Devin
     
    Devin, Jun 3, 2004
    #16
  17. Joe Burke

    Devin Guest

    Joe,

    Now to answer your thread. It all depends on what it is you're doing. If
    scaling of pts from a base in a 3d magnitude is the only operation that
    you're doing to those pts then yes the mathematic scaling is best. But, in
    what I do, I have to create a construction plane and then perform various
    operations to that plane. Creating a construction plane is alot less of a
    headache then working in absolute (sorry, not arbitrary, my bad :)
    coordinates (WCS).

    When you create a construction plane then everything, no matter what
    orientation (base pt and rotation) you have a top down view of the working
    area. This lends itself to some simpler math than the other way. For
    example if I wanted to project a point along the construction plane I could
    use a simple polar or if I wanted a point 10,10,10 out then it would be
    10,10,10. You estanblish a plane and then after all operations or done, you
    convert the data back to the WCS for storage and usage. I know it seems
    more time consuming, but it's actually matrix math and can save quite a bit
    of time in the long run.

    Now if I didn't want to set up a UCS (and when I say UCS I really mean 3d
    rotation matrix as I don't use UCS's but rather matrix math) then I would
    have to incorperate the orientation rotation and translation for each
    operation depending on the operation. Each operation would include a 1.
    rotation/translating to construction plane 2. operation to be performed 3.
    rotation/translation back to WCS. When I set up the plane, I just rotate
    and translate once to the plane then perform all operations then at the end
    rotate and translate back. It actually cuts out steps.

    Of course if there's a simpler way for the operations you would take it,
    even game programmers use a rotation matrix as it really is one of the
    fastest ways to manipulate vector data.

    I hope that helps,

    Devin
     
    Devin, Jun 3, 2004
    #17
  18. Joe Burke

    Joe Burke Guest

    Devin,

    This works fine. It's similar to the method Tony posted.

    As I said to Tony, I tried to do it like that. Got frustrated with the nested stuff.
    Decided to post as is, with the idea the intermediate variables might make the
    thought process clearer.

    BTW, not forgetting, I asked for an "easier method". Vague for sure. :)

    Thanks
    Joe
     
    Joe Burke, Jun 4, 2004
    #18
  19. Joe Burke

    Devin Guest

    Joe,

    If I'm correct, which I think I am, Tony's method was the same as yours he
    just didn't assign the values returned by mapcar to variables, instead he
    ported the values directly into the next mapcar.

    My method is shorter as it only performs two mapcars instead of three or
    four and does all the math at once for each vector element. I beleive it is
    both shorter and faster. But you'ld have to test it out to be sure.

    Devin
     
    Devin, Jun 4, 2004
    #19
  20. Joe Burke

    Joe Burke Guest

    Devin,

    I *think* I understand. I assume you've developed some utility functions which do the
    matrix math?

    Here's something I've been working on. Might be of interest. It returns the same 4x4
    matrix as nentselp, given a block reference passed. Why bother? Well from this
    follows an inverse matrix function. And a couple functions which transform a point
    from OSC to WCS, or WCS to OCS.

    Joe Burke

    ;; Apply a transformation matrix to a vector by Vladimir Nesterovsky
    (defun mxv (m v)
    (mapcar '(lambda (row) (apply '+ (mapcar '* row v))) m)
    ) ;end

    ;; Multiply two matrices by Vladimir Nesterovsky
    (defun mxm (m q / qt)
    (setq qt (apply 'mapcar (cons 'list q)))
    (mapcar '(lambda (mrow) (mxv qt mrow)) m)
    ) ;end

    ;; argument: a block ref ename or equivalent vla-object
    ;; returns a 4x4 matrix
    (defun ObjMatrix ( vobj / ang inspt xsf ysf zxf
    sclmatrix rotmatrix movmatrix resmatrix )
    (if (= (type vobj) 'ENAME)
    (setq vobj (vlax-ename->vla-object vobj))
    )
    (and
    (= "AcDbBlockReference" (vlax-get vobj 'ObjectName))
    (setq ang (vlax-get vobj 'Rotation))
    (setq inspt (vlax-get vobj 'InsertionPoint))
    (setq xsf (vlax-get vobj 'XScaleFactor))
    (setq ysf (vlax-get vobj 'YScaleFactor))
    (setq zsf (vlax-get vobj 'ZScaleFactor))
    (equal (abs xsf) (abs ysf) 1e-8)
    (equal (abs ysf) (abs zsf) 1e-8)
    (setq sclmatrix
    (list
    (list xsf 0 0 0)
    (list 0 ysf 0 0)
    (list 0 0 zsf 0)
    (list 0 0 0 1)
    )
    )
    ;; if block is mirrored only X, Y or Z, then...
    ;; all other mirrored combinations including none, else...
    (if
    (or
    (and (minusp xsf) (not (minusp ysf)) (not (minusp zsf)))
    (and (not (minusp xsf)) (minusp ysf) (not (minusp zsf)))
    (and (not (minusp xsf)) (not (minusp ysf)) (minusp zsf))
    )
    (setq rotmatrix
    (list
    (list (cos ang) (sin ang) 0 0)
    (list (- (sin ang)) (cos ang) 0 0)
    (list 0 0 1 0)
    (list 0 0 0 1)
    )
    )
    (setq rotmatrix
    (list
    (list (cos ang) (- (sin ang)) 0 0)
    (list (sin ang) (cos ang) 0 0)
    (list 0 0 1 0)
    (list 0 0 0 1)
    )
    )
    )
    (setq movmatrix
    (list
    (list 1 0 0 (car inspt))
    (list 0 1 0 (cadr inspt))
    (list 0 0 1 (caddr inspt))
    (list 0 0 0 1)
    )
    )
    (setq resmatrix (mxm movmatrix (mxm sclmatrix rotmatrix)))
    ) ;and
    resmatrix
    ) ;end
     
    Joe Burke, Jun 4, 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.