Author Topic: Anti Gravity Movement demo  (Read 3007 times)

0 Members and 1 Guest are viewing this topic.

pkohut

  • Bull Frog
  • Posts: 483
Anti Gravity Movement demo
« on: March 03, 2011, 06:54:07 PM »
An Autolisp conversion of Anti Gravity Movement as found at http://nakkaya.com/2010/09/13/anti-gravity-movement/ (dude is an excellent blogger)

notes:
1) since grread blocks until it has something to return, wiggle the mouse a little bit so the "player" will track towards the mouse position.
2) player will collide with objects (unexpeded) (http://robowiki.net/wiki/Anti-Gravity_Tutorial anti gravity formula seems a little different than nakkaya's)
3) I dabble in Autolisp once or twice a year, so the code below may have bugs and is not supported.
4) enjoy!!
5) edit: attached an ARX/C++ version.

Code: [Select]
;;; Anti-Gravity Movement demo in Autolisp
;;; Autolisp translation by Paul Kohut 2011
;;; Original Clojure Lisp version by Nurullah Akkaya
;;; http://nakkaya.com/2010/09/13/anti-gravity-movement/

(defun c:AGM (/ state startPt tmp)
  (command "zoom" "w" "0,0" "640,480")
  (initget 6)
  (setq tmp (getreal (strcat "Obstacle repel strength <" (rtos g_obrs 2 2) ">: ")))
  (if (/= tmp nil) (setq g_obrs tmp))
  (initget 6)
  (setq tmp (getreal (strcat "Target attraction factor  <" (rtos g_taf 2 2) ">: ")))
  (if (/= tmp nil) (setq g_taf tmp))
  
  (setq startPt (getpoint "\n Click a starting position to begin demo"))
  (setq state (append (list (list 'player startPt))
     (list (list 'target startPt))
     (list (list 'obstacles
 (list (list 135.0 223.0 0.0) (list 560.0 290.0 0.0)
(list 550.0 120.0 0.0) (list 145.0 70.0 0.0)
(list 350.0 320.0 0.0) (list 60.0 50.0 0.0)
(list 210.0 313.0 0.0) (list 450.0 210.0 0.0))))))
  (while T
    (setq state (PlayerMousePosition state))
    (redraw)
    (DrawGrCircle 3 10.0 (cadr (assoc 'target state)))
    (DrawGrCircle 2 10.0 (cadr (assoc 'player state)))
    (mapcar '(lambda (x) (DrawGrCircle 4 20.0 x))
   (cadr (assoc 'obstacles state))
    )
    (setq state (steer state))
    (acet-sys-sleep 1)
  )
)

(setq g_obrs 2000 g_taf 2.0)
(defun gravity-vector (u v / force uvAngle |u| |v| mag)
  (setq mag (magnitude (mapcar '- u v)))
  (setq force (/ g_obrs (expt (magnitude (mapcar '- u v)) g_taf))
|u| (unit u)
|v| (unit v)
uvAngle (- (atan (cadr |v|) (car |v|)) (atan (cadr |u|) (car |u|)))
  )
  (list (* (sin uvAngle) force) (* (cos uvAngle) force) 0.0)
)

(defun total-gravitational-force (state / vec)
  (setq vec '(0.0 0.0 0.0))
  (setq tt 0)
  (foreach x (cadr (assoc 'obstacles state))
    (setq vec (v+v vec (gravity-vector (cadr (assoc 'player state)) x)))
    (setq tt (1+ tt))
  )
  vec
)

(defun seek (state / vec)
  (unit (v+v (unit (v-v (cadr (assoc 'target state))
(cadr (assoc 'player state))
  )
    )
    (total-gravitational-force state)
)
  )
)

(defun steer (state / player)
  (setq player (cadr (assoc 'player state)))
  (if (> (distance player (cadr (assoc 'target state))) 1.0)
    (setq state
  (alter-player-state state 'player (v+v player (seek state)))
    )
  )
  state
)

(defun PlayerMousePosition (state / grVal)
  (setq grVal (grread T))
  (if (= 5 (car grVal))
    (setq state (alter-player-state state 'target (car (cdr grVal))))
  )
  state
)

(defun DrawGrCircle (color scale coord / x y)
  (setq x (car coord) y (cadr coord))
  (grvecs (list
   color (list 0.000000 1.000000 0.000000) (list 0.382683 0.923880 0.000000)
   color (list 0.382683 0.923880 0.000000) (list 0.707107 0.707107 0.000000)
   color (list 0.707107 0.707107 0.000000) (list 0.923880 0.382683 0.000000)
   color (list 0.923880 0.382683 0.000000) (list 1.000000 0.000000 0.000000)
   color (list 1.000000 0.000000 0.000000) (list 0.923880 -0.382683 0.000000)
   color (list 0.923880 -0.382683 0.000000) (list 0.707107 -0.707107 0.000000)
   color (list 0.707107 -0.707107 0.000000) (list 0.382683 -0.923880 0.000000)
   color (list 0.382683 -0.923880 0.000000) (list 0.000000 -1.000000 0.000000)
   color (list 0.000000 -1.000000 0.000000) (list -0.382683 -0.923880 0.000000)
   color (list -0.382683 -0.923880 0.000000) (list -0.707107 -0.707107 0.000000)
   color (list -0.707107 -0.707107 0.000000) (list -0.923880 -0.382683 0.000000)
   color (list -0.923880 -0.382683 0.000000) (list -1.000000 0.000000 0.000000)
   color (list -1.000000 0.000000 0.000000)  (list -0.923880 0.382683 0.000000)
   color (list -0.923880 0.382683 0.000000) (list -0.707107 0.707107 0.000000)
   color (list -0.707107 0.707107 0.000000) (list -0.382683 0.923880 0.000000)
   color (list -0.382683 0.923880 0.000000) (list 0.000000 1.000000 0.000000)
 )
 (list (list scale 0.0 0.0 x)
(list 0.0 scale 0.0 y)
(list 0.0 0.0 1.0 0.0)
(list 0.0 0.0 0.0 1.0)))
)

(defun magnitude (v / mag) (setq mag (sqrt (vxv v v))))

(defun alter-player-state (state who coord / x)
  (subst (list who coord) (assoc who state) state))

;; Vector Stuff by - Lee Mac 2010
(defun vxs (v s) (mapcar '(lambda (n) (* n s)) v))
(defun vxv (u v) (apply '+ (mapcar '* u v)))
(defun v-v (u v) (mapcar '- u v))
(defun v+v (u v) (mapcar '+ u v))
(defun norm (v) (sqrt (apply '+ (mapcar '* v v))))
(defun unit (v) ((lambda (n) (if (equal 0.0 n 1e-14) nil
      (vxs v (/ 1.0 n)))) (norm v)))


C++/ARX version implementation.
Code: [Select]
#include "StdAfx.h"
#include "Gravity.h"
#include <algorithm>

#define _USE_MATH_DEFINES 1
#include <math.h>

inline double Deg2Rad(const double dVal) { return dVal * (M_PI / 180.0); }
inline double Rad2Deg(const double dVal) { return dVal * (180.0 / M_PI); }

CGravity::CGravity(void)
{
    m_pCircleVect = NULL;
    m_ptObstacles.push_back(AcGePoint3d(135.0, 223.0, 0.0));
    m_ptObstacles.push_back(AcGePoint3d(560.0, 290.0, 0.0));
    m_ptObstacles.push_back(AcGePoint3d(550.0, 120.0, 0.0));
    m_ptObstacles.push_back(AcGePoint3d(145.0, 70.0, 0.0));
    m_ptObstacles.push_back(AcGePoint3d(350.0, 320.0, 0.0));
    m_ptObstacles.push_back(AcGePoint3d(210.0, 313.0, 0.0));
    m_ptObstacles.push_back(AcGePoint3d(450.0, 210.0, 0.0));
    InitGrCircles();
}

CGravity::~CGravity(void)
{
    acutRelRb(m_pCircleVect);
    m_pCircleVect = NULL;
}

void CGravity::InitGrCircles(void)
{
    m_pCircleVect = acutNewRb(RTSHORT);
    resbuf * pRb = m_pCircleVect;

    pRb->resval.rint = 2;

    int nSegments = 16;
    double dSeg = Deg2Rad(360.0 / nSegments);
    double dAngle = 0.0;
    double dRadius = 1.0;
    for(int i = 0; i < nSegments; i++)
    {
        AcGePoint3d pt1(dRadius * sin(dAngle), dRadius * cos(dAngle), 0.0);
        AcGePoint3d pt2(dRadius * sin(dAngle + dSeg), dRadius * cos(dAngle + dSeg), 0.0);

        pRb->rbnext = acutNewRb(RTPOINT);
        pRb = pRb->rbnext;
        pRb->resval.rpoint[0] = pt1.x;
        pRb->resval.rpoint[1] = pt1.y;
        pRb->resval.rpoint[2] = pt1.z;

        pRb->rbnext = acutNewRb(RTPOINT);
        pRb = pRb->rbnext;
        pRb->resval.rpoint[0] = pt2.x;
        pRb->resval.rpoint[1] = pt2.y;
        pRb->resval.rpoint[2] = pt2.z;

        dAngle += dSeg;
    }
}

void CGravity::DrawGrCircle(int nColor, double dRadius, const AcGePoint3d & pt)
{
    m_pCircleVect->resval.rint = nColor;
    AcGeMatrix3d mat;       
    mat.setToScaling(dRadius);
    mat.setTranslation(pt.asVector());
    int nRetVal = acedGrVecs(m_pCircleVect, *(ads_matrix*)&mat);

}

AcGeVector3d CGravity::GravityVector(const AcGeVector3d & u, const AcGeVector3d & v)
{
   
    double dForce = (2000.0 / pow((u - v).length(), 2.0));
    AcGeVector3d uu = u.normal();
    AcGeVector3d vv = v.normal();
    double dAngle = atan2(vv.y, vv.x) - atan2(uu.y, uu.x);
    return AcGeVector3d(sin(dAngle) * dForce, cos(dAngle) * dForce, 0.0);
}

AcGeVector3d CGravity::TotalGravitationalForce(void)
{
    AcGeVector3d vec;
    std::vector<AcGePoint3d>::iterator it;
    for(it = m_ptObstacles.begin(); it != m_ptObstacles.end(); it++) {
        vec += GravityVector(m_ptPlayer.asVector(), it->asVector());
    }   
    return vec;
}

AcGeVector3d CGravity::Seek(void)
{
    AcGeVector3d vec = m_ptTarget - m_ptPlayer;
    vec.normalize();
    vec += TotalGravitationalForce();
    vec.normalize();
    return vec;
}

void CGravity::Steer(void)
{
    if(m_ptPlayer.distanceTo(m_ptTarget) > 1.0) {
        m_ptPlayer += Seek();
    }
}

int CGravity::GetTarget(void)
{
    int nGrReadType;
    resbuf rbResult;
    int nRet = acedGrRead(15, &nGrReadType, &rbResult);
    if(nRet == RTNORM) {
        if(nGrReadType == 5) {
            m_ptTarget = asPnt3d(rbResult.resval.rpoint);
        }
    }
    return nRet;
}

void CGravity::Run( void )
{
    acedCommand(RTSTR, L"_zoom", RTSTR, L"w", RTSTR, L"0.0, 0.0",
        RTSTR, L"640.0, 480.0", RTNONE);
    AcGePoint3d ptTarget;
    int nRet;
    if(acedGetPoint(NULL, L"\nClick a starting position to begin demo",
        asDblArray(ptTarget)) != RTNORM) {
            acutPrintf(L"\nProgram exiting");
            return;
    }

    m_ptPlayer = m_ptTarget = ptTarget;


    for(;;) {
        if(GetTarget() != RTNORM)
            break;
        acedRedraw(NULL, 0);
        DrawGrCircle(3, 20.0, m_ptTarget);
        DrawGrCircle(2, 20.0, m_ptPlayer);
        std::vector<AcGePoint3d>::iterator it;
        for(it = m_ptObstacles.begin(); it != m_ptObstacles.end(); it++)
            DrawGrCircle(4, 20.0, *it);
        Steer();
        Sleep(5);
    }
}
« Last Edit: March 03, 2011, 07:06:09 PM by pkohut »
New tread (not retired) - public repo at https://github.com/pkohut

Lee Mac

  • Seagull
  • Posts: 12914
  • London, England
Re: Anti Gravity Movement demo
« Reply #1 on: March 03, 2011, 08:07:30 PM »
Very nice Paul! It works well  :-)

I like your use of association lists to pass the data between functions - its great to see something different from someone who doesn't code in LISP as regularly, as I tend to get stuck using the same methods, so its nice to see a new approach to things.

Lee

pkohut

  • Bull Frog
  • Posts: 483
Re: Anti Gravity Movement demo
« Reply #2 on: March 03, 2011, 10:40:51 PM »
Very nice Paul! It works well  :-)

I like your use of association lists to pass the data between functions - its great to see something different from someone who doesn't code in LISP as regularly, as I tend to get stuck using the same methods, so its nice to see a new approach to things.

Lee

Thanks Lee. Initially I thought I could do the conversion to Autolisp in a few minutes and see the animation, but Clojure syntax is so different and my alisp skills rusty that I spent most of the day with writing the code. The C++ version about an hour to write.
New tread (not retired) - public repo at https://github.com/pkohut

SEANT

  • Bull Frog
  • Posts: 345
Re: Anti Gravity Movement demo
« Reply #3 on: March 06, 2011, 06:03:15 AM »
Very amusing.  It reminds me of my days of chasing a skirt around a pub, while avoiding people I owed money to and ex girlfriends.  Just kidding.   :-)

As a comment relatively off topic:  Given that the demos are in 2d, should the attenuation falloff be proportional to the distance instead of an implemented inverse-square law?  As a resident of “Flatland” an individual would have to wonder where the gravitational force went.

Actually, I’m kidding here as well.  The setup makes perfect sense. I’m just recalling an old conversation where a suggestion was made that if any of the four primary interactions (strong nuclear, in particular) attenuated more aggressively than the inverse-square law, could dimensions > 3 be inferred?


Edit:  Must remember . . . . mine is not a widely shared sense of amusement.
« Last Edit: March 08, 2011, 07:50:18 AM by SEANT »
Sean Tessier
AutoCAD 2016 Mechanical