00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include <nav_grid_iterators/circle_outline.h>
00036 #include <nav_grid/coordinate_conversion.h>
00037
00038 namespace nav_grid_iterators
00039 {
00040 CircleOutline::CircleOutline(const nav_grid::NavGridInfo* info, double center_x, double center_y, double radius)
00041 : CircleOutline(info, center_x, center_y, static_cast<unsigned int>(ceil(radius / info->resolution)))
00042 {
00043 }
00044
00045 CircleOutline::CircleOutline(const nav_grid::NavGridInfo* info, double center_x, double center_y, unsigned int radius)
00046 : BaseIterator(info), distance_(radius), init_(false)
00047 {
00048 signed_width_ = static_cast<int>(info->width);
00049 signed_height_ = static_cast<int>(info->height);
00050
00051
00052 worldToGrid(*info_, center_x, center_y, center_index_x_, center_index_y_);
00053
00054 point_x_ = distance_;
00055 point_y_ = 0;
00056
00057 if (!isValidIndex(center_index_x_ + point_x_, center_index_y_ + point_y_))
00058 {
00059 increment();
00060 init_ = !isValidIndex(center_index_x_ + point_x_, center_index_y_ + point_y_);
00061 }
00062 index_.x = center_index_x_ + point_x_;
00063 index_.y = center_index_y_ + point_y_;
00064 start_index_ = index_;
00065 }
00066
00067 CircleOutline::CircleOutline(const nav_grid::NavGridInfo* info, const nav_grid::Index& index,
00068 int center_index_x, int center_index_y, unsigned int distance,
00069 bool init, const nav_grid::Index& start_index)
00070 : BaseIterator(info, index),
00071 center_index_x_(center_index_x), center_index_y_(center_index_y), distance_(distance), init_(init),
00072 start_index_(start_index)
00073 {
00074 signed_width_ = static_cast<int>(info->width);
00075 signed_height_ = static_cast<int>(info->height);
00076 point_x_ = distance_;
00077 point_y_ = 0;
00078 }
00079
00080 CircleOutline CircleOutline::begin() const
00081 {
00082 return CircleOutline(info_, start_index_, center_index_x_, center_index_y_,
00083 distance_, false, start_index_);
00084 }
00085
00086 CircleOutline CircleOutline::end() const
00087 {
00088 return CircleOutline(info_, start_index_, center_index_x_, center_index_y_,
00089 distance_, true, start_index_);
00090 }
00091
00092 void CircleOutline::increment()
00093 {
00094 init_ = true;
00095 while (true)
00096 {
00097 int nx = -signum(point_y_);
00098 int ny = signum(point_x_);
00099 if (nx != 0 && isOnOutline(point_x_ + nx, point_y_))
00100 {
00101 point_x_ += nx;
00102 }
00103 else if (ny != 0 && isOnOutline(point_x_, point_y_ + ny))
00104 {
00105 point_y_ += ny;
00106 }
00107 else
00108 {
00109 point_x_ += nx;
00110 point_y_ += ny;
00111 }
00112
00113 if (isValidIndex(center_index_x_ + point_x_, center_index_y_ + point_y_))
00114 {
00115 break;
00116 }
00117 if (point_x_ == static_cast<int>(distance_) && point_y_ == 0)
00118 {
00119 index_ = start_index_;
00120 return;
00121 }
00122 }
00123 index_.x = center_index_x_ + point_x_;
00124 index_.y = center_index_y_ + point_y_;
00125 }
00126
00127 bool CircleOutline::fieldsEqual(const CircleOutline& other)
00128 {
00129 return center_index_x_ == other.center_index_x_ && center_index_y_ == other.center_index_y_ &&
00130 distance_ == other.distance_ && init_ == other.init_;
00131 }
00132
00133 bool CircleOutline::isValidIndex(int x, int y) const
00134 {
00135 return x >= 0 && y >= 0 && x < signed_width_ && y < signed_height_;
00136 }
00137
00138 bool CircleOutline::isOnOutline(int dx, int dy) const
00139 {
00140 return static_cast<unsigned int>(hypot(dx, dy)) == distance_;
00141 }
00142
00143 }