/** * Calculate a field of view from source at (x,y), pointing * in the given direction and with the given angle. The larger * the angle, the wider, "less focused" the beam. Each side of the * line pointing in the direction from the source will be half the * angle given such that the angle specified will be represented on * the raster. * * \param settings data structure containing settings. * \param map map data structure to be passed to callbacks. * \param source data structure holding source of light. * \param source_x x-axis coordinate from which to start. * \param source_y y-axis coordinate from which to start. * \param radius Euclidean distance from (x,y) after which to stop. * \param direction One of eight directions the beam of light can point. * \param angle The angle at the base of the beam of light, in degrees. */ public void fov_beam(fov_settings_type settings, map _map, Color source, int source_x, int source_y, uint radius, fov_direction_type direction, float angle) { fov_private_data_type data = new fov_private_data_type(); float start_slope, end_slope, a; data.settings = settings; data._map = _map; data.source = source; data.source_x = source_x; data.source_y = source_y; data.radius = radius; if (angle <= 0.0f) { return; } else if (angle >= 360.0f) { _fov_circle(data); } /* Calculate the angle as a percentage of 45 degrees, halved (for * each side of the centre of the beam). e.g. angle = 180.0f means * half the beam is 90.0 which is 2x45, so the result is 2.0. */ a = angle / 90.0f; if (direction == fov_direction_type.FOV_EAST) { end_slope = betweenf(a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, 0.0f, end_slope); if (a - 1.0f > Mathf.Epsilon) { /* a > 1.0f */ start_slope = betweenf(2.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, start_slope, 1.0f); } if (a - 2.0f > Mathf.Epsilon) { /* a > 2.0f */ end_slope = betweenf(a - 2.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, 0.0f, end_slope); } if (a - 3.0f > Mathf.Epsilon) { /* a > 3.0f */ start_slope = betweenf(4.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, start_slope, 1.0f); } } if (direction == fov_direction_type.FOV_WEST) { end_slope = betweenf(a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, 0.0f, end_slope); if (a - 1.0f > Mathf.Epsilon) { /* a > 1.0f */ start_slope = betweenf(2.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, start_slope, 1.0f); } if (a - 2.0f > Mathf.Epsilon) { /* a > 2.0f */ end_slope = betweenf(a - 2.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, 0.0f, end_slope); } if (a - 3.0f > Mathf.Epsilon) { /* a > 3.0f */ start_slope = betweenf(4.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, start_slope, 1.0f); } } if (direction == fov_direction_type.FOV_NORTH) { end_slope = betweenf(a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, 0.0f, end_slope); if (a - 1.0f > Mathf.Epsilon) { /* a > 1.0f */ start_slope = betweenf(2.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, start_slope, 1.0f); } if (a - 2.0f > Mathf.Epsilon) { /* a > 2.0f */ end_slope = betweenf(a - 2.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, 0.0f, end_slope); } if (a - 3.0f > Mathf.Epsilon) { /* a > 3.0f */ start_slope = betweenf(4.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, start_slope, 1.0f); } } if (direction == fov_direction_type.FOV_SOUTH) { end_slope = betweenf(a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, 0.0f, end_slope); if (a - 1.0f > Mathf.Epsilon) { /* a > 1.0f */ start_slope = betweenf(2.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, start_slope, 1.0f); } if (a - 2.0f > Mathf.Epsilon) { /* a > 2.0f */ end_slope = betweenf(a - 2.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, 0.0f, end_slope); } if (a - 3.0f > Mathf.Epsilon) { /* a > 3.0f */ start_slope = betweenf(4.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, start_slope, 1.0f); } } if (direction == fov_direction_type.FOV_NORTHEAST) { start_slope = betweenf(1.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, start_slope, 1.0f); if (a - 1.0f > Mathf.Epsilon) { /* a > 1.0f */ end_slope = betweenf(a - 1.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, 0.0f, end_slope); } if (a - 2.0f > Mathf.Epsilon) { /* a > 2.0f */ start_slope = betweenf(3.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, start_slope, 1.0f); } if (a - 3.0f > Mathf.Epsilon) { /* a > 3.0f */ end_slope = betweenf(a - 3.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, 0.0f, end_slope); } } if (direction == fov_direction_type.FOV_NORTHWEST) { start_slope = betweenf(1.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, start_slope, 1.0f); if (a - 1.0f > Mathf.Epsilon) { /* a > 1.0f */ end_slope = betweenf(a - 1.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, 0.0f, end_slope); } if (a - 2.0f > Mathf.Epsilon) { /* a > 2.0f */ start_slope = betweenf(3.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, start_slope, 1.0f); } if (a - 3.0f > Mathf.Epsilon) { /* a > 3.0f */ end_slope = betweenf(a - 3.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, 0.0f, end_slope); } } if (direction == fov_direction_type.FOV_SOUTHEAST) { start_slope = betweenf(1.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, start_slope, 1.0f); if (a - 1.0f > Mathf.Epsilon) { /* a > 1.0f */ end_slope = betweenf(a - 1.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, 0.0f, end_slope); } if (a - 2.0f > Mathf.Epsilon) { /* a > 2.0f */ start_slope = betweenf(3.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, start_slope, 1.0f); } if (a - 3.0f > Mathf.Epsilon) { /* a > 3.0f */ end_slope = betweenf(a - 3.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, 0.0f, end_slope); } } if (direction == fov_direction_type.FOV_SOUTHWEST) { start_slope = betweenf(1.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMY, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPN, data, 1, start_slope, 1.0f); if (a - 1.0f > Mathf.Epsilon) { /* a > 1.0f */ end_slope = betweenf(a - 1.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPY, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMN, data, 1, 0.0f, end_slope); } if (a - 2.0f > Mathf.Epsilon) { /* a > 2.0f */ start_slope = betweenf(3.0f - a, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PPN, data, 1, start_slope, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_MMY, data, 1, start_slope, 1.0f); } if (a - 3.0f > Mathf.Epsilon) { /* a > 3.0f */ end_slope = betweenf(a - 3.0f, 0.0f, 1.0f); _fov_octant_part(fov_octants_part.FOV_OCTANT_PMN, data, 1, 0.0f, end_slope); _fov_octant_part(fov_octants_part.FOV_OCTANT_MPY, data, 1, 0.0f, end_slope); } } }