#include <Polygon.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <AffineTransform.h>
#define MAX_POINT_COUNT 10000000
BPolygon::BPolygon(const BPoint* points, int32 count)
:
fBounds(0.0f, 0.0f, -1.0f, -1.0f),
fCount(0),
fPoints(NULL)
{
_AddPoints(points, count, true);
}
BPolygon::BPolygon(const BPolygon& other)
:
fBounds(0.0f, 0.0f, -1.0f, -1.0f),
fCount(0),
fPoints(NULL)
{
*this = other;
}
BPolygon::BPolygon(const BPolygon* other)
:
fBounds(0.0f, 0.0f, -1.0f, -1.0f),
fCount(0),
fPoints(NULL)
{
*this = *other;
}
BPolygon::BPolygon()
:
fBounds(0.0f, 0.0f, -1.0f, -1.0f),
fCount(0),
fPoints(NULL)
{
}
BPolygon::~BPolygon()
{
free(fPoints);
}
BPolygon&
BPolygon::operator=(const BPolygon& other)
{
if (this == &other)
return *this;
free(fPoints);
fPoints = NULL;
fCount = 0;
fBounds.Set(0.0f, 0.0f, -1.0f, -1.0f);
if (_AddPoints(other.fPoints, other.fCount, false))
fBounds = other.fBounds;
return *this;
}
BRect
BPolygon::Frame() const
{
return fBounds;
}
void
BPolygon::AddPoints(const BPoint* points, int32 count)
{
_AddPoints(points, count, true);
}
int32
BPolygon::CountPoints() const
{
return fCount;
}
void
BPolygon::MapTo(BRect source, BRect destination)
{
for (uint32 i = 0; i < fCount; i++)
_MapPoint(fPoints + i, source, destination);
_MapRectangle(&fBounds, source, destination);
}
void
BPolygon::PrintToStream() const
{
for (uint32 i = 0; i < fCount; i++)
fPoints[i].PrintToStream();
}
bool
BPolygon::_AddPoints(const BPoint* points, int32 count, bool computeBounds)
{
if (points == NULL || count <= 0)
return false;
if (count > MAX_POINT_COUNT || (fCount + count) > MAX_POINT_COUNT) {
fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") - too many points"
"\n", count);
return false;
}
BPoint* newPoints = (BPoint*)realloc((void*)fPoints, (fCount + count)
* sizeof(BPoint));
if (newPoints == NULL) {
fprintf(stderr, "BPolygon::_AddPoints(%" B_PRId32 ") out of memory\n",
count);
return false;
}
fPoints = newPoints;
memcpy((void*)(fPoints + fCount), points, count * sizeof(BPoint));
fCount += count;
if (computeBounds)
fBounds = _ComputeBounds(fPoints, fCount);
return true;
}
BRect
BPolygon::_ComputeBounds(const BPoint* points, uint32 count)
{
if (count == 0)
return BRect(0.0, 0.0, -1.0f, -1.0f);
BRect bounds(points[0], points[0]);
for (uint32 i = 1; i < count; i++) {
if (points[i].x < bounds.left)
bounds.left = points[i].x;
if (points[i].y < bounds.top)
bounds.top = points[i].y;
if (points[i].x > bounds.right)
bounds.right = points[i].x;
if (points[i].y > bounds.bottom)
bounds.bottom = points[i].y;
}
return bounds;
}
void
BPolygon::_MapPoint(BPoint* point, const BRect& source,
const BRect& destination)
{
point->x = (point->x - source.left) * destination.Width() / source.Width()
+ destination.left;
point->y = (point->y - source.top) * destination.Height() / source.Height()
+ destination.top;
}
void
BPolygon::_MapRectangle(BRect* rect, const BRect& source,
const BRect& destination)
{
BPoint leftTop = rect->LeftTop();
BPoint bottomRight = rect->RightBottom();
_MapPoint(&leftTop, source, destination);
_MapPoint(&bottomRight, source, destination);
*rect = BRect(leftTop, bottomRight);
}