FillEllipsoidWithPoints2D
The purpose of filling up a bunch of uniformly generated points within an Ellipsoid Volume is to provide random spot-check raycasts against characters who are hiding behind cover to determine if they ended up detected or not. http://stackoverflow.com/a/18734831
Press P to fire a random shot.
A 3D version can be found here.
http://wonderfl.net/c/bGHS
/**
* Copyright Glidias ( http://wonderfl.net/user/Glidias )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4ZVD
*/
package {
import flash.media.Video;
import flash.events.KeyboardEvent;
import flash.display.Sprite;
import flash.geom.Vector3D;
import flash.ui.Keyboard;
public class FillEllipsoidWithPoints2D extends Sprite {
private var _pointSamples:EllipsoidPointSamples;
private var _targetSpr:Sprite;
private static const ORIGIN_X:Number = 127;
private static const ORIGIN_Y:Number = 127;
private static const SCALE:Number = 128;
public function FillEllipsoidWithPoints2D() {
//Quuestion: http://stackoverflow.com/questions/18731239/gnuplot-plot-random-points-inside-an-ellipsoid
//Solution: http://stackoverflow.com/a/18734831
// Any better way to fill it up more evenly, or is this the best?
var pts:EllipsoidPointSamples = new EllipsoidPointSamples();
_pointSamples = pts;
pts.init2D(new Vector3D(32, 72, 32), 3*10*2*10*1);
graphics.beginFill(0xFF0000, 1);
for (var i:int = 0; i < pts.numPoints; i++) {
var baseI:int = i * 3;
graphics.drawCircle(127+pts.points[baseI]*SCALE, 127+pts.points[baseI+1]*SCALE, 1);
}
var spr:Sprite = new Sprite();
spr.x = ORIGIN_X;
spr.y = ORIGIN_Y;
spr.graphics.lineStyle(0, 0, 1);
spr.graphics.drawCircle(0, 0, 1);
spr.scaleX = pts.a * SCALE;
spr.scaleY = pts.b * SCALE;
addChild(spr);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
_targetSpr = new Sprite();
_targetSpr.x = 0;
_targetSpr.y = 0;
_targetSpr.graphics.beginFill(0x0000FF);
_targetSpr.graphics.drawCircle(0, 0, 2);
addChild(_targetSpr);
}
private function onKeyDown(e:KeyboardEvent):void {
if (e.keyCode ===Keyboard.P) {
var randomPt:int = int(Math.random() * _pointSamples.numPoints) * 3;
_targetSpr.x = ORIGIN_X + _pointSamples.points[randomPt]*SCALE;
_targetSpr.y = ORIGIN_Y + _pointSamples.points[randomPt+1]*SCALE;
}
}
}
}
//package arena.components.char {
// import util.geom.Vec3;
//public
import flash.geom.Vector3D;
class EllipsoidPointSamples {
public function EllipsoidPointSamples() : void {
}
protected function check2(x : Number,y : Number) : Boolean {
return this.exponentiation(x / this.a,2) + this.exponentiation(y / this.b,2) <= 1;
}
protected function check(x : Number,y : Number,z : Number) : Boolean {
return check2(x,y) && check2(x,z) && check2(y,z);
//return x / this.a * 2 + this.exponentiation(y / this.b,2) + this.exponentiation(z / this.c,2) <= 1;
}
protected function max(x : Number,y : Number,z : Number) : Number {
return this.mx(this.mx(x,y),this.mx(x,z));
}
protected function mx(x : Number,y : Number) : Number {
return ((x > y)?x:y);
}
protected function rand(val : Number) : Number {
return ((val != 0)?Math.random() * (1 - val) + val:Math.random());
}
protected function exponentiation(valuer : Number,amt : Number) : Number {
return Math.pow(valuer,amt);
}
protected function ey(x : Number,y : Number) : Number {
var valuer : Number = 2 * x - 1;
return this.b * Math.sqrt(1 - this.exponentiation(valuer,2)) * (2 * y - 1);
}
protected function ex(x : Number,y : Number) : Number {
return this.a * (2 * x - 1);
}
protected function oneOrZero() : Number {
return ((Math.random() > .5)?1:0);
}
protected function createRandomPoints3D() : void {
var count : int = 0;
var x : Number;
var y : Number;
var z : Number;
var rx : Number;
var ry : Number;
var rz : Number;
{
var _g1 : int = 0, _g : int = this.numPoints;
while(_g1 < _g) {
var i : int = _g1++;
while(true) {
x = 2 * this.a * (this.rand(0) - 0.5);
y = 2 * this.b * (this.rand(0) - 0.5);
z = 2 * this.c * (this.rand(0) - 0.5);
if(this.check(x,y,z)) {
rx = x - y * 0;
ry = x * 0 + y;
rz = z;
this.points[count++] = rx;
this.points[count++] = ry;
this.points[count++] = rz;
break;
}
}
}
}
}
protected function createRandomPoints2D() : void {
var count : int = 0;
var x : Number;
var y : Number;
var z : Number;
var rx : Number;
var ry : Number;
var rz : Number;
{
var _g1 : int = 0, _g : int = this.numPoints;
while(_g1 < _g) {
var i : int = _g1++;
while(true) {
x = 2 * this.a * (this.rand(0) - 0.5);
y = 2 * this.b * (this.rand(0) - 0.5);
z = 2 * this.c * (this.rand(0) - 0.5);
if(this.check2(x,y)) {
rx = x - y * 0;
ry = x * 0 + y;
rz = z;
this.points[count++] = rx;
this.points[count++] = ry;
this.points[count++] = rz;
break;
}
}
}
}
}
protected function myInit(ellipsoid : Vector3D,numPoints : int = 100) : void {
this.a = ellipsoid.x;
this.b = ellipsoid.y;
this.c = ellipsoid.z;
var d : Number = 1 / Math.sqrt(this.a * this.a + this.b * this.b + this.c * this.c);
this.a *= d;
this.b *= d;
this.c *= d;
d = this.max(this.a,this.b,this.c);
this.numPoints = numPoints;
this.points = new Vector.<Number>(numPoints * 3,true);
}
public function init2D(ellipsoid : Vector3D,numPoints : int = 100) : EllipsoidPointSamples {
this.myInit(ellipsoid,numPoints);
this.createRandomPoints2D();
return this;
}
public function init(ellipsoid : Vector3D,numPoints : int = 100) : EllipsoidPointSamples {
this.myInit(ellipsoid,numPoints);
this.createRandomPoints3D();
return this;
}
public var numPoints : int;
public var points : Vector.<Number>;
public var c : Number;
public var b : Number;
public var a : Number;
static protected var phi : Number = 3;
static protected var COS_0 : Number = 1;
static protected var SIN_0 : Number = 0;
}
//}