Пример #1
0
        /**
         * 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);
                }
            }
        }