Clean up grid.

This commit is contained in:
jmsgrogan 2023-01-16 08:54:45 +00:00
parent d4bb2b2744
commit 3c6756d7a1
27 changed files with 210 additions and 227 deletions

View file

@ -10,8 +10,6 @@ list(APPEND HEADERS
CommandLineArgs.h CommandLineArgs.h
data_structures/RawTree.h data_structures/RawTree.h
data_structures/List.h data_structures/List.h
data_structures/ListT.h
data_structures/ListFactory.h
data_structures/Tree.h data_structures/Tree.h
encoding/ByteUtils.h encoding/ByteUtils.h
encoding/StringUtils.h encoding/StringUtils.h
@ -35,7 +33,6 @@ list(APPEND LIB_INCLUDES
CommandLineArgs.cpp CommandLineArgs.cpp
data_structures/RawTree.cpp data_structures/RawTree.cpp
data_structures/Tree.cpp data_structures/Tree.cpp
data_structures/ListFactory.cpp
loggers/FileLogger.cpp loggers/FileLogger.cpp
file_utilities/Directory.cpp file_utilities/Directory.cpp
file_utilities/File.cpp file_utilities/File.cpp

View file

@ -1,23 +1,69 @@
#pragma once #pragma once
#include <cstddef> #include <vector>
#include <string>
#include <stdexcept>
class List class AbstractList
{ {
public: public:
enum class Type virtual ~AbstractList() = default;
{
UCHAR,
UINT8,
DOUBLE,
COLOR,
LIST,
UNKNOWN
};
~List() = default;
virtual Type getType() const = 0;
virtual std::size_t getLength() const = 0; virtual std::size_t getLength() const = 0;
}; };
template<typename T>
class List : public AbstractList
{
public:
List() = default;
void initializeTo(std::size_t size, T value)
{
mData = std::vector<T>(size, value);
}
const T* getDataPtr() const
{
return mData.data();
}
const std::vector<T>& getData() const
{
return mData;
}
T getItem(std::size_t index) const
{
if (index < mData.size())
{
return mData[index];
}
else
{
const auto msg = "Tried to access out of range index: " + std::to_string(index) + " with size " + std::to_string(mData.size());
throw std::out_of_range(msg);
}
}
void setData(const std::vector<T>& data)
{
mData = data;
}
void setItem(std::size_t index, T item)
{
if (index < mData.size())
{
mData[index] = item;
}
}
std::size_t getLength() const override
{
return mData.size();
}
private:
std::vector<T> mData;
};

View file

@ -1,26 +0,0 @@
#include "ListFactory.h"
#include "ListT.h"
#include "Color.h"
std::unique_ptr<List> ListFactory::Create(List::Type type, std::size_t size)
{
std::unique_ptr<List> list;
if (type == List::Type::DOUBLE)
{
list = std::make_unique<ListT<double>>(type, size, 0.0);
}
else if (type == List::Type::UCHAR)
{
list = std::make_unique<ListT<unsigned char> >(type, size, 0);
}
else if (type == List::Type::UINT8)
{
list = std::make_unique<ListT<uint8_t>>(type, size, 0);
}
else if (type == List::Type::COLOR)
{
list = std::make_unique<ListT<Color>>(type, size, Color());
}
return std::move(list);
}

View file

@ -1,11 +0,0 @@
#pragma once
#include "List.h"
#include <memory>
class ListFactory
{
public:
static std::unique_ptr<List> Create(List::Type type, std::size_t size = 0);
};

View file

@ -1,69 +0,0 @@
#pragma once
#include "List.h"
#include <vector>
class ListFactory;
template<typename T>
class ListT : public List
{
public:
ListT() = delete;
ListT(List::Type type, std::size_t size, T value)
: mType(type)
{
if (size > 0)
{
initialize(size, value);
}
}
virtual Type getType() const override
{
return mType;
}
const T* getDataPtr() const
{
return mData.data();
}
const std::vector<T>& getData() const
{
return mData;
}
void setData(const std::vector<T>& data)
{
mData = data;
}
void setDataItem(std::size_t index, T item)
{
if (index < mData.size())
{
mData[index] = item;
}
}
void initialize(std::size_t size, T value)
{
mData.resize(size);
for (std::size_t idx = 0; idx < size; idx++)
{
mData[idx] = value;
}
}
std::size_t getLength() const override
{
return mData.size();
}
private:
List::Type mType{ List::Type::UNKNOWN };
std::vector<T> mData;
};

View file

@ -3,7 +3,8 @@
#include "Bounds.h" #include "Bounds.h"
#include "Point.h" #include "Point.h"
class Grid; template<typename T>
class SparseGrid;
class AbstractGeometricItem class AbstractGeometricItem
{ {
@ -28,7 +29,7 @@ public:
virtual const Point& getLocation() const = 0; virtual const Point& getLocation() const = 0;
virtual void sample(Grid* grid) const = 0; virtual void sample(SparseGrid<bool>* grid) const = 0;
virtual Type getType() const { return Type::UNKNOWN; }; virtual Type getType() const { return Type::UNKNOWN; };
}; };

View file

@ -4,6 +4,7 @@ list(APPEND HEADERS
AbstractGeometricItem.h AbstractGeometricItem.h
Bounds.h Bounds.h
grid/AbstractGrid.h grid/AbstractGrid.h
grid/TypedGrid.h
grid/Grid.h grid/Grid.h
grid/SparseGrid.h grid/SparseGrid.h
math/Linalg.h math/Linalg.h
@ -26,8 +27,6 @@ list(APPEND HEADERS
list(APPEND LIB_INCLUDES list(APPEND LIB_INCLUDES
Transform.cpp Transform.cpp
grid/AbstractGrid.cpp grid/AbstractGrid.cpp
grid/Grid.cpp
grid/SparseGrid.cpp
math/Linalg.cpp math/Linalg.cpp
math/Matrix.cpp math/Matrix.cpp
math/Vector.cpp math/Vector.cpp

View file

@ -1,11 +1,10 @@
#include "AbstractGrid.h" #include "AbstractGrid.h"
#include "ListT.h" AbstractGrid::AbstractGrid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, std::size_t numPointsZ)
AbstractGrid::AbstractGrid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, List::Type dataType)
: mBounds(bounds), : mBounds(bounds),
mNumX(numPointsX), mNumX(numPointsX),
mNumY(numPointsY) mNumY(numPointsY),
mNumZ(numPointsZ)
{ {
} }
@ -30,10 +29,4 @@ double AbstractGrid::getYSpacing() const
void AbstractGrid::resetBounds(const Bounds& bounds) void AbstractGrid::resetBounds(const Bounds& bounds)
{ {
mBounds = bounds; mBounds = bounds;
initializeData(mData->getType());
}
List::Type AbstractGrid::getDataType()
{
return mData->getType();
} }

View file

@ -1,54 +1,28 @@
#pragma once #pragma once
#include "Bounds.h" #include "Bounds.h"
#include "List.h"
#include "ListT.h"
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <stdexcept>
class AbstractGrid class AbstractGrid
{ {
public: public:
AbstractGrid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, List::Type dataType = List::Type::DOUBLE); AbstractGrid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, std::size_t numPointsZ = 1);
const Bounds& getBounds() const; const Bounds& getBounds() const;
virtual std::size_t getDataSize() const = 0;
double getXSpacing() const; double getXSpacing() const;
double getYSpacing() const; double getYSpacing() const;
List::Type getDataType();
template<typename T>
const std::vector<T> getData() const
{
if (!dynamic_cast<ListT<T>*>(mData.get()))
{
throw std::logic_error("Invalid data type request for Grid data.");
}
return dynamic_cast<ListT<T>*>(mData.get())->getData();
}
template<typename T>
void setData(const std::vector<std::size_t> indices, const std::vector<T>& values)
{
if (auto list_t = dynamic_cast<ListT<T>*>(mData.get()))
{
list_t->setData(indices, values);
}
}
virtual void initializeData(List::Type dataType) = 0;
void resetBounds(const Bounds& bounds); void resetBounds(const Bounds& bounds);
protected: protected:
Bounds mBounds; Bounds mBounds;
std::unique_ptr<List> mData;
std::size_t mNumX{ 0 }; std::size_t mNumX{ 0 };
std::size_t mNumY{ 0 }; std::size_t mNumY{ 0 };
std::size_t mNumZ{ 0 };
}; };

View file

@ -1,14 +0,0 @@
#include "Grid.h"
#include "ListFactory.h"
Grid::Grid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, List::Type dataType)
: AbstractGrid(bounds, numPointsX, numPointsY, dataType)
{
initializeData(dataType);
}
void Grid::initializeData(List::Type dataType)
{
mData = ListFactory::Create(dataType, mNumX * mNumY);
}

View file

@ -1,12 +1,34 @@
#pragma once #pragma once
#include "AbstractGrid.h" #include "TypedGrid.h"
class Grid : public AbstractGrid template<typename T>
class Grid : public TypedGrid<T>
{ {
public: public:
Grid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, List::Type dataType = List::Type::DOUBLE); Grid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, std::size_t numPointsZ = 1)
: TypedGrid<T>(bounds, numPointsX, numPointsY, numPointsZ)
{
this->mData->initializeTo(numPointsX * numPointsY * numPointsZ, T());
}
private: T getItem(std::size_t idx, std::size_t jdx, std::size_t kdx) const override
void initializeData(List::Type dataType) override; {
return this->mData->getItem(getOffset(idx, jdx, kdx));
}
std::size_t getOffset(std::size_t idx, std::size_t jdx, std::size_t kdx) const
{
return idx * this->mNumZ + jdx * this->mNumX * this->mNumZ + kdx;
}
void setItem(std::size_t idx, std::size_t jdx, std::size_t kdx, const T& value) override
{
this->mData->setItem(getOffset(idx, jdx, kdx), value);
}
std::size_t getDataSize() const
{
return this->mData->getLength();
}
}; };

View file

@ -1,2 +1,15 @@
#pragma once #pragma once
#include "TypedGrid.h"
template<typename T>
class SparseGrid : public TypedGrid
{
public:
SparseGrid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY)
: TypedGrid<T>(bounds, numPointsX, numPointsY)
{
}
};

View file

@ -0,0 +1,24 @@
#pragma once
#include "List.h"
#include "AbstractGrid.h"
#include <memory>
template <typename T>
class TypedGrid : public AbstractGrid
{
public:
TypedGrid(const Bounds& bounds, std::size_t numPointsX, std::size_t numPointsY, std::size_t numPointsZ = 1)
: AbstractGrid(bounds, numPointsX, numPointsY, numPointsZ),
mData(std::make_unique<List<T> >())
{
}
virtual T getItem(std::size_t idx, std::size_t jdx, std::size_t kdx) const = 0;
virtual void setItem(std::size_t idx, std::size_t jdx, std::size_t kdx, const T& value) = 0;
protected:
std::unique_ptr<List<T> > mData;
};

View file

@ -18,7 +18,7 @@ public:
Bounds getBounds() const override; Bounds getBounds() const override;
void sample(Grid* grid) const override {}; void sample(SparseGrid<bool>* grid) const override {};
private: private:
Point mStartPoint; Point mStartPoint;

View file

@ -27,7 +27,7 @@ const Point& LineSegment::getPoint1() const
return mP1; return mP1;
} }
void LineSegment::sample(Grid* grid) const void LineSegment::sample(SparseGrid<bool>* grid) const
{ {
} }

View file

@ -15,7 +15,7 @@ public:
const Point& getPoint1() const; const Point& getPoint1() const;
void sample(Grid* grid) const override; void sample(SparseGrid<bool>* grid) const override;
Bounds getBounds() const override; Bounds getBounds() const override;

View file

@ -27,7 +27,7 @@ void Circle::setMinorRadius(double radius)
mMinorRadius = radius; mMinorRadius = radius;
} }
void Circle::sample(Grid* grid) const void Circle::sample(SparseGrid<bool>* grid) const
{ {
} }

View file

@ -22,7 +22,7 @@ public:
void setMinorRadius(double radius); void setMinorRadius(double radius);
void sample(Grid* grid) const override; void sample(SparseGrid<bool>* grid) const override;
private: private:
double mMinorRadius{ 0.5 }; double mMinorRadius{ 0.5 };

View file

@ -31,7 +31,7 @@ namespace ntk {
return { minX , maxX , minY , maxY }; return { minX , maxX , minY , maxY };
} }
void Rectangle::sample(Grid* grid) const void Rectangle::sample(SparseGrid<bool>* grid) const
{ {
} }

View file

@ -19,7 +19,7 @@ public:
Type getType() const override; Type getType() const override;
void sample(Grid* grid) const override; void sample(SparseGrid<bool>* grid) const override;
private: private:
Point mBottomLeft; Point mBottomLeft;

View file

@ -5,10 +5,12 @@
#include "Grid.h" #include "Grid.h"
RasterPainter::RasterPainter(DrawingContext* context) RasterPainter::RasterPainter(DrawingContext* context)
: AbstractPainter(context), : AbstractPainter(context)
mGrid(std::make_unique<Grid>(Bounds{0.0, 0.0, 100.0, 100.0}))
{ {
const auto width = context->getSurface()->getWidth();
const auto height = context->getSurface()->getHeight();
mGrid = std::make_unique<Grid<unsigned char> >(Bounds{ 0.0, 0.0, 100.0, 100.0 }, width, height);
} }
void RasterPainter::paint() void RasterPainter::paint()

View file

@ -5,6 +5,8 @@
#include <memory> #include <memory>
class DrawingContext; class DrawingContext;
template<typename T>
class Grid; class Grid;
class RasterPainter : public AbstractPainter class RasterPainter : public AbstractPainter
@ -15,5 +17,5 @@ public:
void paint() override; void paint() override;
private: private:
std::unique_ptr<Grid> mGrid; std::unique_ptr<Grid<unsigned char> > mGrid;
}; };

View file

@ -31,7 +31,7 @@ list(APPEND platform_LIB_INCLUDES
) )
endif() endif()
list(APPEND image_LIBS core compression) list(APPEND image_LIBS core compression geometry)
list(APPEND image_DEFINES "") list(APPEND image_DEFINES "")
add_library(image SHARED ${image_LIB_INCLUDES} ${platform_LIB_INCLUDES} ${image_HEADERS}) add_library(image SHARED ${image_LIB_INCLUDES} ${platform_LIB_INCLUDES} ${image_HEADERS})

View file

@ -1,12 +1,13 @@
#include "Image.h" #include "Image.h"
#include "Color.h" #include "Color.h"
#include "Grid.h"
#ifdef _WIN32 #ifdef _WIN32
#include "Win32WicImage.h" #include "Win32WicImage.h"
#endif #endif
Image::Image(unsigned width, unsigned height, ImageData::Type dataType) Image::Image(unsigned width, unsigned height, DataType dataType)
: mWidth(width), : mWidth(width),
mHeight(height), mHeight(height),
mDataType(dataType) mDataType(dataType)
@ -19,38 +20,43 @@ Image::~Image()
} }
std::unique_ptr<Image> Image::Create(unsigned width, unsigned height, ImageData::Type dataType) std::unique_ptr<Image> Image::Create(unsigned width, unsigned height, DataType dataType)
{ {
return std::make_unique<Image>(width, height, dataType); return std::make_unique<Image>(width, height, dataType);
} }
void Image::initialize() void Image::initialize()
{ {
if (mDataType == ImageData::Type::UCHAR || mDataType == ImageData::Type::UNKNOWN) Bounds bounds(0.0, mWidth, 0.0, mHeight);
if (mDataType == DataType::UCHAR)
{ {
auto data = std::unique_ptr<ImageDataT<unsigned char> >(); mData = std::make_unique<Grid<unsigned char> >(bounds, mWidth, mHeight, mNumChannels);
data->initialize(getBytesPerRow() * mHeight, 0);
mData = std::move(data);
} }
else else
{ {
auto data = std::unique_ptr<ImageDataT<uint8_t> >(); mData = std::make_unique<Grid<uint8_t> >(bounds, mWidth, mHeight, mNumChannels);
data->initialize(getBytesPerRow() * mHeight, 0);
mData = std::move(data);
} }
} }
void Image::setPixelValue(unsigned idx, unsigned jdx, const Color& color) void Image::setPixelValues(const Indices& indices, const std::vector<Color>& colors)
{ {
if (!mData) if (!mData)
{ {
initialize(); initialize();
} }
const auto offset = jdx * getBytesPerRow() + idx * 3; if (mDataType == DataType::UCHAR)
mData->setDataItem(offset, color.getR()); {
mData->setDataItem(offset + 1, color.getG()); auto data_t = getDataT<unsigned char>();
mData->setDataItem(offset + 2, color.getB()); for (std::size_t idx=0; idx< indices.size(); idx++)
{
auto id = indices[idx];
auto color = colors[idx];
data_t->setItem(id.first, id.second, 0, color.getR());
data_t->setItem(id.first, id.second, 1, color.getG());
data_t->setItem(id.first, id.second, 2, color.getB());
}
}
} }
unsigned Image::getBytesPerRow() const unsigned Image::getBytesPerRow() const
@ -83,14 +89,20 @@ PlatformImage* Image::getPlatformImage()
return mPlatformImage.get(); return mPlatformImage.get();
} }
ImageData* Image::getData() AbstractGrid* Image::getData() const
{ {
return mData.get(); return mData.get();
} }
unsigned char Image::getAsUnsignedChar(unsigned idx, unsigned jdx) const template<typename T>
Grid<T>* Image::getDataT() const
{ {
return mData->getAsUnsignedChar(jdx * getBytesPerRow() + idx); return dynamic_cast<Grid<T>*>(this->mData.get());
}
Image::DataType Image::getType() const
{
return mDataType;
} }
unsigned Image::getNumChannels() const unsigned Image::getNumChannels() const

View file

@ -1,19 +1,30 @@
#pragma once #pragma once
#include "PlatformImage.h" #include "PlatformImage.h"
#include "ImageData.h"
#include <memory> #include <memory>
#include <vector> #include <vector>
class Color; class Color;
class AbstractGrid;
template<typename T>
class Grid;
class Image class Image
{ {
public: public:
Image(unsigned width, unsigned height, ImageData::Type dataType = ImageData::Type::UCHAR); enum class DataType
{
UCHAR
};
using Index = std::pair<std::size_t, std::size_t>;
using Indices = std::vector<Index>;
Image(unsigned width, unsigned height, DataType dataType = DataType::UCHAR);
~Image(); ~Image();
static std::unique_ptr<Image> Create(unsigned width, unsigned height, ImageData::Type dataType = ImageData::Type::UCHAR); static std::unique_ptr<Image> Create(unsigned width, unsigned height, DataType dataType = DataType::UCHAR);
unsigned getBytesPerRow() const; unsigned getBytesPerRow() const;
unsigned getWidth() const; unsigned getWidth() const;
@ -21,11 +32,15 @@ public:
unsigned getBitDepth() const; unsigned getBitDepth() const;
unsigned getNumChannels() const; unsigned getNumChannels() const;
ImageData* getData(); AbstractGrid* getData() const;
unsigned char getAsUnsignedChar(unsigned idx, unsigned jdx) const;
template<typename T>
Grid<T>* getDataT() const;
DataType getType() const;
PlatformImage* getPlatformImage(); PlatformImage* getPlatformImage();
void setPixelValue(unsigned idx, unsigned jdx, const Color& color); void setPixelValues(const Indices& indices, const std::vector<Color>& colors);
void setWidth(unsigned width); void setWidth(unsigned width);
void setHeight(unsigned height); void setHeight(unsigned height);
void setBitDepth(unsigned bitDepth); void setBitDepth(unsigned bitDepth);
@ -39,7 +54,7 @@ private:
unsigned mBitDepth{8}; unsigned mBitDepth{8};
unsigned mNumChannels{4}; unsigned mNumChannels{4};
ImageData::Type mDataType; DataType mDataType;
std::unique_ptr<ImageData> mData; std::unique_ptr<AbstractGrid> mData;
std::unique_ptr<PlatformImage> mPlatformImage; std::unique_ptr<PlatformImage> mPlatformImage;
}; };

View file

@ -1,5 +1,7 @@
#include "ImageBitStream.h" #include "ImageBitStream.h"
#include "AbstractGrid.h"
ImageBitStream::ImageBitStream(Image* image) ImageBitStream::ImageBitStream(Image* image)
: BitStream(), : BitStream(),
mImage(image) mImage(image)
@ -9,7 +11,7 @@ ImageBitStream::ImageBitStream(Image* image)
bool ImageBitStream::isFinished() const bool ImageBitStream::isFinished() const
{ {
return mByteOffset == mImage->getData()->getLength(); return mByteOffset == mImage->getData()->getDataSize();
} }
std::vector<unsigned char> ImageBitStream::peekNextNBytes(unsigned n) const std::vector<unsigned char> ImageBitStream::peekNextNBytes(unsigned n) const
@ -25,8 +27,9 @@ std::optional<unsigned char> ImageBitStream::readNextByte()
{ {
return std::nullopt; return std::nullopt;
} }
const auto val = mImage->getData()->getAsUnsignedChar(mByteOffset); //const auto val = mImage->getData()->getAsUnsignedChar(mByteOffset);
return val; //return val;
return {};
} }
void ImageBitStream::writeByte(unsigned char data, bool checkOverflow ) void ImageBitStream::writeByte(unsigned char data, bool checkOverflow )
@ -37,6 +40,6 @@ void ImageBitStream::writeByte(unsigned char data, bool checkOverflow )
{ {
return; return;
} }
mImage->getData()->setDataItem(mByteOffset, data); //mImage->getData()->setDataItem(mByteOffset, data);
} }