} END_TEST


#pragma mark -
#pragma mark test_shape_impl_geometry_lat_range_gc_seg

START_TEST (test_shape_impl_geometry_lat_range_gc_seg) {
	// arbitrary course northern hemisphere
	int i = 1;
	// New York to Berlin
	atlas_shp_coordinate_t c11 = {-73.7789, 40.6397};
	atlas_shp_coordinate_t c12 = { 13.2833, 52.5667};
	double result_min_1, result_max_1;
	
	int latr_1 = atlas_lat_range_gc_seg(&result_min_1, &result_max_1,
										&c11, &c12);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_1);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_1);
	
	fail_unless(40 < result_min_1 < 41);
	fail_unless(56 < result_max_1 < 57);
	
	
	// arbitrary course southern hemisphere
	i++;
	atlas_shp_coordinate_t c21 = { 110, -40};
	atlas_shp_coordinate_t c22 = {-150, -50};
	double result_min_2, result_max_2;
	
	int latr_2 = atlas_lat_range_gc_seg(&result_min_2, &result_max_2,
										&c21, &c22);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_2);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_2);
	
	fail_unless(-57.9 > result_min_2 > -58.1);
	fail_unless(abs_value_check(result_max_2, -40.0, 0.1));
	
	
	// northern hemisphere, one points south, the other one north
	i++;
	atlas_shp_coordinate_t c31 = {-10, 50};
	atlas_shp_coordinate_t c32 = { 30, 30};
	double result_min_3, result_max_3;
	
	int latr_3 = atlas_lat_range_gc_seg(&result_min_3, &result_max_3,
										&c31, &c32);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_3);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_3);
	
	fail_unless(abs_value_check(result_max_3, 50.0, 0.1));
	fail_unless(abs_value_check(result_min_3, 30.0, 0.1));
	
	
	// northern hemisphere, one points south, the other one north
	i++;
	atlas_shp_coordinate_t c41 = {-10, -50};
	atlas_shp_coordinate_t c42 = {-30, -30};
	double result_min_4, result_max_4;
	
	int latr_4 = atlas_lat_range_gc_seg(&result_min_4, &result_max_4,
										&c41, &c42);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_4);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_4);
	
	fail_unless(abs_value_check(result_max_4, -30.0, 0.1));
	fail_unless(abs_value_check(result_min_4, -50.0, 0.1));
	
	// meridian not crossing pole
	i++;
	atlas_shp_coordinate_t c51 = {10,  80};
	atlas_shp_coordinate_t c52 = {10, -70};
	double result_min_5, result_max_5;
	
	int latr_5 = atlas_lat_range_gc_seg(&result_min_5, &result_max_5,
										&c51, &c52);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_5);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_5);
	
	fail_unless(abs_value_check(result_max_5,  80.0, 0.1));
	fail_unless(abs_value_check(result_min_5, -70.0, 0.1));
	
	// meridian crossing north pole
	i++;
	atlas_shp_coordinate_t c61 = {-170, 80};
	atlas_shp_coordinate_t c62 = {  10, 60};
	double result_min_6, result_max_6;
	
	int latr_6 = atlas_lat_range_gc_seg(&result_min_6, &result_max_6,
										&c61, &c62);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_6);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_6);
	
	fail_unless(abs_value_check(result_max_6, 90.0, 0.1));
	fail_unless(abs_value_check(result_min_6, 60.0, 0.1));
	
	// meridian crossing south pole
	i++;
	atlas_shp_coordinate_t c71 = {-110, -80};
	atlas_shp_coordinate_t c72 = {  70, -60};
	double result_min_7, result_max_7;
	
	int latr_7 = atlas_lat_range_gc_seg(&result_min_7, &result_max_7,
										&c71, &c72);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_7);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_7);
	
	fail_unless(abs_value_check(result_max_7, -60.0, 0.1));
	fail_unless(abs_value_check(result_min_7, -90.0, 0.1));
	
	// BES-NOU (Brest, F - Nouméa, NC), both point north, different hemispheres
	i++;
	atlas_shp_coordinate_t c81 = { -4,  48};
	atlas_shp_coordinate_t c82 = {166, -22};
	double result_min_8, result_max_8;
	
	int latr_8 = atlas_lat_range_gc_seg(&result_min_8, &result_max_8,
										&c81, &c82);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_8);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_8);
	
	fail_unless(76.3 < result_max_8 && result_max_8 < 76.4);
	fail_unless(abs_value_check(result_min_8, -22.0, 0.1));
	
	// both antipodal
	i++;
	atlas_shp_coordinate_t c91 = {-80, -10};
	atlas_shp_coordinate_t c92 = {100,  10};
	double result_min_9, result_max_9;
	
	int latr_9 = atlas_lat_range_gc_seg(&result_min_9, &result_max_9,
										&c91, &c92);
	
	//printf("TEST lat_range_gc_seg %i: min-lat = %f \n", i, result_min_9);
	//printf("TEST lat_range_gc_seg %i: max-lat = %f \n", i, result_max_9);
	
	fail_unless(abs_value_check(result_min_9, -10.0, 0.1));
	fail_unless(abs_value_check(result_max_9,  10.0, 0.1));
	
	
	
} END_TEST
} END_TEST


START_TEST (test_shape_impl_gc_intersection) {
	// first great circle is the equator
	atlas_shp_coordinate_t c_gc_111 = {20.0,  0.0};
	atlas_shp_coordinate_t c_gc_112 = {60.0,  0.0};
	// second great circle is the 10°/-170° longitude
	atlas_shp_coordinate_t c_gc_121 = {10.0, 10.0};
	atlas_shp_coordinate_t c_gc_122 = {10.0, 50.0};
	
	atlas_shp_coordinate_t result11;
	atlas_shp_coordinate_t result12;
	
	int result1 = atlas_shape_gc_intersection(&result11, &result12, &c_gc_111, &c_gc_112, &c_gc_121, &c_gc_122);
	
	fail_unless(result1 == 0);
	
	//printf("GCI (intersect1): lat=%f lon=%f\n", result11.latitude, result11.longitude);
	//printf("GCI (intersect2): lat=%f lon=%f\n", result12.latitude, result12.longitude);
	
	fail_if( abs_value_check(result11.latitude, 0.0, 1.0E-10) == 0 );
	fail_if( abs_value_check(result11.longitude, 10.0, 1.0E-10) == 0 );
	fail_if( abs_value_check(result12.latitude, 0.0, 1.0E-10) == 0 );
	fail_if( abs_value_check(result12.longitude, -170.0, 1.0E-10) == 0 );
	
	
	
	// KSEA
	atlas_shp_coordinate_t c_gc_211 = {-122.309306, 47.449};
	// LOWW
	atlas_shp_coordinate_t c_gc_212 = {16.569722, 48.110278};
	// KJFK
	atlas_shp_coordinate_t c_gc_221 = {-73.778925, 40.63975};
	// EFHK
	atlas_shp_coordinate_t c_gc_222 = {24.963333, 60.317222};
	
	atlas_shp_coordinate_t result21;
	atlas_shp_coordinate_t result22;
	
	int result2 = atlas_shape_gc_intersection(&result21, &result22, &c_gc_211, &c_gc_212, &c_gc_221, &c_gc_222);
	
	fail_unless(result2 == 0);
	
	//printf("GCI (intersect1): lat=%f lon=%f\n", result21.latitude, result21.longitude);
	//printf("GCI (intersect2): lat=%f lon=%f\n", result22.latitude, result22.longitude);
	
	fail_if( abs_value_check(result21.latitude, 64.0, 1.0) == 0 );
	fail_if( abs_value_check(result21.longitude, -4.0, 1.0) == 0 );
	fail_if( abs_value_check(result22.latitude, -64.0, 1.0) == 0 );
	fail_if( abs_value_check(result22.longitude, 176.0, 1.0) == 0 );
	
	
	// meridian 1
	atlas_shp_coordinate_t c_gc_311 = {20.0, 90.0};
	atlas_shp_coordinate_t c_gc_312 = {20.0, 20.0};
	// meridian 2
	atlas_shp_coordinate_t c_gc_321 = {-60.0, 70.0};
	atlas_shp_coordinate_t c_gc_322 = {-60.0, 50.0};
	
	atlas_shp_coordinate_t result31;
	atlas_shp_coordinate_t result32;
	
	int result3 = atlas_shape_gc_intersection(&result31, &result32, &c_gc_311, &c_gc_312, &c_gc_321, &c_gc_322);
	
	fail_unless(result3 == 0);
	
	//printf("GCI (intersect1): lat=%f lon=%f\n", result31.latitude, result31.longitude);
	//printf("GCI (intersect2): lat=%f lon=%f\n", result32.latitude, result32.longitude);
	
	fail_if( abs_value_check(result31.latitude, 90.0, 1.0E-10) == 0 );
	fail_if( abs_value_check(result31.longitude, 0.0, 1.0E-10) == 0 );
	fail_if( abs_value_check(result32.latitude, -90.0, 1.0E-10) == 0 );
	fail_if( abs_value_check(result32.longitude, 0.0, 1.0E-10) == 0 );
	
	
	//printf("Equal GC\n");
	atlas_shp_coordinate_t c_gc_411 = {5.0, 89.0};
	atlas_shp_coordinate_t c_gc_412 = {10.0, -89.0};
	atlas_shp_coordinate_t c_gc_421 = {-175.0, -89.0};
	atlas_shp_coordinate_t c_gc_422 = {-170.0, 89.0};
		
	atlas_shp_coordinate_t result41;
	atlas_shp_coordinate_t result42;
	
	int result4 = atlas_shape_gc_intersection(&result41, &result42, &c_gc_411, &c_gc_412, &c_gc_421, &c_gc_422);
	
	fail_unless( result4 == 1 );
	
	
	//printf("GCI (intersect1): lat=%f lon=%f\n", result41.latitude, result41.longitude);
	//printf("GCI (intersect2): lat=%f lon=%f\n", result42.latitude, result42.longitude);
	
	
} END_TEST
} END_TEST


#pragma mark -
#pragma mark test_shape_impl_geometry_initial_course

START_TEST (test_shape_impl_geometry_initial_course) {
	// arbitrary course northern hemisphere
	int i = 1;
	atlas_shp_coordinate_t c11 = {-73.7789, 40.6397};
	atlas_shp_coordinate_t c12 = { 13.2833, 52.5667};
	double hdg11, hdg12;
	atlas_gc_initial_course(&hdg11, &c11, &c12);
	//printf("TEST initial_course %i: course1 = %f \n", i, hdg11);
	atlas_gc_initial_course(&hdg12, &c12, &c11);
	//printf("TEST initial_course %i: course2 = %f \n", i, hdg12);
	fail_unless(hdg11 > 46 && hdg11 < 47);
	fail_unless(hdg12 > 295 && hdg12 < 296);
	
	// arbitrary course southern hemisphere
	i++;
	atlas_shp_coordinate_t c21 = {-120, -40};
	atlas_shp_coordinate_t c22 = {  15, -60};
	
	double hdg21, hdg22;
	atlas_gc_initial_course(&hdg21, &c21, &c22);
	//printf("TEST initial_course %i: course1 = %f \n", i, hdg21);
	atlas_gc_initial_course(&hdg22, &c22, &c21);
	//printf("TEST initial_course %i: course2 = %f \n", i, hdg22);
	fail_unless(hdg21 > 158 && hdg21 < 159);
	fail_unless(hdg22 > 214 && hdg22 < 215);
	
	// course along meridian
	i++;
	atlas_shp_coordinate_t c31 = {15, 50};
	atlas_shp_coordinate_t c32 = {15, -20};
	
	double hdg31, hdg32;
	atlas_gc_initial_course(&hdg31, &c31, &c32);
	//printf("TEST initial_course %i: course1 = %f \n", i, hdg31);
	atlas_gc_initial_course(&hdg32, &c32, &c31);
	//printf("TEST initial_course %i: course2 = %f \n", i, hdg32);
	fail_unless(abs_value_check(hdg31, 180.0, 0.1) == 1);
	fail_unless(abs_value_check(hdg32, 0.0, 0.1) == 1);
	
	// course over pole
	i++;
	atlas_shp_coordinate_t c41 = {-80, -70};
	atlas_shp_coordinate_t c42 = {100, -75};
	
	double hdg41, hdg42;
	atlas_gc_initial_course(&hdg41, &c41, &c42);
	//printf("TEST initial_course %i: course1 = %f \n", i, hdg41);
	atlas_gc_initial_course(&hdg42, &c42, &c41);
	//printf("TEST initial_course %i: course2 = %f \n", i, hdg42);
	fail_unless(abs_value_check(hdg41, 180.0, 0.1) == 1);
	fail_unless(abs_value_check(hdg42, 180.0, 0.1) == 1);
	
	// course southern hemisphere across dateline
	i++;
	atlas_shp_coordinate_t c51 = { 110, -40};
	atlas_shp_coordinate_t c52 = {-150, -50};
    
	double hdg51, hdg52;
	atlas_gc_initial_course(&hdg51, &c51, &c52);
	//printf("TEST initial_course %i: course1 = %f \n", i, hdg51);
	atlas_gc_initial_course(&hdg52, &c52, &c51);
	//printf("TEST initial_course %i: course2 = %f \n", i, hdg52);
	fail_unless(hdg51 > 136 && hdg51 < 137);
	fail_unless(hdg52 > 235 && hdg52 < 236);
	
	// point only
	i++;
	atlas_shp_coordinate_t c61 = {0, 0};
	atlas_shp_coordinate_t c62 = {0, 0};
	;
	double hdg61, hdg62;
	atlas_gc_initial_course(&hdg61, &c61, &c62);
	//printf("TEST initial_course %i: course1 = %f \n", i, hdg61);
	atlas_gc_initial_course(&hdg52, &c62, &c61);
	//printf("TEST initial_course %i: course2 = %f \n", i, hdg62);
	
	
} END_TEST