Polygon: Use std::vector to store the vertices
This commit is contained in:
parent
eaf91fcf1f
commit
5af6d6af3d
|
@ -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_;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
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);
|
||||
} else {
|
||||
Error("Not enough coordinates to form a polygon!");
|
||||
n_coords = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue