From e9bd096d3d358fd470ebc98ccc879c24f5e16503 Mon Sep 17 00:00:00 2001 From: ChristianFeldmann Date: Wed, 17 Jul 2024 00:49:36 +0200 Subject: [PATCH] Add VTBMS stats test --- YUViewUnitTest/statistics/CheckFunctions.cpp | 132 +++++++++++ YUViewUnitTest/statistics/CheckFunctions.h | 80 +++++++ .../statistics/StatisticsFileCSVTest.cpp | 83 ++----- .../statistics/StatisticsFileVTMBMSTest.cpp | 219 ++++++++++++++++++ 4 files changed, 454 insertions(+), 60 deletions(-) create mode 100644 YUViewUnitTest/statistics/CheckFunctions.cpp create mode 100644 YUViewUnitTest/statistics/CheckFunctions.h create mode 100644 YUViewUnitTest/statistics/StatisticsFileVTMBMSTest.cpp diff --git a/YUViewUnitTest/statistics/CheckFunctions.cpp b/YUViewUnitTest/statistics/CheckFunctions.cpp new file mode 100644 index 000000000..b3b98353e --- /dev/null +++ b/YUViewUnitTest/statistics/CheckFunctions.cpp @@ -0,0 +1,132 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CheckFunctions.h" + +#include "gtest/gtest.h" + +namespace yuviewTest::statistics +{ + +void checkVectorList(const std::vector &vectors, + const std::vector &checkItems) +{ + EXPECT_EQ(vectors.size(), checkItems.size()); + for (unsigned i = 0; i < vectors.size(); i++) + { + const auto vec = vectors[i]; + const auto chk = checkItems[i]; + EXPECT_EQ(unsigned(vec.pos[0]), chk.x); + EXPECT_EQ(unsigned(vec.pos[1]), chk.y); + EXPECT_EQ(unsigned(vec.size[0]), chk.w); + EXPECT_EQ(unsigned(vec.size[1]), chk.h); + EXPECT_EQ(vec.point[0].x, chk.v0); + EXPECT_EQ(vec.point[0].y, chk.v1); + } +} + +void checkValueList(const std::vector &values, + const std::vector &checkItems) +{ + EXPECT_EQ(values.size(), checkItems.size()); + for (unsigned i = 0; i < values.size(); i++) + { + const auto val = values[i]; + const auto chk = checkItems[i]; + EXPECT_EQ(unsigned(val.pos[0]), chk.x); + EXPECT_EQ(unsigned(val.pos[1]), chk.y); + EXPECT_EQ(unsigned(val.size[0]), chk.w); + EXPECT_EQ(unsigned(val.size[1]), chk.h); + EXPECT_EQ(val.value, chk.v0); + } +} + +void checkAffineTFVectorList(const std::vector &affineTFvectors, + const std::vector &checkItems) +{ + EXPECT_EQ(affineTFvectors.size(), checkItems.size()); + for (unsigned i = 0; i < affineTFvectors.size(); i++) + { + auto vec = affineTFvectors[i]; + auto chk = checkItems[i]; + EXPECT_EQ(unsigned(vec.pos[0]), chk.x); + EXPECT_EQ(unsigned(vec.pos[1]), chk.y); + EXPECT_EQ(unsigned(vec.size[0]), chk.w); + EXPECT_EQ(unsigned(vec.size[1]), chk.h); + EXPECT_EQ(vec.point[0].x, chk.v0); + EXPECT_EQ(vec.point[0].y, chk.v1); + EXPECT_EQ(vec.point[1].x, chk.v2); + EXPECT_EQ(vec.point[1].y, chk.v3); + EXPECT_EQ(vec.point[2].x, chk.v4); + EXPECT_EQ(vec.point[2].y, chk.v5); + } +} + +void checkLineList(const std::vector &lines, + const std::vector &checkItems) +{ + EXPECT_EQ(lines.size(), checkItems.size()); + for (unsigned i = 0; i < lines.size(); i++) + { + auto vec = lines[i]; + auto chk = checkItems[i]; + EXPECT_EQ(unsigned(vec.pos[0]), chk.x); + EXPECT_EQ(unsigned(vec.pos[1]), chk.y); + EXPECT_EQ(unsigned(vec.size[0]), chk.w); + EXPECT_EQ(unsigned(vec.size[1]), chk.h); + EXPECT_EQ(vec.point[0].x, chk.v0); + EXPECT_EQ(vec.point[0].y, chk.v1); + EXPECT_EQ(vec.point[1].x, chk.v2); + EXPECT_EQ(vec.point[1].y, chk.v3); + } +} + +void checkPolygonvectorList(const std::vector &polygonList, + const std::vector &checkItems) +{ + EXPECT_EQ(polygonList.size(), checkItems.size()); + for (unsigned i = 0; i < polygonList.size(); i++) + { + auto polygon = polygonList[i]; + auto chk = checkItems[i]; + for (unsigned i = 0; i < polygon.corners.size(); i++) + { + auto corner = polygon.corners[i]; + EXPECT_EQ(unsigned(corner.x), chk.x[i]); + EXPECT_EQ(unsigned(corner.y), chk.y[i]); + } + EXPECT_EQ(polygon.point.x, chk.v0); + EXPECT_EQ(polygon.point.y, chk.v1); + } +} + +} // namespace yuviewTest::statistics diff --git a/YUViewUnitTest/statistics/CheckFunctions.h b/YUViewUnitTest/statistics/CheckFunctions.h new file mode 100644 index 000000000..074d47d7c --- /dev/null +++ b/YUViewUnitTest/statistics/CheckFunctions.h @@ -0,0 +1,80 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +namespace yuviewTest::statistics +{ + +struct CheckStatsItem +{ + unsigned x{}, y{}, w{}, h{}; + int v0{}, v1{}; +}; + +struct CheckAffineTFItem +{ + unsigned x{}, y{}, w{}, h{}; + int v0{}, v1{}, v2{}, v3{}, v4{}, v5{}; +}; + +struct CheckLineItem +{ + unsigned x{}, y{}, w{}, h{}; + int v0{}, v1{}, v2{}, v3{}; +}; + +struct CheckPolygonVectorItem +{ + int v0{}, v1{}; + unsigned x[5]; + unsigned y[5]; +}; + +void checkValueList(const std::vector &values, + const std::vector &checkItems); + +void checkVectorList(const std::vector &vectors, + const std::vector &checkItems); + +void checkAffineTFVectorList(const std::vector &affineTFvectors, + const std::vector &checkItems); + +void checkLineList(const std::vector &lines, + const std::vector &checkItems); + +void checkPolygonvectorList(const std::vector &polygonList, + const std::vector &checkItems); + +} // namespace yuviewTest::statistics diff --git a/YUViewUnitTest/statistics/StatisticsFileCSVTest.cpp b/YUViewUnitTest/statistics/StatisticsFileCSVTest.cpp index 078a86585..75400552d 100644 --- a/YUViewUnitTest/statistics/StatisticsFileCSVTest.cpp +++ b/YUViewUnitTest/statistics/StatisticsFileCSVTest.cpp @@ -32,6 +32,8 @@ #include "gtest/gtest.h" +#include "CheckFunctions.h" + #include #include @@ -101,45 +103,6 @@ ByteVector getCSVTestData() return data; } -struct CheckStatsItem -{ - unsigned x{}, y{}, w{}, h{}; - int v0{}, v1{}; -}; - -void checkVectorList(const std::vector &vectors, - const std::vector &checkItems) -{ - EXPECT_EQ(vectors.size(), checkItems.size()); - for (unsigned i = 0; i < vectors.size(); i++) - { - const auto vec = vectors[i]; - const auto chk = checkItems[i]; - EXPECT_EQ(unsigned(vec.pos[0]), chk.x); - EXPECT_EQ(unsigned(vec.pos[1]), chk.y); - EXPECT_EQ(unsigned(vec.size[0]), chk.w); - EXPECT_EQ(unsigned(vec.size[1]), chk.h); - EXPECT_EQ(vec.point[0].x, chk.v0); - EXPECT_EQ(vec.point[0].y, chk.v1); - } -} - -void checkValueList(const std::vector &values, - const std::vector &checkItems) -{ - EXPECT_EQ(values.size(), checkItems.size()); - for (unsigned i = 0; i < values.size(); i++) - { - const auto val = values[i]; - const auto chk = checkItems[i]; - EXPECT_EQ(unsigned(val.pos[0]), chk.x); - EXPECT_EQ(unsigned(val.pos[1]), chk.y); - EXPECT_EQ(unsigned(val.size[0]), chk.w); - EXPECT_EQ(unsigned(val.size[1]), chk.h); - EXPECT_EQ(val.value, chk.v0); - } -} - TEST(StatisticsFileCSV, testCSVFileParsing) { yuviewTest::TemporaryFile csvFile(getCSVTestData()); @@ -270,36 +233,36 @@ TEST(StatisticsFileCSV, testCSVFileParsing) // Now we should get the data statFile.loadStatisticData(statData, 1, 9); EXPECT_EQ(statData.getFrameIndex(), 1); - checkVectorList(statData[9].vectorData, - {{0, 32, 8, 16, 1, 0}, - {8, 32, 8, 16, 0, 0}, - {112, 56, 4, 8, 0, 0}, - {116, 56, 4, 8, 0, 0}, - {128, 32, 32, 16, 0, 0}, - {128, 48, 32, 16, 0, 0}}); + yuviewTest::statistics::checkVectorList(statData[9].vectorData, + {{0, 32, 8, 16, 1, 0}, + {8, 32, 8, 16, 0, 0}, + {112, 56, 4, 8, 0, 0}, + {116, 56, 4, 8, 0, 0}, + {128, 32, 32, 16, 0, 0}, + {128, 48, 32, 16, 0, 0}}); EXPECT_EQ(statData[9].valueData.size(), size_t(0)); statFile.loadStatisticData(statData, 1, 11); EXPECT_EQ(statData.getFrameIndex(), 1); - checkVectorList(statData[11].vectorData, - {{0, 32, 8, 16, 31, 0}, - {8, 32, 8, 16, -33, 0}, - {112, 56, 4, 8, -30, 0}, - {116, 56, 4, 8, -30, 0}, - {128, 32, 32, 16, -31, 0}, - {128, 48, 32, 16, -31, 0}, - {160, 32, 32, 16, -31, 0}}); + yuviewTest::statistics::checkVectorList(statData[11].vectorData, + {{0, 32, 8, 16, 31, 0}, + {8, 32, 8, 16, -33, 0}, + {112, 56, 4, 8, -30, 0}, + {116, 56, 4, 8, -30, 0}, + {128, 32, 32, 16, -31, 0}, + {128, 48, 32, 16, -31, 0}, + {160, 32, 32, 16, -31, 0}}); EXPECT_EQ(statData[11].valueData.size(), size_t(0)); statFile.loadStatisticData(statData, 7, 3); EXPECT_EQ(statData.getFrameIndex(), 7); EXPECT_EQ(statData[3].vectorData.size(), size_t(0)); - checkValueList(statData[3].valueData, - {{0, 32, 8, 16, 1}, - {128, 48, 32, 16, 0}, - {384, 0, 64, 64, 0}, - {520, 32, 24, 32, 0}, - {576, 40, 32, 24, 0}}); + yuviewTest::statistics::checkValueList(statData[3].valueData, + {{0, 32, 8, 16, 1}, + {128, 48, 32, 16, 0}, + {384, 0, 64, 64, 0}, + {520, 32, 24, 32, 0}, + {576, 40, 32, 24, 0}}); } } // namespace \ No newline at end of file diff --git a/YUViewUnitTest/statistics/StatisticsFileVTMBMSTest.cpp b/YUViewUnitTest/statistics/StatisticsFileVTMBMSTest.cpp new file mode 100644 index 000000000..ad76b3c40 --- /dev/null +++ b/YUViewUnitTest/statistics/StatisticsFileVTMBMSTest.cpp @@ -0,0 +1,219 @@ +/* This file is part of YUView - The YUV player with advanced analytics toolset + * + * Copyright (C) 2015 Institut für Nachrichtentechnik, RWTH Aachen University, GERMANY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + * + * You must obey the GNU General Public License in all respects for all + * of the code used other than OpenSSL. If you modify file(s) with this + * exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do + * so, delete this exception statement from your version. If you delete + * this exception statement from all source files in the program, then + * also delete it here. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "gtest/gtest.h" + +#include "CheckFunctions.h" + +#include +#include + +namespace +{ + +ByteVector getVTMBSTestData() +{ + const std::string stats_str = + R"(# VTMBMS Block Statistics +# Sequence size: [2048x 872] +# Block Statistic Type: PredMode; Integer; [0, 4] +# Block Statistic Type: MVDL0; Vector; Scale: 4 +# Block Statistic Type: AffineMVL0; AffineTFVectors; Scale: 4 +# Block Statistic Type: GeoPartitioning; Line; +# Block Statistic Type: GeoMVL0; VectorPolygon; Scale: 4 +BlockStat: POC 0 @( 0, 0) [64x64] PredMode=1 +BlockStat: POC 0 @( 64, 0) [32x16] PredMode=1 +BlockStat: POC 0 @( 384, 0) [64x64] PredMode=2 +BlockStat: POC 0 @( 520, 32) [16x32] PredMode=4 +BlockStat: POC 0 @( 320, 0) [32x24] PredMode=1 +BlockStat: POC 0 @( 320, 64) [32x8] PredMode=1 +BlockStat: POC 2 @( 384, 128) [64x64] MVDL0={ 12, 3} +BlockStat: POC 2 @( 384, 128) [64x64] PredMode=1 +BlockStat: POC 2 @( 448, 128) [64x64] PredMode=2 +BlockStat: POC 2 @( 384, 192) [64x64] MVDL0={ 52, -44} +BlockStat: POC 2 @( 480, 192) [ 8x16] MVDL0={ 520, 888} +BlockStat: POC 2 @( 488, 192) [ 8x16] MVDL0={ -234, -256} +BlockStat: POC 2 @( 496, 192) [16x16] PredMode=2 +BlockStat: POC 8 @( 640, 128) [128x128] AffineMVL0={ -61,-128, -53,-101, -99,-139} +BlockStat: POC 8 @(1296, 128) [32x64] AffineMVL0={ -68, 32, -65, 39, -79, 25} +BlockStat: POC 8 @(1328, 128) [16x64] AffineMVL0={ -64, 40, -63, 43, -75, 33} +BlockStat: POC 8 @( 288, 544) [16x32] GeoPartitioning={ 5, 0, 6, 32} +BlockStat: POC 8 @(1156, 592) [ 8x 8] GeoPartitioning={ 1, 0, 8, 5} +BlockStat: POC 8 @( 276, 672) [ 8x16] GeoPartitioning={ 5, 0, 3, 16} +BlockStat: POC 8 @[(240, 384)--(256, 384)--(256, 430)--(240, 416)--] GeoMVL0={ 291, 233} +BlockStat: POC 8 @[(1156, 592)--(1157, 592)--(1164, 597)--(1164, 600)--(1156, 600)--] GeoMVL0={ 152, 24} +BlockStat: POC 8 @[(544, 760)--(545, 768)--(544, 768)--] GeoMVL0={ 180, 38} +)"; + + ByteVector data(stats_str.begin(), stats_str.end()); + return data; +} + +TEST(StatisticsFileCSV, testCSVFileParsing) +{ + yuviewTest::TemporaryFile vtmbmsFile(getVTMBSTestData()); + + stats::StatisticsData statData; + stats::StatisticsFileVTMBMS statFile(QString::fromStdString(vtmbmsFile.getFilePath()), statData); + + EXPECT_EQ(statData.getFrameSize(), Size(2048, 872)); + + auto types = statData.getStatisticsTypes(); + EXPECT_EQ(types.size(), size_t(5)); + + EXPECT_EQ(types[0].typeID, 1); + EXPECT_EQ(types[1].typeID, 2); + EXPECT_EQ(types[2].typeID, 3); + EXPECT_EQ(types[3].typeID, 4); + EXPECT_EQ(types[4].typeID, 5); + EXPECT_EQ(types[0].typeName, QString("PredMode")); + EXPECT_EQ(types[1].typeName, QString("MVDL0")); + EXPECT_EQ(types[2].typeName, QString("AffineMVL0")); + EXPECT_EQ(types[3].typeName, QString("GeoPartitioning")); + EXPECT_EQ(types[4].typeName, QString("GeoMVL0")); + + EXPECT_EQ(types[0].hasVectorData, false); + EXPECT_EQ(types[0].hasValueData, true); + EXPECT_EQ(types[0].colorMapper.valueRange.min, 0); + EXPECT_EQ(types[0].colorMapper.valueRange.max, 4); + EXPECT_EQ(types[0].colorMapper.predefinedType, stats::color::PredefinedType::Jet); + EXPECT_EQ(types[0].gridStyle.color.toHex(), std::string("#000000")); + + EXPECT_EQ(types[1].hasVectorData, true); + EXPECT_EQ(types[1].hasValueData, false); + auto debugName = types[1].vectorStyle.color.toHex(); + EXPECT_EQ(types[1].vectorStyle.color.toHex(), std::string("#ff0000")); + EXPECT_EQ(types[1].vectorScale, 4); + + EXPECT_EQ(types[2].hasVectorData, false); + EXPECT_EQ(types[2].hasValueData, false); + EXPECT_EQ(types[2].hasAffineTFData, true); + debugName = types[2].vectorStyle.color.toHex(); + EXPECT_EQ(types[2].vectorStyle.color.toHex(), std::string("#ff0000")); + EXPECT_EQ(types[2].vectorScale, 4); + + EXPECT_EQ(types[3].hasVectorData, true); + EXPECT_EQ(types[3].hasValueData, false); + debugName = types[3].vectorStyle.color.toHex(); + EXPECT_EQ(types[3].vectorStyle.color.toHex(), std::string("#ffffff")); + debugName = types[3].gridStyle.color.toHex(); + EXPECT_EQ(types[3].gridStyle.color.toHex(), std::string("#ffffff")); + EXPECT_EQ(types[3].vectorScale, 1); + + EXPECT_EQ(types[4].hasVectorData, true); + EXPECT_EQ(types[4].hasValueData, false); + debugName = types[4].vectorStyle.color.toHex(); + EXPECT_EQ(types[4].vectorStyle.color.toHex(), std::string("#ff0000")); + EXPECT_EQ(types[4].vectorScale, 4); + EXPECT_EQ(types[4].isPolygon, true); + + // We did not let the file parse the positions of the start of each poc/type yet so loading should + // not yield any data yet. + statFile.loadStatisticData(statData, 0, 1); + EXPECT_EQ(statData.getFrameIndex(), 0); + { + auto &frameData = statData[9]; + EXPECT_EQ(frameData.vectorData.size(), size_t(0)); + EXPECT_EQ(frameData.valueData.size(), size_t(0)); + EXPECT_EQ(frameData.affineTFData.size(), size_t(0)); + EXPECT_EQ(frameData.polygonValueData.size(), size_t(0)); + EXPECT_EQ(frameData.polygonVectorData.size(), size_t(0)); + } + + std::atomic_bool breakAtomic; + breakAtomic.store(false); + statFile.readFrameAndTypePositionsFromFile(std::ref(breakAtomic)); + + // Now we should get the data + statFile.loadStatisticData(statData, 0, 1); + EXPECT_EQ(statData.getFrameIndex(), 0); + EXPECT_EQ(statData[2].valueData.size(), size_t(0)); + yuviewTest::statistics::checkValueList(statData[1].valueData, + {{0, 0, 64, 64, 1}, + {64, 0, 32, 16, 1}, + {384, 0, 64, 64, 2}, + {520, 32, 16, 32, 4}, + {320, 0, 32, 24, 1}, + {320, 64, 32, 8, 1}}); + EXPECT_EQ(statData[1].vectorData.size(), size_t(0)); + + statFile.loadStatisticData(statData, 2, 1); + statFile.loadStatisticData(statData, 2, 2); + EXPECT_EQ(statData.getFrameIndex(), 2); + yuviewTest::statistics::checkValueList( + statData[1].valueData, {{384, 128, 64, 64, 1}, {448, 128, 64, 64, 2}, {496, 192, 16, 16, 2}}); + EXPECT_EQ(statData[1].vectorData.size(), size_t(0)); + + yuviewTest::statistics::checkVectorList(statData[2].vectorData, + {{384, 128, 64, 64, 12, 3}, + {384, 192, 64, 64, 52, -44}, + {480, 192, 8, 16, 520, 888}, + {488, 192, 8, 16, -234, -256}}); + EXPECT_EQ(statData[2].valueData.size(), size_t(0)); + + statFile.loadStatisticData(statData, 8, 3); + EXPECT_EQ(statData.getFrameIndex(), 8); + yuviewTest::statistics::checkAffineTFVectorList( + statData[3].affineTFData, + { + {640, 128, 128, 128, -61, -128, -53, -101, -99, -139}, + {1296, 128, 32, 64, -68, 32, -65, 39, -79, 25}, + {1328, 128, 16, 64, -64, 40, -63, 43, -75, 33}, + }); + + statFile.loadStatisticData(statData, 8, 4); + EXPECT_EQ(statData.getFrameIndex(), 8); + yuviewTest::statistics::checkLineList(statData[4].vectorData, + { + {288, 544, 16, 32, 5, 0, 6, 32}, + {1156, 592, 8, 8, 1, 0, 8, 5}, + {276, 672, 8, 16, 5, 0, 3, 16}, + }); + + statFile.loadStatisticData(statData, 8, 5); + EXPECT_EQ(statData.getFrameIndex(), 8); + yuviewTest::statistics::checkPolygonvectorList( + statData[5].polygonVectorData, + { + {291, + 233, + {240, 256, 256, 240, 0}, + {384, 384, 430, 416, 0}}, // 4 pt polygon, zeros for padding test struct + {152, 24, {1156, 1157, 1164, 1164, 1156}, {592, 592, 597, 600, 600}}, + {180, + 38, + {544, 545, 544, 0, 0}, + {760, 768, 768, 0, 0}} // 3 pt polygon, zeros for padding test struct + }); +} + +} // namespace