- /* 
- i have an object moving in 2d space. the space is restricted by the screen size defined with HEIGHT,  
- WIDTH. 
- the start location of the object is at start_x, start_y. the object moves on a straight line until 
- it hits the boundary of the screen. i know the moving direction (degrees) of the object, which lies 
- between 0 and 360 degrees. 
-   
- Q: how can i generate a random point which is on the path the object will move until it reaches the  
- screen boundary? 
-   
- figure: https://s...content-available-to-author-only...s.com/aww-imagedata/0353066c-5c8f-432f-88a5-9065c52adc07.png 
- */ 
-   
- #include <iostream> 
- #include <cmath> 
- #include <cassert> 
- using namespace std; 
-   
- // range : [min, max] 
- int random(int min, int max) { 
-    static bool first = true; 
-    if (first) {   
-       srand(time(NULL)); //seeding for the first time only! 
-       first = false; 
-    } 
-    return min + rand() % (max - min + 1); 
- } 
-   
- bool approximately_equal(float a, float b, float epsilon) { 
-     return fabs(a - b) <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); 
- } 
-   
- bool test_is_point_on_path(int start_x, int start_y, int max_x, int max_y, int heading_dir, float point_x, float point_y) { 
- 	float curr_x = start_x; 
- 	float curr_y = start_y; 
- 	float heading_rad = heading_dir * (M_PI / 180); 
-     int inc_Len = 1; 
-     float x_inc = cos(heading_rad) * inc_Len; 
-     float y_inc = sin(heading_rad) * inc_Len; 
-   
- 	while (curr_x > 0 && curr_x < max_x && 
- 	       curr_y > 0 && curr_y < max_y) { 
-   
- 		if (approximately_equal(curr_x, point_x, 0.02) && 
- 		    approximately_equal(curr_y, point_y, 0.02)) { 
- 			return true; 
- 		} 
-   
- 		curr_x += x_inc; 
- 		curr_y += y_inc; 
- 	} 
-   
- 	return false; 
- } 
-   
- std::pair<float,float> get_end_point(int start_x, int start_y, int max_x, int max_y, int heading_dir) { 
- 	int len = 0; 
- 	float end_x = 0; 
- 	float prev_end_x = 0; 
- 	float end_y = 0; 
- 	float prev_end_y = 0; 
- 	float heading_rad = heading_dir * (M_PI / 180); 
-   
- 	while (true) { 
- 		end_x = start_x + len * cos(heading_rad); 
-     	end_y = start_y + len * sin(heading_rad); 
-   
-     	if (end_x > max_x || end_x < 0 || 
-     	    end_y > max_y || end_y < 0) { 
-     		break; 
-     	} 
-   
-     	prev_end_x = end_x; 
-     	prev_end_y = end_y; 
-     	len++; 
- 	} 
-   
- 	return std::make_pair(prev_end_x, prev_end_y); 
- } 
-   
- std::pair<float,float> rand_point_on_path(float start_x, float start_y, float end_x, float end_y, int heading_dir) { 
-     float heading_rad = heading_dir * (M_PI / 180); 
-     float delta_x = abs(end_x - start_x); 
-     float delta_y = abs(end_y - start_y); 
-     float max_len = sqrt(delta_x * delta_x + delta_y * delta_y); 
-     int rand_len = random(0, max_len); 
-   
-     float calc_x = start_x + rand_len * cos(heading_rad); 
-     float calc_y = start_y + rand_len * sin(heading_rad); 
-   
-     return std::make_pair(calc_x, calc_y); 
- } 
-   
- int main() { 
- 	int start_x = 200; 
- 	int start_y = 100; 
- 	int WIDTH = 500; 
- 	int HEIGHT = 500; 
- 	int dir = 45; 
-   
- 	cout << "start_point_x: " << start_x << ", start_point_y: " << start_y << endl; 
-   
- 	auto end_point = get_end_point(start_x, start_y, WIDTH, HEIGHT, dir); 
- 	cout << "end_point_x: " << end_point.first << ", end_point_y: " << end_point.second << endl; 
-   
- 	auto rand_point = rand_point_on_path(start_x, start_y, end_point.first, end_point.second, dir); 
- 	cout << "rand_point_x: " << rand_point.first << ", rand_point_y: " << rand_point.second << endl; 
-   
- 	assert(test_is_point_on_path(start_x, start_y, WIDTH, HEIGHT, dir, rand_point.first, rand_point.second) == true); 
-   
- 	return 0; 
- } 
				LyoKaSBoYXZlIGFuIG9iamVjdCBtb3ZpbmcgaW4gMmQgc3BhY2UuIHRoZSBzcGFjZSBpcyByZXN0cmljdGVkIGJ5IHRoZSBzY3JlZW4gc2l6ZSBkZWZpbmVkIHdpdGggSEVJR0hULCAKV0lEVEguCnRoZSBzdGFydCBsb2NhdGlvbiBvZiB0aGUgb2JqZWN0IGlzIGF0IHN0YXJ0X3gsIHN0YXJ0X3kuIHRoZSBvYmplY3QgbW92ZXMgb24gYSBzdHJhaWdodCBsaW5lIHVudGlsCml0IGhpdHMgdGhlIGJvdW5kYXJ5IG9mIHRoZSBzY3JlZW4uIGkga25vdyB0aGUgbW92aW5nIGRpcmVjdGlvbiAoZGVncmVlcykgb2YgdGhlIG9iamVjdCwgd2hpY2ggbGllcwpiZXR3ZWVuIDAgYW5kIDM2MCBkZWdyZWVzLgoKUTogaG93IGNhbiBpIGdlbmVyYXRlIGEgcmFuZG9tIHBvaW50IHdoaWNoIGlzIG9uIHRoZSBwYXRoIHRoZSBvYmplY3Qgd2lsbCBtb3ZlIHVudGlsIGl0IHJlYWNoZXMgdGhlIApzY3JlZW4gYm91bmRhcnk/CgpmaWd1cmU6IGh0dHBzOi8vcy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4ucy5jb20vYXd3LWltYWdlZGF0YS8wMzUzMDY2Yy01YzhmLTQzMmYtODhhNS05MDY1YzUyYWRjMDcucG5nCiovCgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxjbWF0aD4KI2luY2x1ZGUgPGNhc3NlcnQ+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CiAKLy8gcmFuZ2UgOiBbbWluLCBtYXhdCmludCByYW5kb20oaW50IG1pbiwgaW50IG1heCkgewogICBzdGF0aWMgYm9vbCBmaXJzdCA9IHRydWU7CiAgIGlmIChmaXJzdCkgeyAgCiAgICAgIHNyYW5kKHRpbWUoTlVMTCkpOyAvL3NlZWRpbmcgZm9yIHRoZSBmaXJzdCB0aW1lIG9ubHkhCiAgICAgIGZpcnN0ID0gZmFsc2U7CiAgIH0KICAgcmV0dXJuIG1pbiArIHJhbmQoKSAlIChtYXggLSBtaW4gKyAxKTsKfQoKYm9vbCBhcHByb3hpbWF0ZWx5X2VxdWFsKGZsb2F0IGEsIGZsb2F0IGIsIGZsb2F0IGVwc2lsb24pIHsKICAgIHJldHVybiBmYWJzKGEgLSBiKSA8PSAoIChmYWJzKGEpIDwgZmFicyhiKSA/IGZhYnMoYikgOiBmYWJzKGEpKSAqIGVwc2lsb24pOwp9Cgpib29sIHRlc3RfaXNfcG9pbnRfb25fcGF0aChpbnQgc3RhcnRfeCwgaW50IHN0YXJ0X3ksIGludCBtYXhfeCwgaW50IG1heF95LCBpbnQgaGVhZGluZ19kaXIsIGZsb2F0IHBvaW50X3gsIGZsb2F0IHBvaW50X3kpIHsKCWZsb2F0IGN1cnJfeCA9IHN0YXJ0X3g7CglmbG9hdCBjdXJyX3kgPSBzdGFydF95OwoJZmxvYXQgaGVhZGluZ19yYWQgPSBoZWFkaW5nX2RpciAqIChNX1BJIC8gMTgwKTsKICAgIGludCBpbmNfTGVuID0gMTsKICAgIGZsb2F0IHhfaW5jID0gY29zKGhlYWRpbmdfcmFkKSAqIGluY19MZW47CiAgICBmbG9hdCB5X2luYyA9IHNpbihoZWFkaW5nX3JhZCkgKiBpbmNfTGVuOwogICAgICAKCXdoaWxlIChjdXJyX3ggPiAwICYmIGN1cnJfeCA8IG1heF94ICYmCgkgICAgICAgY3Vycl95ID4gMCAmJiBjdXJyX3kgPCBtYXhfeSkgewoJCQoJCWlmIChhcHByb3hpbWF0ZWx5X2VxdWFsKGN1cnJfeCwgcG9pbnRfeCwgMC4wMikgJiYKCQkgICAgYXBwcm94aW1hdGVseV9lcXVhbChjdXJyX3ksIHBvaW50X3ksIDAuMDIpKSB7CgkJCXJldHVybiB0cnVlOwoJCX0KCQkKCQljdXJyX3ggKz0geF9pbmM7CgkJY3Vycl95ICs9IHlfaW5jOwoJfQoJCglyZXR1cm4gZmFsc2U7Cn0KCnN0ZDo6cGFpcjxmbG9hdCxmbG9hdD4gZ2V0X2VuZF9wb2ludChpbnQgc3RhcnRfeCwgaW50IHN0YXJ0X3ksIGludCBtYXhfeCwgaW50IG1heF95LCBpbnQgaGVhZGluZ19kaXIpIHsKCWludCBsZW4gPSAwOwoJZmxvYXQgZW5kX3ggPSAwOwoJZmxvYXQgcHJldl9lbmRfeCA9IDA7CglmbG9hdCBlbmRfeSA9IDA7CglmbG9hdCBwcmV2X2VuZF95ID0gMDsKCWZsb2F0IGhlYWRpbmdfcmFkID0gaGVhZGluZ19kaXIgKiAoTV9QSSAvIDE4MCk7CgkKCXdoaWxlICh0cnVlKSB7CgkJZW5kX3ggPSBzdGFydF94ICsgbGVuICogY29zKGhlYWRpbmdfcmFkKTsKICAgIAllbmRfeSA9IHN0YXJ0X3kgKyBsZW4gKiBzaW4oaGVhZGluZ19yYWQpOwogICAgCQogICAgCWlmIChlbmRfeCA+IG1heF94IHx8IGVuZF94IDwgMCB8fAogICAgCSAgICBlbmRfeSA+IG1heF95IHx8IGVuZF95IDwgMCkgewogICAgCQlicmVhazsKICAgIAl9CiAgICAJCiAgICAJcHJldl9lbmRfeCA9IGVuZF94OwogICAgCXByZXZfZW5kX3kgPSBlbmRfeTsKICAgIAlsZW4rKzsKCX0KCQoJcmV0dXJuIHN0ZDo6bWFrZV9wYWlyKHByZXZfZW5kX3gsIHByZXZfZW5kX3kpOwp9CgpzdGQ6OnBhaXI8ZmxvYXQsZmxvYXQ+IHJhbmRfcG9pbnRfb25fcGF0aChmbG9hdCBzdGFydF94LCBmbG9hdCBzdGFydF95LCBmbG9hdCBlbmRfeCwgZmxvYXQgZW5kX3ksIGludCBoZWFkaW5nX2RpcikgewogICAgZmxvYXQgaGVhZGluZ19yYWQgPSBoZWFkaW5nX2RpciAqIChNX1BJIC8gMTgwKTsKICAgIGZsb2F0IGRlbHRhX3ggPSBhYnMoZW5kX3ggLSBzdGFydF94KTsKICAgIGZsb2F0IGRlbHRhX3kgPSBhYnMoZW5kX3kgLSBzdGFydF95KTsKICAgIGZsb2F0IG1heF9sZW4gPSBzcXJ0KGRlbHRhX3ggKiBkZWx0YV94ICsgZGVsdGFfeSAqIGRlbHRhX3kpOwogICAgaW50IHJhbmRfbGVuID0gcmFuZG9tKDAsIG1heF9sZW4pOwogICAgCiAgICBmbG9hdCBjYWxjX3ggPSBzdGFydF94ICsgcmFuZF9sZW4gKiBjb3MoaGVhZGluZ19yYWQpOwogICAgZmxvYXQgY2FsY195ID0gc3RhcnRfeSArIHJhbmRfbGVuICogc2luKGhlYWRpbmdfcmFkKTsKICAgIAogICAgcmV0dXJuIHN0ZDo6bWFrZV9wYWlyKGNhbGNfeCwgY2FsY195KTsKfQoJCmludCBtYWluKCkgewoJaW50IHN0YXJ0X3ggPSAyMDA7CglpbnQgc3RhcnRfeSA9IDEwMDsKCWludCBXSURUSCA9IDUwMDsKCWludCBIRUlHSFQgPSA1MDA7CglpbnQgZGlyID0gNDU7CgkKCWNvdXQgPDwgInN0YXJ0X3BvaW50X3g6ICIgPDwgc3RhcnRfeCA8PCAiLCBzdGFydF9wb2ludF95OiAiIDw8IHN0YXJ0X3kgPDwgZW5kbDsKCQoJYXV0byBlbmRfcG9pbnQgPSBnZXRfZW5kX3BvaW50KHN0YXJ0X3gsIHN0YXJ0X3ksIFdJRFRILCBIRUlHSFQsIGRpcik7Cgljb3V0IDw8ICJlbmRfcG9pbnRfeDogIiA8PCBlbmRfcG9pbnQuZmlyc3QgPDwgIiwgZW5kX3BvaW50X3k6ICIgPDwgZW5kX3BvaW50LnNlY29uZCA8PCBlbmRsOwoJCglhdXRvIHJhbmRfcG9pbnQgPSByYW5kX3BvaW50X29uX3BhdGgoc3RhcnRfeCwgc3RhcnRfeSwgZW5kX3BvaW50LmZpcnN0LCBlbmRfcG9pbnQuc2Vjb25kLCBkaXIpOwoJY291dCA8PCAicmFuZF9wb2ludF94OiAiIDw8IHJhbmRfcG9pbnQuZmlyc3QgPDwgIiwgcmFuZF9wb2ludF95OiAiIDw8IHJhbmRfcG9pbnQuc2Vjb25kIDw8IGVuZGw7CgkKCWFzc2VydCh0ZXN0X2lzX3BvaW50X29uX3BhdGgoc3RhcnRfeCwgc3RhcnRfeSwgV0lEVEgsIEhFSUdIVCwgZGlyLCByYW5kX3BvaW50LmZpcnN0LCByYW5kX3BvaW50LnNlY29uZCkgPT0gdHJ1ZSk7CgoJcmV0dXJuIDA7Cn0=