Skip to content

Commit d31df43

Browse files
committed
fix square and diamond range
1 parent 6c1f253 commit d31df43

File tree

4 files changed

+213
-25
lines changed

4 files changed

+213
-25
lines changed

include/gf2/core/Array2D.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ namespace gf {
122122
{
123123
assert(valid(position));
124124

125-
auto dx = range(position.x - std::min(position.x, radius), position.x + std::min(m_size.w - position.x, radius));
126-
auto dy = range(position.y - std::min(position.y, radius), position.y + std::min(m_size.h - position.y, radius));
125+
auto dx = range(position.x - std::min(position.x, radius), position.x + std::min(m_size.w - position.x - 1, radius) + 1);
126+
auto dy = range(position.y - std::min(position.y, radius), position.y + std::min(m_size.h - position.y - 1, radius) + 1);
127127

128128
return { dx, dy, position };
129129
}
@@ -132,8 +132,8 @@ namespace gf {
132132
{
133133
assert(valid(position));
134134

135-
auto dx = range(position.x - std::min(position.x, radius), position.x + std::min(m_size.w - position.x, radius));
136-
auto dy = range(position.y - std::min(position.y, radius), position.y + std::min(m_size.h - position.y, radius));
135+
auto dx = range(position.x - std::min(position.x, radius), position.x + std::min(m_size.w - position.x - 1, radius) + 1);
136+
auto dy = range(position.y - std::min(position.y, radius), position.y + std::min(m_size.h - position.y - 1, radius) + 1);
137137

138138
return { dx, dy, position, radius };
139139
}

include/gf2/core/Range.h

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ namespace gf {
300300
return copy;
301301
}
302302

303-
constexpr bool operator!=(const Iterator& other) const noexcept { return m_current != other.m_current; }
304-
constexpr bool operator==(const Iterator& other) const noexcept { return m_current == other.m_current; }
303+
constexpr bool operator!=(Vec2<T> other) const noexcept { return m_current != other; }
304+
constexpr bool operator==(Vec2<T> other) const noexcept { return m_current == other; }
305305

306306
private:
307307
void step() noexcept
@@ -348,14 +348,9 @@ namespace gf {
348348
};
349349
}
350350

351-
constexpr Iterator end() const
351+
constexpr Vec2<T> end() const
352352
{
353-
return {
354-
{ m_dx.lo(), m_dy.hi() },
355-
m_dx,
356-
m_dy,
357-
m_origin
358-
};
353+
return { m_dx.lo(), m_dy.hi() };
359354
}
360355

361356
private:
@@ -367,7 +362,7 @@ namespace gf {
367362
template<typename T>
368363
constexpr NeighborSquareRange<T> neighbor_square_range(Vec2<T> origin, T radius = T(1)) noexcept
369364
{
370-
return { range(origin.x - radius, origin.x + radius), range(origin.y - radius, origin.y + radius), origin };
365+
return { range(origin.x - radius, origin.x + radius + 1), range(origin.y - radius, origin.y + radius + 1), origin };
371366
}
372367

373368
template<typename T>
@@ -429,8 +424,8 @@ namespace gf {
429424
return copy;
430425
}
431426

432-
constexpr bool operator!=(const Iterator& other) const noexcept { return m_current != other.m_current; }
433-
constexpr bool operator==(const Iterator& other) const noexcept { return m_current == other.m_current; }
427+
constexpr bool operator!=(Vec2<T> other) const noexcept { return m_current != other; }
428+
constexpr bool operator==(Vec2<T> other) const noexcept { return m_current == other; }
434429

435430
private:
436431
void step() noexcept
@@ -485,15 +480,9 @@ namespace gf {
485480
};
486481
}
487482

488-
constexpr Iterator end() const
483+
constexpr Vec2<T> end() const
489484
{
490-
return {
491-
{ m_dx.lo(), m_dy.hi() },
492-
m_dx,
493-
m_dy,
494-
m_origin,
495-
m_radius
496-
};
485+
return { m_dx.lo(), m_dy.hi() };
497486
}
498487

499488
private:
@@ -506,7 +495,7 @@ namespace gf {
506495
template<typename T>
507496
constexpr NeighborDiamondRange<T> neighbor_diamond_range(Vec2<T> origin, T radius = T(1)) noexcept
508497
{
509-
return { range(origin.x - radius, origin.x + radius), range(origin.y - radius, origin.y + radius), origin, radius };
498+
return { range(origin.x - radius, origin.x + radius + 1), range(origin.y - radius, origin.y + radius + 1), origin, radius };
510499
}
511500

512501
template<typename T>

tests/tests_core_Array2D.cc

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <gf2/core/Array2D.h>
2+
3+
#include "gtest/gtest.h"
4+
5+
#include <iostream>
6+
7+
constexpr gf::Vec2I Size = { 7, 7 };
8+
9+
TEST(Array2DTest, PositionRange) {
10+
gf::Array2D<char> array(Size);
11+
int count = 0;
12+
13+
for (auto position : array.position_range()) {
14+
ASSERT_TRUE(array.valid(position));
15+
++count;
16+
}
17+
18+
EXPECT_EQ(count, Size.x * Size.y);
19+
}
20+
21+
TEST(Array2DTest, FourNeighbors) {
22+
gf::Array2D<char> array(Size);
23+
24+
for (auto position : array.position_range()) {
25+
for (auto neighbor : array.compute_4_neighbors_range(position)) {
26+
ASSERT_TRUE(array.valid(neighbor));
27+
}
28+
}
29+
}
30+
31+
TEST(Array2DTest, EightNeighbors) {
32+
gf::Array2D<char> array(Size);
33+
34+
for (auto position : array.position_range()) {
35+
for (auto neighbor : array.compute_8_neighbors_range(position)) {
36+
ASSERT_TRUE(array.valid(neighbor));
37+
}
38+
}
39+
}
40+
41+
TEST(Array2DTest, TwelveNeighbors) {
42+
gf::Array2D<char> array(Size);
43+
44+
for (auto position : array.position_range()) {
45+
for (auto neighbor : array.compute_12_neighbors_range(position)) {
46+
ASSERT_TRUE(array.valid(neighbor));
47+
}
48+
}
49+
}
50+
51+
TEST(Array2DTest, TwentyFourNeighbors) {
52+
gf::Array2D<char> array(Size);
53+
54+
for (auto position : array.position_range()) {
55+
for (auto neighbor : array.compute_24_neighbors_range(position)) {
56+
ASSERT_TRUE(array.valid(neighbor));
57+
}
58+
}
59+
}

tests/tests_core_Range.cc

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
#include "gtest/gtest.h"
44

5+
#include <iostream>
6+
57
using RangeI = gf::Range<int>;
68
using RangeF = gf::Range<float>;
79

@@ -91,3 +93,141 @@ TEST(RangeTest, BeginEnd) {
9193

9294
ASSERT_EQ(count, ri.size());
9395
}
96+
97+
/*
98+
* NeighborSquareRange
99+
*/
100+
101+
TEST(RangeTest, NeighborSquareCanonical) {
102+
for (int radius = 1; radius < 5; ++radius) {
103+
const gf::NeighborSquareRange<int> range = gf::neighbor_square_range({ 0, 0 }, radius);
104+
int count = 0;
105+
106+
for ([[maybe_unused]] auto position : range) {
107+
++count;
108+
}
109+
110+
ASSERT_EQ(count, ((2 * radius + 1) * (2 * radius + 1)) - 1);
111+
}
112+
}
113+
114+
TEST(RangeTest, NeighborSquareCorner) {
115+
for (int radius = 1; radius < 5; ++radius) {
116+
const gf::NeighborSquareRange<int> range(gf::range(0, radius + 1), gf::range(0, radius + 1), { 0, 0 });
117+
int count = 0;
118+
119+
for ([[maybe_unused]] auto position : range) {
120+
++count;
121+
}
122+
123+
ASSERT_EQ(count, ((radius + 1) * (radius + 1)) - 1);
124+
}
125+
}
126+
127+
TEST(RangeTest, NeighborSquareOppositeCorner) {
128+
for (int radius = 1; radius < 5; ++radius) {
129+
const gf::NeighborSquareRange<int> range(gf::range(0, radius + 1), gf::range(0, radius + 1), { radius, radius });
130+
int count = 0;
131+
132+
for ([[maybe_unused]] auto position : range) {
133+
++count;
134+
}
135+
136+
ASSERT_EQ(count, ((radius + 1) * (radius + 1)) - 1);
137+
}
138+
}
139+
140+
TEST(RangeTest, NeighborSquareHorizontalSide) {
141+
for (int radius = 1; radius < 5; ++radius) {
142+
const gf::NeighborSquareRange<int> range(gf::range(0, (2 * radius) + 1), gf::range(0, radius), { radius, 0 });
143+
int count = 0;
144+
145+
for ([[maybe_unused]] auto position : range) {
146+
++count;
147+
}
148+
149+
ASSERT_EQ(count, (radius * (2 * radius + 1)) - 1);
150+
}
151+
}
152+
153+
TEST(RangeTest, NeighborSquareVerticalSide) {
154+
for (int radius = 1; radius < 5; ++radius) {
155+
const gf::NeighborSquareRange<int> range(gf::range(0, radius), gf::range(0, (2 * radius) + 1), { 0, radius });
156+
int count = 0;
157+
158+
for ([[maybe_unused]] auto position : range) {
159+
++count;
160+
}
161+
162+
ASSERT_EQ(count, (radius * (2 * radius + 1)) - 1);
163+
}
164+
}
165+
166+
/*
167+
* NeighborDiamondRange
168+
*/
169+
170+
TEST(RangeTest, NeighborDiamondCanonical) {
171+
for (int radius = 1; radius < 5; ++radius) {
172+
const gf::NeighborDiamondRange<int> range = gf::neighbor_diamond_range({ 0, 0 }, radius);
173+
int count = 0;
174+
175+
for ([[maybe_unused]] auto position : range) {
176+
++count;
177+
}
178+
179+
ASSERT_EQ(count, (radius * radius) + ((radius + 1) * (radius + 1)) - 1);
180+
}
181+
}
182+
183+
TEST(RangeTest, NeighborDiamondCorner) {
184+
for (int radius = 1; radius < 5; ++radius) {
185+
const gf::NeighborDiamondRange<int> range(gf::range(0, radius + 1), gf::range(0, radius + 1), { 0, 0 }, radius);
186+
int count = 0;
187+
188+
for ([[maybe_unused]] auto position : range) {
189+
++count;
190+
}
191+
192+
ASSERT_EQ(count, ((radius + 1) * (radius + 2) / 2) - 1);
193+
}
194+
}
195+
196+
TEST(RangeTest, NeighborDiamondOppositeCorner) {
197+
for (int radius = 1; radius < 5; ++radius) {
198+
const gf::NeighborDiamondRange<int> range(gf::range(0, radius + 1), gf::range(0, radius + 1), { radius, radius }, radius);
199+
int count = 0;
200+
201+
for ([[maybe_unused]] auto position : range) {
202+
++count;
203+
}
204+
205+
ASSERT_EQ(count, ((radius + 1) * (radius + 2) / 2) - 1);
206+
}
207+
}
208+
209+
TEST(RangeTest, NeighborDiamondHorizontalSide) {
210+
for (int radius = 1; radius < 5; ++radius) {
211+
const gf::NeighborDiamondRange<int> range(gf::range(0, (2 * radius) + 2), gf::range(0, radius + 1), { radius, 0 }, radius);
212+
int count = 0;
213+
214+
for ([[maybe_unused]] auto position : range) {
215+
++count;
216+
}
217+
218+
ASSERT_EQ(count, ((radius + 1) * (radius + 1)) - 1);
219+
}
220+
}
221+
222+
TEST(RangeTest, NeighborDiamondVerticalSide) {
223+
for (int radius = 1; radius < 5; ++radius) {
224+
const gf::NeighborDiamondRange<int> range(gf::range(0, radius + 1), gf::range(0, (2 * radius) + 2), { 0, radius }, radius);
225+
int count = 0;
226+
227+
for ([[maybe_unused]] auto position : range) {
228+
++count;
229+
}
230+
231+
ASSERT_EQ(count, ((radius + 1) * (radius + 1)) - 1);
232+
}
233+
}

0 commit comments

Comments
 (0)