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.
;;; 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.
#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);
}
}