Polygon: Use std::vector to store the vertices

This commit is contained in:
Peter Keresztes Schmidt 2021-05-08 22:25:53 +02:00
parent eaf91fcf1f
commit 5af6d6af3d
5 changed files with 92 additions and 145 deletions

View File

@ -2382,12 +2382,12 @@ void Image::Outline( Rgb colour, const Polygon &polygon ) {
}
/* Convert the colour's RGBA subpixel order into the image's subpixel order */
colour = rgb_convert(colour,subpixelorder);
colour = rgb_convert(colour, subpixelorder);
int n_coords = polygon.getNumCoords();
for ( int j = 0, i = n_coords-1; j < n_coords; i = j++ ) {
const Vector2 &p1 = polygon.getCoord(i);
const Vector2 &p2 = polygon.getCoord(j);
size_t n_coords = polygon.GetVertices().size();
for (size_t j = 0, i = n_coords - 1; j < n_coords; i = j++) {
const Vector2 &p1 = polygon.GetVertices()[i];
const Vector2 &p2 = polygon.GetVertices()[j];
int x1 = p1.x_;
int x2 = p2.x_;
@ -2466,12 +2466,12 @@ void Image::Fill(Rgb colour, int density, const Polygon &polygon) {
/* Convert the colour's RGBA subpixel order into the image's subpixel order */
colour = rgb_convert(colour, subpixelorder);
int n_coords = polygon.getNumCoords();
size_t n_coords = polygon.GetVertices().size();
int n_global_edges = 0;
Edge global_edges[n_coords];
for ( int j = 0, i = n_coords-1; j < n_coords; i = j++ ) {
const Vector2 &p1 = polygon.getCoord(i);
const Vector2 &p2 = polygon.getCoord(j);
for (size_t j = 0, i = n_coords - 1; j < n_coords; i = j++) {
const Vector2 &p1 = polygon.GetVertices()[i];
const Vector2 &p2 = polygon.GetVertices()[j];
int x1 = p1.x_;
int x2 = p2.x_;

View File

@ -1482,20 +1482,21 @@ void Monitor::DumpZoneImage(const char *zone_string) {
}
for (const Zone &zone : zones) {
if ( exclude_id && (!extra_colour || extra_zone.getNumCoords()) && zone.Id() == exclude_id )
if (exclude_id && (!extra_colour || !extra_zone.GetVertices().empty()) && zone.Id() == exclude_id) {
continue;
}
Rgb colour;
if ( exclude_id && !extra_zone.getNumCoords() && zone.Id() == exclude_id ) {
if (exclude_id && extra_zone.GetVertices().empty() && zone.Id() == exclude_id) {
colour = extra_colour;
} else {
if ( zone.IsActive() ) {
if (zone.IsActive()) {
colour = kRGBRed;
} else if ( zone.IsInclusive() ) {
} else if (zone.IsInclusive()) {
colour = kRGBOrange;
} else if ( zone.IsExclusive() ) {
} else if (zone.IsExclusive()) {
colour = kRGBPurple;
} else if ( zone.IsPreclusive() ) {
} else if (zone.IsPreclusive()) {
colour = kRGBBlue;
} else {
colour = kRGBWhite;
@ -1505,7 +1506,7 @@ void Monitor::DumpZoneImage(const char *zone_string) {
zone_image->Outline(colour, zone.GetPolygon());
}
if ( extra_zone.getNumCoords() ) {
if (!extra_zone.GetVertices().empty()) {
zone_image->Fill(extra_colour, 2, extra_zone);
zone_image->Outline(extra_colour, extra_zone);
}

View File

@ -21,84 +21,54 @@
#include <cmath>
Polygon::Polygon(std::vector<Vector2> vertices) : vertices_(std::move(vertices)) {
int min_x = -1;
int max_x = -1;
int min_y = -1;
int max_y = -1;
for (const Vector2 &vertex : vertices_) {
if (min_x == -1 || vertex.x_ < min_x)
min_x = vertex.x_;
if (max_x == -1 || vertex.x_ > max_x)
max_x = vertex.x_;
if (min_y == -1 || vertex.y_ < min_y)
min_y = vertex.y_;
if (max_y == -1 || vertex.y_ > max_y)
max_y = vertex.y_;
}
extent = Box({min_x, min_y}, {max_x, max_y});
calcArea();
calcCentre();
}
void Polygon::calcArea() {
double float_area = 0.0L;
for (int i = 0, j = n_coords - 1; i < n_coords; j = i++) {
double trap_area = ((coords[i].x_ - coords[j].x_) * ((coords[i].y_ + coords[j].y_))) / 2.0L;
for (size_t i = 0, j = vertices_.size() - 1; i < vertices_.size(); j = i++) {
double trap_area = ((vertices_[i].x_ - vertices_[j].x_) * ((vertices_[i].y_ + vertices_[j].y_))) / 2.0L;
float_area += trap_area;
//printf( "%.2f (%.2f)\n", float_area, trap_area );
}
area = (int) round(fabs(float_area));
}
void Polygon::calcCentre() {
if (!area && n_coords)
if (!area && !vertices_.empty())
calcArea();
double float_x = 0.0L, float_y = 0.0L;
for (int i = 0, j = n_coords - 1; i < n_coords; j = i++) {
float_x += ((coords[i].y_ - coords[j].y_) * ((coords[i].x_ * 2) + (coords[i].x_ * coords[j].x_) + (coords[j].x_ * 2)));
float_y += ((coords[j].x_ - coords[i].x_) * ((coords[i].y_ * 2) + (coords[i].y_ * coords[j].y_) + (coords[j].y_ * 2)));
for (size_t i = 0, j = vertices_.size() - 1; i < vertices_.size(); j = i++) {
float_x += ((vertices_[i].y_ - vertices_[j].y_) * ((vertices_[i].x_ * 2) + (vertices_[i].x_ * vertices_[j].x_) + (vertices_[j].x_ * 2)));
float_y += ((vertices_[j].x_ - vertices_[i].x_) * ((vertices_[i].y_ * 2) + (vertices_[i].y_ * vertices_[j].y_) + (vertices_[j].y_ * 2)));
}
float_x /= (6 * area);
float_y /= (6 * area);
centre = Vector2((int) round(float_x), (int) round(float_y));
}
Polygon::Polygon(int p_n_coords, const Vector2 *p_coords) : n_coords(p_n_coords) {
coords = new Vector2[n_coords];
int min_x = -1;
int max_x = -1;
int min_y = -1;
int max_y = -1;
for (int i = 0; i < n_coords; i++) {
coords[i] = p_coords[i];
if (min_x == -1 || coords[i].x_ < min_x)
min_x = coords[i].x_;
if (max_x == -1 || coords[i].x_ > max_x)
max_x = coords[i].x_;
if (min_y == -1 || coords[i].y_ < min_y)
min_y = coords[i].y_;
if (max_y == -1 || coords[i].y_ > max_y)
max_y = coords[i].y_;
}
extent = Box({min_x, min_y}, {max_x, max_y});
calcArea();
calcCentre();
}
Polygon::Polygon(const Polygon &p_polygon) :
n_coords(p_polygon.n_coords),
extent(p_polygon.extent),
area(p_polygon.area),
centre(p_polygon.centre) {
coords = new Vector2[n_coords];
for (int i = 0; i < n_coords; i++) {
coords[i] = p_polygon.coords[i];
}
}
Polygon &Polygon::operator=(const Polygon &p_polygon) {
n_coords = p_polygon.n_coords;
Vector2 *new_coords = new Vector2[n_coords];
for (int i = 0; i < n_coords; i++) {
new_coords[i] = p_polygon.coords[i];
}
delete[] coords;
coords = new_coords;
extent = p_polygon.extent;
area = p_polygon.area;
centre = p_polygon.centre;
return *this;
}
bool Polygon::isInside(const Vector2 &coord) const {
bool Polygon::Contains(const Vector2 &coord) const {
bool inside = false;
for (int i = 0, j = n_coords - 1; i < n_coords; j = i++) {
if ((((coords[i].y_ <= coord.y_) && (coord.y_ < coords[j].y_)) || ((coords[j].y_ <= coord.y_) && (coord.y_ < coords[i].y_)))
&& (coord.x_ < (coords[j].x_ - coords[i].x_) * (coord.y_ - coords[i].y_) / (coords[j].y_ - coords[i].y_) + coords[i].x_)) {
for (size_t i = 0, j = vertices_.size() - 1; i < vertices_.size(); j = i++) {
if ((((vertices_[i].y_ <= coord.y_) && (coord.y_ < vertices_[j].y_)) || ((vertices_[j].y_ <= coord.y_) && (coord.y_ < vertices_[i].y_)))
&& (coord.x_ < (vertices_[j].x_ - vertices_[i].x_) * (coord.y_ - vertices_[i].y_) / (vertices_[j].y_ - vertices_[i].y_) + vertices_[i].x_)) {
inside = !inside;
}
}

View File

@ -21,6 +21,7 @@
#define ZM_POLY_H
#include "zm_box.h"
#include <vector>
struct Edge {
int min_y;
@ -44,50 +45,12 @@ struct Edge {
// defined by two coordinates
//
class Polygon {
protected:
struct Slice {
int min_x;
int max_x;
int n_edges;
int *edges;
public:
Polygon() : area(0) {}
explicit Polygon(std::vector<Vector2> vertices);
Slice() {
min_x = 0;
max_x = 0;
n_edges = 0;
edges = nullptr;
}
~Slice() {
delete edges;
}
};
protected:
int n_coords;
Vector2 *coords;
Box extent;
int area;
Vector2 centre;
protected:
void initialiseEdges();
void calcArea();
void calcCentre();
public:
inline Polygon() : n_coords(0), coords(nullptr), area(0) {
}
Polygon(int p_n_coords, const Vector2 *p_coords);
Polygon(const Polygon &p_polygon);
~Polygon() {
delete[] coords;
}
Polygon &operator=( const Polygon &p_polygon );
inline int getNumCoords() const { return n_coords; }
inline const Vector2 &getCoord( int index ) const {
return coords[index];
const std::vector<Vector2> &GetVertices() const {
return vertices_;
}
const Box &Extent() const { return extent; }
@ -96,11 +59,22 @@ public:
int LoY(int p_lo_y) { return extent.LoY(p_lo_y); }
int HiY(int p_hi_y) { return extent.HiY(p_hi_y); }
inline int Area() const { return area; }
inline const Vector2 &Centre() const {
int Area() const { return area; }
const Vector2 &Centre() const {
return centre;
}
bool isInside(const Vector2 &coord) const;
bool Contains(const Vector2 &coord) const;
private:
void calcArea();
void calcCentre();
private:
std::vector<Vector2> vertices_;
Box extent;
int area;
Vector2 centre;
};
#endif // ZM_POLY_H

View File

@ -748,37 +748,39 @@ bool Zone::CheckAlarms(const Image *delta_image) {
bool Zone::ParsePolygonString(const char *poly_string, Polygon &polygon) {
char *str = (char *)poly_string;
int n_coords = 0;
int max_n_coords = strlen(str)/4;
Vector2 *coords = new Vector2[max_n_coords];
std::vector<Vector2> vertices;
vertices.reserve(max_n_coords);
while (*str != '\0') {
char *cp = strchr(str, ',');
if (!cp) {
Error("Bogus coordinate %s found in polygon string", str);
break;
}
int x = atoi(str);
int y = atoi(cp+1);
int y = atoi(cp + 1);
Debug(3, "Got coordinate %d,%d from polygon string", x, y);
coords[n_coords++] = Vector2(x, y);
vertices.emplace_back(x, y);
char *ws = strchr(cp+2, ' ');
if (ws)
str = ws+1;
else
break;
} // end while ! end of string
if (n_coords > 2) {
Debug(3, "Successfully parsed polygon string %s", str);
polygon = Polygon(n_coords, coords);
char *ws = strchr(cp + 2, ' ');
if (ws) {
str = ws + 1;
} else {
Error("Not enough coordinates to form a polygon!");
n_coords = 0;
break;
}
}
delete[] coords;
return n_coords ? true : false;
if (vertices.size() > 2) {
Debug(3, "Successfully parsed polygon string %s", str);
polygon = Polygon(vertices);
} else {
Error("Not enough coordinates to form a polygon!");
}
return !vertices.empty();
} // end bool Zone::ParsePolygonString(const char *poly_string, Polygon &polygon)
bool Zone::ParseZoneString(const char *zone_string, int &zone_id, int &colour, Polygon &polygon) {
@ -937,9 +939,9 @@ bool Zone::DumpSettings(char *output, bool /*verbose*/) const {
type==INACTIVE?"Inactive":(
type==PRIVACY?"Privacy":"Unknown"
))))));
sprintf( output+strlen(output), " Shape : %d points\n", polygon.getNumCoords() );
for ( int i = 0; i < polygon.getNumCoords(); i++ ) {
sprintf(output+strlen(output), " %i: %d,%d\n", i, polygon.getCoord( i ).x_, polygon.getCoord(i ).y_ );
sprintf( output+strlen(output), " Shape : %zu points\n", polygon.GetVertices().size() );
for (size_t i = 0; i < polygon.GetVertices().size(); i++) {
sprintf(output + strlen(output), " %zu: %d,%d\n", i, polygon.GetVertices()[i].x_, polygon.GetVertices()[i].y_);
}
sprintf( output+strlen(output), " Alarm RGB : %06x\n", alarm_rgb );
sprintf( output+strlen(output), " Check Method: %d - %s\n", check_method,