* MIT License
* Copyright (c) 2021 - 2023 _VIFEXTech
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "PointContainer.h"
#include <limits.h>
#include <stdlib.h>
#include <string.h>
PointContainer::PointContainer()
: _curPushPoint { 0 }
, _curPopPoint { 0 }
, _curPopIndex(0)
{
}
PointContainer::~PointContainer()
{
}
bool PointContainer::isFlag(const DiffPoint_t* point)
{
if (point->x == FLAG_END_POINT && point->y == FLAG_END_POINT) {
return true;
}
if (point->x == FLAG_FULL_POINT && point->y == FLAG_FULL_POINT) {
return true;
}
return false;
}
void PointContainer::pushPoint(const FullPoint_t* point)
{
size_t curIndex = vecPoints.size();
if (curIndex == 0) {
_curPushPoint = *point;
pushFullPoint(point);
return;
}
int32_t diffX = point->x - _curPushPoint.x;
int32_t diffY = point->y - _curPushPoint.y;
_curPushPoint = *point;
if (std::abs((int)diffX) > SCHAR_MAX || std::abs((int)diffY) > SCHAR_MAX) {
pushFullPoint(point);
return;
}
const DiffPoint_t diffPoint = { (int8_t)diffX, (int8_t)diffY };
if (isFlag(&diffPoint)) {
pushFullPoint(point);
return;
}
vecPoints.push_back(diffPoint);
}
void PointContainer::pushFullPoint(const FullPoint_t* point)
{
vecPoints.push_back(makeFlag(FLAG_FULL_POINT));
const DiffPoint_t* pData = (const DiffPoint_t*)point;
for (size_t i = 0; i < sizeof(FullPoint_t) / sizeof(DiffPoint_t); i++) {
vecPoints.push_back(pData[i]);
}
}
bool PointContainer::popFullPoint(FullPoint_t* point)
{
size_t size = vecPoints.size();
if (size - _curPopIndex < 4) {
return false;
}
DiffPoint_t* pData = (DiffPoint_t*)point;
for (size_t i = 0; i < sizeof(FullPoint_t) / sizeof(DiffPoint_t); i++) {
pData[i] = vecPoints[_curPopIndex];
_curPopIndex++;
}
return true;
}
bool PointContainer::popPoint(FullPoint_t* point)
{
size_t size = vecPoints.size();
if (size - _curPopIndex == 0) {
return false;
}
DiffPoint_t diffPoint = vecPoints[_curPopIndex];
if (diffPoint.x == FLAG_FULL_POINT && diffPoint.y == FLAG_FULL_POINT) {
_curPopIndex++;
if (popFullPoint(point)) {
_curPopPoint = *point;
} else {
return false;
}
} else {
_curPopPoint.x += diffPoint.x;
_curPopPoint.y += diffPoint.y;
*point = _curPopPoint;
_curPopIndex++;
}
return true;
}
void PointContainer::popStart()
{
_curPopIndex = 0;
}