Breshnham算法找出两点的连线经过的栅格,代码:
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
struct Vector2Int {
int x;
int y;
Vector2Int(int _x, int _y) : x(_x), y(_y) {}
Vector2Int operator-(const Vector2Int& other) const {
return Vector2Int(x - other.x, y - other.y);
}
};
class GridHelper {
public:
static std::vector<Vector2Int> GetTouchedPosBetweenTwoPoints(Vector2Int from, Vector2Int to) {
std::vector<Vector2Int> touchedGrids = GetTouchedPosBetweenOrigin2Target(to - from);
Offset(touchedGrids, from);
return touchedGrids;
}
private:
static std::vector<Vector2Int> GetTouchedPosBetweenOrigin2Target(Vector2Int target) {
std::vector<Vector2Int> touched;
bool steep = std::abs(target.y) > std::abs(target.x);
int x = steep ? target.y : target.x;
int y = steep ? target.x : target.y;
float tangent = static_cast<float>(y) / x;
float delta = x > 0 ? 0.5f : -0.5f;
for (int i = 1; i < 2 * std::abs(x); i++) {
float tempX = i * delta;
float tempY = tangent * tempX;
bool isOnEdge = std::abs(tempY - std::floor(tempY)) == 0.5f;
if ((i & 1) == 0) {//偶数
if (isOnEdge) {//若在边缘则添加两个格,不在边缘则添加一个格
//std::round(tempX) 对 tempX 进行四舍五入,而 std::ceil(tempY) 则将 tempY 向上取整,std::floor(tempY)向下取整
touched.push_back(Vector2Int(std::round(tempX), std::ceil(tempY)));
touched.push_back(Vector2Int(std::round(tempX), std::floor(tempY)));
} else {
touched.push_back(Vector2Int(std::round(tempX), std::round(tempY)));
}
} else {//奇数
if (isOnEdge) {//经过对角,不添加格
continue;
} else {
touched.push_back(Vector2Int(std::ceil(tempX), std::round(tempY)));
touched.push_back(Vector2Int(std::floor(tempX), std::round(tempY)));
}
}
}
if (steep) {
for (size_t i = 0; i < touched.size(); i++) {
Vector2Int& v = touched[i];
v.x = v.x ^ v.y;
v.y = v.x ^ v.y;
v.x = v.x ^ v.y;
}
}
touched = Except(touched, {Vector2Int(0, 0), target});
return touched;
}
static void Offset(std::vector<Vector2Int>& vec, const Vector2Int& offset) {
for (size_t i = 0; i < vec.size(); i++) {
vec[i].x += offset.x;
vec[i].y += offset.y;
}
}
static std::vector<Vector2Int> Except(std::vector<Vector2Int>& vec, const std::vector<Vector2Int>& exceptions) {
std::vector<Vector2Int> result;
for (const auto& v : vec) {
bool isException = false;
for (const auto& e : exceptions) {
if (v.x == e.x && v.y == e.y) {
isException = true;
break;
}
}
if (!isException) {
result.push_back(v);
}
}
return result;
}
};
std::vector<Vector2Int> removeDuplicates(const std::vector<Vector2Int>& input) {
std::vector<Vector2Int> result;
for (size_t i = 0; i < input.size(); ++i) {
bool duplicate = false;
for (size_t j = 0; j < i; ++j) {
if (input[i].x == input[j].x && input[i].y == input[j].y) {
duplicate = true;
break;
}
}
if (!duplicate) {
result.push_back(input[i]);
}
}
return result;
}
int main() {
Vector2Int from(1, 1);
Vector2Int to(10, 4);
std::vector<Vector2Int> touchedGrids = GridHelper::GetTouchedPosBetweenTwoPoints(from, to);
std::vector<Vector2Int>result=removeDuplicates(touchedGrids);
std::cout << "Touched Grids:" << std::endl;
for (const auto& grid : result) {
std::cout << "(" << grid.x << ", " << grid.y << ")" << std::endl;
}
return 0;
}
c++程序由下面链接里代码改写而来,原理详见这里: