Skip to content

Commit 87347e1

Browse files
committed
Added bresenham line 3d algorithm and basic ray trace impl.
-- Adapted the bresenham line 2d algorithm to voxels -- Added a basic ray trace implementation with simple occupancy algo.
1 parent 6f993c6 commit 87347e1

File tree

2 files changed

+151
-8
lines changed

2 files changed

+151
-8
lines changed

analyser.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,24 @@ Grid covers: [-149.2 -236.9 -9.5] to [155.6 141.5 43.1]
6060
=== STARTING MAPPING ===
6161
saiga@sai-Ideapad:~/Downloads/ModernCppProject2025/build$ cd ..
6262
```
63+
64+
### Basic Functionality Test
65+
66+
```bash
67+
saiga@sai-Ideapad:~/Downloads/ModernCppProject2025/build$ ./occupancy_grid_main
68+
=== TESTING BASIC FUNCTIONALITY ===
69+
OccupancyGrid3D initialized:
70+
Dimensions: 50×50×25
71+
Resolution: 1m
72+
Origin: -25 -25 0
73+
Total voxels: 62500
74+
Coordinate Conversion Test:
75+
World: 5.5 -3.2 2.8
76+
Grid: 30 21 2
77+
Back to World: 5.5 -3.5 2.5
78+
In Bounds: YES
79+
Occupancy after update: 0.85
80+
Occupancy after 5 updates: 5
81+
82+
=== BASIC FUNCTIONALITY TEST COMPLETED ===
83+
```

src/occupancy_grid.cpp

Lines changed: 130 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,24 +78,146 @@ float OccupancyGrid::getOccupancy(const Vector3i& grid_index) const {
7878
return grid_data[to_LinearIndex(grid_index)];
7979
}
8080

81-
// PLACEHOLDER FUNCTIONS - IMPLEMENT
8281
std::vector<Vector3i> OccupancyGrid::draw_bresenham3d_line(const Vector3i& start, const Vector3i& end) const {
83-
// TODO: Implement 3D Bresenham algorithm
84-
// PRIORITY: CRITICAL - Core mapping algorithm
82+
//Implement 3D Bresenham algorithm - adapted from 2D impl. mentioned in https://youtu.be/CceepU1vIKo, https://youtu.be/8gIhNSAXYcQ
8583
std::vector<Vector3i> voxels;
86-
voxels.push_back(start);
87-
voxels.push_back(end); // Temporary placeholder
84+
85+
int x0 = start.x(), y0 = start.y(), z0 = start.z();
86+
int x1 = end.x(), y1 = end.y(), z1 = end.z();
87+
88+
const int dx = std::abs(x1 - x0);
89+
const int dy = std::abs(y1- y0);
90+
const int dz = std::abs(z1 - z0);
91+
92+
voxels.reserve(std::max({dx,dy,dz})+1);
93+
auto drawLineH = [&]() {
94+
if (x0 > x1) {
95+
std::swap(x0,x1);
96+
std::swap(y0,y1);
97+
std::swap(z0,z1);
98+
}
99+
//direction control for non-driving axes
100+
int dir_y = (y1 >= y0) ? 1: -1;
101+
int dir_z = (z1 >= z0) ? 1 : -1;
102+
103+
// decision parameters
104+
int p1 = 2 * dy - dx;
105+
int p2 = 2 * dz - dx;
106+
107+
int y = y0, z = z0;
108+
109+
for (int x= x0; x <= x1; ++x) {
110+
voxels.emplace_back(Vector3i(x,y,z));
111+
if (x == x1) break; // once reach the end point, stop processing
112+
113+
if(p1 >=0) {
114+
y+=dir_y;
115+
p1 -= 2 * dx;
116+
}
117+
if (p2 >=0) {
118+
z+=dir_z;
119+
p2 -= 2 * dx;
120+
}
121+
p1 += 2 * dy;
122+
p2 += 2 * dz;
123+
}
124+
};
125+
126+
auto drawLineV = [&]() {
127+
if (y0 > y1) {
128+
std::swap(x0,x1);
129+
std::swap(y0,y1);
130+
std::swap(z0,z1);
131+
}
132+
//direction control for non-driving axes
133+
int dir_x = (x1 >= x0) ? 1: -1;
134+
int dir_z = (z1 >= z0) ? 1 : -1;
135+
136+
// decision parameters
137+
int p1 = 2 * dx - dy;
138+
int p2 = 2 * dz - dy;
139+
140+
int x = x0, z = z0;
141+
142+
for (int y= y0; y <= y1; ++y) {
143+
voxels.emplace_back(Vector3i(x,y,z));
144+
if (y == y1) break; // once reach the end point, stop processing
145+
146+
if(p1 >=0) {
147+
x+=dir_x;
148+
p1 -= 2 * dy;
149+
}
150+
if (p2 >=0) {
151+
z+=dir_z;
152+
p2 -= 2 * dy;
153+
}
154+
p1 += 2 * dx;
155+
p2 += 2 * dz;
156+
}
157+
};
158+
159+
auto drawLineD = [&]() {
160+
if (z0 > z1) {
161+
std::swap(x0,x1);
162+
std::swap(y0,y1);
163+
std::swap(z0,z1);
164+
}
165+
//direction control for non-driving axes
166+
int dir_x = (x1 >= x0) ? 1: -1;
167+
int dir_y = (y1 >= y0) ? 1 : -1;
168+
169+
// decision parameters
170+
int p1 = 2 * dy - dz;
171+
int p2 = 2 * dx - dz;
172+
173+
int x = x0, y = y0;
174+
175+
for (int z= z0; z <= z1; ++z) {
176+
voxels.emplace_back(Vector3i(x,y,z));
177+
if (z == z1) break; // once reach the end point, stop processing
178+
179+
if(p1 >=0) {
180+
y += dir_y;
181+
p1 -= 2 * dz;
182+
}
183+
if (p2 >=0) {
184+
x += dir_x;
185+
p2 -= 2 * dz;
186+
}
187+
p1 += 2 * dy;
188+
p2 += 2 * dx;
189+
}
190+
};
191+
192+
if (dx >= dy && dx >=dz) { // drawLineH
193+
drawLineH();
194+
} else if (dy >=dx && dy >=dz) { // drawLineV
195+
drawLineV();
196+
} else { // drawLineD
197+
drawLineD();
198+
}
199+
88200
return voxels;
89201
}
90202

203+
204+
205+
91206
void OccupancyGrid::rayTrace(const Vector3d& start, const Vector3d& end) {
92-
// TODO: Implement ray tracing
93-
// PRIORITY: CRITICAL - Main occupancy update method
207+
//Implement ray tracing - main occupancy update method
94208
Vector3i start_grid = world_to_grid(start);
95209
Vector3i end_grid = world_to_grid(end);
96210

211+
// only compute occupancy for valid rays
97212
if (is_InBounds(start_grid) && is_InBounds(end_grid)) {
98-
update_occupied(end_grid); // Temporary: just mark endpoint
213+
std::vector<Vector3i> ray_voxels = draw_bresenham3d_line(start_grid,end_grid);
214+
std::for_each(ray_voxels.begin(), ray_voxels.end()-1,
215+
[this](const Vector3i& voxel) {
216+
if (is_InBounds(voxel)) {
217+
update_free(voxel);
218+
}
219+
});
220+
update_occupied(end_grid);
99221
}
100222
}
101223

0 commit comments

Comments
 (0)