#include "PolygonItem.h" #include "IMapRender.h" bool IsPointInsidePolygon(const Array& p, Point s) { int i, j; bool parity = false; for (i = 0, j = p.GetCount() - 1; i < p.GetCount(); j = i++) { if ( ( p[i].y < s.y && s.y <= p[j].y || p[j].y < s.y && s.y <= p[i].y ) && (s.x > (p[j].x - p[i].x) * (s.y - p[i].y) / (p[j].y - p[i].y) + p[i].x)) parity = !parity; } return parity; } Rect RectOfFigure(const Array& p) { if (!p.GetCount()) return Null; Point s = Point(INT_MAX, INT_MAX); Point e = Point(-1, -1); for (int i = 0; i < p.GetCount(); i++) { s.x = min(p[i].x, s.x); s.y = min(p[i].y, s.y); e.x = max(p[i].x, e.x); e.y = max(p[i].y, e.y); } return Rect(s, e); } Point CenterOfFigure(const Array& p) { return RectOfFigure(p).CenterPoint(); } Point TopLeftOfFigure(const Array& p) { if (!p.GetCount()) return Null; Point s = p[0]; for (int i = 1; i < p.GetCount(); i++) { if (s.x > p[i].x && s.y > p[i].y) s = p[i]; } return s; } PolygonItem::PolygonItem(IMapRender* render) : IMapItem(render), _display(new PolygonItemDisplay()), _stdDisplay(true) { } Callback1 > PolygonItem::WhenClick; PolygonItem::~PolygonItem() { if (_stdDisplay && _display) delete _display; } PolygonItem* PolygonItem::SetDisplay(PolygonItemDisplay* disp) { if (_stdDisplay && _display) delete _display; _display = disp; return this; } Rect PolygonItem::GetRect() { return RectOfFigure(GetVertices()); } Point PolygonItem::GetCenter() { return CenterOfFigure(GetVertices()); } Point PolygonItem::GetTopLeft() { return TopLeftOfFigure(GetVertices()); } bool PolygonItem::Contains(const Point& p) { return IsPointInsidePolygon(GetVertices(), p); } void PolygonItem::Render(Draw* w) { _display->Paint(w, this); } void PolygonItemDisplay::Paint(Draw* w, PolygonItem* item) const { if (!item->GetTopRender()) return; Vector points; for (int i = 0; i < item->GetVertices().GetCount(); ++i) points << item->GetTopRender()->ViewToScene(item->GetVertices()[i]); if (item->IsFound()) { w->DrawPolygon(points, item->IsSelected() ? Yellow() : LtRed(), 1, Black()); } else if (item->IsSelected() && !item->IsFound()) w->DrawPolygon(points, Yellow(), 1, Black()); else if (item->IsState(STATE_EDIT)) w->DrawPolygon(points, Green(), 1, Black()); }