ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
polygon.cpp
Go to the documentation of this file.
1#include "polygon.h"
2
4
5#include <cstdio>
6
7namespace esphome::ld2450 {
8
9namespace {
10
11class Scanner {
12 public:
13 Scanner(const char *str, size_t len) : pos_(str), end_(str + len) {}
14
15 bool at_end() const { return this->pos_ == this->end_; }
16
17 void skip_spaces() {
18 while (this->pos_ != this->end_ && *this->pos_ == ' ')
19 this->pos_++;
20 }
21
22 bool consume(char c) {
23 this->skip_spaces();
24 if (this->pos_ != this->end_ && *this->pos_ == c) {
25 this->pos_++;
26 return true;
27 }
28 return false;
29 }
30
32 bool read_int(int16_t min, int16_t max, int16_t &out) {
33 bool negative = this->consume('-');
34 int32_t value = 0;
35 uint8_t digits = 0;
36 while (this->pos_ != this->end_ && *this->pos_ >= '0' && *this->pos_ <= '9') {
37 // Six digits is already beyond any valid coordinate; stop before value can overflow
38 if (++digits > 6)
39 return false;
40 value = value * 10 + (*this->pos_ - '0');
41 this->pos_++;
42 }
43 if (digits == 0)
44 return false;
45 if (negative)
46 value = -value;
47 if (value < min || value > max)
48 return false;
49 out = static_cast<int16_t>(value);
50 return true;
51 }
52
53 protected:
54 const char *pos_;
55 const char *end_;
56};
57
58} // namespace
59
60bool Polygon::is_valid() const {
61 if (this->count == 0)
62 return true;
63 if (this->count < MIN_POLYGON_POINTS || this->count > MAX_POLYGON_POINTS)
64 return false;
65 for (uint8_t i = 0; i < this->count; i++) {
66 const Point &p = this->points[i];
67 if (p.x < POLYGON_MIN_X || p.x > POLYGON_MAX_X || p.y < POLYGON_MIN_Y || p.y > POLYGON_MAX_Y)
68 return false;
69 }
70 return true;
71}
72
73bool Polygon::contains(int16_t x, int16_t y) const {
74 bool inside = false;
75 for (uint8_t i = 0, j = this->count - 1; i < this->count; j = i++) {
76 const Point &a = this->points[i];
77 const Point &b = this->points[j];
78 if ((a.y > y) == (b.y > y))
79 continue;
80 // Does the edge a-b cross the ray going from (x, y) towards +x? Compare
81 // x - a.x < (y - a.y) * (b.x - a.x) / (b.y - a.y) without division; values fit in 32 bits.
82 const int32_t dy = static_cast<int32_t>(b.y) - a.y;
83 const int32_t lhs = (static_cast<int32_t>(x) - a.x) * dy;
84 const int32_t rhs = (static_cast<int32_t>(y) - a.y) * (static_cast<int32_t>(b.x) - a.x);
85 if (dy > 0 ? lhs < rhs : lhs > rhs)
86 inside = !inside;
87 }
88 return inside;
89}
90
91bool Polygon::parse(const char *str, size_t len) {
92 Polygon result;
93 Scanner scanner(str, len);
94 scanner.skip_spaces();
95 while (!scanner.at_end()) {
96 if (result.count == MAX_POLYGON_POINTS)
97 return false;
98 Point &p = result.points[result.count];
99 if (!scanner.read_int(POLYGON_MIN_X, POLYGON_MAX_X, p.x) || !scanner.consume(',') ||
100 !scanner.read_int(POLYGON_MIN_Y, POLYGON_MAX_Y, p.y))
101 return false;
102 result.count++;
103 bool separator = scanner.consume(';');
104 scanner.skip_spaces();
105 if (!separator && !scanner.at_end())
106 return false;
107 }
108 if (!result.is_valid())
109 return false;
110 *this = result;
111 return true;
112}
113
114void Polygon::format(char *buf) const {
115 size_t pos = 0;
116 buf[0] = '\0';
117 for (uint8_t i = 0; i < this->count; i++) {
118 pos = buf_append_printf(buf, POLYGON_STR_SIZE, pos, "%s%d,%d", i == 0 ? "" : ";", this->points[i].x,
119 this->points[i].y);
120 }
121}
122
123} // namespace esphome::ld2450
std::vector< uint8_t > & out
Definition gif.cpp:49
const void size_t len
Definition hal.h:68
size_t size_t pos
Definition helpers.h:1179
const char * end_
Definition polygon.cpp:55
const char * pos_
Definition polygon.cpp:54
A polygon in radar coordinates. Trivially copyable so it can be saved to preferences as-is.
Definition polygon.h:26
void format(char *buf) const
Write the polygon as "x,y;x,y;..." into buf, which must hold at least POLYGON_STR_SIZE bytes.
Definition polygon.cpp:114
std::array< Point, MAX_POLYGON_POINTS > points
Definition polygon.h:27
bool parse(const char *str, size_t len)
Parse "x,y;x,y;..." (mm) into this polygon.
Definition polygon.cpp:91
bool is_valid() const
True when the polygon is empty, or has a valid number of points that are all inside the radar area.
Definition polygon.cpp:60
bool contains(int16_t x, int16_t y) const
Return whether the point is inside the polygon (even-odd rule). Always false for an empty polygon.
Definition polygon.cpp:73
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6