Code Monkey home page Code Monkey logo

scratchedhologramfrom3d's Introduction

Build Status Build status Codacy Badge

ScratchedHologramFrom3D

Tool to transform a 3D-model into scratches picture, that can be engraved onto semi-reflective material (vinil, aluminium) and used to show fake-hologram.

For more information check project wiki

A hologram example

GIF

scratchedhologramfrom3d's People

Contributors

panoni avatar shchuko avatar tulesha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

scratchedhologramfrom3d's Issues

Exteng File2DProcessingTools::IVectorGraphicsDataWriter interface

  • Implemented
  • Test coverage made

Add new method:

void IVectorGraphicsDataWriter::writeMul(std::string filepath, const std::vector<CVectorGraphicsData> &data, bool write_force = false);

Writes several CVectorGraphicsData objects into one file

Method call example:

std::vector<CVectorGraphicsData> vec;
vec.emplace_back(someData1);
vec.emplace_back(someData2);
// ...

Writer w;
w.writeMul("some_path", vec);

Implement CliTools library

CliTools::COption - immutable

  • getShortName()
  • getLongName()
  • getDescription()
  • isRequired() - обязательная ли опция*
  • isHasArgument() - имеет ли опция аргументы
    *если установить флаг true и опции не будет среди аргументов, парсер бросит исключения

CliTools::COptionBuilder

  • addShortName(char c)

  • addLongName(std::string)

  • addDescription(std::string)

  • setValued(bool has_value, bool option_required = false)
    has_value - опция принимает значение, option_required - опция обязательная

  • buildOption() returns CliTools::COption throws EOptionBuildError

  • reset() - сбросить билдер к начальному значению

CliTools::CArgsParser

  • addOption(CliTools::COption) - добавить опцию в словапь опций парсера
  • parse(char** args) throws ERequiredOptionNotPresent, EValuedOptionWithoutValue - распарсить args
  • getOptionValue(std::string) throws EOptionNotPresentInDictionary - значение опции. Если опция не найдена в словаре, бросает исключение. Если опция найдена, но не должна принимать значение, отдает пустую строку
  • isOptionPresent() - присутствует ли опция
  • getOptionValue(char) throws EOptionNotPresentInDictionary
  • getPureArgsCount() - число аргументов без опций
  • getPureArg(arg_index)

Exceptions:

  • CliTools::EOptionBuildError - исключение - билдер не получил достаточно аргументов

  • CliTools::EParserError - общий класс для исключений парсера

  • CliTools::ERequiredOptionNotPresent extends EParseError - обязательная опция не присутствует среди аргументов

  • CliTools::EValuedOptionWithoutValue extends EParseError - за опцией, принимающей значение, значение отсутствует

  • CliTools::EOptionNotPresentInDictionary extends EParseError - опция не найдена в словаре опций

Incorrect args parsing

image

Here valued option -s was given without value, but no errors are displayed and -s's parsed value is next readable value 10000

Add File2DProcessingTools::CVectorGraphicsData

[Uses Geometry2D library]

  • CVectorGraphicsData
// For now it's gonna be enough:
class CVectorGraphicsData {
public:
    CVectorGraphicsData() = default;
    CVectorGraphicsData(const CVectorGraphicsData &data) = default;
    CVectorGraphicsData(CVectorGraphicsData &&data) = default;

    CVectorGraphicsData &operator=(const CVectorGraphicsData &data) = default;
    CVectorGraphicsData &operator=(CVectorGraphicsData &&data) = default;

    void addLineSegment(CLineSegment2D) noexcept; // Store line segment [std::move() here]
    const std::vector<CLineSegment2D>& getLineSegments() const noexcept; // Get all stored line 
segments
};

Add new class Geometry3D::CLinkedLine3D

Defines line object in 3D-space. Line linked to Geometry3D::AVector3D direction vector and Geometry3D::CPoint3D.
Определяет объект "линия" в трехмерном пространстве как совокупность направляющего вектора Geometry3D::AVector3D и точки Geometry3D::CPoint3D.

класс-перечесление с типом отношений между прямыми: (скрещиваются, параллельны, пересекаются, совпадают)

  • enum class RelationType { SKEW, PARALLEL, CROSSING, OVERLAP } -- класс-перечесление с типом отношений между прямыми: (скрещиваются, параллельны, пересекаются, совпадают)
  • enum class CoordinateName { X, Y, Z } -- класс-перечисление имен координат для формирования запросов
  • setDirectionVector - set new direction vector
  • setLinkedPoint - set new linked point
  • getDirectionVector
  • getLinkedPoint
  • getRelationType - check and return relation between two lines
  • getCrossingPoint - get lines crossing point. If no crossing {nan, nan, nan}, if overlap {inf, inf, inf}
  • isCrossesPoint - true if line crosses point, else false
    Методы для получения координат точки, лежащей на прямой, зная одну из других координат через канонический вид уравнения:
  • getLinePointX - получить значение координаты X, зная Y или Z
  • getLinePointY - получить значение координаты Y, зная X или Z
  • getLinePointZ - получить значение координаты Z, зная X или Y
    Если получить координату невозможно (прямая параллельна соответствующей оси, координата направляющего вектора соответсвующей оси равна 0, и невозможно по известной координате установить другие), вернуть NaN

It's better to use const pointers.

class CLinkedLine3D {
private:
    const AVector3D* p_direction_vector = nullprt;
    const CPoint3D* p_linked_point = nullprt;

public:
    enum class RelationType { SKEW, PARALLEL, CROSSING };
    enum class CoordinateName { X, Y, Z };

    CLinkedLine3D(const AVector3D& direction_vector, const CPoint3D& linked_point) noexcept;
    void setDirectionVector(const AVector3D& direction_vector) noexcept;
    void setLinkedPoint(const CPoint3D& linked_point) noexcept;
    const AVector3D& getDirectionVector() const noexcept;
    const CPoint3D& getLinkedPoint() const noexcept;
    RelationType getRelationType(const CLinkedLine3D& line) const noexcept;
    CPoint3D getCrossingPoint(const CLinkedLine3D& line) const noexcept;
    bool isCrossesPoint(const CPoint3D& point) const noexcept;
    double getLinePointX(double known_coordinate, CoordinateName known_coordinate_name) const noexcept;
    double getLinePointY(double known_coordinate, CoordinateName known_coordinate_name) const noexcept;
    double getLinePointZ(double known_coordinate, CoordinateName known_coordinate_name) const noexcept;

private:
    // Leave with no definition
    CLinkedLine3D(AVector3D&& direction_vector, CPoint3D&& linked_point) noexcept;
    void setDirectionVector(AVector3D&& direction_vector) noexcept;
    void setLinkedPoint(CPoint3D&& linked_point) noexcept;
};

NaN and INF example:

#include <iostream>
#include <cmath>
#include <limits>


int main() {
    double nan_val = std::numeric_limits<double>::quiet_NaN();
    double inf_val = std::numeric_limits<double>::infinity();
    double normal_val = 3.9;
    
    std::cout << nan_val << ' ' << std::isnormal(nan_val) << '\n';
    std::cout << inf_val << ' ' << std::isnormal(inf_val) << '\n';
    std::cout << normal_val << ' ' << std::isnormal(normal_val) << '\n';

}

Extend CVectorGraphicsData interface, fix precision for zero-closed values printing in CSvgFileWriter

  • Change existing methods:
void addLineSegments(Geometry2D::CLineSegment2D line_segment, unsigned int width_pixels = 1) noexcept;

void addLineSegments(InputIterator begin, InputIterator end, unsigned int width_pixels = 1) noexcept;
  • Add new type:
CColor_T
  • Add new methods:
// Next color should be used for all next added objects 
// Default is black
void setNextColor(CColor_T color) noexcept;

const std::vector<unsigned int> &getLineSegmentsWidths() const noexcept;
const std::vector<CColor_T> &getLineSegmentsColors() const noexcept;
  • Update IVectorGraphicsDataWriter inheritors with changed CVectorGraphicsData interface: let line segment color and width be printed correctly

Geometry3D::CPoint3D , ::CVector3D add setters&copy assignment operator

  • CPoint3D setters
  • CVector3D setters
  • CVector3D copy assignment operator
// CPoint3D
void setX(double x) noexcept;
void setY(double x) noexcept;
void setZ(double x) noexcept;
// CVector3D
void setX(double x) noexcept;
void setY(double x) noexcept;
void setZ(double x) noexcept;
CVector3D& operator=(const CVector3D& vec) noexcept);

Update IVectorGraphicsDataWriter & its inheritors

Add methods:

// Input data should be scaled to height
// Width should be recalculated by input data aspect ratio
virtual IVectorGraphicsDataWriter::setCanvasHeight(unsigned int height_px) noexcept;

// Input data should be scaled to width
// Height should be recalculated by input data aspect ratio
virtual IVectorGraphicsDataWriter::setCanvasWidth(unsigned int width_px) noexcept;

// Input data should be scaled to fit height and width
virtual IVectorGraphicsDataWriter::setCanvasSize(unsigned int height_px, unsigned int width_px) noexcept;

// Padding.first = vertical  (up-side, down-side) padding width in pixels
// Padding.second = horizontal (left-side, right-side) padding width in pixels
// Rescale input data to fit if needed
virtual IVectorGraphicsDataWriter::setAlignmentCenter(std::pair<unsigned int, unsigned int> padding_зч = std::make_pair(0, 0)) noexcept;

Create app CLI

Pack all the app functionality into command-line interface

  • Done

Extend Geometry3D::CLinkedVector3D interface

Add methods:

  • setPointBegin
  • setPointEnd
  • getPointBegin
  • getPointEnd
void setPointBegin(const CPoint3D& new_point_begin) noexcept;
void setPointEnd(const CPoint3D& new_point_end) noexcept;
const CPoint3D& getPointBegin() const noexcept;
const CPoint3D& getPointBegin() const noexcept;

Note:
As references are not modifiable, to allow begin and end points changing, const pointers should be used. Such pointer declaration allows pointer changing, but not allows to change value.
Заметка:
Так как ссылки неименяемые, чтобы это реализовать, стоит перейти от хранения ссылок к хранению константных указателей. Такое декларирования указателя позволит менять сам указатель, но не значение, на которое он указывает

const CPoint3D *p_point_begin = nullptr;
const CPoint3D *p_point_end = nullptr;

// Assigning values
void setPointBegin(const CPoint3D& new_point_begin) noexcept {
     p_point_begin = &new_point_begin; 
}

Also it's forbidden to pass rvalue as set...() arguments. Make these methods private and leave them with no definition.
Также, необходимо запретить использовать rvalue как параметр set...() методов. Следует задекларировать соответствующие методы private и оставить без определения.

// Just declare with no definition
private:
    void setPointBegin(CPoint3D&& new_point_begin) noexcept;
    void setPointEnd(CPoint3D&& new_point_begin) noexcept;

Extend Geometry3D::AVector interface

Returns coordinate value of same-directed normalized vector

  • getNormalizedX
  • getNormalizedY
  • getNormalizedZ

// Implement in AVector!
virtual double getNormalizedX() const noexcept;
virtual double getNormalizedY() const noexcept;
virtual double getNormalizedZ() const noexcept;

Scratches printed out of svg-canvas borders

Model goes out of svg-canvas:

.\ScratchedHologramFrom3DApp.exe -i cube.obj -o cube.svg -d 100 -h 20 -a 50 -n 500 -x 0.1 -k 0.2 -s 0.7  

Used default Blender cube model

fix setAligmentCenter(...): Does not center the image

Add spline support to vector graphic libraries

  • Add == operator for CPoint2D
  • Add new class "File2DProcessingTools::CPath"
  • Add CSmoothedLine support to CVectorGraphicsData
  • Add CSmoothedLine support to IVectorGraphicsDataWriter

Почекать идеи интерполяции кривой можно:

class CPath {
public:
    CPath(); // Default width 1px, default color BLACK, smoth=false
    CPath(unsigned int width_px, CColor color, bool smooth) noexcept;
    void setColor(const CColor& color)  noexcept; // цвет
    CColor getColor() const noexcept;
    void setWidth(unsigned int width_px) noexcept; // толщина в пикселях
    unsigned int getWidth() const noexcept; 
    void setSmooth(bool flag) noexcept; // сглаживание, атрибут для обработки в дальнейшем
    bool isSmooth() const noexcept;

    // Добавляет следующую точку к линии
    // Если линия имеет одну из координат NaN - разрыв в линии, распознается методом toSeparatedPaths()
    void appendPoint(const CPoint2D& point) noexcept;
    const std::vector<CPoint2D>& getPoints() const noexcept;

    // Разбивает линию на несколько линий, разрыв определяется точкой с NaN-координатой или циклом
    std::vector<CPath> toSeparatedPaths();

   // Проверяет, зациклена ли кривая. Если да - отмечает, что есть цикл, чтоб не дублировать точку начала/конца при записи в файл 
    void updateCycled() noexcept;
    bool isCycled() const noexcept;
    
};

Add File2DProcessingTools ::IVectorGraphicsDataWriter, ::CSvgDataWriter, exeptions

[Uses Geometry2D library]

  • IVectorGraphicsDataWriter
  • CSvgDataWriter
  • EFileAlreadyExistsException
  • EFileCannotBeOverwritten
class IVectorGraphicsDataWriter {
public:
    // [param] write_force
    // -  if true && file already exists, overwrite file
    // -  if false && file already exists, throw EFileAlreadyExistsException
    // If file can't be overwritten force, throw EFileCannotBeOverwritten
    void write(std::string filepath, const CVectorGraphicsData& data, bool write_force) = 0; 
};
class CSvgDataWriter : public IVectorGraphicsDataWriter { 
// Implements IVectorGraphicsDataWriter
// Writes data into *.svg file
// ...
};
class EFileAlreadyExistsException : public std::exception { 
// Extends std::exception
// ...
};
class EFileCannotBeOverwritten : public std::exception { 
// Extends std::exception
// ...
};

Implement File3DProcessingTools library

Typedefs:

  • f3d_v_size_t - typedef std::vectorGeometry3D::CPoint3D::size_type
  • f3d_n_size_t - typedef std::vectorGeometry3D::CVector3D::size_type
  • edge_map_key_t - typedef std::pair<f3d_v_size_t, f3d_v_size_t>

Classes to implement:

  • File3DProcessingTools::CEdge
  • File3DProcessingTools::CPolygon
  • File3DProcessingTools::CObject3DData
  • File3DProcessingTools::CPoints3DStatistics
  • File3DProcessingTools::IFile3DReader
  • File3DProcessingTools::CObjFile3DReader

Used Geometry3D lib;

 typedef std::vector<Geometry3D::CPoint3D>::size_type f3d_v_size_t;
 typedef std::vector<Geometry3D::CVector3D>::size_type f3d_n_size_t;
 typedef std::pair<f3d_v_size_t, f3d_v_size_t> edge_map_key_t;
class CEdge {
private:
    Geometry3D::CLinkedVector3D direction_vector;
    Geometry3D::CLinkedLine3D direction_line;

public:
    CEdge(const Geometry3D::CPoint3D& vertex_first, const Geometry3D::CPoint3D& vertex_second) const noexcept;
    const Geometry3D::CLinkedLine3D& getDirectionLine() const noexcept;
    const Geometry3D::CLinkedVector3D& getDirectionVector() const noexcept;
    const CPoint3D& getFirstPoint() const noexcept;
    const CPoint3D& getSecondPoint() const noexcept; 
};
class CPolygon {
private:
    std::vector<edge_map_key_t> edges_points_indexes;
    f3d_n_size_t normal_index;
    bool polygon_build = false;

public:
    CPolygon(f3d_n_size_t  _normal_index) noexcept;
    void linkEdge(edge_map_key_t edge) noexcept;
    void makeReadonly() noexcept;

    const  std::vector<edge_map_key_t>& getEdges() const noexcept;
    f3d_n_size_t getNormalIndex() const noexcept;
   
    double getEquationA() const noexcept;
    double getEquationB() const noexcept;
    double getEquationC() const noexcept;
    double getEquationD() const noexcept;
};
class CObject3DData {
protected:
    double max_x = 0.0;
    double min_x = 0.0;
    double max_y = 0.0;
    double min_y = 0.0;
    double max_z = 0.0;
    double min_z = 0.0;

    std::vector<Geometry3D::CPoint3D> vertxes;
    std::unordered_map<edge_map_key_t, CEdge, f_pair_hash> edges;
    std::vector<Geometry3D::CVector3D> polygons_normals;
    std::vector<CPolygon> polygons;

public:
    void addVertex(CPoint3D point) noexcept;
    void addPolygonNormal(CVector3D normal) noexcept;
    void addPolygon(CPolygon polygon) noexcept;
};
class IFile3DReader {
public:
    virtual CObject3DData getData(const std::string& filename) = 0; // Throws an exception if file cannot be readed

};
class CObjFile3DReader : public IFile3DReader {
    virtual CObject3DData getData(const std::string& filename); // Throws an exception if file cannot be readed
};
class EWrongFileFormat : public std::exception {
public:
    EFWrongFileFormat() = default;
    EFWrongFileFormat(std::string cause);
    char *what() const noexcept override;
};
class CPoints3DStatistics {
    public:
        explicit CPoints3DStatistics(const std::vector<Geometry3D::CPoint3D> &point) noexcept;
        double getMaxX() const noexcept;
        double getMinX() const noexcept;
        double getMaxY() const noexcept;
        double getMinY() const noexcept;
        double getMaxZ() const noexcept;
        double getMinZ() const noexcept;
    };

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.