enum AREA_DISTRIBUTION {
	area,
	border
}

enum AREA_SCATTER {
	uniform,
	random
}

function area_get_bbox(area) {
	return [ area[0] - area[2], area[1] - area[3], area[0] + area[2], area[1] + area[3] ];
}

function area_get_random_point(area, distrib = AREA_DISTRIBUTION.area, scatter = AREA_SCATTER.random, index = 0, total = 1) {
	if(total == 0) return [0, 0];
	
	var _area_x = array_safe_get_fast(area, 0);
	var _area_y = array_safe_get_fast(area, 1);
	var _area_w = array_safe_get_fast(area, 2);
	var _area_h = array_safe_get_fast(area, 3);
	var _area_t = array_safe_get_fast(area, 4);
	var xx = 0, yy = 0;
	
	index = safe_mod(index, total);
	
	switch(distrib) {
		case AREA_DISTRIBUTION.area : 
			if(scatter == AREA_SCATTER.uniform) {
				if(_area_t == AREA_SHAPE.rectangle) {
					
					var _col = ceil(sqrt(total));
					var _row = ceil(total / _col);
					
					var _iwid = _area_w * 2 / _col;
					var _ihig = _area_h * 2 / _row;
					
					var _irow = floor(index / _col);
					var _icol = safe_mod(index, _col);
					
					xx = _area_x - _area_w + (_icol + 0.5) * _iwid;
					yy = _area_y - _area_h + (_irow + 0.5) * _ihig;
					
					//print($"{yy} = {_area_y} - {_area_h} + ({_irow} + 0.5) * {_ihig}")
					
				} else {
					if(index == 0) {
						xx = _area_x;
						yy = _area_y;
						break;
					}
					
					var _r = _area_w;
					var _a = _area_w / _area_h;
					
					var _tm = floor(total / (2 * pi));
					var _tn = ceil(sqrt(2 * _tm + 1 / 2) - 1 / 2);
					var _s  = _r / _tn;
					
					var _m = floor(index / (2 * pi));
					var _n = floor(sqrt(2 * _m + 1 / 2) - 1 / 2);
					
					var _sr = (_n + 1) * _s;
					var _tt = floor((_n * (_n + 1)) / 2 * pi * 2);
					var _sa = (index - _tt) / (min(total - _tt, floor((_n + 1) * 2 * pi)) - 1) * 360;
					
					xx = _area_x + lengthdir_x(_sr, _sa);
					yy = _area_y + lengthdir_y(_sr, _sa) / _a;
				}
				
			} else if(scatter == AREA_SCATTER.random) {
				if(_area_t == AREA_SHAPE.rectangle) {
					xx = _area_x + random_range(-_area_w, _area_w);
					yy = _area_y + random_range(-_area_h, _area_h);
					
				} else if(_area_t == AREA_SHAPE.elipse) {
					var rr = random(360);
					xx = _area_x + lengthdir_x(1, rr) * random(_area_w);
					yy = _area_y + lengthdir_y(1, rr) * random(_area_h);
				}
			}
			break;
		
		case AREA_DISTRIBUTION.border :
			if(scatter == AREA_SCATTER.uniform) {
				if(_area_t == AREA_SHAPE.rectangle) {
					var perimeter = _area_w * 4 + _area_h * 4;
					var d = perimeter / total;
					var l = perimeter * index / total;
					
					if(l <= _area_w * 2) {
						xx = _area_x - _area_w + l;
						yy = _area_y - _area_h;
						break;
					} l -= _area_w * 2;
					
					if(l <= _area_h * 2) {
						xx = _area_x + _area_w;
						yy = _area_y - _area_h + l;
						break;
					} l -= _area_h * 2;
					
					if(l <= _area_w * 2) {
						xx = _area_x + _area_w - l;
						yy = _area_y + _area_h;
						break;
					} l -= _area_w * 2;
					
					if(l <= _area_h * 2) {
						xx = _area_x - _area_w;
						yy = _area_y + _area_h - l;
						break;
					} l -= _area_h * 2;
					
				} else if(_area_t == AREA_SHAPE.elipse) {
					var rr = 360 * index / total;
					xx = _area_x + lengthdir_x(_area_w, rr);
					yy = _area_y + lengthdir_y(_area_h, rr);
				}
				
			} else if(scatter == AREA_SCATTER.random) {
				if(_area_t == AREA_SHAPE.rectangle) {
					var perimeter = _area_w * 2 + _area_h * 2;
					var i = random(perimeter);
					if(i < _area_w) {
						xx = _area_x + random_range(-_area_w, _area_w);
						yy = _area_y - _area_h;
					} else if(i < _area_w + _area_h) {
						xx = _area_x - _area_w;
						yy = _area_y + random_range(-_area_h, _area_h);
					} else if(i < _area_w * 2 + _area_h) {
						xx = _area_x + random_range(-_area_w, _area_w);
						yy = _area_y + _area_h;	
					} else {
						xx = _area_x + _area_w;
						yy = _area_y + random_range(-_area_h, _area_h);
					}
					
				} else if(_area_t == AREA_SHAPE.elipse) {
					var rr = random(360);
					xx = _area_x + lengthdir_x(_area_w, rr);
					yy = _area_y + lengthdir_y(_area_h, rr);
				}
			}
			break;
	}
	
	return [xx, yy];
}

function area_point_in(_area, _x, _y) {
	var _area_x = _area[0];
	var _area_y = _area[1];
	var _area_w = _area[2];
	var _area_h = _area[3];
	var _area_t = _area[4];
	
	var _area_x0 = _area_x - _area_w;
	var _area_x1 = _area_x + _area_w;
	var _area_y0 = _area_y - _area_h;
	var _area_y1 = _area_y + _area_h;
	
	var in = false;
	
	if(_area_t == AREA_SHAPE.rectangle) {
		in = point_in_rectangle(_x, _y, _area_x0, _area_y0, _area_x1, _area_y1);
	} else if(_area_t == AREA_SHAPE.elipse) {
		var _dirr = point_direction(_area_x, _area_y, _x, _y);
		var _epx = _area_x + lengthdir_x(_area_w, _dirr);
		var _epy = _area_y + lengthdir_y(_area_h, _dirr);
		
		in = point_distance(_area_x, _area_y, _x, _y) < point_distance(_area_x, _area_y, _epx, _epy);
	}
	
	return in;
}

function area_point_in_fallout(_area, _x, _y, _fall_distance) {
	if(_fall_distance == 0) return area_point_in(_area, _x, _y);
	
	var _area_x = _area[0];
	var _area_y = _area[1];
	var _area_w = _area[2];
	var _area_h = _area[3];
	var _area_t = _area[4];
	
	var _area_x0 = _area_x - _area_w;
	var _area_x1 = _area_x + _area_w;
	var _area_y0 = _area_y - _area_h;
	var _area_y1 = _area_y + _area_h;
	
	var str = 0, in, _dst;
	
	if(_area_t == AREA_SHAPE.rectangle) {
		in = point_in_rectangle(_x, _y, _area_x0, _area_y0, _area_x1, _area_y1)
		_dst = min(	distance_to_line(_x, _y, _area_x0, _area_y0, _area_x1, _area_y0), 
					distance_to_line(_x, _y, _area_x0, _area_y1, _area_x1, _area_y1), 
					distance_to_line(_x, _y, _area_x0, _area_y0, _area_x0, _area_y1), 
					distance_to_line(_x, _y, _area_x1, _area_y0, _area_x1, _area_y1));
					
	} else if(_area_t == AREA_SHAPE.elipse) {
		var _dirr = point_direction(_area_x, _area_y, _x, _y);
		var _epx = _area_x + lengthdir_x(_area_w, _dirr);
		var _epy = _area_y + lengthdir_y(_area_h, _dirr);
		
		in   = point_distance(_area_x, _area_y, _x, _y) < point_distance(_area_x, _area_y, _epx, _epy);
		_dst = point_distance(_x, _y, _epx, _epy);
	}
	
	if(_dst <= _fall_distance) {
		var inf = in? 0.5 + _dst / _fall_distance : 0.5 - _dst / _fall_distance;
		str = clamp(inf, 0., 1.);
		
	} else if(in)
		str = 1;
	
	return str;
}